c encoder for string types

This commit is contained in:
Mike Dirolf 2009-03-04 10:05:50 -05:00
parent bdec973ff4
commit 064ddacd5e
2 changed files with 51 additions and 3 deletions

View File

@ -1,4 +1,5 @@
#include "ruby.h" #include "ruby.h"
#include "st.h"
#include <assert.h> #include <assert.h>
#define INITIAL_BUFFER_SIZE 256 #define INITIAL_BUFFER_SIZE 256
@ -9,6 +10,8 @@ typedef struct {
int position; int position;
} bson_buffer; } bson_buffer;
static char zero = 0;
static bson_buffer* buffer_new(void) { static bson_buffer* buffer_new(void) {
bson_buffer* buffer; bson_buffer* buffer;
buffer = (bson_buffer*)malloc(sizeof(bson_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; 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) { static VALUE method_serialize(VALUE self, VALUE doc) {
char data[5] = {0x05, 0x00, 0x00, 0x00, 0x00}; bson_buffer* buffer = buffer_new();
return rb_str_new(data, 5); assert(buffer);
write_doc(buffer, doc);
VALUE result = rb_str_new(buffer->buffer, buffer->position);
buffer_free(buffer);
return result;
} }
void Init_cbson() { void Init_cbson() {

View File

@ -255,7 +255,10 @@ class BSON
def deserialize_string_data(buf) def deserialize_string_data(buf)
len = buf.get_int len = buf.get_int
bytes = buf.get(len) 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' if RUBY_VERSION >= '1.9'
str.force_encoding("utf-8") str.force_encoding("utf-8")
end end