diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-11 10:29:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2002-03-11 10:29:40 -0300 |
commit | c97dc294a9db1645a96958dc8f2ab61783ad7a83 (patch) | |
tree | 576ce78b11b848f2edba5facc73f2521ac5a6a67 | |
parent | 71c716e5a88a6993369505c79cd1383ef27366c4 (diff) | |
download | lua-c97dc294a9db1645a96958dc8f2ab61783ad7a83.tar.gz lua-c97dc294a9db1645a96958dc8f2ab61783ad7a83.tar.bz2 lua-c97dc294a9db1645a96958dc8f2ab61783ad7a83.zip |
first implementation of `gfind'
-rw-r--r-- | lstrlib.c | 62 |
1 files changed, 53 insertions, 9 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ | 2 | ** $Id: lstrlib.c,v 1.77 2002/02/08 22:39:36 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 | */ |
@@ -434,12 +434,18 @@ static void push_onecapture (MatchState *ms, int i) { | |||
434 | } | 434 | } |
435 | 435 | ||
436 | 436 | ||
437 | static int push_captures (MatchState *ms) { | 437 | static int push_captures (MatchState *ms, const char *s, const char *e) { |
438 | int i; | 438 | int i; |
439 | luaL_check_stack(ms->L, ms->level, "too many captures"); | 439 | luaL_check_stack(ms->L, ms->level, "too many captures"); |
440 | for (i=0; i<ms->level; i++) | 440 | if (ms->level == 0 && s) { /* no explicit captures? */ |
441 | push_onecapture(ms, i); | 441 | lua_pushlstring(ms->L, s, e-s); /* return whole match */ |
442 | return ms->level; /* number of strings pushed */ | 442 | return 1; |
443 | } | ||
444 | else { /* return all captures */ | ||
445 | for (i=0; i<ms->level; i++) | ||
446 | push_onecapture(ms, i); | ||
447 | return ms->level; /* number of strings pushed */ | ||
448 | } | ||
443 | } | 449 | } |
444 | 450 | ||
445 | 451 | ||
@@ -472,7 +478,7 @@ static int str_find (lua_State *L) { | |||
472 | if ((res=match(&ms, s1, p)) != NULL) { | 478 | if ((res=match(&ms, s1, p)) != NULL) { |
473 | lua_pushnumber(L, s1-s+1); /* start */ | 479 | lua_pushnumber(L, s1-s+1); /* start */ |
474 | lua_pushnumber(L, res-s); /* end */ | 480 | lua_pushnumber(L, res-s); /* end */ |
475 | return push_captures(&ms) + 2; | 481 | return push_captures(&ms, NULL, 0) + 2; |
476 | } | 482 | } |
477 | } while (s1++<ms.src_end && !anchor); | 483 | } while (s1++<ms.src_end && !anchor); |
478 | } | 484 | } |
@@ -481,7 +487,44 @@ static int str_find (lua_State *L) { | |||
481 | } | 487 | } |
482 | 488 | ||
483 | 489 | ||
484 | static void add_s (MatchState *ms, luaL_Buffer *b) { | 490 | static int gfind_aux (lua_State *L) { |
491 | MatchState ms; | ||
492 | const char *s = lua_tostring(L, lua_upvalueindex(1)); | ||
493 | size_t ls = lua_strlen(L, lua_upvalueindex(1)); | ||
494 | const char *p = lua_tostring(L, lua_upvalueindex(2)); | ||
495 | const char *src; | ||
496 | ms.L = L; | ||
497 | ms.src_init = s; | ||
498 | ms.src_end = s+ls; | ||
499 | for (src = s + (size_t)lua_tonumber(L, lua_upvalueindex(3)); | ||
500 | src <= ms.src_end; | ||
501 | src++) { | ||
502 | const char *e; | ||
503 | ms.level = 0; | ||
504 | if ((e = match(&ms, src, p)) != NULL) { | ||
505 | int newstart = e-s; | ||
506 | if (e == src) newstart++; /* empty match? go at least one position */ | ||
507 | lua_pushnumber(L, newstart); | ||
508 | lua_replace(L, lua_upvalueindex(3)); | ||
509 | return push_captures(&ms, src, e); | ||
510 | } | ||
511 | } | ||
512 | return 0; /* not found */ | ||
513 | } | ||
514 | |||
515 | |||
516 | static int gfind (lua_State *L) { | ||
517 | luaL_check_string(L, 1); | ||
518 | luaL_check_string(L, 2); | ||
519 | lua_settop(L, 2); | ||
520 | lua_pushnumber(L, 0); | ||
521 | lua_pushcclosure(L, gfind_aux, 3); | ||
522 | return 1; | ||
523 | } | ||
524 | |||
525 | |||
526 | static void add_s (MatchState *ms, luaL_Buffer *b, | ||
527 | const char *s, const char *e) { | ||
485 | lua_State *L = ms->L; | 528 | lua_State *L = ms->L; |
486 | if (lua_isstring(L, 3)) { | 529 | if (lua_isstring(L, 3)) { |
487 | const char *news = lua_tostring(L, 3); | 530 | const char *news = lua_tostring(L, 3); |
@@ -505,7 +548,7 @@ static void add_s (MatchState *ms, luaL_Buffer *b) { | |||
505 | else { /* is a function */ | 548 | else { /* is a function */ |
506 | int n; | 549 | int n; |
507 | lua_pushvalue(L, 3); | 550 | lua_pushvalue(L, 3); |
508 | n = push_captures(ms); | 551 | n = push_captures(ms, s, e); |
509 | lua_rawcall(L, n, 1); | 552 | lua_rawcall(L, n, 1); |
510 | if (lua_isstring(L, -1)) | 553 | if (lua_isstring(L, -1)) |
511 | luaL_addvalue(b); /* add return to accumulated result */ | 554 | luaL_addvalue(b); /* add return to accumulated result */ |
@@ -537,7 +580,7 @@ static int str_gsub (lua_State *L) { | |||
537 | e = match(&ms, src, p); | 580 | e = match(&ms, src, p); |
538 | if (e) { | 581 | if (e) { |
539 | n++; | 582 | n++; |
540 | add_s(&ms, &b); | 583 | add_s(&ms, &b, src, e); |
541 | } | 584 | } |
542 | if (e && e>src) /* non empty match? */ | 585 | if (e && e>src) /* non empty match? */ |
543 | src = e; /* skip it */ | 586 | src = e; /* skip it */ |
@@ -674,6 +717,7 @@ static const luaL_reg strlib[] = { | |||
674 | {"concat", str_concat}, | 717 | {"concat", str_concat}, |
675 | {"format", str_format}, | 718 | {"format", str_format}, |
676 | {"strfind", str_find}, | 719 | {"strfind", str_find}, |
720 | {"gfind", gfind}, | ||
677 | {"gsub", str_gsub} | 721 | {"gsub", str_gsub} |
678 | }; | 722 | }; |
679 | 723 | ||