Project

General

Profile

Feature #6219 ยป 0001-Hash-store-return-old-value.patch

nobu (Nobuyoshi Nakada), 03/30/2012 01:09 AM

View differences:

hash.c
263 263
}
264 264

  
265 265
static void
266
hash_update_fail(void)
267
{
268
    rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
269
}
270

  
271
static void
266 272
hash_update(VALUE hash, VALUE key)
267 273
{
268 274
    if (RHASH(hash)->iter_lev > 0 && !st_lookup(RHASH(hash)->ntbl, key, 0)) {
269
	rb_raise(rb_eRuntimeError, "can't add a new key into hash during iteration");
275
	hash_update_fail();
270 276
    }
271 277
}
272 278

  
......
480 486
    return hash;
481 487
}
482 488

  
489
static VALUE
490
hash_default_value(VALUE hash, VALUE key)
491
{
492
    if (!FL_TEST(hash, HASH_PROC_DEFAULT) &&
493
	rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
494
	return RHASH_IFNONE(hash);
495
    }
496
    else {
497
	return rb_funcall(hash, id_default, 1, key);
498
    }
499
}
500

  
483 501
/*
484 502
 *  call-seq:
485 503
 *     hsh[key]    ->  value
......
500 518
    st_data_t val;
501 519

  
502 520
    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val)) {
503
	if (!FL_TEST(hash, HASH_PROC_DEFAULT) &&
504
	    rb_method_basic_definition_p(CLASS_OF(hash), id_default)) {
505
	    return RHASH_IFNONE(hash);
506
	}
507
	else {
508
	    return rb_funcall(hash, id_default, 1, key);
509
	}
521
	return hash_default_value(hash, key);
510 522
    }
511 523
    return (VALUE)val;
512 524
}
......
1093 1105
    return hash;
1094 1106
}
1095 1107

  
1096
static st_data_t
1097
copy_str_key(st_data_t str)
1108
struct hash_aset_tuple {
1109
    st_data_t old;
1110
    st_data_t new;
1111
    int iter_lev;
1112
};
1113

  
1114
static int
1115
hash_aset_i(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
1116
{
1117
    struct hash_aset_tuple *ptr = (void *)arg;
1118
    if (existing) {
1119
	ptr->old = *value;
1120
    }
1121
    else {
1122
	if (ptr->iter_lev > 0) hash_update_fail();
1123
    }
1124
    *value = ptr->new;
1125
    return ST_CONTINUE;
1126
}
1127

  
1128
static int
1129
hash_aset_copy_i(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
1130
{
1131
    struct hash_aset_tuple *ptr = (void *)arg;
1132
    if (existing) {
1133
	ptr->old = *value;
1134
    }
1135
    else {
1136
	if (ptr->iter_lev > 0) hash_update_fail();
1137
	*key = (st_data_t)rb_str_new4((VALUE)*key);
1138
    }
1139
    *value = ptr->new;
1140
    return ST_CONTINUE;
1141
}
1142

  
1143
static VALUE
1144
hash_store(VALUE hash, VALUE key, VALUE val)
1098 1145
{
1099
    return (st_data_t)rb_str_new4((VALUE)str);
1146
    st_update_callback_func *func;
1147
    struct hash_aset_tuple t;
1148
    rb_hash_modify(hash);
1149
    t.new = val;
1150
    t.old = Qundef;
1151
    t.iter_lev = RHASH(hash)->iter_lev;
1152
    if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString) {
1153
	func = hash_aset_i;
1154
    }
1155
    else {
1156
	func = hash_aset_copy_i;
1157
    }
1158
    st_update(RHASH(hash)->ntbl, key, func, (st_data_t)&t);
1159
    return t.old;
1100 1160
}
1101 1161

  
1102 1162
/*
1103 1163
 *  call-seq:
1104 1164
 *     hsh[key] = value        -> value
1105
 *     hsh.store(key, value)   -> value
1106 1165
 *
1107 1166
 *  Element Assignment---Associates the value given by
1108 1167
 *  <i>value</i> with the key given by <i>key</i>.
......
1120 1179
VALUE
1121 1180
rb_hash_aset(VALUE hash, VALUE key, VALUE val)
1122 1181
{
1123
    rb_hash_modify(hash);
1124
    hash_update(hash, key);
1125
    if (RHASH(hash)->ntbl->type == &identhash || rb_obj_class(key) != rb_cString) {
1126
	st_insert(RHASH(hash)->ntbl, key, val);
1127
    }
1128
    else {
1129
	st_insert2(RHASH(hash)->ntbl, key, val, copy_str_key);
1130
    }
1182
    hash_store(hash, key, val);
1183
    return val;
1184
}
1185

  
1186
/*
1187
 *  call-seq:
1188
 *     hsh.store(key, value)   -> old_value
1189
 *
1190
 *  Associates the value given by <i>value</i> with the key given by
1191
 *  <i>key</i>.  Almostly equivalent to Hash#[]=, but returns old
1192
 *  value which was associated with <i>key</i>.
1193
 *
1194
 *     h = { "a" => 100, "b" => 200 }
1195
 *     h.store("a", 9)  #=> 100
1196
 *     h.store("c", 4)  #=> nil
1197
 *     h   #=> {"a"=>9, "b"=>200, "c"=>4}
1198
 *
1199
 */
