mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 12:43:09 +00:00
bson support meta array
This commit is contained in:
@@ -238,8 +238,6 @@ write_double(struct bson *b, lua_Number d) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pack_dict(lua_State *L, struct bson *b, bool array, int depth);
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
append_key(struct bson *bs, int type, const char *key, size_t sz) {
|
||||||
write_byte(bs, type);
|
write_byte(bs, type);
|
||||||
@@ -269,25 +267,7 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth);
|
||||||
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
|
||||||
size_t len = lua_rawlen(L, -1);
|
|
||||||
bool isarray = false;
|
|
||||||
if (len > 0) {
|
|
||||||
lua_pushinteger(L, len);
|
|
||||||
if (lua_next(L,-2) == 0) {
|
|
||||||
isarray = true;
|
|
||||||
} else {
|
|
||||||
lua_pop(L,2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isarray) {
|
|
||||||
append_key(bs, BSON_ARRAY, key, sz);
|
|
||||||
} else {
|
|
||||||
append_key(bs, BSON_DOCUMENT, key, sz);
|
|
||||||
}
|
|
||||||
pack_dict(L, bs, isarray, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_binary(struct bson *b, const void * buffer, size_t sz) {
|
write_binary(struct bson *b, const void * buffer, size_t sz) {
|
||||||
@@ -409,65 +389,59 @@ bson_numstr( char *str, unsigned int i ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pack_dict_data(lua_State *L, struct bson *b, bool isarray, int depth, int kt) {
|
pack_array(lua_State *L, struct bson *b, int depth, size_t len) {
|
||||||
char numberkey[32];
|
|
||||||
const char * key = NULL;
|
|
||||||
size_t sz;
|
|
||||||
if (isarray) {
|
|
||||||
if (kt != LUA_TNUMBER) {
|
|
||||||
luaL_error(L, "Invalid array key type : %s", lua_typename(L, kt));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1);
|
|
||||||
key = numberkey;
|
|
||||||
|
|
||||||
append_one(b, L, key, sz, depth);
|
|
||||||
lua_pop(L,1);
|
|
||||||
} else {
|
|
||||||
switch(kt) {
|
|
||||||
case LUA_TNUMBER:
|
|
||||||
// copy key, don't change key type
|
|
||||||
lua_pushvalue(L,-2);
|
|
||||||
lua_insert(L,-2);
|
|
||||||
key = lua_tolstring(L,-2,&sz);
|
|
||||||
append_one(b, L, key, sz, depth);
|
|
||||||
lua_pop(L,2);
|
|
||||||
break;
|
|
||||||
case LUA_TSTRING:
|
|
||||||
key = lua_tolstring(L,-2,&sz);
|
|
||||||
append_one(b, L, key, sz, depth);
|
|
||||||
lua_pop(L,1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pack_simple_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
|
||||||
if (depth > MAX_DEPTH) {
|
|
||||||
luaL_error(L, "Too depth while encoding bson");
|
|
||||||
}
|
|
||||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
|
||||||
int length = reserve_length(b);
|
int length = reserve_length(b);
|
||||||
lua_pushnil(L);
|
size_t i;
|
||||||
while(lua_next(L,-2) != 0) {
|
for (i=1;i<=len;i++) {
|
||||||
int kt = lua_type(L, -2);
|
char numberkey[32];
|
||||||
pack_dict_data(L, b, isarray, depth, kt);
|
size_t sz = bson_numstr(numberkey, i - 1);
|
||||||
|
const char * key = numberkey;
|
||||||
|
lua_geti(L, -1, i);
|
||||||
|
append_one(b, L, key, sz, depth);
|
||||||
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
write_byte(b,0);
|
write_byte(b,0);
|
||||||
write_length(b, b->size - length, length);
|
write_length(b, b->size - length, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pack_dict_data(lua_State *L, struct bson *b, int depth, int kt) {
|
||||||
|
const char * key = NULL;
|
||||||
|
size_t sz;
|
||||||
|
switch(kt) {
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
// copy key, don't change key type
|
||||||
|
lua_pushvalue(L,-2);
|
||||||
|
lua_insert(L,-2);
|
||||||
|
key = lua_tolstring(L,-2,&sz);
|
||||||
|
append_one(b, L, key, sz, depth);
|
||||||
|
lua_pop(L,2);
|
||||||
|
break;
|
||||||
|
case LUA_TSTRING:
|
||||||
|
key = lua_tolstring(L,-2,&sz);
|
||||||
|
append_one(b, L, key, sz, depth);
|
||||||
|
lua_pop(L,1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pack_meta_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
pack_simple_dict(lua_State *L, struct bson *b, int depth) {
|
||||||
if (depth > MAX_DEPTH) {
|
int length = reserve_length(b);
|
||||||
luaL_error(L, "Too depth while encoding bson");
|
lua_pushnil(L);
|
||||||
|
while(lua_next(L,-2) != 0) {
|
||||||
|
int kt = lua_type(L, -2);
|
||||||
|
pack_dict_data(L, b, depth, kt);
|
||||||
}
|
}
|
||||||
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
write_byte(b,0);
|
||||||
|
write_length(b, b->size - length, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pack_meta_dict(lua_State *L, struct bson *b, int depth) {
|
||||||
int length = reserve_length(b);
|
int length = reserve_length(b);
|
||||||
|
|
||||||
lua_pushvalue(L, -2); // push meta_obj
|
lua_pushvalue(L, -2); // push meta_obj
|
||||||
@@ -483,18 +457,51 @@ pack_meta_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
|||||||
lua_pop(L, 4); // pop all k, v, next_func, obj
|
lua_pop(L, 4); // pop all k, v, next_func, obj
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pack_dict_data(L, b, isarray, depth, kt);
|
pack_dict_data(L, b, depth, kt);
|
||||||
}
|
}
|
||||||
write_byte(b,0);
|
write_byte(b,0);
|
||||||
write_length(b, b->size - length, length);
|
write_length(b, b->size - length, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_rawarray(lua_State *L) {
|
||||||
|
size_t len = lua_rawlen(L, -1);
|
||||||
|
if (len > 0) {
|
||||||
|
lua_pushinteger(L, len);
|
||||||
|
if (lua_next(L,-2) == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
lua_pop(L,2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
|
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
|
||||||
if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
|
if (depth > MAX_DEPTH) {
|
||||||
pack_meta_dict(L, b, isarray, depth);
|
luaL_error(L, "Too depth while encoding bson");
|
||||||
|
}
|
||||||
|
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
|
||||||
|
if (luaL_getmetafield(L, -1, "__len") != LUA_TNIL) {
|
||||||
|
lua_pushvalue(L, -2);
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
if (!lua_isinteger(L, -1)) {
|
||||||
|
luaL_error(L, "__len should return integer");
|
||||||
|
}
|
||||||
|
size_t len = lua_tointeger(L, -1);
|
||||||
|
lua_pop(L, 1);
|
||||||
|
append_key(bs, BSON_ARRAY, key, sz);
|
||||||
|
pack_array(L, bs, depth, len);
|
||||||
|
} else if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
|
||||||
|
append_key(bs, BSON_DOCUMENT, key, sz);
|
||||||
|
pack_meta_dict(L, bs, depth);
|
||||||
|
} else if (is_rawarray(L)) {
|
||||||
|
append_key(bs, BSON_ARRAY, key, sz);
|
||||||
|
pack_array(L, bs, depth, lua_rawlen(L, -1));
|
||||||
} else {
|
} else {
|
||||||
pack_simple_dict(L, b, isarray, depth);
|
append_key(bs, BSON_DOCUMENT, key, sz);
|
||||||
|
pack_simple_dict(L, bs, depth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,7 +902,11 @@ lencode(lua_State *L) {
|
|||||||
bson_create(&b);
|
bson_create(&b);
|
||||||
lua_settop(L,1);
|
lua_settop(L,1);
|
||||||
luaL_checktype(L, 1, LUA_TTABLE);
|
luaL_checktype(L, 1, LUA_TTABLE);
|
||||||
pack_dict(L, &b, false, 0);
|
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);
|
void * ud = lua_newuserdata(L, b.size);
|
||||||
memcpy(ud, b.ptr, b.size);
|
memcpy(ud, b.ptr, b.size);
|
||||||
bson_destroy(&b);
|
bson_destroy(&b);
|
||||||
|
|||||||
95
test/testbson.lua
Normal file
95
test/testbson.lua
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
local bson = require "bson"
|
||||||
|
|
||||||
|
sub = bson.encode_order( "hello", 1, "world", 2 )
|
||||||
|
|
||||||
|
local function tbl_next(...)
|
||||||
|
print("--- next.a", ...)
|
||||||
|
local k, v = next(...)
|
||||||
|
print("--- next.b", k, v)
|
||||||
|
return k, v
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tbl_pairs(obj)
|
||||||
|
return tbl_next, obj.__data, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local obj_a = {
|
||||||
|
__data = {
|
||||||
|
[1] = 2,
|
||||||
|
[3] = 4,
|
||||||
|
[5] = 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(
|
||||||
|
obj_a,
|
||||||
|
{
|
||||||
|
__index = obj_a.__data,
|
||||||
|
__pairs = tbl_pairs,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
local obj_b = {
|
||||||
|
__data = {
|
||||||
|
[7] = 8,
|
||||||
|
[9] = 10,
|
||||||
|
[11] = obj_a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setmetatable(
|
||||||
|
obj_b,
|
||||||
|
{
|
||||||
|
__index = obj_b.__data,
|
||||||
|
__pairs = tbl_pairs,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
local metaarray = setmetatable({ n = 5 }, {
|
||||||
|
__len = function(self) return self.n end,
|
||||||
|
__index = function(self, idx) return tostring(idx) end,
|
||||||
|
})
|
||||||
|
|
||||||
|
b = bson.encode {
|
||||||
|
a = 1,
|
||||||
|
b = true,
|
||||||
|
c = bson.null,
|
||||||
|
d = { 1,2,3,4 },
|
||||||
|
e = bson.binary "hello",
|
||||||
|
f = bson.regex ("*","i"),
|
||||||
|
g = bson.regex "hello",
|
||||||
|
h = bson.date (os.time()),
|
||||||
|
i = bson.timestamp(os.time()),
|
||||||
|
j = bson.objectid(),
|
||||||
|
k = { a = false, b = true },
|
||||||
|
l = {},
|
||||||
|
m = bson.minkey,
|
||||||
|
n = bson.maxkey,
|
||||||
|
o = sub,
|
||||||
|
p = 2^32-1,
|
||||||
|
q = obj_b,
|
||||||
|
r = metaarray,
|
||||||
|
}
|
||||||
|
|
||||||
|
print "\n[before replace]"
|
||||||
|
t = b:decode()
|
||||||
|
|
||||||
|
for k, v in pairs(t) do
|
||||||
|
print(k,type(v))
|
||||||
|
end
|
||||||
|
|
||||||
|
for k,v in ipairs(t.r) do
|
||||||
|
print(k,v)
|
||||||
|
end
|
||||||
|
|
||||||
|
b:makeindex()
|
||||||
|
b.a = 2
|
||||||
|
b.b = false
|
||||||
|
b.h = bson.date(os.time())
|
||||||
|
b.i = bson.timestamp(os.time())
|
||||||
|
b.j = bson.objectid()
|
||||||
|
|
||||||
|
print "\n[after replace]"
|
||||||
|
t = b:decode()
|
||||||
|
|
||||||
|
print("o.hello", bson.type(t.o.hello))
|
||||||
Reference in New Issue
Block a user