--- /dev/null
+
+#include "luabson.h"
+#include <lualib.h>
+#include <lauxlib.h>
+
+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;
+}
+
+
#include <lauxlib.h>
#include <tcejdb/ejdb.h>
+#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)
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");
}
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) {
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);
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) {
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) {
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;
}