From 11c7b8f264a30cb874b74adba168b190a6a7d102 Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Wed, 31 Oct 2012 16:28:23 +0100 Subject: [PATCH 1/3] refactor with luaL_buffer (which is the string buffer included in Lua) --- lua_cmsgpack.c | 95 +++++++++++++++----------------------------------- 1 file changed, 28 insertions(+), 67 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index 9061213..9d10b47 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -56,42 +56,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 @@ -138,7 +102,7 @@ static void mp_cur_free(mp_cur *cursor) { /* --------------------------- Low level MP encoding -------------------------- */ -static void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { +static void mp_encode_bytes(luaL_Buffer *buf, const unsigned char *s, size_t len) { unsigned char hdr[5]; int hdrlen; @@ -158,12 +122,12 @@ 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); + luaL_addlstring(buf,(const char*)s,len); } /* 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; @@ -172,16 +136,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; @@ -250,10 +214,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; @@ -273,10 +237,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; @@ -296,12 +260,12 @@ 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; @@ -309,12 +273,12 @@ static void mp_encode_lua_string(lua_State *L, mp_buf *buf) { mp_encode_bytes(buf,(const unsigned char*)s,len); } -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) { @@ -324,10 +288,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); @@ -339,7 +303,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 @@ -396,21 +360,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 @@ -421,17 +382,17 @@ 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 int mp_pack(lua_State *L) { - mp_buf *buf = mp_buf_new(); + luaL_Buffer buf; + luaL_buffinit(L, &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 */ return 1; } From 387ef72ba20d8b1c7fff08941bc87724491d3d25 Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Wed, 31 Oct 2012 18:05:15 +0100 Subject: [PATCH 2/3] refactor without malloc --- lua_cmsgpack.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index 9d10b47..8094074 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -75,17 +74,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) @@ -618,7 +610,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."); @@ -626,23 +618,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 7d025aa7209ff36fc868add9486768e6e3bf8b80 Mon Sep 17 00:00:00 2001 From: Francois Perrad Date: Thu, 1 Nov 2012 23:24:02 +0100 Subject: [PATCH 3/3] fix luaL_buffer --- lua_cmsgpack.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lua_cmsgpack.c b/lua_cmsgpack.c index 8094074..8a9f975 100644 --- a/lua_cmsgpack.c +++ b/lua_cmsgpack.c @@ -94,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(luaL_Buffer *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; @@ -115,7 +115,6 @@ static void mp_encode_bytes(luaL_Buffer *buf, const unsigned char *s, size_t len hdrlen = 5; } luaL_addlstring(buf,(const char*)hdr,hdrlen); - luaL_addlstring(buf,(const char*)s,len); } /* we assume IEEE 754 internal format for single and double precision floats. */ @@ -262,7 +261,9 @@ static void mp_encode_lua_string(lua_State *L, luaL_Buffer *buf) { 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, luaL_Buffer *buf) { @@ -379,12 +380,15 @@ static void mp_encode_lua_type(lua_State *L, luaL_Buffer *buf, int level) { lua_pop(L,1); } +static lua_State *L2; + static int mp_pack(lua_State *L) { luaL_Buffer buf; - luaL_buffinit(L, &buf); + luaL_buffinit(L2, &buf); mp_encode_lua_type(L,&buf,0); luaL_pushresult(&buf); /* close buffer */ + lua_xmove(L2,L,1); return 1; } @@ -644,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");