From fa2017633ba7b7c69849d79de3e50dfb902aa8c8 Mon Sep 17 00:00:00 2001 From: Fedor Yudanov Date: Mon, 25 Mar 2013 20:39:29 +0700 Subject: [PATCH] #50 - first test on ruby object saving --- rbejdb/src/rbbson.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ rbejdb/src/rbbson.h | 25 ++++++++++++++++++++ rbejdb/src/rbejdb.c | 44 ++++++++++++++++++++++++++++++++++- rbejdb/test/t1.rb | 12 +++++++++- 4 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 rbejdb/src/rbbson.c create mode 100644 rbejdb/src/rbbson.h diff --git a/rbejdb/src/rbbson.c b/rbejdb/src/rbbson.c new file mode 100644 index 0000000..15ce573 --- /dev/null +++ b/rbejdb/src/rbbson.c @@ -0,0 +1,66 @@ +#include "rbbson.h" + +#include +#include +#include +#include + +#define BSON_RUBY_CLASS "BSON" + +typedef struct { + VALUE obj; + bson* bsonval; +} RBBSON; + +void iterate_attrs_callback(VALUE key, VALUE bsonWrap) { + Check_Type(key, T_STRING); + char* attrName = StringValuePtr(key); + + RBBSON* rbbson; + Data_Get_Struct(bsonWrap, RBBSON, rbbson); + bson* b = rbbson->bsonval; + VALUE val = rb_funcall(rbbson->obj, rb_intern("instance_variable_get"), 1, key); + + bson* subbson; + + switch (TYPE(val)) { + case T_OBJECT: + ruby_to_bson(val, &subbson); + bson_append_bson(b, attrName, subbson); + break; + case T_STRING: + bson_append_string(b, attrName, StringValuePtr(val)); + break; + case T_FIXNUM: + bson_append_int(b, attrName, FIX2INT(val)); + break; + case T_TRUE: + bson_append_bool(b, attrName, 1); + break; + case T_FALSE: + bson_append_bool(b, attrName, 0); + break; + } +} + +void ruby_to_bson(VALUE rbobj, bson** bsonresp) { + Check_Type(rbobj, T_OBJECT); + + VALUE bsonWrapClass = rb_define_class(BSON_RUBY_CLASS, rb_cObject); + VALUE bsonWrap = Data_Wrap_Struct(bsonWrapClass, NULL, NULL, ruby_xmalloc(sizeof(RBBSON))); + + RBBSON* rbbson; + Data_Get_Struct(bsonWrap, RBBSON, rbbson); + rbbson->obj = rbobj; + rbbson->bsonval = bson_create(); + bson_init(rbbson->bsonval); + + VALUE attrs = rb_funcall(rbobj, rb_intern("instance_variables"), 0); + Check_Type(attrs, T_ARRAY); + + rb_iterate(rb_each, attrs, iterate_attrs_callback, bsonWrap); + + bson_finish(rbbson->bsonval); + + *bsonresp = rbbson->bsonval; +} \ No newline at end of file diff --git a/rbejdb/src/rbbson.h b/rbejdb/src/rbbson.h new file mode 100644 index 0000000..172715d --- /dev/null +++ b/rbejdb/src/rbbson.h @@ -0,0 +1,25 @@ +/* + * File: rbbson.h + * Author: yudanov + * + * Created on March 25, 2013, 2:31 PM + */ + +#ifndef RBBSON_H +#define RBBSON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + void ruby_to_bson(VALUE rbobj, bson** bsonbuf); + +#ifdef __cplusplus +} +#endif + +#endif /* RBBSON_H */ + diff --git a/rbejdb/src/rbejdb.c b/rbejdb/src/rbejdb.c index b77fffe..903e5f6 100644 --- a/rbejdb/src/rbejdb.c +++ b/rbejdb/src/rbejdb.c @@ -17,12 +17,21 @@ #include #include +#include "rbbson.h" + #define DEFAULT_OPEN_MODE (JBOWRITER | JBOCREAT | JBOTSYNC) typedef struct { EJDB* ejdb; } RBEJDB; +static int set_ejdb_error(EJDB *ejdb) { + int ecode = ejdbecode(ejdb); + const char *emsg = ejdberrmsg(ecode); + rb_raise(rb_eRuntimeError, emsg); +} + + EJDB* getEJDB(VALUE self) { RBEJDB* rejdb; Data_Get_Struct(self, RBEJDB, rejdb); @@ -55,7 +64,7 @@ VALUE EJDB_open(VALUE self, VALUE path, VALUE mode) { Check_Type(mode, T_FIXNUM); EJDB* ejdb = getEJDB(self); if (!ejdbopen(ejdb, StringValuePtr(path), FIX2INT(mode))) { - return set_ejdb_error(ejdb); + set_ejdb_error(ejdb); } return Qnil; } @@ -65,6 +74,38 @@ VALUE EJDB_is_open(VALUE self) { return ejdb && ejdbisopen(ejdb) ? Qtrue : Qfalse; } +VALUE EJDB_save(int argc, VALUE *argv, VALUE self) { + if (argc < 1) { + rb_raise(rb_eRuntimeError, "Error calling EJDB.save(): need to specify collection name"); + } + + EJDB* ejdb = getEJDB(self); + + VALUE collName = argv[0]; + Check_Type(collName, T_STRING); + EJCOLL *coll = ejdbcreatecoll(ejdb, StringValuePtr(collName), NULL); + if (!coll) { + set_ejdb_error(ejdb); + } + + int i; + for (i = 1; i < argc; i++) { + Check_Type(argv[i], T_OBJECT); + + bson* bsonval; + ruby_to_bson(argv[i], &bsonval); + bson_print(stdout, bsonval); + + bson_oid_t oid; + if (!ejdbsavebson2(coll, bsonval, &oid, true /*TODO read this param*/)) { + bson_destroy(bsonval); + set_ejdb_error(ejdb); + } + + bson_destroy(bsonval); + } + return Qnil; +} Init_rbejdb() { VALUE ejdbClass = rb_define_class("EJDB", rb_cObject); @@ -75,4 +116,5 @@ Init_rbejdb() { rb_define_method(ejdbClass, "open", RUBY_METHOD_FUNC(EJDB_open), 2); rb_define_method(ejdbClass, "is_open?", RUBY_METHOD_FUNC(EJDB_is_open), 0); + rb_define_method(ejdbClass, "save", RUBY_METHOD_FUNC(EJDB_save), -1); } \ No newline at end of file diff --git a/rbejdb/test/t1.rb b/rbejdb/test/t1.rb index b2260af..34082e7 100644 --- a/rbejdb/test/t1.rb +++ b/rbejdb/test/t1.rb @@ -5,4 +5,14 @@ ejdb.open("zoo", EJDB::DEFAULT_OPEN_MODE) raise "Failed to open ejdb" unless ejdb.is_open? -puts "CONGRATULATIONS!!! EJDB tests has passed completely!" \ No newline at end of file +class Parrot + def initialize(name, size) + @name = name + @size = size + end +end + +parrot1 = Parrot.new("Cacadoo", 12) +ejdb.save("parrots", parrot1) + +puts "CONGRATULATIONS!!! EJDB tests has passed completely!" -- 2.7.4