/******************************************************************************
* $Id: regularexp_lua.c,v 1.7 2006/01/13 21:46:55 gareuselesinge Exp $
* This file is part of FreePOPs (http://www.freepops.org) *
* This file is distributed under the terms of GNU GPL license. *
******************************************************************************/
/******************************************************************************
* File description:
* regexp bindings
* Notes:
*
* Authors:
* Name <gareuselesinge@users.sourceforge.net>
******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef FREEBSD
#include <sys/types.h>
#endif
#include <regex.h>
#include "lua.h"
#include "lauxlib.h"
#include "luabind.h"
#include "compat-5.1.h"
#define METANAME "regularep.t"
// returns and checks a stringhack from the stack
static regex_t * check_regularexp(lua_State*L)
{
void* tmp = luaL_checkudata(L,1,METANAME);
luaL_argcheck(L,tmp != NULL,1,METANAME" expected");
return (regex_t *)tmp;
}
// creates a new object
static int regularexp_comp(lua_State *L) {
const char *pattern;
int res;
regex_t *pr;
L_checknarg(L,1,"regularexp.new wants one argument (string)");
pr = (regex_t *)lua_newuserdata(L, sizeof(regex_t));
pattern = luaL_checkstring(L,1);
res = regcomp(pr, pattern, REG_EXTENDED);
if (res != 0) {
size_t sz = regerror(res, pr, NULL, 0);
char errbuf[sz];
regerror(res, pr, errbuf, sz);
lua_pushstring(L, errbuf);
lua_error(L);
}
luaL_getmetatable(L,METANAME);
lua_setmetatable(L, -2);
return 1;
}
// matches every occurrence
static int regularexp_match(lua_State *L) {
int res = 0;
int nmatch = 0;
int max;
const char *text;
regex_t *pr;
#ifndef __sun
regmatch_t pm[1]={{-1,-1}};
#else
regmatch_t pm[1];
pm[0].rm_so = -1;
pm[0].rm_eo = -1;
#endif
pr = check_regularexp(L);
text = luaL_checkstring(L,2);
max = luaL_optint(L,3,0);
max = max < 0 ? 0 : max;
lua_newtable(L);
while(res == 0 && (max == 0 || nmatch < max) ) {
res = regexec(pr, text , 1, pm, 0);
if (res == 0) {
nmatch++;
lua_pushlstring(L, text + pm->rm_so,pm->rm_eo - pm->rm_so);
lua_rawseti(L, -2,nmatch);
text += pm->rm_eo;
}
}
luaL_setn(L,-1,nmatch);
return 1;
}
// iterates over the occurrences
static int regularexp_gmatch(lua_State *L) {
int res = 0;
int nmatch = 0;
int max;
size_t cur=0;
const char *text;
regex_t *pr;
#ifndef __sun
regmatch_t pm[1]={{-1,-1}};
#else
regmatch_t pm[1];
pm[0].rm_so = -1;
pm[0].rm_eo = -1;
#endif
pr = check_regularexp(L);
text = luaL_checkstring(L,2);
luaL_checktype(L, 3, LUA_TFUNCTION);
max = luaL_optint(L,4,0);
max = max < 0 ? 0 : max;
while(res == 0 && (max == 0 || nmatch < max) ) {
res = regexec(pr, text , 1, pm, 0);
if (res == 0) {
nmatch++;
lua_pushvalue(L, 3);
lua_pushnumber(L,cur + pm->rm_so);
lua_pushnumber(L,cur + pm->rm_eo);
lua_pushlstring(L, text + pm->rm_so,pm->rm_eo - pm->rm_so);
lua_call(L, 3, 1);
if (!lua_isnil(L,-1)) {
res = 1;
}
lua_pop(L,1);
text += pm->rm_eo;
cur += pm->rm_eo;
}
}
return 0;
}
static int regularexp_gc (lua_State *L) {
regex_t *r = check_regularexp(L);
if (r)
regfree(r);
return 0;
}
static const luaL_reg regularexpmeta[] = {
{"match", regularexp_match},
{"gmatch", regularexp_gmatch},
{NULL, NULL}
};
/* Open the library */
static const luaL_reg regularexp[] = {
{"new", regularexp_comp},
{NULL, NULL}
};
int luaopen_regularexp(lua_State *L)
{
luaL_newmetatable(L,METANAME);
lua_pushstring(L,"__gc");
lua_pushcfunction(L,regularexp_gc);
lua_settable(L,-3);
lua_pushstring(L,"__index");
lua_pushvalue(L,-2);
lua_settable(L,-3);
luaL_openlib(L, NULL, regularexpmeta, 0);
luaL_openlib(L, "regularexp", regularexp, 0);
return 1;
}
syntax highlighted by Code2HTML, v. 0.9.1