aboutsummaryrefslogtreecommitdiff
path: root/lauxlib.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-06-18 11:23:14 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2015-06-18 11:23:14 -0300
commite7f34ad395284b4ad2b53b092aa4576616ede7c5 (patch)
tree2f69a023d9047354c115385ca35de0ed17965b85 /lauxlib.c
parenta5cbb7c3a7b26d962fd85ff50dc7e0cea84d93af (diff)
downloadlua-e7f34ad395284b4ad2b53b092aa4576616ede7c5.tar.gz
lua-e7f34ad395284b4ad2b53b092aa4576616ede7c5.tar.bz2
lua-e7f34ad395284b4ad2b53b092aa4576616ede7c5.zip
better implementation for buffers (reallocated memory directly
with allocation function; generates much less garbage)
Diffstat (limited to 'lauxlib.c')
-rw-r--r--lauxlib.c60
1 files changed, 52 insertions, 8 deletions
diff --git a/lauxlib.c b/lauxlib.c
index cd32f555..04cb373b 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp roberto $ 2** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 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*/
@@ -289,7 +289,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
289 if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ 289 if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
290 return 0; /* leave previous value on top, but return 0 */ 290 return 0; /* leave previous value on top, but return 0 */
291 lua_pop(L, 1); 291 lua_pop(L, 1);
292 lua_newtable(L); /* create metatable */ 292 lua_createtable(L, 0, 2); /* create metatable */
293 lua_pushstring(L, tname); 293 lua_pushstring(L, tname);
294 lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ 294 lua_setfield(L, -2, "__name"); /* metatable.__name = tname */
295 lua_pushvalue(L, -1); 295 lua_pushvalue(L, -1);
@@ -435,6 +435,47 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
435** ======================================================= 435** =======================================================
436*/ 436*/
437 437
438/* userdata to box arbitrary data */
439typedef struct UBox {
440 void *box;
441 size_t bsize;
442} UBox;
443
444
445static void *resizebox (lua_State *L, int idx, size_t newsize) {
446 void *ud;
447 lua_Alloc allocf = lua_getallocf(L, &ud);
448 UBox *box = (UBox *)lua_touserdata(L, idx);
449 void *temp = allocf(ud, box->box, box->bsize, newsize);
450 if (temp == NULL && newsize > 0) { /* allocation error? */
451 resizebox(L, idx, 0); /* free buffer */
452 luaL_error(L, "not enough memory for buffer allocation");
453 }
454 box->box = temp;
455 box->bsize = newsize;
456 return temp;
457}
458
459
460static int boxgc (lua_State *L) {
461 resizebox(L, 1, 0);
462 return 0;
463}
464
465
466static void *newbox (lua_State *L, size_t newsize) {
467 UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
468 box->box = NULL;
469 box->bsize = 0;
470 if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */
471 lua_pushcfunction(L, boxgc);
472 lua_setfield(L, -2, "__gc"); /* metatalbe.__gc = boxgc */
473 }
474 lua_setmetatable(L, -2);
475 return resizebox(L, -1, newsize);
476}
477
478
438/* 479/*
439** check whether buffer is using a userdata on the stack as a temporary 480** check whether buffer is using a userdata on the stack as a temporary
440** buffer 481** buffer
@@ -455,11 +496,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
455 if (newsize < B->n || newsize - B->n < sz) 496 if (newsize < B->n || newsize - B->n < sz)
456 luaL_error(L, "buffer too large"); 497 luaL_error(L, "buffer too large");
457 /* create larger buffer */ 498 /* create larger buffer */
458 newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
459 /* move content to new buffer */
460 memcpy(newbuff, B->b, B->n * sizeof(char));
461 if (buffonstack(B)) 499 if (buffonstack(B))
462 lua_remove(L, -2); /* remove old buffer */ 500 newbuff = (char *)resizebox(L, -1, newsize);
501 else { /* no buffer yet */
502 newbuff = (char *)newbox(L, newsize);
503 memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
504 }
463 B->b = newbuff; 505 B->b = newbuff;
464 B->size = newsize; 506 B->size = newsize;
465 } 507 }
@@ -482,8 +524,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
482LUALIB_API void luaL_pushresult (luaL_Buffer *B) { 524LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
483 lua_State *L = B->L; 525 lua_State *L = B->L;
484 lua_pushlstring(L, B->b, B->n); 526 lua_pushlstring(L, B->b, B->n);
485 if (buffonstack(B)) 527 if (buffonstack(B)) {
486 lua_remove(L, -2); /* remove old buffer */ 528 resizebox(L, -2, 0); /* delete old buffer */
529 lua_remove(L, -2); /* remove its header from the stack */
530 }
487} 531}
488 532
489 533