#include "hash_ext.h" #include "enumerable.c" static VALUE mJSON; static VALUE cCircularDatastructure; void Init_hash_ext() { mJSON = rb_const_get(rb_cObject, rb_intern("JSON")); rb_cJsonState = rb_const_get(mJSON, rb_intern("State")); cCircularDatastructure = rb_const_get(mJSON, rb_intern("CircularDatastructure")); rb_define_method(rb_cHash, "to_json", (VALUE(*)(ANYARGS)) &to_json, -1); } /** private **/ static VALUE json_transform(self, state, depth) VALUE self, state, depth; { VALUE delim = rb_str_new2(","); VALUE object_nl = Qnil; if(state != Qnil) object_nl = rb_funcall(state, rb_intern("object_nl"), 0); new_line(delim, object_nl); VALUE result = rb_str_new2("{"); new_line(result, object_nl); process_internal_json(self, result, state, depth, delim, object_nl); new_line(result, object_nl); if(rb_json_should_shift(state, object_nl) == Qtrue) json_shift(result, state, depth); rb_str_append(result, rb_str_new2("}")); return result; } static VALUE process_internal_json(self, json, state, depth, delim, object_nl) VALUE self, json, state, depth, delim, object_nl; { // TODO: Use st_foreach for even better performance VALUE key_value_pairs = rb_funcall(self, rb_intern("to_a"), 0); VALUE new_depth = LONG2NUM(NUM2LONG(depth) + 1); VALUE space = rb_funcall(state, rb_intern("space"), 0); VALUE key_value = Qnil; int i; for(i = 0; i < RARRAY(key_value_pairs)->len; i++) { if(i > 0) { rb_str_concat(json, delim); } key_value = rb_ary_entry(key_value_pairs, i); VALUE key = rb_ary_entry(key_value, 0); VALUE value = rb_ary_entry(key_value, 1); if(rb_json_should_shift(state, object_nl) == Qtrue) json_shift(json, state, depth); VALUE key_string = rb_funcall(key, rb_intern("to_s"), 0); rb_str_append(json, rb_to_json(key_string, state, new_depth)); rb_str_cat2(json, ":"); rb_str_append(json, space); rb_str_append(json, rb_to_json(value, state, new_depth)); } }