towards c decoder
This commit is contained in:
parent
66cb1d492c
commit
d0d043323f
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue