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 | ||
