Skip to content

Commit

Permalink
More work on the native serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
dima committed Jun 3, 2010
1 parent 7bbb0ce commit 45da081
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 10 deletions.
118 changes: 111 additions & 7 deletions ext/restfulx/ext/amf/serializer/serializer.c
Expand Up @@ -38,7 +38,11 @@ static VALUE t_object_cache(VALUE self);
static VALUE t_string_cache(VALUE self);
static VALUE t_to_s(VALUE self);
static VALUE t_serialize_property(VALUE self, VALUE prop);
static VALUE t_write_reference(VALUE self, VALUE index);
static VALUE t_write_utf8_vr(VALUE self, VALUE prop);
static VALUE t_write_hash(VALUE self, VALUE prop);
static VALUE t_foobar(VALUE self);
static VALUE t_pack_integer(VALUE self, VALUE val);

void Init_serializer() {
rb_mRestfulX = rb_define_module("RestfulX");
Expand All @@ -52,15 +56,33 @@ void Init_serializer() {
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "string_cache", t_string_cache, 0);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "to_s", t_to_s, 0);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "serialize_property", t_serialize_property, 1);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "write_reference", t_write_reference, 1);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "write_utf8_vr", t_write_utf8_vr, 1);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "write_hash", t_write_hash, 1);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "pack_integer", t_pack_integer, 1);
rb_define_method(rb_cRestfulX_AMF_Ext_AMF3Serializer, "foobar", t_foobar, 0);
}

static inline VALUE t_write_hash_attrs(VALUE pair, VALUE self) {
VALUE key = rb_ary_entry(pair, 0);
VALUE value = rb_ary_entry(pair, 1);

t_write_utf8_vr(self, rb_funcall3(key, rb_intern("to_s"), 0, 0));
t_serialize_property(self, value);

return Qnil;
}

static VALUE t_init(VALUE self) {
rb_iv_set(self, "@stream", rb_str_new2(""));
rb_iv_set(self, "@object_cache", rb_funcall3(rb_const_get(rb_mRestfulX_AMF, rb_intern("SerializerCache")), rb_intern("new"), 0, 0));
rb_iv_set(self, "@string_cache", rb_funcall3(rb_const_get(rb_mRestfulX_AMF, rb_intern("SerializerCache")), rb_intern("new"), 0, 0));
}

static VALUE t_pack_integer(VALUE self, VALUE val) {
return rb_pack_c_integer(NUM2INT(val));
}

