static VALUE rhash_create(VALUE klass, SEL sel, int argc, VALUE *argv) { if (argc == 1) { VALUE tmp = rhash_try_convert(Qnil, 0, argv[0]); if (!NIL_P(tmp)) { VALUE hash = rhash_alloc(klass, 0); if (IS_RHASH(tmp)) { GC_WB(&RHASH(hash)->tbl, st_copy(RHASH(tmp)->tbl)); } else { VALUE keys = rb_hash_keys(tmp); for (long i = 0, count = RARRAY_LEN(keys); i < count; i++) { VALUE key = RARRAY_AT(keys, i); VALUE val = rb_hash_lookup(tmp, key); rhash_aset(hash, 0, key, val); } } return hash; } tmp = rb_check_array_type(argv[0]); if (!NIL_P(tmp)) { VALUE hash = rhash_alloc(klass, 0); for (int i = 0; i < RARRAY_LEN(tmp); ++i) { VALUE v = rb_check_array_type(RARRAY_AT(tmp, i)); if (NIL_P(v)) { continue; } const long len = RARRAY_LEN(v); if (len < 1 || 2 < len) { continue; } rhash_aset(hash, 0, RARRAY_AT(v, 0), RARRAY_AT(v, 1)); } return hash; } } if (argc % 2 != 0) { rb_raise(rb_eArgError, "odd number of arguments for Hash"); } VALUE hash = rhash_alloc(klass, 0); for (int i = 0; i < argc; i += 2) { rb_hash_aset(hash, argv[i], argv[i + 1]); } return hash; }
static int update_i(VALUE key, VALUE value, VALUE hash) { if (key != Qundef) { rhash_aset(hash, 0, key, value); } return ST_CONTINUE; }
static int invert_i(VALUE key, VALUE value, VALUE hash) { if (key != Qundef) { rhash_aset(hash, 0, value, key); } return ST_CONTINUE; }
static int update_block_i(VALUE key, VALUE value, VALUE hash) { if (key != Qundef) { if (rhash_has_key(hash, 0, key)) { value = rb_yield_values(3, key, rhash_aref(hash, 0, key), value); ST_STOP_IF_BROKEN(); } rhash_aset(hash, 0, key, value); } return ST_CONTINUE; }
PRIMITIVE VALUE vm_fast_aset(VALUE obj, VALUE other1, VALUE other2, unsigned char overriden) { if (overriden == 0 && !SPECIAL_CONST_P(obj)) { VALUE klass = *(VALUE *)obj; if (klass == rb_cRubyArray) { if (FIXNUM_P(other1)) { rary_store(obj, FIX2LONG(other1), other2); return other2; } } else if (klass == rb_cRubyHash) { return rhash_aset(obj, 0, other1, other2); } } VALUE args[] = {other1, other2}; return vm_dispatch(0, obj, selASET, NULL, 0, 2, args); }
VALUE rb_hash_new_fast(int argc, ...) { assert(argc % 2 == 0); VALUE hash = rhash_alloc(rb_cRubyHash, 0); va_list ar; va_start(ar, argc); for (int i = 0; i < argc; i += 2) { VALUE key = va_arg(ar, VALUE); VALUE val = va_arg(ar, VALUE); rhash_aset(hash, 0, key, val); } va_end(ar); return hash; }