#51
authoradam <adamansky@gmail.com>
Mon, 11 Mar 2013 10:51:38 +0000 (17:51 +0700)
committeradam <adamansky@gmail.com>
Mon, 11 Mar 2013 10:51:38 +0000 (17:51 +0700)
.gitignore
luaejdb/luabson.c
tcejdb/configure
tcejdb/configure.ac
tcejdb/tcutil.h

index df447b3..75f8433 100644 (file)
@@ -96,5 +96,4 @@ tcejdb/debian/*.debhelper
 /python3-ejdb_*.deb
 
 
-luaejdb/Makefile
 luaejdb/test/testdb*
index 09c1f7b..8a37595 100644 (file)
@@ -2,6 +2,7 @@
 #include "luabson.h"
 #include <lualib.h>
 #include <lauxlib.h>
+#include <math.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);
@@ -126,38 +127,172 @@ int lua_from_bson(lua_State *L) {
     bson_iterator it;
     bson_iterator_from_buffer(&it, bsdata);
     lua_push_bson_table(L, &it);
-    return 0;
+    return 1;
 }
 
 int lua_to_bson(lua_State *L) {
+    luaL_checktype(L, lua_gettop(L), LUA_TTABLE);
     bson bs;
     bson_init_as_query(&bs);
     lua_to_bson_impl(L, lua_gettop(L), &bs);
-    if (bs.err) {
+    if (bs.err || bson_finish(&bs)) {
         lua_pushstring(L, bson_first_errormsg(&bs));
+        bson_destroy(&bs);
         return lua_error(L);
     }
     lua_pushlstring(L, bson_data(&bs), bson_size(&bs));
+    bson_destroy(&bs);
     return 1;
 }
 
-static void lua_append_bson(lua_State *L, const char *key, int vpos, bson *bs, int tref) {
+static void lua_val_to_bson(lua_State *L, const char *key, int vpos, bson *bs, int tref) {
     int vtype = lua_type(L, vpos);
-    
+    char nbuf[TCNUMBUFSIZ];
+    switch (vtype) {
+        case LUA_TTABLE:
+        {
+            if (vpos < 0) vpos = lua_gettop(L) + vpos + 1;
+            lua_checkstack(L, 3);
+            int bsontype_found = luaL_getmetafield(L, vpos, "__bsontype");
+            if (!bsontype_found) {
+                //check if registry tbl contains traversed tbl
+                lua_rawgeti(L, LUA_REGISTRYINDEX, tref);
+                lua_pushvalue(L, vpos);
+                lua_rawget(L, -2);
+                if (lua_toboolean(L, -1)) { //already traversed
+                    lua_pop(L, 2);
+                    break;
+                }
+                //setup traversed state
+                lua_pop(L, 1);
+                lua_pushvalue(L, vpos);
+                lua_pushboolean(L, 1);
+                lua_rawset(L, -3);
+                lua_pop(L, 1);
+
+                bool array = true;
+                int len = 0;
+                for (lua_pushnil(L); lua_next(L, vpos); lua_pop(L, 1)) {
+                    ++len;
+                    if ((lua_type(L, -2) != LUA_TNUMBER) || (lua_tointeger(L, -2) != len)) {
+                        lua_pop(L, 2);
+                        array = false;
+                        break;
+                    }
+                }
+                if (array) {
+                    bson_append_start_array(bs, key);
+                    for (int i = 0; i < len; i++) {
+                        lua_rawgeti(L, vpos, i + 1);
+                        bson_numstrn(nbuf, TCNUMBUFSIZ, (int64_t) i);
+                        lua_val_to_bson(L, nbuf, -1, bs, tref);
+                        lua_pop(L, 1);
+                    }
+                    bson_append_finish_array(bs);
+                } else {
+                    for (lua_pushnil(L); lua_next(L, vpos); lua_pop(L, 1)) {
+                        int ktype = lua_type(L, -2);
+                        if (ktype == LUA_TNUMBER) {
+                            char key[TCNUMBUFSIZ];
+                            bson_numstrn(key, TCNUMBUFSIZ, (int64_t) lua_tointeger(L, -2));
+                            lua_val_to_bson(L, key, -1, bs, tref);
+                        } else if (ktype == LUA_TSTRING) {
+                            lua_val_to_bson(L, lua_tostring(L, -2), -1, bs, tref);
+                        }
+                    }
+                }
+            } else {
+                int bson_type = lua_tointeger(L, -1);
+                lua_pop(L, 1); //pop metafield __bsontype
+                lua_rawgeti(L, -1, 1); //get first value
+                switch (bson_type) {
+                    case BSON_OID:
+                    {
+                        const char* boid = lua_tostring(L, -1);
+                        if (boid && strlen(boid) == 24) {
+                            bson_oid_t oid;
+                            bson_oid_from_string(&oid, boid);
+                            bson_append_oid(bs, key, &oid);
+                        }
+                        break;
+                    }
+                    case BSON_DATE:
+                        bson_append_date(bs, key, (bson_date_t) lua_tonumber(L, -1));
+                        break;
+                    case BSON_REGEX:
+                    {
+                        const char* regex = lua_tostring(L, -1);
+                        lua_rawgeti(L, -2, 2); // re opts
+                        const char* options = lua_tostring(L, -1);
+                        lua_pop(L, 1);
+                        if (regex && options) {
+                            bson_append_regex(bs, key, regex, options);
+                        }
+                        break;
+                    }
+                    case BSON_BINDATA:
+                    {
+                        size_t len;
+                        const char* cbuf = lua_tolstring(L, -1, &len);
+                        bson_append_binary(bs, key, BSON_BIN_BINARY, cbuf, len);
+                        break;
+                    }
+                    case BSON_NULL:
+                        bson_append_null(bs, key);
+                        break;
+                    case BSON_UNDEFINED:
+                        bson_append_undefined(bs, key);
+                        break;
+                    default:
+                        break;
+                }
+            }
+            break;
+        }
+        case LUA_TNIL:
+            bson_append_null(bs, key);
+            break;
+        case LUA_TNUMBER:
+        {
+            lua_Number numval = lua_tonumber(L, vpos);
+            if (numval == floor(numval)) {
+                int64_t iv = (int64_t) numval;
+                if (-(1LL << 31) <= iv && iv <= (1LL << 31)) {
+                    bson_append_int(bs, key, iv);
+                } else {
+                    bson_append_long(bs, key, iv);
+                }
+            }
+            break;
+        }
+        case LUA_TBOOLEAN:
+            bson_append_bool(bs, key, lua_toboolean(L, vpos));
+            break;
+
+        case LUA_TSTRING:
+            bson_append_string(bs, key, lua_tostring(L, vpos));
+            break;
+    }
 }
 
 static void lua_to_bson_impl(lua_State *L, int tpos, bson *bs) {
-    lua_newtable(L);
+    lua_newtable(L); //traverse state table
     int tref = luaL_ref(L, LUA_REGISTRYINDEX);
     for (lua_pushnil(L); lua_next(L, tpos); lua_pop(L, 1)) {
         int ktype = lua_type(L, -2);
         if (ktype == LUA_TNUMBER) {
             char key[TCNUMBUFSIZ];
             bson_numstrn(key, TCNUMBUFSIZ, (int64_t) lua_tonumber(L, -2));
-            key[TCNUMBUFSIZ - 1] = '\0';
-            lua_append_bson(L, key, -1, bs, tref);
+            lua_val_to_bson(L, key, -1, bs, tref);
         } else if (ktype == LUA_TSTRING) {
-            lua_append_bson(L, lua_tostring(L, -2), -1, bs, tref);
+            const char* key = lua_tostring(L, -2);
+            if (lua_type(L, -1) == LUA_TSTRING && !strcmp("_id", key)) { //root level OID as string
+                //pack OID as type table
+                lua_pushvalue(L, -1); //dup oid on stack
+                lua_push_bsontype_table(L, BSON_OID); //push type table
+                lua_rawseti(L, -2, 1); //pop oid val
+            }
+            lua_val_to_bson(L, key, -1, bs, tref);
         }
     }
     lua_unref(L, tref);
index 29b53d9..1c652e5 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for tcejdb 1.0.65.
+# Generated by GNU Autoconf 2.69 for tcejdb 1.0.66.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -577,8 +577,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='tcejdb'
 PACKAGE_TARNAME='tcejdb'
-PACKAGE_VERSION='1.0.65'
-PACKAGE_STRING='tcejdb 1.0.65'
+PACKAGE_VERSION='1.0.66'
+PACKAGE_STRING='tcejdb 1.0.66'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1258,7 +1258,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures tcejdb 1.0.65 to adapt to many kinds of systems.
+\`configure' configures tcejdb 1.0.66 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1319,7 +1319,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of tcejdb 1.0.65:";;
+     short | recursive ) echo "Configuration of tcejdb 1.0.66:";;
    esac
   cat <<\_ACEOF
 
@@ -1426,7 +1426,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-tcejdb configure 1.0.65
+tcejdb configure 1.0.66
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1724,7 +1724,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by tcejdb $as_me 1.0.65, which was
+It was created by tcejdb $as_me 1.0.66, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4893,7 +4893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by tcejdb $as_me 1.0.65, which was
+This file was extended by tcejdb $as_me 1.0.66, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4946,7 +4946,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-tcejdb config.status 1.0.65
+tcejdb config.status 1.0.66
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 6983dba..29a270e 100644 (file)
@@ -11,7 +11,7 @@ test -n "$CPPFLAGS" && MYCPPFLAGS="$CPPFLAGS $MYCPPFLAGS"
 test -n "$LDFLAGS" && MYLDFLAGS="$LDFLAGS $MYLDFLAGS"
 
 # Package name
-AC_INIT(tcejdb, 1.0.65)
+AC_INIT(tcejdb, 1.0.66)
 
 # Package information
 MYLIBVER=9
index 6c01ab0..b35ac05 100644 (file)
@@ -3719,7 +3719,7 @@ typedef unsigned char TCBITMAP;          /* type of a bit map object */
 
 #include <stdio.h>
 
-#define _TC_VERSION    "1.0.65"
+#define _TC_VERSION    "1.0.66"
 #define _TC_LIBVER     911
 #define _TC_FORMATVER  "1.0"