Skip to content

Instantly share code, notes, and snippets.

@radare
Created June 18, 2015 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radare/9d871b76835cd9ba9123 to your computer and use it in GitHub Desktop.
Save radare/9d871b76835cd9ba9123 to your computer and use it in GitHub Desktop.
sdb.cc
/* sdb-nan.js - pancake@nopcode.org // 2015 */
#include <nan.h>
#include <sdb.h>
using namespace v8;
class Database : public node::ObjectWrap {
public:
// static void Init(Handle<Object> exports);
static Init(Handle<Object> exports, Handle<Value> module);
static NAN_METHOD(Open);
static NAN_METHOD(Close);
static NAN_METHOD(Ns);
static NAN_METHOD(New);
static NAN_METHOD(Add);
static NAN_METHOD(Set);
static NAN_METHOD(UnSet);
static NAN_METHOD(UnSetLike);
static NAN_METHOD(Drain);
static NAN_METHOD(Type);
static NAN_METHOD(Expire);
static NAN_METHOD(Reset);
static NAN_METHOD(Sync);
static NAN_METHOD(Query);
static NAN_METHOD(Like);
static NAN_METHOD(UnLink);
static NAN_METHOD(Get);
static NAN_METHOD(GetVersion);
static NAN_METHOD(Exists);
Database() {
this->obj = sdb_new0 ();
}
Database(const char *file) {
this->obj = sdb_new (NULL, file, 0);
}
Database(Sdb *db) {
this->obj = db;
}
~Database() {
sdb_free (this->obj);
}
private:
Sdb *obj;
};
NAN_METHOD(Database::Like) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
char **res = NULL;
switch (args.Length()) {
case 1:
if (args[0]->IsString()) {
NanUtf8String k (args[0]);
res = sdb_like(sdb, *k, NULL, NULL);
} else {
NanThrowTypeError ("string expected");
}
break;
case 2:
char *key = NULL, *val = NULL;
// TODO: fail if type is bool, object, ...
if (args[0]->IsString()) {
NanUtf8String k (args[0]);
key = *k;
}
if (args[1]->IsString()) {
NanUtf8String v (args[1]);
val = *v;
}
res = sdb_like (sdb, key, val, NULL);
break;
}
if (res) {
Local<Object> obj = NanNew<Object>();
for (int i = 0; res[i]; i+=2) {
obj->Set(NanNew(res[i]), NanNew(res[i+1]));
}
NanReturnValue(obj);
}
}
NAN_METHOD(Database::UnSetLike) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("string expected");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
sdb_unset_like (sdb, *k);
}
}
NAN_METHOD(Database::Open) {
int fd = -1;
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("string expected");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
fd = sdb_open (sdb, *k);
}
NanReturnValue(NanNew (fd != -1));
}
NAN_METHOD(Database::Close) {
/* arguments ignored */
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
sdb_close (sdb);
}
NAN_METHOD(Database::Type) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("string expected");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
const char *t = sdb_type (sdb_const_get (sdb, *k, 0));
NanReturnValue(NanNew (t));
}
}
NAN_METHOD(Database::UnSet) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("string expected");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
sdb_unset (sdb, *k, 0);
}
}
NAN_METHOD(Database::Exists) {
bool ret = false;
int len = args.Length();
if (len == 1) {
if (args[0]->IsString()) {
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
int ret = sdb_exists (sdb, *k);
NanReturnValue(NanNew ((bool)ret));
// sdb_num_exists
} else {
NanThrowTypeError ("string key expected");
}
}
NanReturnValue(NanNew(ret));
}
NAN_METHOD(Database::Set) {
int len = args.Length();
if (len == 2) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
NanUtf8String k (args[0]);
if (args[1]->IsBoolean()) {
ut64 v = args[1]->Uint32Value();
(void)sdb_bool_set (sdb, *k, v, 0);
} else if (args[1]->IsNumber()) {
ut64 v = args[1]->Uint32Value();
(void)sdb_num_set (sdb, *k, v, 0);
} else if (args[1]->IsString()) {
NanUtf8String v (args[1]);
(void)sdb_set (sdb, *k, *v, 0);
} else {
NanThrowTypeError ("Second argument must be a string");
}
} else {
NanThrowTypeError ("Sdb.Set Invalid arguments");
}
NanReturnThis();
}
NAN_METHOD(Database::Ns) {
int len = args.Length();
if (len == 1) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
if (!args[0]->IsString()) {
NanThrowTypeError ("namespace must be a string");
}
NanUtf8String k (args[0]);
Sdb *db = sdb_ns (sdb, *k, 0);
Database *so = new Database(db);
NanReturnValue(NanNew (so));
} else if (len == 2) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
if (!args[0]->IsString()) {
NanThrowTypeError ("namespace must be a string");
}
NanUtf8String k (args[0]);
ut32 v = args[1]->Uint32Value();
Sdb *db = sdb_ns (sdb, *k, v);
Database *so = new Database(db);
NanReturnValue(NanNew (so));
} else {
/* return current namespace */
}
}
#if 0
NAN_METHOD(Database::Open) {
/* TODO: call constructor */
}
#endif
NAN_METHOD(Database::Add) {
int ret = 0;
int len = args.Length();
if (len == 2) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
} else if (args[1]->IsNumber()) {
NanUtf8String k (args[0]);
ut64 v = args[1]->Uint32Value();
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
ret = sdb_num_add (sdb, *k, v, 0);
} else if (args[1]->IsString()) {
NanUtf8String k (args[0]);
NanUtf8String v (args[1]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
ret = sdb_add (sdb, *k, *v, 0);
} else {
NanThrowTypeError ("Second argument must be a string");
}
} else {
NanThrowTypeError ("Sdb.Set Invalid arguments");
}
if (ret == 0) {
NanReturnValue(NanNew((bool)ret));
} else {
NanReturnThis();
}
}
NAN_METHOD(Database::GetVersion) {
NanReturnValue(NanNew(SDB_VERSION));
}
NAN_METHOD(Database::Sync) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
bool v = sdb_sync (sdb);
NanReturnValue(NanNew(v));
}
NAN_METHOD(Database::Drain) {
int len = args.Length();
if (len == 1) {
//Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
//Sdb *sdb2 = ((Database*)(args[0]->ToObject()->Get(0)))->obj;
//Sdb *sdb2 = ObjectWrap::Unwrap<Database>(arg)->obj;
//sdb_drain (sdb, sdb2);
NanReturnThis();
} else {
NanThrowTypeError ("Missing destination database");
}
}
NAN_METHOD(Database::Reset) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
sdb_reset (sdb);
NanReturnThis();
}
NAN_METHOD(Database::UnLink) {
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
bool v = sdb_unlink(sdb);
NanReturnValue(NanNew(v));
}
NAN_METHOD(Database::Get) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
const char *v = sdb_const_get (sdb, *k, NULL);
if (v != NULL) {
NanReturnValue(NanNew(v));
}
}
NanReturnUndefined();
}
NAN_METHOD(Encode) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
char *str = sdb_encode ((const ut8*)*k, -1);
NanReturnValue(NanNew(str));
free (str);
}
NanReturnThis();
}
NAN_METHOD(TypeOf) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
NanReturnValue(NanNew(sdb_type (*k)));
}
}
NAN_METHOD(Decode) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
char *str = (char *)sdb_decode (*k, NULL);
NanReturnValue(NanNew(str));
free (str);
}
NanReturnThis();
}
NAN_METHOD(Database::Query) {
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
const char *v = sdb_querys (sdb, *k, -1, NULL);
if (v != NULL) {
NanReturnValue(NanNew(v));
}
}
NanReturnUndefined();
}
NAN_METHOD(Database::Expire) {
ut32 v = 0; // should be 64 bit!
Sdb *sdb = ObjectWrap::Unwrap<Database>(args.This())->obj;
NanUtf8String k (args[0]);
switch (args.Length()) {
case 1:
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
v = sdb_expire_get (sdb, *k, NULL);
break;
case 2:
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
if (args[1]->IsNumber()) {
ut64 n = (ut64)args[1]->Uint32Value();
v = sdb_expire_set (sdb, *k, n, 0);
} else {
NanThrowTypeError ("2nd arg expects a number");
}
break;
default:
NanThrowTypeError ("Missing parameters");
break;
}
NanReturnValue(NanNew(v));
}
static void Database::Init(Handle<Object> exports, Handle<Value> module) {
Local<v8::String> name = NanNew("Database");
Local<v8::FunctionTemplate> ft = NanNew<FunctionTemplate>(New);
ft->SetClassName(name);
ft->InstanceTemplate()->SetInternalFieldCount(1);
#if 0
auto data = Handle<Value>();
auto ift = ft->InstanceTemplate();
auto signature = AccessorSignature::New(isolate, ft);
ift->SetAccessor(String::NewFromUtf8(isolate, "id"),
GetId, 0, data, DEFAULT, ReadOnly, signature);
#endif
NODE_SET_PROTOTYPE_METHOD(ft, "add", Add);
NODE_SET_PROTOTYPE_METHOD(ft, "set", Set);
//NODE_SET_PROTOTYPE_METHOD(ft, "get_length", GetLength);
NODE_SET_PROTOTYPE_METHOD(ft, "unset", UnSet);
NODE_SET_PROTOTYPE_METHOD(ft, "unset_like", UnSetLike);
NODE_SET_PROTOTYPE_METHOD(ft, "reset", Reset);
NODE_SET_PROTOTYPE_METHOD(ft, "drain", Drain);
NODE_SET_PROTOTYPE_METHOD(ft, "unlink", UnLink);
NODE_SET_PROTOTYPE_METHOD(ft, "get", Get);
NODE_SET_PROTOTYPE_METHOD(ft, "type", Type);
NODE_SET_PROTOTYPE_METHOD(ft, "sync", Sync);
NODE_SET_PROTOTYPE_METHOD(ft, "expire", Expire);
NODE_SET_PROTOTYPE_METHOD(ft, "query", Query);
NODE_SET_PROTOTYPE_METHOD(ft, "exists", Exists);
NODE_SET_PROTOTYPE_METHOD(ft, "ns", Ns);
NODE_SET_PROTOTYPE_METHOD(ft, "like", Like);
NODE_SET_PROTOTYPE_METHOD(ft, "open", Open);
NODE_SET_PROTOTYPE_METHOD(ft, "close", Close);
exports->Set(name, ft->GetFunction());
exports->Set(NanNew("version"), NanNew(SDB_VERSION));
exports->Set(NanNew("encode"), NanNew <FunctionTemplate>(Encode)->GetFunction());
exports->Set(NanNew("decode"), NanNew <FunctionTemplate>(Decode)->GetFunction());
exports->Set(NanNew("typeof"), NanNew <FunctionTemplate>(TypeOf)->GetFunction());
module->Set("exports", NanNew<FunctionTemplate>(NewDatabase)->GetFunction());
//exports->Set(NanNew("decode"), Decode);
}
NAN_METHOD(Database::New) {
NanScope();
v8::Isolate *isolate = args.GetIsolate();
if (!args.IsConstructCall()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate,
"Database requires new")));
return;
}
Database *wrapper;
int len = args.Length();
if (len == 1) {
if (!args[0]->IsString()) {
NanThrowTypeError ("First argument must be a string");
}
NanUtf8String k (args[0]);
wrapper = new Database(*k);
} else {
wrapper = new Database();
}
if (wrapper->obj == NULL) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate,
"sdb_new0 returns null")));
return;
}
Local<v8::Object> obj = args.This();
wrapper->Wrap(obj);
NanReturnValue(obj);
}
static void Init(Handle<Object> exports, Handle<Value> module) {
Database::Init(exports, module);
}
NAN_METHOD(NewDatabase) {
eprintf ("NEW DATABASE\n");
Local<v8::Object> obj();
NanReturnValue(obj);
}
NODE_MODULE_CONTEXT_AWARE(sdb, Init)
//NODE_MODULE(sdb, Init)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment