static void pack_one(lua_State *L, struct write_block *b, int index, int depth) { if (depth > MAX_DEPTH) { wb_free(b); luaL_error(L, "serialize can't pack too depth table"); } int type = lua_type(L,index); switch(type) { case LUA_TNIL: wb_nil(b); break; case LUA_TNUMBER: { if (lua_isinteger(L, index)) { lua_Integer x = lua_tointeger(L,index); wb_integer(b, x); } else { lua_Number n = lua_tonumber(L,index); wb_real(b,n); } break; } case LUA_TBOOLEAN: wb_boolean(b, lua_toboolean(L,index)); break; case LUA_TSTRING: { size_t sz = 0; const char *str = lua_tolstring(L,index,&sz); wb_string(b, str, (int)sz); break; } case LUA_TLIGHTUSERDATA: wb_pointer(b, lua_touserdata(L,index)); break; case LUA_TTABLE: { if (index < 0) { index = lua_gettop(L) + index + 1; } wb_table(L, b, index, depth+1); break; } default: wb_free(b); luaL_error(L, "Unsupport type %s to serialize", lua_typename(L, type)); } }
static void wb_table_hash(lua_State *L, struct write_block * wb, int index, int depth, int array_size) { lua_pushnil(L); while (lua_next(L, index) != 0) { if (lua_type(L, -2) == LUA_TNUMBER) { lua_Number k = lua_tonumber(L, -2); int32_t x = (int32_t)lua_tointeger(L, -2); if (k == (lua_Number)x && x > 0 && x <= array_size) { lua_pop(L, 1); continue; } } _pack_one(L, wb, -2, depth); _pack_one(L, wb, -1, depth); lua_pop(L, 1); } wb_nil(wb); }
static void wb_table_hash(lua_State *L, struct write_block * wb, int index, int depth, int array_size) { lua_pushnil(L); while (lua_next(L, index) != 0) { if (lua_type(L,-2) == LUA_TNUMBER) { if (lua_isinteger(L, -2)) { lua_Integer x = lua_tointeger(L,-2); if (x>0 && x<=array_size) { lua_pop(L,1); continue; } } } pack_one(L,wb,-2,depth); pack_one(L,wb,-1,depth); lua_pop(L, 1); } wb_nil(wb); }
static void wb_table_metapairs(lua_State *L, struct write_block *wb, int index, int depth) { uint8_t n = COMBINE_TYPE(TYPE_TABLE, 0); wb_push(wb, &n, 1); lua_pushvalue(L, index); lua_call(L, 1, 3); for(;;) { lua_pushvalue(L, -2); lua_pushvalue(L, -2); lua_copy(L, -5, -3); lua_call(L, 2, 2); int type = lua_type(L, -2); if (type == LUA_TNIL) { lua_pop(L, 4); break; } pack_one(L, wb, -2, depth); pack_one(L, wb, -1, depth); lua_pop(L, 1); } wb_nil(wb); }