From fb315d06aebd21d20511a84088e96b615336e533 Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Fri, 2 Nov 2012 10:12:15 +0100 Subject: [PATCH 1/3] mp_cur doesn't need dynamic allocation the C stack is good enough --- lua_cmsgpack.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index 9061213..c742ef6 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -111,17 +111,10 @@ typedef struct mp_cur { int err; } mp_cur; -static mp_cur *mp_cur_new(const unsigned char *s, size_t len) { - mp_cur *cursor = malloc(sizeof(*cursor)); - +static void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) { cursor->p = s; cursor->left = len; cursor->err = MP_CUR_ERROR_NONE; - return cursor; -} - -static void mp_cur_free(mp_cur *cursor) { - free(cursor); } #define mp_cur_consume(_c,_len) do { _c->p += _len; _c->left -= _len; } while(0) @@ -657,7 +650,7 @@ void mp_decode_to_lua_type(lua_State *L, mp_cur *c) { static int mp_unpack(lua_State *L) { size_t len; const unsigned char *s; - mp_cur *c; + mp_cur c; if (!lua_isstring(L,-1)) { lua_pushstring(L,"MessagePack decoding needs a string as input."); @@ -665,23 +658,19 @@ static int mp_unpack(lua_State *L) { } s = (const unsigned char*) lua_tolstring(L,-1,&len); - c = mp_cur_new(s,len); - mp_decode_to_lua_type(L,c); - - if (c->err == MP_CUR_ERROR_EOF) { - mp_cur_free(c); + mp_cur_init(&c, s,len); + mp_decode_to_lua_type(L,&c); + + if (c.err == MP_CUR_ERROR_EOF) { lua_pushstring(L,"Missing bytes in input."); lua_error(L); - } else if (c->err == MP_CUR_ERROR_BADFMT) { - mp_cur_free(c); + } else if (c.err == MP_CUR_ERROR_BADFMT) { lua_pushstring(L,"Bad data format in input."); lua_error(L); - } else if (c->left != 0) { - mp_cur_free(c); + } else if (c.left != 0) { lua_pushstring(L,"Extra bytes in input."); lua_error(L); } - mp_cur_free(c); return 1; } From d0fd5fee157d2e576e83d15eaffb10f59670ed6a Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Fri, 2 Nov 2012 10:23:05 +0100 Subject: [PATCH 2/3] refactor with luaL_buffer (which is the string buffer included in Lua) --- lua_cmsgpack.c | 103 ++++++++++++++++--------------------------------- 1 file changed, 34 insertions(+), 69 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index c742ef6..8a9f975 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -56,42 +55,6 @@ static void memrevifle(void *ptr, size_t len) { } } -/* ----------------------------- String buffer ---------------------------------- - * This is a simple implementation of string buffers. The only opereation - * supported is creating empty buffers and appending bytes to it. - * The string buffer uses 2x preallocation on every realloc for O(N) append - * behavior. */ - -typedef struct mp_buf { - unsigned char *b; - size_t len, free; -} mp_buf; - -static mp_buf *mp_buf_new(void) { - mp_buf *buf = malloc(sizeof(*buf)); - - buf->b = NULL; - buf->len = buf->free = 0; - return buf; -} - -void mp_buf_append(mp_buf *buf, const unsigned char *s, size_t len) { - if (buf->free < len) { - size_t newlen = buf->len+len; - - buf->b = realloc(buf->b,newlen*2); - buf->free = newlen; - } - memcpy(buf->b+buf->len,s,len); - buf->len += len; - buf->free -= len; -} - -void mp_buf_free(mp_buf *buf) { - free(buf->b); - free(buf); -} - /* ------------------------------ String cursor ---------------------------------- * This simple data structure is used for parsing. Basically you create a cursor * using a string pointer and a length, then it is possible to access the @@ -131,7 +94,7 @@ static void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) { /* --------------------------- Low level MP encoding -------------------------- */ -static void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { +static void mp_encode_string(luaL_Buffer *buf, size_t len) { unsigned char hdr[5]; int hdrlen; @@ -151,12 +114,11 @@ static void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { hdr[4] = len&0xff; hdrlen = 5; } - mp_buf_append(buf,hdr,hdrlen); - mp_buf_append(buf,s,len); + luaL_addlstring(buf,(const char*)hdr,hdrlen); } /* we assume IEEE 754 internal format for single and double precision floats. */ -static void mp_encode_double(mp_buf *buf, double d) { +static void mp_encode_double(luaL_Buffer *buf, double d) { unsigned char b[9]; float f = d; @@ -165,16 +127,16 @@ static void mp_encode_double(mp_buf *buf, double d) { b[0] = 0xca; /* float IEEE 754 */ memcpy(b+1,&f,4); memrevifle(b+1,4); - mp_buf_append(buf,b,5); + luaL_addlstring(buf,(const char*)b,5); } else if (sizeof(d) == 8) { b[0] = 0xcb; /* double IEEE 754 */ memcpy(b+1,&d,8); memrevifle(b+1,8); - mp_buf_append(buf,b,9); + luaL_addlstring(buf,(const char*)b,9); } } -static void mp_encode_int(mp_buf *buf, int64_t n) { +static void mp_encode_int(luaL_Buffer *buf, int64_t n) { unsigned char b[9]; int enclen; @@ -243,10 +205,10 @@ static void mp_encode_int(mp_buf *buf, int64_t n) { enclen = 9; } } - mp_buf_append(buf,b,enclen); + luaL_addlstring(buf,(const char*)b,enclen); } -static void mp_encode_array(mp_buf *buf, int64_t n) { +static void mp_encode_array(luaL_Buffer *buf, int64_t n) { unsigned char b[5]; int enclen; @@ -266,10 +228,10 @@ static void mp_encode_array(mp_buf *buf, int64_t n) { b[4] = n & 0xff; enclen = 5; } - mp_buf_append(buf,b,enclen); + luaL_addlstring(buf,(const char*)b,enclen); } -static void mp_encode_map(mp_buf *buf, int64_t n) { +static void mp_encode_map(luaL_Buffer *buf, int64_t n) { unsigned char b[5]; int enclen; @@ -289,25 +251,27 @@ static void mp_encode_map(mp_buf *buf, int64_t n) { b[4] = n & 0xff; enclen = 5; } - mp_buf_append(buf,b,enclen); + luaL_addlstring(buf,(const char*)b,enclen); } /* ----------------------------- Lua types encoding --------------------------- */ -static void mp_encode_lua_string(lua_State *L, mp_buf *buf) { +static void mp_encode_lua_string(lua_State *L, luaL_Buffer *buf) { size_t len; const char *s; s = lua_tolstring(L,-1,&len); - mp_encode_bytes(buf,(const unsigned char*)s,len); + mp_encode_string(buf,len); + lua_pushlstring(buf->L,s,len); + luaL_addvalue(buf); } -static void mp_encode_lua_bool(lua_State *L, mp_buf *buf) { +static void mp_encode_lua_bool(lua_State *L, luaL_Buffer *buf) { unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2; - mp_buf_append(buf,&b,1); + luaL_addchar(buf, b); } -static void mp_encode_lua_number(lua_State *L, mp_buf *buf) { +static void mp_encode_lua_number(lua_State *L, luaL_Buffer *buf) { lua_Number n = lua_tonumber(L,-1); if (floor(n) != n) { @@ -317,10 +281,10 @@ static void mp_encode_lua_number(lua_State *L, mp_buf *buf) { } } -static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level); +static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level); /* Convert a lua table into a message pack list. */ -static void mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) { +static void mp_encode_lua_table_as_array(lua_State *L, luaL_Buffer *buf, int level) { size_t len = lua_objlen(L,-1), j; mp_encode_array(buf,len); @@ -332,7 +296,7 @@ static void mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) { } /* Convert a lua table into a message pack key-value map. */ -static void mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) { +static void mp_encode_lua_table_as_map(lua_State *L, luaL_Buffer *buf, int level) { size_t len = 0; /* First step: count keys into table. No other way to do it with the @@ -389,21 +353,18 @@ static int table_is_an_array(lua_State *L) { /* If the length operator returns non-zero, that is, there is at least * an object at key '1', we serialize to message pack list. Otherwise * we use a map. */ -static void mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) { +static void mp_encode_lua_table(lua_State *L, luaL_Buffer *buf, int level) { if (table_is_an_array(L)) mp_encode_lua_table_as_array(L,buf,level); else mp_encode_lua_table_as_map(L,buf,level); } -static void mp_encode_lua_null(lua_State *L, mp_buf *buf) { - unsigned char b[1]; - - b[0] = 0xc0; - mp_buf_append(buf,b,1); +static void mp_encode_lua_null(luaL_Buffer *buf) { + luaL_addchar(buf, 0xC0); } -static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) { +static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level) { int t = lua_type(L,-1); /* Limit the encoding of nested tables to a specfiied maximum depth, so that @@ -414,17 +375,20 @@ static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) { case LUA_TBOOLEAN: mp_encode_lua_bool(L,buf); break; case LUA_TNUMBER: mp_encode_lua_number(L,buf); break; case LUA_TTABLE: mp_encode_lua_table(L,buf,level); break; - default: mp_encode_lua_null(L,buf); break; + default: mp_encode_lua_null(buf); break; } lua_pop(L,1); } +static lua_State *L2; + static int mp_pack(lua_State *L) { - mp_buf *buf = mp_buf_new(); + luaL_Buffer buf; + luaL_buffinit(L2, &buf); - mp_encode_lua_type(L,buf,0); - lua_pushlstring(L,(char*)buf->b,buf->len); - mp_buf_free(buf); + mp_encode_lua_type(L,&buf,0); + luaL_pushresult(&buf); /* close buffer */ + lua_xmove(L2,L,1); return 1; } @@ -684,6 +648,7 @@ static const struct luaL_reg thislib[] = { LUALIB_API int luaopen_cmsgpack (lua_State *L) { luaL_register(L, "cmsgpack", thislib); + L2 = luaL_newstate(); lua_pushliteral(L, LUACMSGPACK_VERSION); lua_setfield(L, -2, "_VERSION"); From d6f4eac73e0b49560405cb1aa7075b79789e1cfa Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Sun, 11 Nov 2012 18:48:25 +0100 Subject: [PATCH 3/3] refactor without L2 --- lua_cmsgpack.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index 8a9f975..df18a89 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -258,21 +258,24 @@ static void mp_encode_map(luaL_Buffer *buf, int64_t n) { static void mp_encode_lua_string(lua_State *L, luaL_Buffer *buf) { size_t len; - const char *s; - s = lua_tolstring(L,-1,&len); + (void)lua_tolstring(L,-1,&len); + lua_insert(L, -buf->lvl - 1); mp_encode_string(buf,len); - lua_pushlstring(buf->L,s,len); + lua_pushvalue(L, -buf->lvl - 1); + lua_remove(L, -buf->lvl); luaL_addvalue(buf); } static void mp_encode_lua_bool(lua_State *L, luaL_Buffer *buf) { unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2; + lua_pop(L,1); luaL_addchar(buf, b); } static void mp_encode_lua_number(lua_State *L, luaL_Buffer *buf) { lua_Number n = lua_tonumber(L,-1); + lua_pop(L,1); if (floor(n) != n) { mp_encode_double(buf,(double)n); @@ -287,12 +290,14 @@ static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level); static void mp_encode_lua_table_as_array(lua_State *L, luaL_Buffer *buf, int level) { size_t len = lua_objlen(L,-1), j; + lua_insert(L, -buf->lvl - 1); mp_encode_array(buf,len); for (j = 1; j <= len; j++) { lua_pushnumber(L,j); - lua_gettable(L,-2); + lua_gettable(L,-buf->lvl - 2); mp_encode_lua_type(L,buf,level+1); } + lua_remove(L, -buf->lvl - 1); } /* Convert a lua table into a message pack key-value map. */ @@ -310,14 +315,16 @@ static void mp_encode_lua_table_as_map(lua_State *L, luaL_Buffer *buf, int level } /* Step two: actually encoding of the map. */ + lua_insert(L, -buf->lvl - 1); mp_encode_map(buf,len); lua_pushnil(L); - while(lua_next(L,-2)) { + while(lua_next(L,-buf->lvl - 2)) { /* Stack: ... key value */ lua_pushvalue(L,-2); /* Stack: ... key value key */ mp_encode_lua_type(L,buf,level+1); /* encode key */ mp_encode_lua_type(L,buf,level+1); /* encode val */ } + lua_remove(L, -buf->lvl - 1); } /* Returns true if the Lua table on top of the stack is exclusively composed @@ -360,8 +367,9 @@ static void mp_encode_lua_table(lua_State *L, luaL_Buffer *buf, int level) { mp_encode_lua_table_as_map(L,buf,level); } -static void mp_encode_lua_null(luaL_Buffer *buf) { +static void mp_encode_lua_null(lua_State *L, luaL_Buffer *buf) { luaL_addchar(buf, 0xC0); + lua_pop(L,1); } static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level) { @@ -375,20 +383,16 @@ static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level) { case LUA_TBOOLEAN: mp_encode_lua_bool(L,buf); break; case LUA_TNUMBER: mp_encode_lua_number(L,buf); break; case LUA_TTABLE: mp_encode_lua_table(L,buf,level); break; - default: mp_encode_lua_null(buf); break; + default: mp_encode_lua_null(L,buf); break; } - lua_pop(L,1); } -static lua_State *L2; - static int mp_pack(lua_State *L) { luaL_Buffer buf; - luaL_buffinit(L2, &buf); + luaL_buffinit(L, &buf); mp_encode_lua_type(L,&buf,0); luaL_pushresult(&buf); /* close buffer */ - lua_xmove(L2,L,1); return 1; } @@ -648,7 +652,6 @@ static const struct luaL_reg thislib[] = { LUALIB_API int luaopen_cmsgpack (lua_State *L) { luaL_register(L, "cmsgpack", thislib); - L2 = luaL_newstate(); lua_pushliteral(L, LUACMSGPACK_VERSION); lua_setfield(L, -2, "_VERSION");