|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
-** $Id: lauxlib.c,v 1.279 2014/12/14 18:32:26 roberto Exp roberto $
|
|
|
+** $Id: lauxlib.c,v 1.280 2015/02/03 17:38:24 roberto Exp roberto $
|
|
|
** Auxiliary functions for building Lua libraries
|
|
|
** See Copyright Notice in lua.h
|
|
|
*/
|
|
@@ -289,7 +289,7 @@ LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
|
|
|
if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */
|
|
|
return 0; /* leave previous value on top, but return 0 */
|
|
|
lua_pop(L, 1);
|
|
|
- lua_newtable(L); /* create metatable */
|
|
|
+ lua_createtable(L, 0, 2); /* create metatable */
|
|
|
lua_pushstring(L, tname);
|
|
|
lua_setfield(L, -2, "__name"); /* metatable.__name = tname */
|
|
|
lua_pushvalue(L, -1);
|
|
@@ -435,6 +435,47 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg,
|
|
|
** =======================================================
|
|
|
*/
|
|
|
|
|
|
+/* userdata to box arbitrary data */
|
|
|
+typedef struct UBox {
|
|
|
+ void *box;
|
|
|
+ size_t bsize;
|
|
|
+} UBox;
|
|
|
+
|
|
|
+
|
|
|
+static void *resizebox (lua_State *L, int idx, size_t newsize) {
|
|
|
+ void *ud;
|
|
|
+ lua_Alloc allocf = lua_getallocf(L, &ud);
|
|
|
+ UBox *box = (UBox *)lua_touserdata(L, idx);
|
|
|
+ void *temp = allocf(ud, box->box, box->bsize, newsize);
|
|
|
+ if (temp == NULL && newsize > 0) { /* allocation error? */
|
|
|
+ resizebox(L, idx, 0); /* free buffer */
|
|
|
+ luaL_error(L, "not enough memory for buffer allocation");
|
|
|
+ }
|
|
|
+ box->box = temp;
|
|
|
+ box->bsize = newsize;
|
|
|
+ return temp;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static int boxgc (lua_State *L) {
|
|
|
+ resizebox(L, 1, 0);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void *newbox (lua_State *L, size_t newsize) {
|
|
|
+ UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox));
|
|
|
+ box->box = NULL;
|
|
|
+ box->bsize = 0;
|
|
|
+ if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */
|
|
|
+ lua_pushcfunction(L, boxgc);
|
|
|
+ lua_setfield(L, -2, "__gc"); /* metatalbe.__gc = boxgc */
|
|
|
+ }
|
|
|
+ lua_setmetatable(L, -2);
|
|
|
+ return resizebox(L, -1, newsize);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
** check whether buffer is using a userdata on the stack as a temporary
|
|
|
** buffer
|
|
@@ -455,11 +496,12 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
|
|
|
if (newsize < B->n || newsize - B->n < sz)
|
|
|
luaL_error(L, "buffer too large");
|
|
|
/* create larger buffer */
|
|
|
- newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char));
|
|
|
- /* move content to new buffer */
|
|
|
- memcpy(newbuff, B->b, B->n * sizeof(char));
|
|
|
if (buffonstack(B))
|
|
|
- lua_remove(L, -2); /* remove old buffer */
|
|
|
+ newbuff = (char *)resizebox(L, -1, newsize);
|
|
|
+ else { /* no buffer yet */
|
|
|
+ newbuff = (char *)newbox(L, newsize);
|
|
|
+ memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */
|
|
|
+ }
|
|
|
B->b = newbuff;
|
|
|
B->size = newsize;
|
|
|
}
|
|
@@ -482,8 +524,10 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
|
|
|
LUALIB_API void luaL_pushresult (luaL_Buffer *B) {
|
|
|
lua_State *L = B->L;
|
|
|
lua_pushlstring(L, B->b, B->n);
|
|
|
- if (buffonstack(B))
|
|
|
- lua_remove(L, -2); /* remove old buffer */
|
|
|
+ if (buffonstack(B)) {
|
|
|
+ resizebox(L, -2, 0); /* delete old buffer */
|
|
|
+ lua_remove(L, -2); /* remove its header from the stack */
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|