1200

  
1201
VALUE
1202
rb_hash_store(VALUE hash, VALUE key, VALUE val)
1203
{
1204
    val = hash_store(hash, key, val);
1205
    if (val == Qundef) val = hash_default_value(hash, key);
1131 1206
    return val;
1132 1207
}
1133 1208

  
......
1731 1806
rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
1732 1807
{
1733 1808
    if (key == Qundef) return ST_CONTINUE;
1734
    hash_update(hash, key);
1735 1809
    st_insert(RHASH(hash)->ntbl, key, value);
1736 1810
    return ST_CONTINUE;
1737 1811
}
......
3298 3372
    rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
3299 3373
    rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1);
3300 3374
    rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
3301
    rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
3375
    rb_define_method(rb_cHash,"store", rb_hash_store, 2);
3302 3376
    rb_define_method(rb_cHash,"default", rb_hash_default, -1);
3303 3377
    rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
3304 3378
    rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
test/ruby/test_hash.rb
582 582
  def test_store
583 583
    t = Time.now
584 584
    h = @cls.new
585
    h.store(1, 'one')
586
    h.store(2, 'two')
587
    h.store(3, 'three')
588
    h.store(self, 'self')
589
    h.store(t,  'time')
590
    h.store(nil, 'nil')
591
    h.store('nil', nil)
585
    assert_nil(h.store(1, 'one'))
586
    assert_nil(h.store(2, 'two'))
587
    assert_nil(h.store(3, 'three'))
588
    assert_nil(h.store(self, 'self'))
589
    assert_nil(h.store(t,  'time'))
590
    assert_nil(h.store(nil, 'nil'))
591
    assert_nil(h.store('nil', nil))
592 592
    assert_equal('one',   h[1])
593 593
    assert_equal('two',   h[2])
594 594
    assert_equal('three', h[3])
......
598 598
    assert_equal(nil,     h['nil'])
599 599
    assert_equal(nil,     h['koala'])
600 600

  
601
    h.store(1, 1)
602
    h.store(nil,  99)
603
    h.store('nil', nil)
601
    assert_equal('one',   h.store(1, 1))
602
    assert_equal('nil',   h.store(nil,  99))
603
    assert_equal(nil,     h.store('nil', nil))
604 604
    assert_equal(1,       h[1])
605 605
    assert_equal('two',   h[2])
606 606
    assert_equal('three', h[3])
......
609 609
    assert_equal(99,      h[nil])
610 610
    assert_equal(nil,     h['nil'])
611 611
    assert_equal(nil,     h['koala'])
612

  
613
    h.default = 42
614
    assert_equal(42,      h.store(99, 'wombat'))
615
    assert_equal('wombat', h[99])
616

  
617
    key = nil
618
    h.default_proc = proc {|_, k| key = k; 'foo'}
619
    assert_equal('foo',   h.store(23, 'bar'))
620
    assert_equal('bar',   h[23])
621
    assert_equal(23,      key)
612 622
  end
613 623

  
614 624
  def test_to_a
615
-