|
|
@ -1,5 +1,5 @@ |
|
|
|
/*
|
|
|
|
** $Id: lstrlib.c,v 1.232 2015/07/20 16:30:22 roberto Exp roberto $ |
|
|
|
** $Id: lstrlib.c,v 1.233 2015/09/26 18:45:03 roberto Exp roberto $ |
|
|
|
** Standard library for string operations and pattern-matching |
|
|
|
** See Copyright Notice in lua.h |
|
|
|
*/ |
|
|
@ -677,24 +677,26 @@ static int str_match (lua_State *L) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* state for 'gmatch' */ |
|
|
|
typedef struct GMatchState { |
|
|
|
const char *src; /* current position */ |
|
|
|
const char *p; /* pattern */ |
|
|
|
MatchState ms; /* match state */ |
|
|
|
} GMatchState; |
|
|
|
|
|
|
|
|
|
|
|
static int gmatch_aux (lua_State *L) { |
|
|
|
MatchState ms; |
|
|
|
size_t ls, lp; |
|
|
|
const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); |
|
|
|
const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); |
|
|
|
GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); |
|
|
|
const char *src; |
|
|
|
prepstate(&ms, L, s, ls, p, lp); |
|
|
|
for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); |
|
|
|
src <= ms.src_end; |
|
|
|
src++) { |
|
|
|
for (src = gm->src; src <= gm->ms.src_end; src++) { |
|
|
|
const char *e; |
|
|
|
reprepstate(&ms); |
|
|
|
if ((e = match(&ms, src, p)) != NULL) { |
|
|
|
lua_Integer newstart = e-s; |
|
|
|
if (e == src) newstart++; /* empty match? go at least one position */ |
|
|
|
lua_pushinteger(L, newstart); |
|
|
|
lua_replace(L, lua_upvalueindex(3)); |
|
|
|
return push_captures(&ms, src, e); |
|
|
|
reprepstate(&gm->ms); |
|
|
|
if ((e = match(&gm->ms, src, gm->p)) != NULL) { |
|
|
|
if (e == src) /* empty match? */ |
|
|
|
gm->src =src + 1; /* go at least one position */ |
|
|
|
else |
|
|
|
gm->src = e; |
|
|
|
return push_captures(&gm->ms, src, e); |
|
|
|
} |
|
|
|
} |
|
|
|
return 0; /* not found */ |
|
|
@ -702,10 +704,14 @@ static int gmatch_aux (lua_State *L) { |
|
|
|
|
|
|
|
|
|
|
|
static int gmatch (lua_State *L) { |
|
|
|
luaL_checkstring(L, 1); |
|
|
|
luaL_checkstring(L, 2); |
|
|
|
lua_settop(L, 2); |
|
|
|
lua_pushinteger(L, 0); |
|
|
|
size_t ls, lp; |
|
|
|
const char *s = luaL_checklstring(L, 1, &ls); |
|
|
|
const char *p = luaL_checklstring(L, 2, &lp); |
|
|
|
GMatchState *gm; |
|
|
|
lua_settop(L, 2); /* keep them on closure to avoid being collected */ |
|
|
|
gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); |
|
|
|
prepstate(&gm->ms, L, s, ls, p, lp); |
|
|
|
gm->src = s; gm->p = p; |
|
|
|
lua_pushcclosure(L, gmatch_aux, 3); |
|
|
|
return 1; |
|
|
|
} |
|
|
|