diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-09 13:14:46 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2010-04-09 13:14:46 -0300 |
| commit | 9100f7479afabc4bb2926c619b5ef09693cf9a94 (patch) | |
| tree | ed07e9aa37c8f7f4d8282d4d21670c85ea9b6a6c | |
| parent | 055104f5b6a0264974c5d9f2a55499420a1c9c2a (diff) | |
| download | lua-9100f7479afabc4bb2926c619b5ef09693cf9a94.tar.gz lua-9100f7479afabc4bb2926c619b5ef09693cf9a94.tar.bz2 lua-9100f7479afabc4bb2926c619b5ef09693cf9a94.zip | |
new implementation for Generic Buffer manipulation (using userdata as
temporary buffer space)
| -rw-r--r-- | lauxlib.c | 124 | ||||
| -rw-r--r-- | lauxlib.h | 23 | ||||
| -rw-r--r-- | lstrlib.c | 49 |
3 files changed, 93 insertions, 103 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.c,v 1.205 2010/03/22 17:28:31 roberto Exp roberto $ | 2 | ** $Id: lauxlib.c,v 1.206 2010/03/29 17:44:31 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -347,64 +347,40 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, | |||
| 347 | ** ======================================================= | 347 | ** ======================================================= |
| 348 | */ | 348 | */ |
| 349 | 349 | ||
| 350 | 350 | /* | |
| 351 | #define bufflen(B) ((B)->p - (B)->buffer) | 351 | ** check whether buffer is using a userdata on the stack as a temporary |
| 352 | #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) | 352 | ** buffer |
| 353 | 353 | */ | |
| 354 | #define LIMIT (LUA_MINSTACK/2) | 354 | #define buffonstack(B) ((B)->b != (B)->initb) |
| 355 | |||
| 356 | |||
| 357 | static int emptybuffer (luaL_Buffer *B) { | ||
| 358 | size_t l = bufflen(B); | ||
| 359 | if (l == 0) return 0; /* put nothing on stack */ | ||
| 360 | else { | ||
| 361 | lua_pushlstring(B->L, B->buffer, l); | ||
| 362 | B->p = B->buffer; | ||
| 363 | B->lvl++; | ||
| 364 | return 1; | ||
| 365 | } | ||
| 366 | } | ||
| 367 | 355 | ||
| 368 | 356 | ||
| 369 | static void adjuststack (luaL_Buffer *B) { | 357 | /* |
| 370 | if (B->lvl > 1) { | 358 | ** returns a pointer to a free area with at least 'sz' bytes |
| 371 | lua_State *L = B->L; | 359 | */ |
| 372 | int toget = 1; /* number of levels to concat */ | 360 | LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { |
| 373 | size_t toplen = lua_rawlen(L, -1); | 361 | lua_State *L = B->L; |
| 374 | do { | 362 | if (B->size - B->n < sz) { /* not enough space? */ |
| 375 | size_t l = lua_rawlen(L, -(toget+1)); | 363 | char *newbuff; |
| 376 | if (B->lvl - toget + 1 >= LIMIT || toplen > l) { | 364 | size_t newsize = B->size * 2; /* double buffer size */ |
| 377 | toplen += l; | 365 | if (newsize - B->n < sz) /* not bit enough? */ |
| 378 | toget++; | 366 | newsize = B->n + sz; |
| 379 | } | 367 | if (newsize < B->n || newsize - B->n < sz) |
| 380 | else break; | 368 | luaL_error(L, "string too large"); |
| 381 | } while (toget < B->lvl); | 369 | newbuff = (char *)lua_newuserdata(L, newsize); /* create larger buffer */ |
| 382 | lua_concat(L, toget); | 370 | memcpy(newbuff, B->b, B->n); /* move content to new buffer */ |
| 383 | B->lvl = B->lvl - toget + 1; | 371 | if (buffonstack(B)) |
| 372 | lua_remove(L, -2); /* remove old buffer */ | ||
| 373 | B->b = newbuff; | ||
| 374 | B->size = newsize; | ||
| 384 | } | 375 | } |
| 385 | } | 376 | return &B->b[B->n]; |
| 386 | |||
| 387 | |||
| 388 | LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { | ||
| 389 | if (emptybuffer(B)) | ||
| 390 | adjuststack(B); | ||
| 391 | return B->buffer; | ||
| 392 | } | 377 | } |
| 393 | 378 | ||
| 394 | 379 | ||
| 395 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { | 380 | LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { |
| 396 | while (l) { | 381 | char *b = luaL_prepbuffsize(B, l); |
| 397 | size_t space = bufffree(B); | 382 | memcpy(b, s, l); |
| 398 | if (space == 0) { | 383 | luaL_addsize(B, l); |
| 399 | luaL_prepbuffer(B); | ||
| 400 | space = LUAL_BUFFERSIZE; /* bufffree(B) == LUAL_BUFFERSIZE */ | ||
| 401 | } | ||
| 402 | if (space > l) space = l; | ||
| 403 | memcpy(B->p, s, space); | ||
| 404 | B->p += space; | ||
| 405 | s += space; | ||
| 406 | l -= space; | ||
| 407 | } | ||
| 408 | } | 384 | } |
| 409 | 385 | ||
| 410 | 386 | ||
| @@ -414,35 +390,41 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { | |||
| 414 | 390 | ||
| 415 | 391 | ||
| 416 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { | 392 | LUALIB_API void luaL_pushresult (luaL_Buffer *B) { |
| 417 | emptybuffer(B); | 393 | lua_State *L = B->L; |
| 418 | lua_concat(B->L, B->lvl); | 394 | lua_pushlstring(L, B->b, B->n); |
| 419 | B->lvl = 1; | 395 | if (buffonstack(B)) |
| 396 | lua_remove(L, -2); /* remove old buffer */ | ||
| 397 | } | ||
| 398 | |||
| 399 | |||
| 400 | LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { | ||
| 401 | luaL_addsize(B, sz); | ||
| 402 | luaL_pushresult(B); | ||
| 420 | } | 403 | } |
| 421 | 404 | ||
| 422 | 405 | ||
| 423 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { | 406 | LUALIB_API void luaL_addvalue (luaL_Buffer *B) { |
| 424 | lua_State *L = B->L; | 407 | lua_State *L = B->L; |
| 425 | size_t vl; | 408 | size_t l; |
| 426 | const char *s = lua_tolstring(L, -1, &vl); | 409 | const char *s = lua_tolstring(L, -1, &l); |
| 427 | if (vl <= bufffree(B)) { /* fit into buffer? */ | 410 | if (buffonstack(B)) |
| 428 | memcpy(B->p, s, vl); /* put it there */ | 411 | lua_insert(L, -2); /* put value below buffer */ |
| 429 | B->p += vl; | 412 | luaL_addlstring(B, s, l); |
| 430 | lua_pop(L, 1); /* remove from stack */ | 413 | lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ |
| 431 | } | ||
| 432 | else { | ||
| 433 | if (emptybuffer(B)) | ||
| 434 | lua_insert(L, -2); /* put buffer before new value */ | ||
| 435 | B->lvl++; /* add new value into B stack */ | ||
| 436 | adjuststack(B); | ||
| 437 | } | ||
| 438 | } | 414 | } |
| 439 | 415 | ||
| 440 | 416 | ||
| 441 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { | 417 | LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { |
| 442 | luaL_checkstack(L, LIMIT + LUA_MINSTACK, "no space for new buffer"); | ||
| 443 | B->L = L; | 418 | B->L = L; |
| 444 | B->p = B->buffer; | 419 | B->b = B->initb; |
| 445 | B->lvl = 0; | 420 | B->n = 0; |
| 421 | B->size = LUAL_BUFFERSIZE; | ||
| 422 | } | ||
| 423 | |||
| 424 | |||
| 425 | LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { | ||
| 426 | luaL_buffinit(L, B); | ||
| 427 | return luaL_prepbuffsize(B, sz); | ||
| 446 | } | 428 | } |
| 447 | 429 | ||
| 448 | /* }====================================================== */ | 430 | /* }====================================================== */ |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lauxlib.h,v 1.100 2010/01/21 16:49:21 roberto Exp roberto $ | 2 | ** $Id: lauxlib.h,v 1.101 2010/03/17 21:37:37 roberto Exp roberto $ |
| 3 | ** Auxiliary functions for building Lua libraries | 3 | ** Auxiliary functions for building Lua libraries |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -122,28 +122,31 @@ LUALIB_API int (luaL_cpcall) (lua_State *L, lua_CFunction f, int nargs, | |||
| 122 | ** ======================================================= | 122 | ** ======================================================= |
| 123 | */ | 123 | */ |
| 124 | 124 | ||
| 125 | |||
| 126 | |||
| 127 | typedef struct luaL_Buffer { | 125 | typedef struct luaL_Buffer { |
| 128 | char *p; /* current position in buffer */ | 126 | char *b; /* buffer address */ |
| 129 | int lvl; /* number of strings in the stack (level) */ | 127 | size_t size; /* buffer size */ |
| 128 | size_t n; /* number of characters in buffer */ | ||
| 130 | lua_State *L; | 129 | lua_State *L; |
| 131 | char buffer[LUAL_BUFFERSIZE]; | 130 | char initb[LUAL_BUFFERSIZE]; /* initial buffer */ |
| 132 | } luaL_Buffer; | 131 | } luaL_Buffer; |
| 133 | 132 | ||
| 133 | |||
| 134 | #define luaL_addchar(B,c) \ | 134 | #define luaL_addchar(B,c) \ |
| 135 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ | 135 | ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ |
| 136 | (*(B)->p++ = (char)(c))) | 136 | ((B)->b[(B)->n++] = (c))) |
| 137 | 137 | ||
| 138 | #define luaL_addsize(B,n) ((B)->p += (n)) | 138 | #define luaL_addsize(B,s) ((B)->n += (s)) |
| 139 | 139 | ||
| 140 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); | 140 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); |
| 141 | LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); | 141 | LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); |
| 142 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); | 142 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); |
| 143 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); | 143 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); |
| 144 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); | 144 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); |
| 145 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); | 145 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); |
| 146 | LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz); | ||
| 147 | LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); | ||
| 146 | 148 | ||
| 149 | #define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) | ||
| 147 | 150 | ||
| 148 | /* }====================================================== */ | 151 | /* }====================================================== */ |
| 149 | 152 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstrlib.c,v 1.147 2009/12/17 12:50:20 roberto Exp roberto $ | 2 | ** $Id: lstrlib.c,v 1.148 2010/01/04 16:37:19 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 | */ |
| @@ -65,12 +65,13 @@ static int str_sub (lua_State *L) { | |||
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | static int str_reverse (lua_State *L) { | 67 | static int str_reverse (lua_State *L) { |
| 68 | size_t l; | 68 | size_t l, i; |
| 69 | luaL_Buffer b; | 69 | luaL_Buffer b; |
| 70 | const char *s = luaL_checklstring(L, 1, &l); | 70 | const char *s = luaL_checklstring(L, 1, &l); |
| 71 | luaL_buffinit(L, &b); | 71 | char *p = luaL_buffinitsize(L, &b, l); |
| 72 | while (l--) luaL_addchar(&b, s[l]); | 72 | for (i = 0; i < l; i++) |
| 73 | luaL_pushresult(&b); | 73 | p[i] = s[l - i - 1]; |
| 74 | luaL_pushresultsize(&b, l); | ||
| 74 | return 1; | 75 | return 1; |
| 75 | } | 76 | } |
| 76 | 77 | ||
| @@ -80,10 +81,10 @@ static int str_lower (lua_State *L) { | |||
| 80 | size_t i; | 81 | size_t i; |
| 81 | luaL_Buffer b; | 82 | luaL_Buffer b; |
| 82 | const char *s = luaL_checklstring(L, 1, &l); | 83 | const char *s = luaL_checklstring(L, 1, &l); |
| 83 | luaL_buffinit(L, &b); | 84 | char *p = luaL_buffinitsize(L, &b, l); |
| 84 | for (i=0; i<l; i++) | 85 | for (i=0; i<l; i++) |
| 85 | luaL_addchar(&b, tolower(uchar(s[i]))); | 86 | p[i] = tolower(uchar(s[i])); |
| 86 | luaL_pushresult(&b); | 87 | luaL_pushresultsize(&b, l); |
| 87 | return 1; | 88 | return 1; |
| 88 | } | 89 | } |
| 89 | 90 | ||
| @@ -93,10 +94,10 @@ static int str_upper (lua_State *L) { | |||
| 93 | size_t i; | 94 | size_t i; |
| 94 | luaL_Buffer b; | 95 | luaL_Buffer b; |
| 95 | const char *s = luaL_checklstring(L, 1, &l); | 96 | const char *s = luaL_checklstring(L, 1, &l); |
| 96 | luaL_buffinit(L, &b); | 97 | char *p = luaL_buffinitsize(L, &b, l); |
| 97 | for (i=0; i<l; i++) | 98 | for (i=0; i<l; i++) |
| 98 | luaL_addchar(&b, toupper(uchar(s[i]))); | 99 | p[i] = toupper(uchar(s[i])); |
| 99 | luaL_pushresult(&b); | 100 | luaL_pushresultsize(&b, l); |
| 100 | return 1; | 101 | return 1; |
| 101 | } | 102 | } |
| 102 | 103 | ||
| @@ -136,13 +137,13 @@ static int str_char (lua_State *L) { | |||
| 136 | int n = lua_gettop(L); /* number of arguments */ | 137 | int n = lua_gettop(L); /* number of arguments */ |
| 137 | int i; | 138 | int i; |
| 138 | luaL_Buffer b; | 139 | luaL_Buffer b; |
| 139 | luaL_buffinit(L, &b); | 140 | char *p = luaL_buffinitsize(L, &b, n); |
| 140 | for (i=1; i<=n; i++) { | 141 | for (i=1; i<=n; i++) { |
| 141 | int c = luaL_checkint(L, i); | 142 | int c = luaL_checkint(L, i); |
| 142 | luaL_argcheck(L, uchar(c) == c, i, "invalid value"); | 143 | luaL_argcheck(L, uchar(c) == c, i, "invalid value"); |
| 143 | luaL_addchar(&b, uchar(c)); | 144 | p[i - 1] = uchar(c); |
| 144 | } | 145 | } |
| 145 | luaL_pushresult(&b); | 146 | luaL_pushresultsize(&b, n); |
| 146 | return 1; | 147 | return 1; |
| 147 | } | 148 | } |
| 148 | 149 | ||
| @@ -773,6 +774,9 @@ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { | |||
| 773 | } | 774 | } |
| 774 | 775 | ||
| 775 | 776 | ||
| 777 | /* | ||
| 778 | ** add length modifier into integer formats | ||
| 779 | */ | ||
| 776 | static void addintlen (char *form) { | 780 | static void addintlen (char *form) { |
| 777 | size_t l = strlen(form); | 781 | size_t l = strlen(form); |
| 778 | char spec = form[l - 1]; | 782 | char spec = form[l - 1]; |
| @@ -796,12 +800,13 @@ static int str_format (lua_State *L) { | |||
| 796 | luaL_addchar(&b, *strfrmt++); /* %% */ | 800 | luaL_addchar(&b, *strfrmt++); /* %% */ |
| 797 | else { /* format item */ | 801 | else { /* format item */ |
| 798 | char form[MAX_FORMAT]; /* to store the format (`%...') */ | 802 | char form[MAX_FORMAT]; /* to store the format (`%...') */ |
| 799 | char buff[MAX_ITEM]; /* to store the formatted item */ | 803 | char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ |
| 804 | int nb = 0; /* number of bytes in added item */ | ||
| 800 | arg++; | 805 | arg++; |
| 801 | strfrmt = scanformat(L, strfrmt, form); | 806 | strfrmt = scanformat(L, strfrmt, form); |
| 802 | switch (*strfrmt++) { | 807 | switch (*strfrmt++) { |
| 803 | case 'c': { | 808 | case 'c': { |
| 804 | sprintf(buff, form, luaL_checkint(L, arg)); | 809 | nb = sprintf(buff, form, luaL_checkint(L, arg)); |
| 805 | break; | 810 | break; |
| 806 | } | 811 | } |
| 807 | case 'd': case 'i': | 812 | case 'd': case 'i': |
| @@ -810,17 +815,17 @@ static int str_format (lua_State *L) { | |||
| 810 | LUA_INTFRM_T r = (n < 0) ? (LUA_INTFRM_T)n : | 815 | LUA_INTFRM_T r = (n < 0) ? (LUA_INTFRM_T)n : |
| 811 | (LUA_INTFRM_T)(unsigned LUA_INTFRM_T)n; | 816 | (LUA_INTFRM_T)(unsigned LUA_INTFRM_T)n; |
| 812 | addintlen(form); | 817 | addintlen(form); |
| 813 | sprintf(buff, form, r); | 818 | nb = sprintf(buff, form, r); |
| 814 | break; | 819 | break; |
| 815 | } | 820 | } |
| 816 | case 'e': case 'E': case 'f': | 821 | case 'e': case 'E': case 'f': |
| 817 | case 'g': case 'G': { | 822 | case 'g': case 'G': { |
| 818 | sprintf(buff, form, (double)luaL_checknumber(L, arg)); | 823 | nb = sprintf(buff, form, (double)luaL_checknumber(L, arg)); |
| 819 | break; | 824 | break; |
| 820 | } | 825 | } |
| 821 | case 'q': { | 826 | case 'q': { |
| 822 | addquoted(L, &b, arg); | 827 | addquoted(L, &b, arg); |
| 823 | continue; /* skip the 'addsize' at the end */ | 828 | break; |
| 824 | } | 829 | } |
| 825 | case 's': { | 830 | case 's': { |
| 826 | size_t l; | 831 | size_t l; |
| @@ -830,10 +835,10 @@ static int str_format (lua_State *L) { | |||
| 830 | keep original string */ | 835 | keep original string */ |
| 831 | lua_pushvalue(L, arg); | 836 | lua_pushvalue(L, arg); |
| 832 | luaL_addvalue(&b); | 837 | luaL_addvalue(&b); |
| 833 | continue; /* skip the `addsize' at the end */ | 838 | break; |
| 834 | } | 839 | } |
| 835 | else { | 840 | else { |
| 836 | sprintf(buff, form, s); | 841 | nb = sprintf(buff, form, s); |
| 837 | break; | 842 | break; |
| 838 | } | 843 | } |
| 839 | } | 844 | } |
| @@ -842,7 +847,7 @@ static int str_format (lua_State *L) { | |||
| 842 | LUA_QL("format"), *(strfrmt - 1)); | 847 | LUA_QL("format"), *(strfrmt - 1)); |
| 843 | } | 848 | } |
| 844 | } | 849 | } |
| 845 | luaL_addlstring(&b, buff, strlen(buff)); | 850 | luaL_addsize(&b, nb); |
| 846 | } | 851 | } |
| 847 | } | 852 | } |
| 848 | luaL_pushresult(&b); | 853 | luaL_pushresult(&b); |
