diff options
-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); |