c encoder for string types
This commit is contained in:
parent
bdec973ff4
commit
064ddacd5e
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue