bool rubyval_to_dictionary(mrb_state* mrb, mrb_value arg, __Dictionary** outValue, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); __Dictionary* dic = __Dictionary::create(); for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); Ref* ref = to_ref_value(mrb, hv); dic->setObject(ref, std::string(kstr)); } else { CCASSERT(false, "not supported key value type"); } } *outValue = dic; return true; }
bool rubyval_to_ccvaluemapintkey(mrb_state* mrb, mrb_value arg, cocos2d::ValueMapIntKey* ret, const char* funcName) { if (! mrb_hash_p(arg)) { return false; } mrb_value key_arr = mrb_hash_keys(mrb, arg); mrb_int len = mrb_ary_len(mrb, key_arr); ValueMapIntKey& dict = *ret; for (mrb_int i = 0; i < len; i++) { mrb_value hk = mrb_ary_ref(mrb, key_arr, i); mrb_value hv = mrb_hash_get(mrb, arg, hk); int int_key = 0; if (mrb_string_p(hk)) { char *kstr = mrb_str_to_cstr(mrb, hk); int_key = atoi(kstr); } else if (mrb_symbol_p(hk)) { mrb_sym sym = mrb_symbol(hk); const char* kstr = mrb_sym2name(mrb, sym); int_key = atoi(kstr); } else { return false; } Value val; if (! rubyval_to_ccvalue(mrb, hv, &val)) { return false; } dict[int_key] = val; } return true; }
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 ERL_NIF_TERM make_hash(ErlNifEnv* env, mrb_state* mrb, mrb_value o) { mrb_value keys = mrb_hash_keys(mrb, o); size_t len = (int) RARRAY(keys)->len; ERL_NIF_TERM list = enif_make_list_from_array(env, NULL, 0); for(int i = len; i>0; --i) { mrb_value k = mrb_ary_ref(mrb, keys, (mrb_int)i - 1); ERL_NIF_TERM key = mruby2erl(env, mrb, k); ERL_NIF_TERM value = mruby2erl(env, mrb, mrb_hash_get(mrb, o, k)); list = enif_make_list_cell(env, enif_make_tuple2(env, key, value), list); } return enif_make_tuple1(env, list); }
std::map<std::string, std::string> MRuby::invert(const std::map<std::string, std::string> &lis) const { std::map<std::string, std::string> res; mrb_value a = mrb_hash_new_capa(mMrb, lis.size()); for (auto it = lis.begin(); it != lis.end(); ++it) { mrb_hash_set(mMrb, a, mrb_str_new_cstr(mMrb, it->first.c_str()), mrb_str_new_cstr(mMrb, it->second.c_str())); } mrb_value r = mrb_funcall(mMrb, mrb_top_self(mMrb), "invert", 1, a); mrb_value keys = mrb_hash_keys(mMrb, r); for (int i = 0; i < RARRAY_LEN(keys); ++i) { mrb_value k = mrb_ary_ref(mMrb, keys, i); mrb_value v = mrb_hash_get(mMrb, r, k); res[mrb_str_to_cstr(mMrb, k)] = mrb_str_to_cstr(mMrb, v); } return res; }
static mrb_value mrb_vedis_append_hash(mrb_state *mrb, mrb_value self) { int ai; vedis *vstore = DATA_PTR(self); mrb_value hash, keys, key, val; mrb_get_args(mrb, "H", &hash); keys = mrb_hash_keys(mrb, hash); ai = mrb_gc_arena_save(mrb); while (!mrb_nil_p(key = mrb_ary_pop(mrb, keys))) { val = mrb_hash_get(mrb, hash, key); mrb_vedis_append_s(mrb, key, val, vstore); mrb_gc_arena_restore(mrb, ai); } return mrb_true_value(); }
void mrb_mruby_wslay_gem_init(mrb_state* mrb) { struct RClass *wslay_mod, *wslay_error_cl, *wslay_event_mod, *wslay_event_context_cl, *wslay_event_context_server_cl, *wslay_event_context_client_cl; wslay_mod = mrb_define_module(mrb, "Wslay"); mrb_define_module_function(mrb, wslay_mod, "get_rsv1", mrb_wslay_get_rsv1, MRB_ARGS_REQ(1)); mrb_define_module_function(mrb, wslay_mod, "get_rsv2", mrb_wslay_get_rsv2, MRB_ARGS_REQ(1)); mrb_define_module_function(mrb, wslay_mod, "get_rsv3", mrb_wslay_get_rsv3, MRB_ARGS_REQ(1)); wslay_error_cl = mrb_define_class_under(mrb, wslay_mod, "Err", E_RUNTIME_ERROR); mrb_value wslay_error_hash = mrb_hash_new_capa(mrb, 9 * 2); mrb_define_const(mrb, wslay_mod, "Error", wslay_error_hash); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_WANT_READ), mrb_symbol_value(mrb_intern_lit(mrb, "want_read"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_WANT_WRITE), mrb_symbol_value(mrb_intern_lit(mrb, "want_write"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_PROTO), mrb_symbol_value(mrb_intern_lit(mrb, "proto"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_INVALID_ARGUMENT), mrb_symbol_value(mrb_intern_lit(mrb, "invalid_argument"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_INVALID_CALLBACK), mrb_symbol_value(mrb_intern_lit(mrb, "invalid_callback"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_NO_MORE_MSG), mrb_symbol_value(mrb_intern_lit(mrb, "no_more_msg"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_CALLBACK_FAILURE), mrb_symbol_value(mrb_intern_lit(mrb, "callback_failure"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_WOULDBLOCK), mrb_symbol_value(mrb_intern_lit(mrb, "wouldblock"))); mrb_hash_set(mrb, wslay_error_hash, mrb_fixnum_value(WSLAY_ERR_NOMEM), mrb_symbol_value(mrb_intern_lit(mrb, "nomem"))); mrb_value wslay_error_hash_keys = mrb_hash_keys(mrb, wslay_error_hash); for (mrb_int i = 0; i < RARRAY_LEN(wslay_error_hash_keys); i++) { mrb_value key = mrb_ary_ref(mrb, wslay_error_hash_keys, i); mrb_hash_set(mrb, wslay_error_hash, mrb_hash_get(mrb, wslay_error_hash, key), key); } mrb_value wslay_status_code_hash = mrb_hash_new_capa(mrb, 12 * 2); mrb_define_const(mrb, wslay_mod, "StatusCode", wslay_status_code_hash); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_NORMAL_CLOSURE), mrb_symbol_value(mrb_intern_lit(mrb, "normal_closure"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_GOING_AWAY), mrb_symbol_value(mrb_intern_lit(mrb, "going_away"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_PROTOCOL_ERROR), mrb_symbol_value(mrb_intern_lit(mrb, "protocol_error"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_UNSUPPORTED_DATA), mrb_symbol_value(mrb_intern_lit(mrb, "unsupported_data"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_NO_STATUS_RCVD), mrb_symbol_value(mrb_intern_lit(mrb, "no_status_rcvd"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_ABNORMAL_CLOSURE), mrb_symbol_value(mrb_intern_lit(mrb, "abnormal_closure"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA), mrb_symbol_value(mrb_intern_lit(mrb, "invalid_frame_payload_data"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_POLICY_VIOLATION), mrb_symbol_value(mrb_intern_lit(mrb, "policy_violation"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_MESSAGE_TOO_BIG), mrb_symbol_value(mrb_intern_lit(mrb, "message_too_big"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_MANDATORY_EXT), mrb_symbol_value(mrb_intern_lit(mrb, "mandatory_ext"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_INTERNAL_SERVER_ERROR), mrb_symbol_value(mrb_intern_lit(mrb, "internal_server_error"))); mrb_hash_set(mrb, wslay_status_code_hash, mrb_fixnum_value(WSLAY_CODE_TLS_HANDSHAKE), mrb_symbol_value(mrb_intern_lit(mrb, "tls_handshake"))); mrb_value wslay_status_code_hash_keys = mrb_hash_keys(mrb, wslay_status_code_hash); for (mrb_int i = 0; i < RARRAY_LEN(wslay_status_code_hash_keys); i++) { mrb_value key = mrb_ary_ref(mrb, wslay_status_code_hash_keys, i); mrb_hash_set(mrb, wslay_status_code_hash, mrb_hash_get(mrb, wslay_status_code_hash, key), key); } mrb_value io_flags_hash = mrb_hash_new_capa(mrb, 2); mrb_define_const(mrb, wslay_mod, "IoFlags", io_flags_hash); mrb_hash_set(mrb, io_flags_hash, mrb_fixnum_value(WSLAY_MSG_MORE), mrb_symbol_value(mrb_intern_lit(mrb, "msg_more"))); mrb_hash_set(mrb, io_flags_hash, mrb_symbol_value(mrb_intern_lit(mrb, "msg_more")), mrb_fixnum_value(WSLAY_MSG_MORE)); mrb_value wslay_opcode_hash = mrb_hash_new_capa(mrb, 6 * 2); mrb_define_const(mrb, wslay_mod, "OpCode", wslay_opcode_hash); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_CONTINUATION_FRAME), mrb_symbol_value(mrb_intern_lit(mrb, "continuation_frame"))); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_TEXT_FRAME), mrb_symbol_value(mrb_intern_lit(mrb, "text_frame"))); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_BINARY_FRAME), mrb_symbol_value(mrb_intern_lit(mrb, "binary_frame"))); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_CONNECTION_CLOSE), mrb_symbol_value(mrb_intern_lit(mrb, "connection_close"))); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_PING), mrb_symbol_value(mrb_intern_lit(mrb, "ping"))); mrb_hash_set(mrb, wslay_opcode_hash, mrb_fixnum_value(WSLAY_PONG), mrb_symbol_value(mrb_intern_lit(mrb, "pong"))); mrb_value wslay_opcode_hash_keys = mrb_hash_keys(mrb, wslay_opcode_hash); for (mrb_int i = 0; i < RARRAY_LEN(wslay_opcode_hash_keys); i++) { mrb_value key = mrb_ary_ref(mrb, wslay_opcode_hash_keys, i); mrb_hash_set(mrb, wslay_opcode_hash, mrb_hash_get(mrb, wslay_opcode_hash, key), key); } wslay_event_mod = mrb_define_module_under(mrb, wslay_mod, "Event"); wslay_event_context_cl = mrb_define_class_under(mrb, wslay_event_mod, "Context", mrb->object_class); MRB_SET_INSTANCE_TT(wslay_event_context_cl, MRB_TT_DATA); mrb_define_method(mrb, wslay_event_context_cl, "no_buffering=", mrb_wslay_event_config_set_no_buffering, MRB_ARGS_REQ(1)); mrb_define_method(mrb, wslay_event_context_cl, "max_recv_msg_length=", mrb_wslay_event_config_set_max_recv_msg_length, MRB_ARGS_REQ(1)); mrb_define_method(mrb, wslay_event_context_cl, "recv", mrb_wslay_event_recv, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "send", mrb_wslay_event_send, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "queue_msg", mrb_wslay_event_queue_msg, MRB_ARGS_REQ(2)); mrb_define_method(mrb, wslay_event_context_cl, "queue_close", mrb_wslay_event_queue_close, MRB_ARGS_ARG(1, 1)); mrb_define_method(mrb, wslay_event_context_cl, "want_read?", mrb_wslay_event_want_read, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "want_write?", mrb_wslay_event_want_write, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "close_received?", mrb_wslay_event_get_close_received, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "close_sent?", mrb_wslay_event_get_close_sent, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "status_code_received", mrb_wslay_event_get_status_code_received, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "status_code_sent", mrb_wslay_event_get_status_code_sent, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "queued_msg_count", mrb_wslay_event_get_queued_msg_count, MRB_ARGS_NONE()); mrb_define_method(mrb, wslay_event_context_cl, "queued_msg_length", mrb_wslay_event_get_queued_msg_length, MRB_ARGS_NONE()); wslay_event_context_server_cl = mrb_define_class_under(mrb, wslay_event_context_cl, "Server", wslay_event_context_cl); mrb_define_method(mrb, wslay_event_context_server_cl, "initialize", mrb_wslay_event_context_server_init, MRB_ARGS_REQ(1)); wslay_event_context_client_cl = mrb_define_class_under(mrb, wslay_event_context_cl, "Client", wslay_event_context_cl); mrb_define_method(mrb, wslay_event_context_client_cl, "initialize", mrb_wslay_event_context_client_init, MRB_ARGS_REQ(1)); }
static mrb_value mrb_curl_get(mrb_state *mrb, mrb_value self) { char error[CURL_ERROR_SIZE] = {0}; CURL* curl; CURLcode res = CURLE_OK; MEMFILE* mf; struct RClass* _class_curl; int ssl_verifypeer; struct curl_slist* headerlist = NULL; mrb_value str; struct RClass* _class_http; struct RClass* _class_http_parser; mrb_value parser; mrb_value args[1]; mrb_value url = mrb_nil_value(); mrb_value headers = mrb_nil_value(); mrb_value b = mrb_nil_value(); mrb_get_args(mrb, "S|H&", &url, &headers, &b); if (!mrb_nil_p(headers) && mrb_type(headers) != MRB_TT_HASH) { mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument"); } mf = memfopen(); curl = curl_easy_init(); _class_curl = mrb_class_get(mrb, "Curl"); ssl_verifypeer = mrb_fixnum(mrb_const_get(mrb, mrb_obj_value(_class_curl), mrb_intern_cstr(mrb, "SSL_VERIFYPEER"))); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, ssl_verifypeer); curl_easy_setopt(curl, CURLOPT_URL, RSTRING_PTR(url)); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error); curl_easy_setopt(curl, CURLOPT_WRITEDATA, mf); if (mrb_nil_p(b)) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite); } else { mf->mrb = mrb; mf->proc = b; mf->header = mrb_nil_value(); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, memfwrite_callback); } curl_easy_setopt(curl, CURLOPT_HEADERDATA, mf); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, memfwrite); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 0); if (!mrb_nil_p(headers)) { mrb_value keys = mrb_hash_keys(mrb, headers); int i, l = RARRAY_LEN(keys); for (i = 0; i < l; i++) { mrb_value key = mrb_ary_entry(keys, i); mrb_value header = mrb_str_dup(mrb, key); mrb_str_cat2(mrb, header, ": "); mrb_str_concat(mrb, header, mrb_hash_get(mrb, headers, key)); headerlist = curl_slist_append(headerlist, RSTRING_PTR(header)); } curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); } res = curl_easy_perform(curl); if (headerlist) curl_slist_free_all(headerlist); curl_easy_cleanup(curl); if (res != CURLE_OK) { mrb_raise(mrb, E_RUNTIME_ERROR, error); } if (!mrb_nil_p(b)) { return mrb_nil_value(); } str = mrb_str_new(mrb, mf->data, mf->size); memfclose(mf); _class_http = mrb_class_get(mrb, "HTTP"); _class_http_parser = mrb_class_ptr(mrb_const_get(mrb, mrb_obj_value(_class_http), mrb_intern_cstr(mrb, "Parser"))); parser = mrb_obj_new(mrb, _class_http_parser, 0, NULL); args[0] = str; return mrb_funcall_argv(mrb, parser, mrb_intern_cstr(mrb, "parse_response"), 1, args); }
int value_to_node(mrb_state *mrb, yaml_document_t *document, mrb_value value) { int node; switch (mrb_type(value)) { case MRB_TT_ARRAY: { mrb_int len = mrb_ary_len(mrb, value); mrb_int i; int ai = mrb_gc_arena_save(mrb); node = yaml_document_add_sequence(document, NULL, YAML_ANY_SEQUENCE_STYLE); for (i = 0; i < len; i++) { mrb_value child = mrb_ary_ref(mrb, value, i); int child_node = value_to_node(mrb, document, child); /* Add the child to the sequence */ yaml_document_append_sequence_item(document, node, child_node); mrb_gc_arena_restore(mrb, ai); } break; } case MRB_TT_HASH: { /* Iterating a list of keys is slow, but it only * requires use of the interface defined in `hash.h`. */ mrb_value keys = mrb_hash_keys(mrb, value); mrb_int len = mrb_ary_len(mrb, keys); mrb_int i; int ai = mrb_gc_arena_save(mrb); node = yaml_document_add_mapping(document, NULL, YAML_ANY_MAPPING_STYLE); for (i = 0; i < len; i++) { mrb_value key = mrb_ary_ref(mrb, keys, i); mrb_value child = mrb_hash_get(mrb, value, key); int key_node = value_to_node(mrb, document, key); int child_node = value_to_node(mrb, document, child); /* Add the key/value pair to the mapping */ yaml_document_append_mapping_pair(document, node, key_node, child_node); mrb_gc_arena_restore(mrb, ai); } break; } default: { if (mrb_nil_p(value)) { /* http://yaml.org/type/null.html Canonical form */ value = mrb_str_new_lit(mrb, "~"); } else { /* Equivalent to `obj = obj#to_s` */ value = mrb_obj_as_string(mrb, value); } /* Fallthrough */ } case MRB_TT_STRING: { yaml_scalar_style_t style = YAML_ANY_SCALAR_STYLE; if (RSTRING_LEN(value) == 0) { /* If the String is empty, it may be reloaded as a nil instead of an * empty string, to avoid that place a quoted string instead */ style = YAML_SINGLE_QUOTED_SCALAR_STYLE; } yaml_char_t *value_chars = (unsigned char *) RSTRING_PTR(value); node = yaml_document_add_scalar(document, NULL, value_chars, RSTRING_LEN(value), style); break; } } return node; }
/********************************************************* * 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; }
// based on https://gist.github.com/3066997 static mrb_value migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) { mrb_value nv; switch (mrb_type(v)) { case MRB_TT_OBJECT: case MRB_TT_EXCEPTION: { struct RObject *o = mrb_obj_ptr(v); mrb_value path = mrb_class_path(mrb, o->c); struct RClass *c; if (mrb_nil_p(path)) { mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate class"); } c = mrb_class_get(mrb2, RSTRING_PTR(path)); nv = mrb_obj_value(mrb_obj_alloc(mrb2, mrb_type(v), c)); } migrate_simple_iv(mrb, v, mrb2, nv); break; case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: nv = v; break; case MRB_TT_SYMBOL: nv = mrb_symbol_value(migrate_sym(mrb, mrb_symbol(v), mrb2)); break; case MRB_TT_FLOAT: nv = mrb_float_value(mrb2, mrb_float(v)); break; case MRB_TT_STRING: nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v)); break; case MRB_TT_RANGE: { struct RRange *r = mrb_range_ptr(v); nv = mrb_range_new(mrb2, migrate_simple_value(mrb, r->edges->beg, mrb2), migrate_simple_value(mrb, r->edges->end, mrb2), r->excl); } break; case MRB_TT_ARRAY: { struct RArray *a0, *a1; int i; a0 = mrb_ary_ptr(v); nv = mrb_ary_new_capa(mrb2, a0->len); a1 = mrb_ary_ptr(nv); for (i=0; i<a0->len; i++) { int ai = mrb_gc_arena_save(mrb2); a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2); a1->len++; mrb_gc_arena_restore(mrb2, ai); } } break; case MRB_TT_HASH: { mrb_value ka; int i, l; nv = mrb_hash_new(mrb2); ka = mrb_hash_keys(mrb, v); l = RARRAY_LEN(ka); for (i = 0; i < l; i++) { int ai = mrb_gc_arena_save(mrb2); mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2); mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2); mrb_hash_set(mrb2, nv, k, o); mrb_gc_arena_restore(mrb2, ai); } } migrate_simple_iv(mrb, v, mrb2, nv); break; case MRB_TT_DATA: if (!is_safe_migratable_datatype(DATA_TYPE(v))) mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object"); nv = v; DATA_PTR(nv) = DATA_PTR(v); DATA_TYPE(nv) = DATA_TYPE(v); migrate_simple_iv(mrb, v, mrb2, nv); break; default: mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object"); break; } return nv; }
static mrb_bool is_safe_migratable_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) { switch (mrb_type(v)) { case MRB_TT_OBJECT: case MRB_TT_EXCEPTION: { struct RObject *o = mrb_obj_ptr(v); mrb_value path = mrb_class_path(mrb, o->c); if (mrb_nil_p(path) || !mrb_class_defined(mrb2, RSTRING_PTR(path))) { return FALSE; } } break; case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: case MRB_TT_SYMBOL: case MRB_TT_FLOAT: case MRB_TT_STRING: break; case MRB_TT_RANGE: { struct RRange *r = mrb_range_ptr(v); if (!is_safe_migratable_simple_value(mrb, r->edges->beg, mrb2) || !is_safe_migratable_simple_value(mrb, r->edges->end, mrb2)) { return FALSE; } } break; case MRB_TT_ARRAY: { struct RArray *a0; int i; a0 = mrb_ary_ptr(v); for (i=0; i<a0->len; i++) { if (!is_safe_migratable_simple_value(mrb, a0->ptr[i], mrb2)) { return FALSE; } } } break; case MRB_TT_HASH: { mrb_value ka; int i, l; ka = mrb_hash_keys(mrb, v); l = RARRAY_LEN(ka); for (i = 0; i < l; i++) { mrb_value k = mrb_ary_entry(ka, i); if (!is_safe_migratable_simple_value(mrb, k, mrb2) || !is_safe_migratable_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2)) { return FALSE; } } } break; case MRB_TT_DATA: if (!is_safe_migratable_datatype(DATA_TYPE(v))) return FALSE; break; default: return FALSE; break; } return TRUE; }
// based on https://gist.github.com/3066997 static mrb_value migrate_simple_value(mrb_state *mrb, mrb_value v, mrb_state *mrb2) { mrb_value nv = mrb_nil_value(); nv.tt = v.tt; switch (mrb_type(v)) { case MRB_TT_OBJECT: nv.value.p = v.value.p; break; case MRB_TT_FALSE: case MRB_TT_TRUE: case MRB_TT_FIXNUM: nv.value.i = v.value.i; break; case MRB_TT_SYMBOL: nv = mrb_symbol_value(mrb_intern_str(mrb2, v)); break; case MRB_TT_FLOAT: nv.value.f = v.value.f; break; case MRB_TT_STRING: nv = mrb_str_new(mrb2, RSTRING_PTR(v), RSTRING_LEN(v)); break; case MRB_TT_ARRAY: { struct RArray *a0, *a1; int i; a0 = mrb_ary_ptr(v); nv = mrb_ary_new_capa(mrb2, a0->len); a1 = mrb_ary_ptr(nv); for (i=0; i<a0->len; i++) { int ai = mrb_gc_arena_save(mrb2); a1->ptr[i] = migrate_simple_value(mrb, a0->ptr[i], mrb2); a1->len++; mrb_gc_arena_restore(mrb2, ai); } } break; case MRB_TT_HASH: { mrb_value ka; int i, l; nv = mrb_hash_new(mrb2); ka = mrb_hash_keys(mrb, v); l = RARRAY_LEN(ka); for (i = 0; i < l; i++) { int ai = mrb_gc_arena_save(mrb2); mrb_value k = migrate_simple_value(mrb, mrb_ary_entry(ka, i), mrb2); mrb_value o = migrate_simple_value(mrb, mrb_hash_get(mrb, v, k), mrb2); mrb_hash_set(mrb2, nv, k, o); mrb_gc_arena_restore(mrb2, ai); } } break; default: mrb_raise(mrb, E_TYPE_ERROR, "cannot migrate object"); break; } return nv; }