From c8170272425779f56a233b4740907693f58e40d4 Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 1 Nov 2012 19:10:21 +0700 Subject: [PATCH] #1 --- node/ejdb_native.cc | 214 ++++++++++++++++++++++++++++++++------ node/nbproject/configurations.xml | 12 +++ 2 files changed, 195 insertions(+), 31 deletions(-) diff --git a/node/ejdb_native.cc b/node/ejdb_native.cc index da3fb64..29f02f8 100644 --- a/node/ejdb_native.cc +++ b/node/ejdb_native.cc @@ -27,63 +27,185 @@ static const int CMD_RET_ERROR = 1; namespace ejdb { - static Handle toV8Object(bson_iterator *it) { + typedef struct { + Handle traversed; + } TBSONCTX; + + static Handle toV8Object(bson_iterator *it, bson_type obt = BSON_OBJECT); + static Handle toV8Value(bson_iterator *it); + static void toBSON0(Handle obj, bson *bs, TBSONCTX *ctx); + + static Handle toV8Value(bson_iterator *it) { HandleScope scope; - Local ret = Object::New(); + bson_type bt = bson_iterator_type(it); + + switch (bt) { + case BSON_OID: + { + char xoid[25]; + bson_oid_to_string(bson_iterator_oid(it), xoid); + return scope.Close(String::New(xoid, 24)); + } + case BSON_STRING: + case BSON_SYMBOL: + return scope.Close(String::New(bson_iterator_string(it), bson_iterator_string_len(it))); + case BSON_NULL: + return scope.Close(Null()); + case BSON_UNDEFINED: + return scope.Close(Undefined()); + case BSON_INT: + return scope.Close(Integer::New(bson_iterator_int_raw(it))); + case BSON_LONG: + return scope.Close(Number::New((double) bson_iterator_long_raw(it))); + case BSON_DOUBLE: + return scope.Close(Number::New(bson_iterator_double_raw(it))); + case BSON_BOOL: + return scope.Close(Boolean::New(bson_iterator_bool_raw(it))); + case BSON_OBJECT: + case BSON_ARRAY: + { + bson_iterator nit; + bson_iterator_subiterator(it, &nit); + return scope.Close(toV8Object(&nit)); + } + case BSON_DATE: + return scope.Close(Date::New((double) bson_iterator_date(it))); + case BSON_BINDATA: + //TODO test it! + return scope.Close(Buffer::New(String::New(bson_iterator_bin_data(it), bson_iterator_bin_len(it)))); + case BSON_REGEX: + { + const char *re = bson_iterator_regex(it); + const char *ro = bson_iterator_regex_opts(it); + int rflgs = RegExp::kNone; + for (int i = (strlen(ro) - 1); i >= 0; --i) { + if (ro[i] == 'i') { + rflgs |= RegExp::kIgnoreCase; + } else if (ro[i] == 'g') { + rflgs |= RegExp::kGlobal; + } else if (ro[i] == 'm') { + rflgs |= RegExp::kMultiline; + } + } + return scope.Close(RegExp::New(String::New(re), (RegExp::Flags) rflgs)); + } + default: + break; + } + return scope.Close(Undefined()); + } + + static Handle toV8Object(bson_iterator *it, bson_type obt) { + HandleScope scope; + Local ret; + uint32_t cxnum = 0; + if (obt == BSON_ARRAY) { + ret = Array::New(); + } else if (obt == BSON_OBJECT) { + ret = Object::New(); + } else { + assert(0); + } bson_type bt; while ((bt = bson_iterator_next(it)) != BSON_EOO) { const char *key = bson_iterator_key(it); + if (obt == BSON_ARRAY) { + cxnum = tcatoi(key); + } switch (bt) { case BSON_OID: { char xoid[25]; bson_oid_to_string(bson_iterator_oid(it), xoid); - ret->Set(String::New(key), String::New(xoid, 24)); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, String::New(xoid, 24)); + } else { + ret->Set(String::New(key), String::New(xoid, 24)); + } break; } case BSON_STRING: case BSON_SYMBOL: - ret->Set(String::New(key), - String::New(bson_iterator_string(it), bson_iterator_string_len(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, + String::New(bson_iterator_string(it), bson_iterator_string_len(it))); + } else { + ret->Set(String::New(key), + String::New(bson_iterator_string(it), bson_iterator_string_len(it))); + } break; case BSON_NULL: - ret->Set(String::New(key), Null()); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Null()); + } else { + ret->Set(String::New(key), Null()); + } break; case BSON_UNDEFINED: - ret->Set(String::New(key), Undefined()); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Undefined()); + } else { + ret->Set(String::New(key), Undefined()); + } break; case BSON_INT: - ret->Set(String::New(key), Integer::New(bson_iterator_int_raw(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Integer::New(bson_iterator_int_raw(it))); + } else { + ret->Set(String::New(key), Integer::New(bson_iterator_int_raw(it))); + } break; case BSON_LONG: - ret->Set(String::New(key), Number::New((double) bson_iterator_long_raw(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Number::New((double) bson_iterator_long_raw(it))); + } else { + ret->Set(String::New(key), Number::New((double) bson_iterator_long_raw(it))); + } break; case BSON_DOUBLE: - ret->Set(String::New(key), Number::New(bson_iterator_double_raw(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Number::New(bson_iterator_double_raw(it))); + } else { + ret->Set(String::New(key), Number::New(bson_iterator_double_raw(it))); + } break; case BSON_BOOL: - ret->Set(String::New(key), Boolean::New(bson_iterator_bool_raw(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Boolean::New(bson_iterator_bool_raw(it))); + } else { + ret->Set(String::New(key), Boolean::New(bson_iterator_bool_raw(it))); + } break; case BSON_OBJECT: case BSON_ARRAY: { - int nbt; bson_iterator nit; bson_iterator_subiterator(it, &nit); - while ((nbt = bson_iterator_next(&nit)) != BSON_EOO) { - const char* nkey = bson_iterator_key(&nit); - ret->Set(String::New(nkey), toV8Object(&nit)); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, toV8Object(&nit, bt)); + } else { + ret->Set(String::New(key), toV8Object(&nit, bt)); } break; } case BSON_DATE: - ret->Set(String::New(key), Date::New((double) bson_iterator_date(it))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Date::New((double) bson_iterator_date(it))); + } else { + ret->Set(String::New(key), Date::New((double) bson_iterator_date(it))); + } break; case BSON_BINDATA: //TODO test it! - ret->Set(String::New(key), - Buffer::New(String::New(bson_iterator_bin_data(it), - bson_iterator_bin_len(it)))); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, + Buffer::New(String::New(bson_iterator_bin_data(it), + bson_iterator_bin_len(it)))); + } else { + ret->Set(String::New(key), + Buffer::New(String::New(bson_iterator_bin_data(it), + bson_iterator_bin_len(it)))); + } break; case BSON_REGEX: { @@ -99,22 +221,25 @@ namespace ejdb { rflgs |= RegExp::kMultiline; } } - ret->Set(String::New(key), RegExp::New(String::New(re), (RegExp::Flags) rflgs)); + if (obt == BSON_ARRAY) { + ret->Set(cxnum, RegExp::New(String::New(re), (RegExp::Flags) rflgs)); + } else { + ret->Set(String::New(key), RegExp::New(String::New(re), (RegExp::Flags) rflgs)); + } break; } - default: - //ignore other types + if (obt == BSON_ARRAY) { + ret->Set(cxnum, Undefined()); + } else { + ret->Set(String::New(key), Undefined()); + } break; } } return scope.Close(ret); } - typedef struct { - Handle traversed; - } TBSONCTX; - static void toBSON0(Handle obj, bson *bs, TBSONCTX *ctx) { HandleScope scope; assert(ctx && obj->IsObject()); @@ -504,7 +629,7 @@ namespace ejdb { if (bs) { bson_iterator it; bson_iterator_init(&it, bs); - argv[1] = Local::New(toV8Object(&it)); + argv[1] = Local::New(toV8Object(&it, BSON_OBJECT)); } else { argv[1] = Local::New(Null()); } @@ -719,18 +844,42 @@ finish: return; } int nval = val->Int32Value(); - int sz = TCLISTNUM(c->m_rs); + int rsz = TCLISTNUM(c->m_rs); if (nval < 0) { - nval = sz + nval; + nval = rsz + nval; } - if (nval >= 0 && sz > 0) { - nval = (nval >= sz) ? sz - 1 : nval; + if (nval >= 0 && rsz > 0) { + nval = (nval >= rsz) ? rsz - 1 : nval; } else { nval = 0; } c->m_pos = nval; } + static Handle s_val(const Arguments& args) { + HandleScope scope; + REQ_ARGS(1); + REQ_STR_ARG(0, fpath); + NodeEJDBCursor *c = ObjectWrap::Unwrap (args.This()); + assert(c); + if (!c->m_rs) { + return scope.Close(ThrowException(Exception::Error(String::New("Cursor closed")))); + } + int pos = c->m_pos; + int rsz = TCLISTNUM(c->m_rs); + if (rsz == 0) { + return scope.Close(ThrowException(Exception::Error(String::New("Empty cursor")))); + } + assert(pos < 0 || pos >= rsz); //m_pos correctly set by s_set_pos + void *bsdata = TCLISTVALPTR(c->m_rs, pos); + assert(bsdata); + bson_iterator it; + bson_type bt = bson_find_fieldpath_value2(*fpath, fpath.length(), &it); + //TODO !!! + + return scope.Close(Null()); + } + void close() { if (m_nejdb) { m_nejdb->Unref(); @@ -766,8 +915,11 @@ finish: constructor_template->PrototypeTemplate() ->SetAccessor(String::NewSymbol("pos"), s_get_pos, s_set_pos, Handle (), ALL_CAN_READ); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "close", s_close); NODE_SET_PROTOTYPE_METHOD(constructor_template, "hasNext", s_has_next); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "value", s_val); } void Ref() { diff --git a/node/nbproject/configurations.xml b/node/nbproject/configurations.xml index c158788..43263ca 100644 --- a/node/nbproject/configurations.xml +++ b/node/nbproject/configurations.xml @@ -9,6 +9,18 @@ + Makefile + binding.Makefile + config.gypi + ejdb_native.target.mk + + + + + + + + -- 2.7.4