From f7e0271f192a28ecd5e449ae6235f21b3eb504ba Mon Sep 17 00:00:00 2001 From: adam Date: Sun, 10 Mar 2013 23:46:49 +0700 Subject: [PATCH] #51 --- .gitignore | 1 + luaejdb/luabson.c | 139 +++++++++++++++++++++++++++++++++++++++++ luaejdb/luabson.h | 27 ++++++++ luaejdb/luaejdb-1.0-1.rockspec | 2 +- luaejdb/luaejdb.c | 99 ++++++++++++++++++++++------- 5 files changed, 243 insertions(+), 25 deletions(-) create mode 100644 luaejdb/luabson.c create mode 100644 luaejdb/luabson.h diff --git a/.gitignore b/.gitignore index e429056..df447b3 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,4 @@ tcejdb/debian/*.debhelper luaejdb/Makefile +luaejdb/test/testdb* diff --git a/luaejdb/luabson.c b/luaejdb/luabson.c new file mode 100644 index 0000000..b05bc25 --- /dev/null +++ b/luaejdb/luabson.c @@ -0,0 +1,139 @@ + +#include "luabson.h" +#include +#include + +static void lua_push_bson_value(lua_State *L, bson_iterator *it); +static void lua_push_bson_table(lua_State *L, bson_iterator *it); +static void lua_push_bson_array(lua_State *L, bson_iterator *it); + +void lua_init_bson(lua_State *L) { + if (!lua_istable(L, -1)) { + return luaL_error(L, "luainitbson: Table must be on top of lua stack"); + } + lua_pushcfunction(L, lua_from_bson); + lua_setfield(L, -2, "lua_from_bson"); + + lua_pushcfunction(L, lua_to_bson); + lua_setfield(L, -2, "lua_to_bson"); +} + +static int null_value(lua_State *L) { + lua_pushnil(L); + return 1; +} + +void lua_push_bsontype_table(lua_State* L, int bsontype) { + lua_newtable(L); //table + lua_newtable(L); //metatable + lua_pushstring(L, "__bsontype"); + lua_pushinteger(L, bsontype); + lua_settable(L, -3); + lua_setmetatable(L, -2); +} + +static void lua_push_bson_value(lua_State *L, bson_iterator *it) { + bson_type bt = bson_iterator_type(it); + switch (bt) { + case BSON_OID: + { + char xoid[25]; + bson_oid_to_string(bson_iterator_oid(it), xoid); + lua_pushstring(L, xoid); + break; + } + case BSON_STRING: + case BSON_SYMBOL: + lua_pushstring(L, bson_iterator_string(it)); + break; + case BSON_NULL: + case BSON_UNDEFINED: + lua_pushnil(L); + break; + case BSON_INT: + lua_pushinteger(L, bson_iterator_int(it)); + break; + case BSON_LONG: + case BSON_DOUBLE: + lua_pushnumber(L, (lua_Number) bson_iterator_double(it)); + break; + case BSON_BOOL: + lua_pushboolean(L, bson_iterator_bool(it)); + break; + case BSON_OBJECT: + case BSON_ARRAY: + { + bson_iterator nit; + bson_iterator_subiterator(it, &nit); + if (bt == BSON_OBJECT) { + lua_push_bson_table(L, &nit); + } else { + lua_push_bson_array(L, &nit); + } + break; + } + case BSON_DATE: + { + lua_push_bsontype_table(L, bt); + lua_pushnumber(L, bson_iterator_date(it)); + lua_rawseti(L, -2, 1); + break; + } + case BSON_BINDATA: + { + lua_push_bsontype_table(L, bt); + lua_pushlstring(L, bson_iterator_bin_data(it), bson_iterator_bin_len(it)); + break; + } + case BSON_REGEX: + { + const char *re = bson_iterator_regex(it); + const char *ro = bson_iterator_regex_opts(it); + lua_push_bsontype_table(L, bt); + lua_pushstring(L, re); + lua_rawseti(L, -2, 1); + lua_pushstring(L, ro); + lua_rawseti(L, -2, 2); + break; + } + default: + break; + + } +} + +static void lua_push_bson_table(lua_State *L, bson_iterator *it) { + bson_type bt; + lua_push_bsontype_table(L, BSON_OBJECT); + while ((bt = bson_iterator_next(it)) != BSON_EOO) { + lua_pushstring(L, bson_iterator_key(it)); + lua_push_bson_value(L, it); + lua_rawset(L, -3); + } +} + +static void lua_push_bson_array(lua_State *L, bson_iterator *it) { + bson_type bt; + lua_push_bsontype_table(L, BSON_ARRAY); + for (int i = 1; (bt = bson_iterator_next(it)) != BSON_EOO; ++i) { + lua_push_bson_value(L, it); + lua_rawseti(L, -2, i); + } +} + +int lua_from_bson(lua_State *L) { + const void *bsdata = lua_tostring(L, -1); + if (!bsdata) { + return luaL_error(L, "luafrombson: BSON binary string must be on top of stack"); + } + bson_iterator it; + bson_iterator_from_buffer(&it, bsdata); + lua_push_bson_table(L, &it); + return 0; +} + +int lua_to_bson(lua_State *L) { + return 0; +} + + diff --git a/luaejdb/luabson.h b/luaejdb/luabson.h new file mode 100644 index 0000000..4a97d53 --- /dev/null +++ b/luaejdb/luabson.h @@ -0,0 +1,27 @@ +/* + * File: luabson.h + * Author: adam + * + * Created on March 10, 2013, 5:11 PM + */ + +#ifndef LUABSON_H +#define LUABSON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + void lua_init_bson(lua_State *L); + int lua_from_bson(lua_State *L); + int lua_to_bson(lua_State *L); + +#ifdef __cplusplus +} +#endif + +#endif /* LUABSON_H */ + diff --git a/luaejdb/luaejdb-1.0-1.rockspec b/luaejdb/luaejdb-1.0-1.rockspec index cf0778b..f0c87c7 100644 --- a/luaejdb/luaejdb-1.0-1.rockspec +++ b/luaejdb/luaejdb-1.0-1.rockspec @@ -29,7 +29,7 @@ build = { ["ejdb"] = "ejdb.lua", ["bson"] = "bson.lua", ["luaejdb"] = { - sources = {"luaejdb.c"}, + sources = {"luaejdb.c", "luabson.c"}, libraries = {"tcejdb"} , incdirs = {"$(LIBTCEJDB_INCDIR)"}, libdirs = {"$(LIBTCEJDB_LIBDIR)"} diff --git a/luaejdb/luaejdb.c b/luaejdb/luaejdb.c index f3c21b6..4bf3b18 100644 --- a/luaejdb/luaejdb.c +++ b/luaejdb/luaejdb.c @@ -4,9 +4,12 @@ #include #include +#include "luabson.h" + #define EJDBLIBNAME "luaejdb" #define EJDBUDATAKEY "__ejdb__" #define EJDBUDATAMT "mt.ejdb.db" +#define EJDBCURSORMT "mt.ejdb.cur" #define DEFAULT_OPEN_MODE (JBOWRITER | JBOCREAT | JBOTSYNC) @@ -28,10 +31,14 @@ typedef struct { EJDB *db; } EJDBDATA; +typedef struct { + TCLIST *res; +} CURSORDATA; + #define EJDBERR(_L, _DB) \ return luaL_error((_L), "EJDB ERROR %d|%s", ejdbecode(_DB), ejdberrmsg(ejdbecode(_DB))) -static void initdbconsts(lua_State *L) { +static void init_db_consts(lua_State *L) { if (!lua_istable(L, -1)) { luaL_error(L, "Table must be on top of lua stack"); } @@ -54,7 +61,28 @@ static void initdbconsts(lua_State *L) { TBLSETNUMCONST(DEFAULT_OPEN_MODE); } -int dbdel(lua_State *L) { +static int cursor_del(lua_State *L) { + CURSORDATA *cdata = luaL_checkudata(L, 1, EJDBCURSORMT); + if (cdata->res) { + tclistdel(cdata->res); + cdata->res = NULL; + } + return 0; +} + +static int cursor_field(lua_State *L) { + return 0; +} + +static int cursor_object(lua_State *L) { + return 0; +} + +static int cursor_iter(lua_State *L) { + return 0; +} + +static int db_del(lua_State *L) { EJDBDATA *data = luaL_checkudata(L, 1, EJDBUDATAMT); EJDB *db = data->db; if (db) { @@ -64,7 +92,7 @@ int dbdel(lua_State *L) { return 0; } -int dbclose(lua_State *L) { +static int db_close(lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); //self lua_getfield(L, 1, EJDBUDATAKEY); EJDBDATA *data = luaL_checkudata(L, -1, EJDBUDATAMT); @@ -77,33 +105,40 @@ int dbclose(lua_State *L) { return 0; } -int find(lua_State *L) { +static int db_find(lua_State *L) { //cname, q.toBSON(), orBsons, q.toHintsBSON(), flags luaL_checktype(L, 1, LUA_TTABLE); //self lua_getfield(L, 1, EJDBUDATAKEY); EJDBDATA *data = luaL_checkudata(L, -1, EJDBUDATAMT); const char *cname = luaL_checkstring(L, 2); //collections name - const char *qbson = luaL_checkstring(L, 3); //Query bson + const char *qbsonbuf = luaL_checkstring(L, 3); //Query bson luaL_checktype(L, 4, LUA_TTABLE); //or joined - const char *hbson = luaL_checkstring(L, 5); //Hints bson - if (!data || !data->db || !qbson || !hbson) { - luaL_error(L, "Illegal arguments"); + const char *hbsonbuf = luaL_checkstring(L, 5); //Hints bson + if (!data || !data->db || !qbsonbuf || !hbsonbuf) { + return luaL_error(L, "Illegal arguments"); } + bson oqarrstack[8]; //max 8 $or bsons on stack + bson *oqarr = NULL; + bson qbson = {NULL}; + bson hbson = {NULL}; + EJQ *q = NULL; EJDB *db = data->db; + EJCOLL *coll = NULL; + uint32_t count = 0; - + //lua_objlen(L, 4) //bson_print_raw(stderr, hbson, 0); - return 0; } -int dbopen(lua_State *L) { +static int db_open(lua_State *L) { int argc = lua_gettop(L); const char *path = luaL_checkstring(L, 1); int mode = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : DEFAULT_OPEN_MODE; + //DB table lua_newtable(L); EJDB *db = ejdbnew(); if (!db) { @@ -117,23 +152,19 @@ int dbopen(lua_State *L) { EJDBDATA *udb = lua_newuserdata(L, sizeof (*udb)); udb->db = db; luaL_newmetatable(L, EJDBUDATAMT); - lua_setmetatable(L, -2); - lua_setfield(L, -2, EJDBUDATAKEY); //pop userdata - - //Metatable - lua_newtable(L); - lua_pushcfunction(L, dbdel); + lua_pushcfunction(L, db_del); lua_setfield(L, -2, "__gc"); lua_setmetatable(L, -2); + lua_setfield(L, -2, EJDBUDATAKEY); //pop userdata //Add constants - initdbconsts(L); + init_db_consts(L); //Add methods - lua_pushcfunction(L, dbclose); + lua_pushcfunction(L, db_close); lua_setfield(L, -2, "close"); - lua_pushcfunction(L, find); + lua_pushcfunction(L, db_find); lua_setfield(L, -2, "_find"); if (lua_gettop(L) - argc != 1) { @@ -141,17 +172,37 @@ int dbopen(lua_State *L) { udb->db = NULL; return luaL_error(L, "Invalid stack state %d", lua_gettop(L)); } + if (!lua_istable(L, -1)) { + ejdbdel(db); + udb->db = NULL; + return luaL_error(L, "Table must be on top of lua stack"); + } return 1; } /* Init */ int luaopen_luaejdb(lua_State *L) { lua_settop(L, 0); + + + lua_newtable(L); + lua_init_bson(L); + init_db_consts(L); + + lua_pushcfunction(L, db_open); + lua_setfield(L, -2, "open"); + + //Push cursor methods into metatable + luaL_newmetatable(L, EJDBCURSORMT); lua_newtable(L); - initdbconsts(L); - lua_pushstring(L, "open"); - lua_pushcfunction(L, dbopen); - lua_settable(L, -3); + lua_pushcfunction(L, cursor_object); + lua_setfield(L, -2, "object"); + lua_pushcfunction(L, cursor_field); + lua_setfield(L, -2, "field"); + lua_setfield(L, -2, "__index"); + lua_settop(L, 1); + + return 1; } -- 2.7.4