diff --git a/lualib-src/lua-bson.c b/lualib-src/lua-bson.c index 725de81b..76daef40 100644 --- a/lualib-src/lua-bson.c +++ b/lualib-src/lua-bson.c @@ -551,15 +551,17 @@ static void pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) { int length = reserve_length(b); int i; + size_t sz; + // the first key is at index n + const char * key = lua_tolstring(L, n, &sz); for (i=0;isize - length, length); @@ -938,36 +940,66 @@ bson_meta(lua_State *L) { lua_setmetatable(L, -2); } +static int +encode_bson(lua_State *L) { + struct bson *b = lua_touserdata(L, 2); + lua_settop(L, 1); + if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) { + pack_meta_dict(L, b, 0); + } else { + pack_simple_dict(L, b, 0); + } + void * ud = lua_newuserdata(L, b->size); + memcpy(ud, b->ptr, b->size); + return 1; +} + static int lencode(lua_State *L) { struct bson b; - bson_create(&b); lua_settop(L,1); luaL_checktype(L, 1, LUA_TTABLE); - if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) { - pack_meta_dict(L, &b, 0); - } else { - pack_simple_dict(L, &b, 0); + bson_create(&b); + lua_pushcfunction(L, encode_bson); + lua_pushvalue(L, 1); + lua_pushlightuserdata(L, &b); + if (lua_pcall(L, 2, 1, 0) != LUA_OK) { + bson_destroy(&b); + return lua_error(L); } - void * ud = lua_newuserdata(L, b.size); - memcpy(ud, b.ptr, b.size); bson_destroy(&b); bson_meta(L); return 1; } +static int +encode_bson_byorder(lua_State *L) { + int n = lua_gettop(L); + struct bson *b = lua_touserdata(L, n); + lua_settop(L, --n); + pack_ordered_dict(L, b, n, 0); + lua_settop(L,0); + void * ud = lua_newuserdata(L, b->size); + memcpy(ud, b->ptr, b->size); + return 1; +} + static int lencode_order(lua_State *L) { struct bson b; - bson_create(&b); int n = lua_gettop(L); if (n%2 != 0) { return luaL_error(L, "Invalid ordered dict"); } - pack_ordered_dict(L, &b, n, 0); - lua_settop(L,1); - void * ud = lua_newuserdata(L, b.size); - memcpy(ud, b.ptr, b.size); + bson_create(&b); + lua_pushvalue(L, 1); // copy the first arg to n + lua_pushcfunction(L, encode_bson_byorder); + lua_replace(L, 1); + lua_pushlightuserdata(L, &b); + if (lua_pcall(L, n+1, 1, 0) != LUA_OK) { + bson_destroy(&b); + return lua_error(L); + } bson_destroy(&b); bson_meta(L); return 1;