diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-11 14:38:42 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-09-11 14:38:42 -0300 |
commit | 787a78f83e0484c9e9698189982e2f309808fae8 (patch) | |
tree | 0682eddf4ea5a49bf5078bac937a36f90057df57 /lstrlib.c | |
parent | 70c8a310925d6c41c3ef4f7feeae604a4c9a3a95 (diff) | |
download | lua-787a78f83e0484c9e9698189982e2f309808fae8.tar.gz lua-787a78f83e0484c9e9698189982e2f309808fae8.tar.bz2 lua-787a78f83e0484c9e9698189982e2f309808fae8.zip |
new scheme for buffers
Diffstat (limited to 'lstrlib.c')
-rw-r--r-- | lstrlib.c | 114 |
1 files changed, 52 insertions, 62 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstrlib.c,v 1.50 2000/08/31 20:23:40 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.51 2000/09/05 19:33:32 roberto Exp $ |
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 | */ |
@@ -18,13 +18,6 @@ | |||
18 | 18 | ||
19 | 19 | ||
20 | 20 | ||
21 | static void addnchar (lua_State *L, const char *s, size_t n) { | ||
22 | char *b = luaL_openspace(L, n); | ||
23 | memcpy(b, s, n); | ||
24 | luaL_addsize(L, n); | ||
25 | } | ||
26 | |||
27 | |||
28 | static int str_len (lua_State *L) { | 21 | static int str_len (lua_State *L) { |
29 | size_t l; | 22 | size_t l; |
30 | luaL_check_lstr(L, 1, &l); | 23 | luaL_check_lstr(L, 1, &l); |
@@ -33,11 +26,6 @@ static int str_len (lua_State *L) { | |||
33 | } | 26 | } |
34 | 27 | ||
35 | 28 | ||
36 | static void closeandpush (lua_State *L) { | ||
37 | lua_pushlstring(L, luaL_buffer(L), luaL_getsize(L)); | ||
38 | } | ||
39 | |||
40 | |||
41 | static long posrelat (long pos, size_t len) { | 29 | static long posrelat (long pos, size_t len) { |
42 | /* relative string position: negative means back from end */ | 30 | /* relative string position: negative means back from end */ |
43 | return (pos>=0) ? pos : (long)len+pos+1; | 31 | return (pos>=0) ? pos : (long)len+pos+1; |
@@ -61,11 +49,12 @@ static int str_sub (lua_State *L) { | |||
61 | static int str_lower (lua_State *L) { | 49 | static int str_lower (lua_State *L) { |
62 | size_t l; | 50 | size_t l; |
63 | size_t i; | 51 | size_t i; |
52 | luaL_Buffer b; | ||
64 | const char *s = luaL_check_lstr(L, 1, &l); | 53 | const char *s = luaL_check_lstr(L, 1, &l); |
65 | luaL_resetbuffer(L); | 54 | luaL_buffinit(L, &b); |
66 | for (i=0; i<l; i++) | 55 | for (i=0; i<l; i++) |
67 | luaL_addchar(L, tolower((unsigned char)(s[i]))); | 56 | luaL_putchar(&b, tolower((unsigned char)(s[i]))); |
68 | closeandpush(L); | 57 | luaL_pushresult(&b); |
69 | return 1; | 58 | return 1; |
70 | } | 59 | } |
71 | 60 | ||
@@ -73,22 +62,24 @@ static int str_lower (lua_State *L) { | |||
73 | static int str_upper (lua_State *L) { | 62 | static int str_upper (lua_State *L) { |
74 | size_t l; | 63 | size_t l; |
75 | size_t i; | 64 | size_t i; |
65 | luaL_Buffer b; | ||
76 | const char *s = luaL_check_lstr(L, 1, &l); | 66 | const char *s = luaL_check_lstr(L, 1, &l); |
77 | luaL_resetbuffer(L); | 67 | luaL_buffinit(L, &b); |
78 | for (i=0; i<l; i++) | 68 | for (i=0; i<l; i++) |
79 | luaL_addchar(L, toupper((unsigned char)(s[i]))); | 69 | luaL_putchar(&b, toupper((unsigned char)(s[i]))); |
80 | closeandpush(L); | 70 | luaL_pushresult(&b); |
81 | return 1; | 71 | return 1; |
82 | } | 72 | } |
83 | 73 | ||
84 | static int str_rep (lua_State *L) { | 74 | static int str_rep (lua_State *L) { |
85 | size_t l; | 75 | size_t l; |
76 | luaL_Buffer b; | ||
86 | const char *s = luaL_check_lstr(L, 1, &l); | 77 | const char *s = luaL_check_lstr(L, 1, &l); |
87 | int n = luaL_check_int(L, 2); | 78 | int n = luaL_check_int(L, 2); |
88 | luaL_resetbuffer(L); | 79 | luaL_buffinit(L, &b); |
89 | while (n-- > 0) | 80 | while (n-- > 0) |
90 | addnchar(L, s, l); | 81 | luaL_addlstring(&b, s, l); |
91 | closeandpush(L); | 82 | luaL_pushresult(&b); |
92 | return 1; | 83 | return 1; |
93 | } | 84 | } |
94 | 85 | ||
@@ -106,13 +97,14 @@ static int str_byte (lua_State *L) { | |||
106 | static int str_char (lua_State *L) { | 97 | static int str_char (lua_State *L) { |
107 | int n = lua_gettop(L); /* number of arguments */ | 98 | int n = lua_gettop(L); /* number of arguments */ |
108 | int i; | 99 | int i; |
109 | luaL_resetbuffer(L); | 100 | luaL_Buffer b; |
101 | luaL_buffinit(L, &b); | ||
110 | for (i=1; i<=n; i++) { | 102 | for (i=1; i<=n; i++) { |
111 | int c = luaL_check_int(L, i); | 103 | int c = luaL_check_int(L, i); |
112 | luaL_arg_check(L, (unsigned char)c == c, i, "invalid value"); | 104 | luaL_arg_check(L, (unsigned char)c == c, i, "invalid value"); |
113 | luaL_addchar(L, (unsigned char)c); | 105 | luaL_putchar(&b, (unsigned char)c); |
114 | } | 106 | } |
115 | closeandpush(L); | 107 | luaL_pushresult(&b); |
116 | return 1; | 108 | return 1; |
117 | } | 109 | } |
118 | 110 | ||
@@ -445,43 +437,37 @@ static int str_find (lua_State *L) { | |||
445 | } | 437 | } |
446 | 438 | ||
447 | 439 | ||
448 | static void add_s (lua_State *L, struct Capture *cap) { | 440 | static void add_s (lua_State *L, luaL_Buffer *b, struct Capture *cap) { |
449 | if (lua_isstring(L, 3)) { | 441 | if (lua_isstring(L, 3)) { |
450 | const char *news = lua_tostring(L, 3); | 442 | const char *news = lua_tostring(L, 3); |
451 | size_t l = lua_strlen(L, 3); | 443 | size_t l = lua_strlen(L, 3); |
452 | size_t i; | 444 | size_t i; |
453 | for (i=0; i<l; i++) { | 445 | for (i=0; i<l; i++) { |
454 | if (news[i] != ESC) | 446 | if (news[i] != ESC) |
455 | luaL_addchar(L, news[i]); | 447 | luaL_putchar(b, news[i]); |
456 | else { | 448 | else { |
457 | i++; /* skip ESC */ | 449 | i++; /* skip ESC */ |
458 | if (!isdigit((unsigned char)news[i])) | 450 | if (!isdigit((unsigned char)news[i])) |
459 | luaL_addchar(L, news[i]); | 451 | luaL_putchar(b, news[i]); |
460 | else { | 452 | else { |
461 | int level = check_capture(L, news[i], cap); | 453 | int level = check_capture(L, news[i], cap); |
462 | addnchar(L, cap->capture[level].init, cap->capture[level].len); | 454 | luaL_addlstring(b, cap->capture[level].init, cap->capture[level].len); |
463 | } | 455 | } |
464 | } | 456 | } |
465 | } | 457 | } |
466 | } | 458 | } |
467 | else { /* is a function */ | 459 | else { /* is a function */ |
468 | int status; | 460 | int status; |
469 | size_t oldbuff; | ||
470 | int n; | 461 | int n; |
471 | const char *s; | ||
472 | lua_pushvalue(L, 3); | 462 | lua_pushvalue(L, 3); |
473 | n = push_captures(L, cap); | 463 | n = push_captures(L, cap); |
474 | /* function may use buffer, so save it and create a new one */ | ||
475 | oldbuff = luaL_newbuffer(L, 0); | ||
476 | status = lua_call(L, n, 1); | 464 | status = lua_call(L, n, 1); |
477 | /* restore old buffer */ | ||
478 | luaL_oldbuffer(L, oldbuff); | ||
479 | if (status != 0) | 465 | if (status != 0) |
480 | lua_error(L, NULL); | 466 | lua_error(L, NULL); /* propagate error */ |
481 | s = lua_tostring(L, -1); | 467 | if (lua_isstring(L, -1)) |
482 | if (s) | 468 | luaL_addvalue(b); /* add return to accumulated result */ |
483 | addnchar(L, lua_tostring(L, -1), lua_strlen(L, -1)); | 469 | else |
484 | lua_pop(L, 1); /* pop function result */ | 470 | lua_pop(L, 1); /* function result is not a string: pop it */ |
485 | } | 471 | } |
486 | } | 472 | } |
487 | 473 | ||
@@ -494,10 +480,11 @@ static int str_gsub (lua_State *L) { | |||
494 | int anchor = (*p == '^') ? (p++, 1) : 0; | 480 | int anchor = (*p == '^') ? (p++, 1) : 0; |
495 | int n = 0; | 481 | int n = 0; |
496 | struct Capture cap; | 482 | struct Capture cap; |
483 | luaL_Buffer b; | ||
497 | luaL_arg_check(L, | 484 | luaL_arg_check(L, |
498 | lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), | 485 | lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), |
499 | 3, "string or function expected"); | 486 | 3, "string or function expected"); |
500 | luaL_resetbuffer(L); | 487 | luaL_buffinit(L, &b); |
501 | cap.src_end = src+srcl; | 488 | cap.src_end = src+srcl; |
502 | while (n < max_s) { | 489 | while (n < max_s) { |
503 | const char *e; | 490 | const char *e; |
@@ -505,17 +492,17 @@ static int str_gsub (lua_State *L) { | |||
505 | e = match(L, src, p, &cap); | 492 | e = match(L, src, p, &cap); |
506 | if (e) { | 493 | if (e) { |
507 | n++; | 494 | n++; |
508 | add_s(L, &cap); | 495 | add_s(L, &b, &cap); |
509 | } | 496 | } |
510 | if (e && e>src) /* non empty match? */ | 497 | if (e && e>src) /* non empty match? */ |
511 | src = e; /* skip it */ | 498 | src = e; /* skip it */ |
512 | else if (src < cap.src_end) | 499 | else if (src < cap.src_end) |
513 | luaL_addchar(L, *src++); | 500 | luaL_putchar(&b, *src++); |
514 | else break; | 501 | else break; |
515 | if (anchor) break; | 502 | if (anchor) break; |
516 | } | 503 | } |
517 | addnchar(L, src, cap.src_end-src); | 504 | luaL_addlstring(&b, src, cap.src_end-src); |
518 | closeandpush(L); | 505 | luaL_pushresult(&b); |
519 | lua_pushnumber(L, n); /* number of substitutions */ | 506 | lua_pushnumber(L, n); /* number of substitutions */ |
520 | return 2; | 507 | return 2; |
521 | } | 508 | } |
@@ -523,40 +510,43 @@ static int str_gsub (lua_State *L) { | |||
523 | /* }====================================================== */ | 510 | /* }====================================================== */ |
524 | 511 | ||
525 | 512 | ||
526 | static void luaI_addquoted (lua_State *L, int arg) { | 513 | static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { |
527 | size_t l; | 514 | size_t l; |
528 | const char *s = luaL_check_lstr(L, arg, &l); | 515 | const char *s = luaL_check_lstr(L, arg, &l); |
529 | luaL_addchar(L, '"'); | 516 | luaL_putchar(b, '"'); |
530 | while (l--) { | 517 | while (l--) { |
531 | switch (*s) { | 518 | switch (*s) { |
532 | case '"': case '\\': case '\n': | 519 | case '"': case '\\': case '\n': |
533 | luaL_addchar(L, '\\'); | 520 | luaL_putchar(b, '\\'); |
534 | luaL_addchar(L, *s); | 521 | luaL_putchar(b, *s); |
535 | break; | 522 | break; |
536 | case '\0': addnchar(L, "\\000", 4); break; | 523 | case '\0': luaL_addlstring(b, "\\000", 4); break; |
537 | default: luaL_addchar(L, *s); | 524 | default: luaL_putchar(b, *s); |
538 | } | 525 | } |
539 | s++; | 526 | s++; |
540 | } | 527 | } |
541 | luaL_addchar(L, '"'); | 528 | luaL_putchar(b, '"'); |
542 | } | 529 | } |
543 | 530 | ||
531 | /* maximum size of each formated item (> len(format('%99.99f', -1e308))) */ | ||
532 | #define MAX_ITEM 512 | ||
544 | /* maximum size of each format specification (such as '%-099.99d') */ | 533 | /* maximum size of each format specification (such as '%-099.99d') */ |
545 | #define MAX_FORMAT 20 /* arbitrary limit */ | 534 | #define MAX_FORMAT 20 |
546 | 535 | ||
547 | static int str_format (lua_State *L) { | 536 | static int str_format (lua_State *L) { |
548 | int arg = 1; | 537 | int arg = 1; |
549 | const char *strfrmt = luaL_check_string(L, arg); | 538 | const char *strfrmt = luaL_check_string(L, arg); |
550 | luaL_resetbuffer(L); | 539 | luaL_Buffer b; |
540 | luaL_buffinit(L, &b); | ||
551 | while (*strfrmt) { | 541 | while (*strfrmt) { |
552 | if (*strfrmt != '%') | 542 | if (*strfrmt != '%') |
553 | luaL_addchar(L, *strfrmt++); | 543 | luaL_putchar(&b, *strfrmt++); |
554 | else if (*++strfrmt == '%') | 544 | else if (*++strfrmt == '%') |
555 | luaL_addchar(L, *strfrmt++); /* %% */ | 545 | luaL_putchar(&b, *strfrmt++); /* %% */ |
556 | else { /* format item */ | 546 | else { /* format item */ |
557 | struct Capture cap; | 547 | struct Capture cap; |
558 | char form[MAX_FORMAT]; /* to store the format ('%...') */ | 548 | char form[MAX_FORMAT]; /* to store the format ('%...') */ |
559 | char *buff; /* to store the formatted item */ | 549 | char buff[MAX_ITEM]; /* to store the formatted item */ |
560 | const char *initf = strfrmt; | 550 | const char *initf = strfrmt; |
561 | form[0] = '%'; | 551 | form[0] = '%'; |
562 | if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { | 552 | if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { |
@@ -572,7 +562,6 @@ static int str_format (lua_State *L) { | |||
572 | lua_error(L, "invalid format (width or precision too long)"); | 562 | lua_error(L, "invalid format (width or precision too long)"); |
573 | strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ | 563 | strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ |
574 | form[strfrmt-initf+2] = 0; | 564 | form[strfrmt-initf+2] = 0; |
575 | buff = luaL_openspace(L, 512); /* 512 > len(format('%99.99f', -1e308)) */ | ||
576 | switch (*strfrmt++) { | 565 | switch (*strfrmt++) { |
577 | case 'c': case 'd': case 'i': | 566 | case 'c': case 'd': case 'i': |
578 | sprintf(buff, form, luaL_check_int(L, arg)); | 567 | sprintf(buff, form, luaL_check_int(L, arg)); |
@@ -584,7 +573,7 @@ static int str_format (lua_State *L) { | |||
584 | sprintf(buff, form, luaL_check_number(L, arg)); | 573 | sprintf(buff, form, luaL_check_number(L, arg)); |
585 | break; | 574 | break; |
586 | case 'q': | 575 | case 'q': |
587 | luaI_addquoted(L, arg); | 576 | luaI_addquoted(L, &b, arg); |
588 | continue; /* skip the "addsize" at the end */ | 577 | continue; /* skip the "addsize" at the end */ |
589 | case 's': { | 578 | case 's': { |
590 | size_t l; | 579 | size_t l; |
@@ -592,7 +581,8 @@ static int str_format (lua_State *L) { | |||
592 | if (cap.capture[1].len == 0 && l >= 100) { | 581 | if (cap.capture[1].len == 0 && l >= 100) { |
593 | /* no precision and string is too long to be formatted; | 582 | /* no precision and string is too long to be formatted; |
594 | keep original string */ | 583 | keep original string */ |
595 | addnchar(L, s, l); | 584 | lua_pushvalue(L, arg); |
585 | luaL_addvalue(&b); | ||
596 | continue; /* skip the "addsize" at the end */ | 586 | continue; /* skip the "addsize" at the end */ |
597 | } | 587 | } |
598 | else { | 588 | else { |
@@ -603,10 +593,10 @@ static int str_format (lua_State *L) { | |||
603 | default: /* also treat cases 'pnLlh' */ | 593 | default: /* also treat cases 'pnLlh' */ |
604 | lua_error(L, "invalid option in `format'"); | 594 | lua_error(L, "invalid option in `format'"); |
605 | } | 595 | } |
606 | luaL_addsize(L, strlen(buff)); | 596 | luaL_addlstring(&b, buff, strlen(buff)); |
607 | } | 597 | } |
608 | } | 598 | } |
609 | closeandpush(L); /* push the result */ | 599 | luaL_pushresult(&b); |
610 | return 1; | 600 | return 1; |
611 | } | 601 | } |
612 | 602 | ||