c encoder for string types
This commit is contained in:
parent
bdec973ff4
commit
064ddacd5e
|
@ -1,4 +1,5 @@
|
|||
#include "ruby.h"
|
||||
#include "st.h"
|
||||
#include <assert.h>
|
||||
|
||||
#define INITIAL_BUFFER_SIZE 256
|
||||
|
@ -9,6 +10,8 @@ typedef struct {
|
|||
int position;
|
||||
} bson_buffer;
|
||||
|
||||
static char zero = 0;
|
||||
|
||||
static bson_buffer* buffer_new(void) {
|
||||
bson_buffer* buffer;
|
||||
buffer = (bson_buffer*)malloc(sizeof(bson_buffer));
|
||||
|
@ -65,9 +68,51 @@ static void buffer_write_bytes(bson_buffer* buffer, const char* bytes, int size)
|
|||
buffer->position += size;
|
||||
}
|
||||
|
||||
static void write_name_and_type(bson_buffer* buffer, VALUE name, char type) {
|
||||
buffer_write_bytes(buffer, &type, 1);
|
||||
buffer_write_bytes(buffer, RSTRING(name)->ptr, RSTRING(name)->len);
|
||||
buffer_write_bytes(buffer, &zero, 1);
|
||||
}
|
||||
|
||||
static int write_element(VALUE key, VALUE value, VALUE extra) {
|
||||
bson_buffer* buffer = (bson_buffer*)extra;
|
||||
|
||||
switch(TYPE(value)) {
|
||||
case T_STRING:
|
||||
write_name_and_type(buffer, key, 0x02);
|
||||
int length = RSTRING(value)->len + 1;
|
||||
buffer_write_bytes(buffer, (char*)&length, 4);
|
||||
buffer_write_bytes(buffer, RSTRING(value)->ptr, length - 1);
|
||||
buffer_write_bytes(buffer, &zero, 1);
|
||||
break;
|
||||
default:
|
||||
rb_raise(rb_eTypeError, "no c encoder for this type yet");
|
||||
break;
|
||||
}
|
||||
return ST_CONTINUE;
|
||||
}
|
||||
|
||||
static void write_doc(bson_buffer* buffer, VALUE hash) {
|
||||
int start_position = buffer->position;
|
||||
int length_location = buffer_save_bytes(buffer, 4);
|
||||
|
||||
rb_hash_foreach(hash, write_element, (VALUE)buffer);
|
||||
|
||||
// write null byte and fill in length
|
||||
buffer_write_bytes(buffer, &zero, 1);
|
||||
int length = buffer->position - start_position;
|
||||
memcpy(buffer->buffer + length_location, &length, 4);
|
||||
}
|
||||
|
||||
static VALUE method_serialize(VALUE self, VALUE doc) {
|
||||
char data[5] = {0x05, 0x00, 0x00, 0x00, 0x00};
|
||||
return rb_str_new(data, 5);
|
||||
bson_buffer* buffer = buffer_new();
|
||||
assert(buffer);
|
||||
|
||||
write_doc(buffer, doc);
|
||||
|
||||
VALUE result = rb_str_new(buffer->buffer, buffer->position);
|
||||
buffer_free(buffer);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Init_cbson() {
|
||||
|
|
|
@ -255,7 +255,10 @@ class BSON
|
|||
def deserialize_string_data(buf)
|
||||
len = buf.get_int
|
||||
bytes = buf.get(len)
|
||||
str = bytes[0..-2].pack("C*")
|
||||
str = bytes[0..-2]
|
||||
if str.respond_to? "pack"
|
||||
str = str.pack("C*")
|
||||
end
|
||||
if RUBY_VERSION >= '1.9'
|
||||
str.force_encoding("utf-8")
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue