static mrb_value mrb_value_to_string(mrb_state* mrb, mrb_value value) { mrb_value str; ARENA_SAVE; switch (mrb_type(value)) { case MRB_TT_FIXNUM: case MRB_TT_FLOAT: case MRB_TT_TRUE: case MRB_TT_FALSE: case MRB_TT_UNDEF: str = mrb_funcall(mrb, value, "to_s", 0, NULL); break; case MRB_TT_STRING: str = mrb_funcall(mrb, value, "inspect", 0, NULL); break; case MRB_TT_HASH: { str = mrb_str_new_cstr(mrb, "{"); mrb_value keys = mrb_hash_keys(mrb, value); int n, l = RARRAY_LEN(keys); for (n = 0; n < l; n++) { mrb_value key = mrb_ary_entry(keys, n); mrb_value enckey = mrb_funcall(mrb, key, "to_s", 0, NULL); enckey = mrb_funcall(mrb, enckey, "inspect", 0, NULL); mrb_str_concat(mrb, str, enckey); mrb_str_cat2(mrb, str, ":"); mrb_value obj = mrb_hash_get(mrb, value, key); mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj)); if (n != l - 1) { mrb_str_cat2(mrb, str, ","); } ARENA_RESTORE; } mrb_str_cat2(mrb, str, "}"); break; } case MRB_TT_ARRAY: { mrb_value str = mrb_str_new_cstr(mrb, "["); int n, l = RARRAY_LEN(value); for (n = 0; n < l; n++) { mrb_value obj = mrb_ary_entry(value, n); mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj)); if (n != l - 1) { mrb_str_cat2(mrb, str, ","); } ARENA_RESTORE; } mrb_str_cat2(mrb, str, "]"); break; } default: mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } ARENA_RESTORE; return str; }
static mrb_value mrb_json_stringify(mrb_state *mrb, mrb_value self) { mrb_value obj; mrb_get_args(mrb, "o", &obj); return mrb_value_to_string(mrb, obj); }
static mrb_value mrb_json_stringify(mrb_state *mrb, mrb_value self) { int argc; mrb_value* argv = NULL; if (mrb_get_args(mrb, "*", &argv, &argc) != 1) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } return mrb_value_to_string(mrb, argv[0]); }
/********************************************************* * main *********************************************************/ static mrb_value mrb_value_to_string(mrb_state* mrb, mrb_value value) { mrb_value str; if (mrb_nil_p(value)) { return mrb_str_new_cstr(mrb, "null"); } switch (mrb_type(value)) { case MRB_TT_FIXNUM: case MRB_TT_FLOAT: case MRB_TT_TRUE: case MRB_TT_FALSE: case MRB_TT_UNDEF: str = mrb_funcall(mrb, value, "to_s", 0, NULL); break; case MRB_TT_SYMBOL: value = mrb_funcall(mrb, value, "to_s", 0, NULL); /* FALLTHROUGH */ case MRB_TT_STRING: { int ai = mrb_gc_arena_save(mrb); char* ptr = RSTRING_PTR(value); char* end = RSTRING_END(value); str = mrb_str_new_cstr(mrb, "\""); while (ptr < end && *ptr) { switch (*ptr) { case '\\': str = mrb_str_cat_cstr(mrb, str, "\\\\"); break; case '"': str = mrb_str_cat_cstr(mrb, str, "\\\""); break; case '\b': str = mrb_str_cat_cstr(mrb, str, "\\b"); break; case '\f': str = mrb_str_cat_cstr(mrb, str, "\\f"); break; case '\n': str = mrb_str_cat_cstr(mrb, str, "\\n"); break; case '\r': str = mrb_str_cat_cstr(mrb, str, "\\r"); break; case '\t': str = mrb_str_cat_cstr(mrb, str, "\\t"); break; default: // TODO: handle unicode str = mrb_str_cat(mrb, str, ptr, 1); } ptr++; } mrb_str_cat_cstr(mrb, str, "\""); mrb_gc_arena_restore(mrb, ai); } break; case MRB_TT_HASH: { mrb_value keys; int n, l; str = mrb_str_new_cstr(mrb, "{"); keys = mrb_hash_keys(mrb, value); l = RARRAY_LEN(keys); for (n = 0; n < l; n++) { mrb_value obj; int ai = mrb_gc_arena_save(mrb); mrb_value key = mrb_ary_entry(keys, n); mrb_value enckey = mrb_funcall(mrb, key, "to_s", 0, NULL); enckey = mrb_funcall(mrb, enckey, "inspect", 0, NULL); mrb_str_concat(mrb, str, enckey); mrb_str_cat_cstr(mrb, str, ":"); obj = mrb_hash_get(mrb, value, key); mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj)); if (n != l - 1) { mrb_str_cat_cstr(mrb, str, ","); } mrb_gc_arena_restore(mrb, ai); } mrb_str_cat_cstr(mrb, str, "}"); break; } case MRB_TT_ARRAY: { int n, l; str = mrb_str_new_cstr(mrb, "["); l = RARRAY_LEN(value); for (n = 0; n < l; n++) { int ai = mrb_gc_arena_save(mrb); mrb_value obj = mrb_ary_entry(value, n); mrb_str_concat(mrb, str, mrb_value_to_string(mrb, obj)); if (n != l - 1) { mrb_str_cat_cstr(mrb, str, ","); } mrb_gc_arena_restore(mrb, ai); } mrb_str_cat_cstr(mrb, str, "]"); break; } default: mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } return str; }