commit c97dc294a9db1645a96958dc8f2ab61783ad7a83
parent 71c716e5a88a6993369505c79cd1383ef27366c4
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Mon, 11 Mar 2002 10:29:18 -0300
first implementation of `gfind'
Diffstat:
M | lstrlib.c | | | 62 | +++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
1 file changed, 53 insertions(+), 9 deletions(-)
diff --git a/lstrlib.c b/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $
+** $Id: lstrlib.c,v 1.77 2002/02/08 22:39:36 roberto Exp roberto $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -434,12 +434,18 @@ static void push_onecapture (MatchState *ms, int i) {
}
-static int push_captures (MatchState *ms) {
+static int push_captures (MatchState *ms, const char *s, const char *e) {
int i;
luaL_check_stack(ms->L, ms->level, "too many captures");
- for (i=0; i<ms->level; i++)
- push_onecapture(ms, i);
- return ms->level; /* number of strings pushed */
+ if (ms->level == 0 && s) { /* no explicit captures? */
+ lua_pushlstring(ms->L, s, e-s); /* return whole match */
+ return 1;
+ }
+ else { /* return all captures */
+ for (i=0; i<ms->level; i++)
+ push_onecapture(ms, i);
+ return ms->level; /* number of strings pushed */
+ }
}
@@ -472,7 +478,7 @@ static int str_find (lua_State *L) {
if ((res=match(&ms, s1, p)) != NULL) {
lua_pushnumber(L, s1-s+1); /* start */
lua_pushnumber(L, res-s); /* end */
- return push_captures(&ms) + 2;
+ return push_captures(&ms, NULL, 0) + 2;
}
} while (s1++<ms.src_end && !anchor);
}
@@ -481,7 +487,44 @@ static int str_find (lua_State *L) {
}
-static void add_s (MatchState *ms, luaL_Buffer *b) {
+static int gfind_aux (lua_State *L) {
+ MatchState ms;
+ const char *s = lua_tostring(L, lua_upvalueindex(1));
+ size_t ls = lua_strlen(L, lua_upvalueindex(1));
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
+ const char *src;
+ ms.L = L;
+ ms.src_init = s;
+ ms.src_end = s+ls;
+ for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3));
+ src <= ms.src_end;
+ src++) {
+ const char *e;
+ ms.level = 0;
+ if ((e = match(&ms, src, p)) != NULL) {
+ int newstart = e-s;
+ if (e == src) newstart++; /* empty match? go at least one position */
+ lua_pushnumber(L, newstart);
+ lua_replace(L, lua_upvalueindex(3));
+ return push_captures(&ms, src, e);
+ }
+ }
+ return 0; /* not found */
+}
+
+
+static int gfind (lua_State *L) {
+ luaL_check_string(L, 1);
+ luaL_check_string(L, 2);
+ lua_settop(L, 2);
+ lua_pushnumber(L, 0);
+ lua_pushcclosure(L, gfind_aux, 3);
+ return 1;
+}
+
+
+static void add_s (MatchState *ms, luaL_Buffer *b,
+ const char *s, const char *e) {
lua_State *L = ms->L;
if (lua_isstring(L, 3)) {
const char *news = lua_tostring(L, 3);
@@ -505,7 +548,7 @@ static void add_s (MatchState *ms, luaL_Buffer *b) {
else { /* is a function */
int n;
lua_pushvalue(L, 3);
- n = push_captures(ms);
+ n = push_captures(ms, s, e);
lua_rawcall(L, n, 1);
if (lua_isstring(L, -1))
luaL_addvalue(b); /* add return to accumulated result */
@@ -537,7 +580,7 @@ static int str_gsub (lua_State *L) {
e = match(&ms, src, p);
if (e) {
n++;
- add_s(&ms, &b);
+ add_s(&ms, &b, src, e);
}
if (e && e>src) /* non empty match? */
src = e; /* skip it */
@@ -674,6 +717,7 @@ static const luaL_reg strlib[] = {
{"concat", str_concat},
{"format", str_format},
{"strfind", str_find},
+{"gfind", gfind},
{"gsub", str_gsub}
};