static VALUE t_stream(VALUE self) {
return rb_iv_get(self, "@stream");
}
Expand All @@ -84,27 +106,109 @@ static VALUE t_to_s(VALUE self) {
static VALUE t_serialize_property(VALUE self, VALUE prop) {
VALUE stream = rb_iv_get(self, "@stream");
char type;

if (TYPE(prop) == T_NIL) {
if (BUILTIN_TYPE(prop) == T_NIL) {
type = AMF3_NULL_MARKER;
stream = rb_str_cat(stream, &type, 1);
} else if (TYPE(prop) == T_TRUE) {
} else if (BUILTIN_TYPE(prop) == T_TRUE) {
type = AMF3_TRUE_MARKER;
stream = rb_str_cat(stream, &type, 1);
} else if (TYPE(prop) == T_FALSE) {
} else if (BUILTIN_TYPE(prop) == T_FALSE) {
type = AMF3_FALSE_MARKER;
stream = rb_str_cat(stream, &type, 1);
} else if (TYPE(prop) == T_FLOAT) {
} else if (BUILTIN_TYPE(prop) == T_FLOAT) {
type = AMF3_DOUBLE_MARKER;
stream = rb_str_cat(stream, &type, 1);
stream = rb_str_append(stream, rb_pack_c_double(NUM2DOUBLE(prop)));
} else if (TYPE(prop) == T_FIXNUM) {
} else if (BUILTIN_TYPE(prop) == T_FIXNUM) {
type = AMF3_INTEGER_MARKER;
stream = rb_str_cat(stream, &type, 1);
stream = rb_str_append(stream, rb_pack_c_integer(NUM2INT(prop)));
} else if (BUILTIN_TYPE(prop) == T_STRING || BUILTIN_TYPE(prop) == T_SYMBOL) {
type = AMF3_STRING_MARKER;
stream = rb_str_cat(stream, &type, 1);
t_write_utf8_vr(self, rb_funcall3(prop, rb_intern("to_s"), 0, 0));
} else if (BUILTIN_TYPE(prop) == T_HASH) {
t_write_hash(self, prop);
}

return self;
}

static VALUE t_write_reference(VALUE self, VALUE index) {
VALUE stream = rb_iv_get(self, "@stream");
char header = NUM2INT(index) << 1;

stream = rb_str_cat(stream, &header, 1);

return self;
}

static VALUE t_write_hash(VALUE self, VALUE prop) {
char object_type = AMF3_OBJECT_MARKER;
char dyn_object_type = AMF3_DYNAMIC_OBJECT;
char anon_object_type = AMF3_ANONYMOUS_OBJECT;
char close_dynobject_type = AMF3_CLOSE_DYNAMIC_OBJECT;

VALUE stream = rb_iv_get(self, "@stream");
VALUE object_cache = rb_iv_get(self, "@object_cache");
VALUE object_key;
VALUE *pargs;
VALUE args[2];

args[0] = prop;
args[1] = Qnil;

pargs = args;

stream = rb_str_cat(stream, &object_type, 1);
object_key = rb_funcall3(object_cache, rb_intern("fetch"), 2, pargs);
if (object_key != Qnil) {
t_write_reference(self, object_key);
} else {
rb_funcall3(object_cache, rb_intern("cache"), 1, &prop);
stream = rb_str_cat(stream, &dyn_object_type, 1);
stream = rb_str_cat(stream, &anon_object_type, 1);

rb_iterate(rb_each, prop, t_write_hash_attrs, self);

stream = rb_str_cat(stream, &close_dynobject_type, 1);
}

return stream;
return Qnil;
}

static VALUE t_write_utf8_vr(VALUE self, VALUE prop) {
size_t length;
int header;
char empty_string = AMF3_EMPTY_STRING;
char *value = rb_str2cstr(prop, &length);
VALUE stream = rb_iv_get(self, "@stream");
VALUE string_cache = rb_iv_get(self, "@string_cache");
VALUE string_key;
VALUE *pargs;
VALUE args[2];

args[0] = prop;
args[1] = Qnil;
pargs = args;

if (length == 0) {
stream = rb_str_cat(stream, &empty_string, 1);
} else {
string_key = rb_funcall3(string_cache, rb_intern("fetch"), 2, pargs);
if (string_key != Qnil) {
t_write_reference(self, string_key);
} else {
rb_funcall3(string_cache, rb_intern("cache"), 1, &prop);
header = (unsigned int)length << 1;
header = header | 1;
stream = rb_str_append(stream, rb_pack_c_integer(header));
stream = rb_str_append(stream, prop);
}
}

return Qnil;
}

static VALUE t_foobar(VALUE self) {
Expand Down
8 changes: 5 additions & 3 deletions lib/restfulx/amf/pure/serializer.rb
Expand Up @@ -113,9 +113,9 @@ def write_hash(hash, &block)
# Always serialize things as dynamic objects
@stream << AMF3_DYNAMIC_OBJECT << AMF3_ANONYMOUS_OBJECT

hash.keys.each do |name|
write_utf8_vr(name.to_s.camelize(:lower))
serialize_property(hash[name])
hash.each do |key, value|
write_utf8_vr(key.to_s.camelize(:lower))
serialize_property(value)
end

block.call(self) if block_given?
Expand All @@ -140,6 +140,8 @@ def write_utf8_vr(str)
@stream << pack_integer(header)
@stream << str
end

return nil
end

private
Expand Down

0 comments on commit 45da081

Please sign in to comment.