aboutsummaryrefslogtreecommitdiff
path: root/lstrlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-09-28 15:05:01 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-09-28 15:05:01 -0300
commit10fffcd80abb2830935a5aa6b1bd1da9b1a77d97 (patch)
tree2cea1e1b1e5e613e05b6a334e95a27dbdc6e8746 /lstrlib.c
parent8264dbc2bb42d4119ec54caa55e4bece2d6985d6 (diff)
downloadlua-10fffcd80abb2830935a5aa6b1bd1da9b1a77d97.tar.gz
lua-10fffcd80abb2830935a5aa6b1bd1da9b1a77d97.tar.bz2
lua-10fffcd80abb2830935a5aa6b1bd1da9b1a77d97.zip
'gmatch' keeps its state in a userdata (keeping the same 'MatchState'
across calls)
Diffstat (limited to 'lstrlib.c')
-rw-r--r--lstrlib.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/lstrlib.c b/lstrlib.c
index a257e872..5a58c7f1 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lstrlib.c,v 1.232 2015/07/20 16:30:22 roberto Exp roberto $ 2** $Id: lstrlib.c,v 1.233 2015/09/26 18:45:03 roberto Exp roberto $
3** Standard library for string operations and pattern-matching 3** Standard library for string operations and pattern-matching
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -677,24 +677,26 @@ static int str_match (lua_State *L) {
677} 677}
678 678
679 679
680/* state for 'gmatch' */
681typedef struct GMatchState {
682 const char *src; /* current position */
683 const char *p; /* pattern */
684 MatchState ms; /* match state */
685} GMatchState;
686
687
680static int gmatch_aux (lua_State *L) { 688static int gmatch_aux (lua_State *L) {
681 MatchState ms; 689 GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3));
682 size_t ls, lp;
683 const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
684 const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp);
685 const char *src; 690 const char *src;
686 prepstate(&ms, L, s, ls, p, lp); 691 for (src = gm->src; src <= gm->ms.src_end; src++) {
687 for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
688 src <= ms.src_end;
689 src++) {
690 const char *e; 692 const char *e;
691 reprepstate(&ms); 693 reprepstate(&gm->ms);
692 if ((e = match(&ms, src, p)) != NULL) { 694 if ((e = match(&gm->ms, src, gm->p)) != NULL) {
693 lua_Integer newstart = e-s; 695 if (e == src) /* empty match? */
694 if (e == src) newstart++; /* empty match? go at least one position */ 696 gm->src =src + 1; /* go at least one position */
695 lua_pushinteger(L, newstart); 697 else
696 lua_replace(L, lua_upvalueindex(3)); 698 gm->src = e;
697 return push_captures(&ms, src, e); 699 return push_captures(&gm->ms, src, e);
698 } 700 }
699 } 701 }
700 return 0; /* not found */ 702 return 0; /* not found */
@@ -702,10 +704,14 @@ static int gmatch_aux (lua_State *L) {
702 704
703 705
704static int gmatch (lua_State *L) { 706static int gmatch (lua_State *L) {
705 luaL_checkstring(L, 1); 707 size_t ls, lp;
706 luaL_checkstring(L, 2); 708 const char *s = luaL_checklstring(L, 1, &ls);
707 lua_settop(L, 2); 709 const char *p = luaL_checklstring(L, 2, &lp);
708 lua_pushinteger(L, 0); 710 GMatchState *gm;
711 lua_settop(L, 2); /* keep them on closure to avoid being collected */
712 gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState));
713 prepstate(&gm->ms, L, s, ls, p, lp);
714 gm->src = s; gm->p = p;
709 lua_pushcclosure(L, gmatch_aux, 3); 715 lua_pushcclosure(L, gmatch_aux, 3);
710 return 1; 716 return 1;
711} 717}