Project

General

Profile

Feature #3995 ยป hash_update.diff

nobu (Nobuyoshi Nakada), 10/28/2010 07:17 PM

View differences:

w/hash.c
return ST_CONTINUE;
}
static VALUE
rb_enum_update_i(VALUE obj, VALUE hash, int argc, VALUE *argv)
{
if (argc == 1 && RB_TYPE_P(obj, T_ARRAY)) {
argc = RARRAY_LEN(obj);
argv = RARRAY_PTR(obj);
}
if (argc == 2) {
st_insert(RHASH(hash)->ntbl, argv[0], argv[1]);
}
return Qnil;
}
static VALUE
rb_enum_update_block_i(VALUE obj, VALUE hash, int argc, VALUE *argv)
{
VALUE key, value = Qundef, oldval;
if (argc == 1 && RB_TYPE_P(obj, T_ARRAY)) {
argc = RARRAY_LEN(obj);
argv = RARRAY_PTR(obj);
}
switch (argc) {
case 2:
value = argv[1];
case 1:
key = argv[0];
oldval = rb_hash_lookup2(hash, key, Qundef);
if (oldval != Qundef) {
value = rb_yield_values(argc + 1, key, oldval, value);
}
else if (value == Qundef) {
value = rb_yield(key);
}
st_insert(RHASH(hash)->ntbl, key, value);
break;
}
return Qnil;
}
/*
* call-seq:
* hsh.merge!(other_hash) -> hsh
......
* h2 = { "b" => 254, "c" => 300 }
* h1.merge!(h2) { |key, v1, v2| v1 }
* #=> {"a"=>100, "b"=>200, "c"=>300}
*
* If <i>other_hash</i> is not a Hash but an Enumerable, its #each
* method should yield [key, newval] pairs or mere key. In the latter
* case, thegiven block is always called regardless oldval, but without
* newval.
*
* h1 = { "a" => 100, "b" => 200 }
* e1 = [["b", 254], ["c", 300]]
* h1.merge!(e1) { |key, *v| v }
* #=> {"a"=>100, "b"=>[200,254], "c"=>300}
*
* h1 = { "a" => 100, "b" => 200 }
* e1 = [["b"], ["c"]]
* h1.merge!(e1) { |key, v1, v2| v1 }
* #=> {"a"=>100, "b"=>[200], "c"=>[]}
*/
static VALUE
rb_hash_update(VALUE hash1, VALUE hash2)
{
VALUE tmp;
rb_hash_modify(hash1);
hash2 = to_hash(hash2);
tmp = rb_check_hash_type(hash2);
if (NIL_P(tmp)) {
VALUE (*bfunc)(ANYARGS) = rb_block_given_p() ?
rb_enum_update_block_i : rb_enum_update_i;
rb_each_call(hash2, 0, 0, bfunc, hash1);
return hash1;
}
hash2 = tmp;
if (rb_block_given_p()) {
rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
}
w/include/ruby/ruby.h
typedef VALUE rb_block_call_func(VALUE, VALUE, int, VALUE*);
VALUE rb_each(VALUE);
VALUE rb_each_call(VALUE,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
VALUE rb_yield(VALUE);
VALUE rb_yield_values(int n, ...);
VALUE rb_yield_values2(int n, const VALUE *argv);
w/vm_eval.c
return rb_call(obj, idEach, 0, 0, CALL_FCALL);
}
VALUE
rb_each_call(VALUE obj, int argc, VALUE *argv, VALUE (*bl_proc)(ANYARGS), VALUE arg)
{
return rb_block_call(obj, idEach, argc, argv, bl_proc, arg);
}
static VALUE
eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *volatile file, volatile int line)
{
    (1-1/1)