diff options
author | Lamont Granquist <lamont@scriptkiddie.org> | 2014-11-22 15:20:17 -0800 |
---|---|---|
committer | Lamont Granquist <lamont@scriptkiddie.org> | 2014-11-22 15:20:17 -0800 |
commit | fd2e17e64d6eded4b96fe09bfe376c401f720682 (patch) | |
tree | 58ce17c6106e2b547e7106bd0099733d6d8c1b07 /ext/ffi_yajl/ext | |
parent | 9ad03a7b89c9fad16f677879da9d91275e997cfb (diff) | |
download | ffi-yajl-fd2e17e64d6eded4b96fe09bfe376c401f720682.tar.gz |
support calling #to_s on all types for keys
compatibility with JSON gem and yajl-ruby
closes #14
Diffstat (limited to 'ext/ffi_yajl/ext')
-rw-r--r-- | ext/ffi_yajl/ext/encoder/encoder.c | 128 |
1 files changed, 100 insertions, 28 deletions
diff --git a/ext/ffi_yajl/ext/encoder/encoder.c b/ext/ffi_yajl/ext/encoder/encoder.c index 90b125b..3c22f8d 100644 --- a/ext/ffi_yajl/ext/encoder/encoder.c +++ b/ext/ffi_yajl/ext/encoder/encoder.c @@ -78,19 +78,30 @@ static VALUE rb_cHash_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - extra = rb_hash_new(); /* FIXME: reduce garbage */ + if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { + ID sym_to_s = rb_intern("to_s"); + VALUE str = rb_funcall(self, sym_to_s, 0); + char *cptr = RSTRING_PTR(str); + int len = RSTRING_LEN(str); + + CHECK_STATUS( + yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) + ); + } else { + extra = rb_hash_new(); /* FIXME: reduce garbage */ - rb_hash_aset(extra, rb_str_new2("yajl_gen"), rb_yajl_gen); + rb_hash_aset(extra, rb_str_new2("yajl_gen"), rb_yajl_gen); - rb_hash_aset(extra, rb_str_new2("state"), state); + rb_hash_aset(extra, rb_str_new2("state"), state); - CHECK_STATUS( - yajl_gen_map_open(yajl_gen) - ); - rb_hash_foreach(self, rb_cHash_ffi_yajl_callback, extra); - CHECK_STATUS( - yajl_gen_map_close(yajl_gen) - ); + CHECK_STATUS( + yajl_gen_map_open(yajl_gen) + ); + rb_hash_foreach(self, rb_cHash_ffi_yajl_callback, extra); + CHECK_STATUS( + yajl_gen_map_close(yajl_gen) + ); + } return Qnil; } @@ -103,16 +114,27 @@ static VALUE rb_cArray_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - CHECK_STATUS( - yajl_gen_array_open(yajl_gen) - ); - for(i=0; i<RARRAY_LEN(self); i++) { - val = rb_ary_entry(self, i); - rb_funcall(val, sym_ffi_yajl, 2, rb_yajl_gen, state); + if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { + ID sym_to_s = rb_intern("to_s"); + VALUE str = rb_funcall(self, sym_to_s, 0); + char *cptr = RSTRING_PTR(str); + int len = RSTRING_LEN(str); + + CHECK_STATUS( + yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) + ); + } else { + CHECK_STATUS( + yajl_gen_array_open(yajl_gen) + ); + for(i=0; i<RARRAY_LEN(self); i++) { + val = rb_ary_entry(self, i); + rb_funcall(val, sym_ffi_yajl, 2, rb_yajl_gen, state); + } + CHECK_STATUS( + yajl_gen_array_close(yajl_gen) + ); } - CHECK_STATUS( - yajl_gen_array_close(yajl_gen) - ); return Qnil; } @@ -121,9 +143,22 @@ static VALUE rb_cNilClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { yajl_gen_status status; struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - CHECK_STATUS( - yajl_gen_null(yajl_gen) - ); + + if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { + ID sym_to_s = rb_intern("to_s"); + VALUE str = rb_funcall(self, sym_to_s, 0); + char *cptr = RSTRING_PTR(str); + int len = RSTRING_LEN(str); + + CHECK_STATUS( + yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) + ); + } else { + CHECK_STATUS( + yajl_gen_null(yajl_gen) + ); + } + return Qnil; } @@ -131,9 +166,22 @@ static VALUE rb_cTrueClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) yajl_gen_status status; struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - CHECK_STATUS( - yajl_gen_bool(yajl_gen, 1) - ); + + if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { + ID sym_to_s = rb_intern("to_s"); + VALUE str = rb_funcall(self, sym_to_s, 0); + char *cptr = RSTRING_PTR(str); + int len = RSTRING_LEN(str); + + CHECK_STATUS( + yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) + ); + } else { + CHECK_STATUS( + yajl_gen_bool(yajl_gen, 1) + ); + } + return Qnil; } @@ -141,9 +189,22 @@ static VALUE rb_cFalseClass_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) yajl_gen_status status; struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); - CHECK_STATUS( - yajl_gen_bool(yajl_gen, 0) - ); + + if ( rb_hash_aref(state, rb_str_new2("processing_key")) == Qtrue ) { + ID sym_to_s = rb_intern("to_s"); + VALUE str = rb_funcall(self, sym_to_s, 0); + char *cptr = RSTRING_PTR(str); + int len = RSTRING_LEN(str); + + CHECK_STATUS( + yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) + ); + } else { + CHECK_STATUS( + yajl_gen_bool(yajl_gen, 0) + ); + } + return Qnil; } @@ -168,6 +229,7 @@ static VALUE rb_cFixnum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { yajl_gen_number(yajl_gen, cptr, len) ); } + return Qnil; } @@ -179,6 +241,7 @@ static VALUE rb_cBignum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { int len = RSTRING_LEN(str); struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); + if (memcmp(cptr, "NaN", 3) == 0 || memcmp(cptr, "Infinity", 8) == 0 || memcmp(cptr, "-Infinity", 9) == 0) { rb_raise(cEncodeError, "'%s' is an invalid number", cptr); } @@ -191,6 +254,7 @@ static VALUE rb_cBignum_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { yajl_gen_number(yajl_gen, cptr, len) ); } + return Qnil; } @@ -202,6 +266,7 @@ static VALUE rb_cFloat_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { int len = RSTRING_LEN(str); struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); + if (memcmp(cptr, "NaN", 3) == 0 || memcmp(cptr, "Infinity", 8) == 0 || memcmp(cptr, "-Infinity", 9) == 0) { rb_raise(cEncodeError, "'%s' is an invalid number", cptr); } @@ -214,6 +279,7 @@ static VALUE rb_cFloat_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { yajl_gen_number(yajl_gen, cptr, len) ); } + return Qnil; } @@ -221,9 +287,11 @@ static VALUE rb_cString_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { yajl_gen_status status; struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); + CHECK_STATUS( yajl_gen_string(yajl_gen, (unsigned char *)RSTRING_PTR(self), RSTRING_LEN(self)) ); + return Qnil; } @@ -236,9 +304,11 @@ static VALUE object_to_s_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { int len = RSTRING_LEN(str); struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); + CHECK_STATUS( yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) ); + return Qnil; } @@ -258,9 +328,11 @@ static VALUE rb_cTime_ffi_yajl(VALUE self, VALUE rb_yajl_gen, VALUE state) { int len = RSTRING_LEN(str); struct yajl_gen_t *yajl_gen; Data_Get_Struct(rb_yajl_gen, struct yajl_gen_t, yajl_gen); + CHECK_STATUS( yajl_gen_string(yajl_gen, (unsigned char *)cptr, len) ); + return Qnil; } |