@@ -14,7 +14,6 @@ class RubyObjectEncoder {
1414 Writer<StringBuffer> writer;
1515
1616 void test () {
17- writer.StartObject ();
1817 writer.Key (" hello" );
1918 writer.String (" world" );
2019 writer.Key (" t" );
@@ -35,22 +34,105 @@ class RubyObjectEncoder {
3534 writer.EndObject ();
3635 }
3736
37+ void encode_array (VALUE ary) {
38+ writer.StartArray ();
39+ int length = RARRAY_LEN (ary);
40+ RARRAY_PTR_USE (ary, ptr, {
41+ for (int i = 0 ; i < length; i++) {
42+ encode_any (ptr[i]);
43+ }
44+ });
45+ writer.EndArray ();
46+ }
47+
48+ void encode_key (VALUE key) {
49+ switch (rb_type (key)) {
50+ case T_STRING:
51+ writer.Key (RSTRING_PTR (key), RSTRING_LEN (key));
52+ return ;
53+ default :
54+ raise_unknown (key);
55+ }
56+ }
57+
58+ static int encode_hash_i_cb (VALUE key, VALUE val, VALUE ctx) {
59+ RubyObjectEncoder *encoder = (RubyObjectEncoder *)ctx;
60+ encoder->encode_hash_i (key, val);
61+ return ST_CONTINUE;
62+ }
63+
64+ void encode_hash_i (VALUE key, VALUE val) {
65+ encode_key (key);
66+ encode_any (val);
67+ }
68+
69+ void encode_hash (VALUE hash) {
70+ writer.StartObject ();
71+ rb_hash_foreach (hash, encode_hash_i_cb, (VALUE)this );
72+ writer.EndObject ();
73+ }
74+
75+ void encode_fixnum (VALUE v) {
76+ writer.Int (RB_FIX2INT (v));
77+ }
78+
79+ void encode_float (VALUE v) {
80+ double f = rb_float_value (v);
81+ writer.Double (f);
82+ }
83+
84+ void encode_string (VALUE v) {
85+ // fixme: copy boolean?
86+ writer.String (RSTRING_PTR (v), RSTRING_LEN (v));
87+ }
88+
89+ void encode_any (VALUE v) {
90+ switch (rb_type (v)) {
91+ case T_NIL:
92+ writer.Null ();
93+ return ;
94+ case T_FALSE:
95+ writer.Bool (false );
96+ return ;
97+ case T_TRUE:
98+ writer.Bool (true );
99+ return ;
100+ case T_FIXNUM:
101+ return encode_fixnum (v);
102+ case T_FLOAT:
103+ return encode_float (v);
104+ case T_HASH:
105+ return encode_hash (v);
106+ case T_ARRAY:
107+ return encode_array (v);
108+ case T_STRING:
109+ return encode_string (v);
110+ default :
111+ raise_unknown (v);
112+ }
113+ }
114+
115+ void raise_unknown (VALUE obj) {
116+ VALUE inspect = rb_inspect (obj);
117+ rb_raise (rb_eRuntimeError, " can't encode type: %s" , StringValueCStr (inspect));
118+ }
119+
38120 public:
39121 RubyObjectEncoder (): depth(0 ), buf(), writer(buf) {
40122 };
41123
42124 int depth;
43125
44- VALUE encode () {
45- test ( );
126+ VALUE encode (VALUE obj ) {
127+ encode_any (obj );
46128 VALUE ruby_string = rb_str_new (buf.GetString (), buf.GetSize ());
47129 return ruby_string;
48130 }
49131};
50132
51133VALUE encode (VALUE _self, VALUE obj) {
52134 RubyObjectEncoder encoder;
53- return encoder.encode ();
135+ return encoder.encode (obj );
54136}
55137
56138extern " C" void
0 commit comments