towards c decoder

This commit is contained in:
Mike Dirolf 2009-03-10 10:23:42 -04:00
parent 66cb1d492c
commit d0d043323f
2 changed files with 142 additions and 64 deletions

View File

@ -353,7 +353,72 @@ static VALUE method_serialize(VALUE self, VALUE doc) {
return result;
}
static VALUE get_value(const char* buffer, int* position, int type) {
VALUE value;
switch (type) {
case 1:
{
double d;
memcpy(&d, buffer + *position, 8);
value = DBL2NUM(d);
*position += 8;
break;
}
case 2:
{
*position += 4;
int value_length = strlen(buffer + *position);
value = rb_str_new(buffer+ *position, value_length);
*position += value_length + 1;
break;
}
case 8:
{
value = buffer[(*position)++] ? Qtrue : Qfalse;
break;
}
case 16:
{
int i;
memcpy(&i, buffer + *position, 4);
value = INT2FIX(i);
*position += 4;
break;
}
default:
rb_raise(rb_eTypeError, "no c decoder for this type yet (%d)", type);
break;
}
return value;
}
static VALUE elements_to_hash(const char* buffer, int max) {
VALUE hash = rb_hash_new();
int position = 0;
while (position < max) {
int type = (int)buffer[position++];
int name_length = strlen(buffer + position);
VALUE name = rb_str_new(buffer + position, name_length);
position += name_length + 1;
VALUE value = get_value(buffer, &position, type);
rb_hash_aset(hash, name, value);
}
return hash;
}
static VALUE method_deserialize(VALUE self, VALUE bson) {
const char* buffer = RSTRING(bson)->ptr;
int remaining = RSTRING(bson)->len;
// NOTE we just swallow the size and end byte here
buffer += 4;
remaining -= 5;
return elements_to_hash(buffer, remaining);
}
void Init_cbson() {
VALUE CBson = rb_define_module("CBson");
rb_define_module_function(CBson, "serialize", method_serialize, 1);
rb_define_module_function(CBson, "deserialize", method_deserialize, 1);
}

View File

@ -131,73 +131,86 @@ class BSON
end
end
def deserialize(buf=nil, parent=nil)
# If buf is nil, use @buf, assumed to contain already-serialized BSON.
# This is only true during testing.
if buf.is_a? String
@buf = ByteBuffer.new(buf) if buf
else
@buf = ByteBuffer.new(buf.to_a) if buf
end
@buf.rewind
@buf.get_int # eat message size
doc = OrderedHash.new
while @buf.more?
type = @buf.get
case type
when STRING, CODE
key = deserialize_cstr(@buf)
doc[key] = deserialize_string_data(@buf)
when SYMBOL
key = deserialize_cstr(@buf)
doc[key] = deserialize_string_data(@buf).intern
when NUMBER
key = deserialize_cstr(@buf)
doc[key] = deserialize_number_data(@buf)
when NUMBER_INT
key = deserialize_cstr(@buf)
doc[key] = deserialize_number_int_data(@buf)
when OID
key = deserialize_cstr(@buf)
doc[key] = deserialize_oid_data(@buf)
when ARRAY
key = deserialize_cstr(@buf)
doc[key] = deserialize_array_data(@buf, doc)
when REGEX
key = deserialize_cstr(@buf)
doc[key] = deserialize_regex_data(@buf)
when OBJECT
key = deserialize_cstr(@buf)
doc[key] = deserialize_object_data(@buf, doc)
when BOOLEAN
key = deserialize_cstr(@buf)
doc[key] = deserialize_boolean_data(@buf)
when DATE
key = deserialize_cstr(@buf)
doc[key] = deserialize_date_data(@buf)
when NULL
key = deserialize_cstr(@buf)
doc[key] = nil
when UNDEFINED
key = deserialize_cstr(@buf)
doc[key] = Undefined.new
when REF
key = deserialize_cstr(@buf)
doc[key] = deserialize_dbref_data(@buf, key, parent)
when BINARY
key = deserialize_cstr(@buf)
doc[key] = deserialize_binary_data(@buf)
when CODE_W_SCOPE
# TODO CODE_W_SCOPE unimplemented; may be removed
raise "unimplemented type #{type}"
when EOO
break
begin
require 'mongo/ext/cbson'
def deserialize(buf=nil, parent=nil)
if buf.is_a? String
@buf = ByteBuffer.new(buf) if buf
else
raise "Unknown type #{type}, key = #{key}"
@buf = ByteBuffer.new(buf.to_a) if buf
end
@buf.rewind
CBson.deserialize(@buf.to_s)
end
rescue LoadError
def deserialize(buf=nil, parent=nil)
# If buf is nil, use @buf, assumed to contain already-serialized BSON.
# This is only true during testing.
if buf.is_a? String
@buf = ByteBuffer.new(buf) if buf
else
@buf = ByteBuffer.new(buf.to_a) if buf
end
@buf.rewind
@buf.get_int # eat message size
doc = OrderedHash.new
while @buf.more?
type = @buf.get
case type
when STRING, CODE
key = deserialize_cstr(@buf)
doc[key] = deserialize_string_data(@buf)
when SYMBOL
key = deserialize_cstr(@buf)
doc[key] = deserialize_string_data(@buf).intern
when NUMBER
key = deserialize_cstr(@buf)
doc[key] = deserialize_number_data(@buf)
when NUMBER_INT
key = deserialize_cstr(@buf)
doc[key] = deserialize_number_int_data(@buf)
when OID
key = deserialize_cstr(@buf)
doc[key] = deserialize_oid_data(@buf)
when ARRAY
key = deserialize_cstr(@buf)
doc[key] = deserialize_array_data(@buf, doc)
when REGEX
key = deserialize_cstr(@buf)
doc[key] = deserialize_regex_data(@buf)
when OBJECT
key = deserialize_cstr(@buf)
doc[key] = deserialize_object_data(@buf, doc)
when BOOLEAN
key = deserialize_cstr(@buf)
doc[key] = deserialize_boolean_data(@buf)
when DATE
key = deserialize_cstr(@buf)
doc[key] = deserialize_date_data(@buf)
when NULL
key = deserialize_cstr(@buf)
doc[key] = nil
when UNDEFINED
key = deserialize_cstr(@buf)
doc[key] = Undefined.new
when REF
key = deserialize_cstr(@buf)
doc[key] = deserialize_dbref_data(@buf, key, parent)
when BINARY
key = deserialize_cstr(@buf)
doc[key] = deserialize_binary_data(@buf)
when CODE_W_SCOPE
# TODO CODE_W_SCOPE unimplemented; may be removed
raise "unimplemented type #{type}"
when EOO
break
else
raise "Unknown type #{type}, key = #{key}"
end
end
@buf.rewind
doc
end
@buf.rewind
doc
end
# For debugging.