summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-13 09:21:18 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2002-08-13 09:21:18 +0000
commitcf5d04f663e9e7a61da4dda66e78097aefe66919 (patch)
tree431e5afae10458ab9e139683d74724bd713b0ed8 /hash.c
parent510c93caacad0911261f3adeed73b43fc5fca57f (diff)
* hash.c (rb_hash_replace): should copy ifnone.
* hash.c (rb_hash_dup): should preserve HASH_PROC_DEFAULT and HASH_DELETED flags. * hash.c (rb_hash_shift): shift from empty hash should not return its default proc. * hash.c (rb_hash_default_proc): new method. [new] * array.c (rb_ary_aref): no need for Bignum check. * array.c (rb_ary_aset): explicit Bignum check removd. * numeric.c (fix_aref): normalize bignum before bit-op. * bignum.c (rb_big_rand): max may be Bignum zero. * bignum.c (rb_cstr_to_inum): should normalize bignums, to avoid returning fixable bignum value. * bignum.c (rb_uint2big): there should be no zero sized bignum. * ext/extmk.rb.in: extmake() that works properly for both tkutil (tk/tkutil.so) and digest/sha1. * hash.c (rb_hash_equal): should check HASH_PROC_DEFAULT too. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2706 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c47
1 files changed, 44 insertions, 3 deletions
diff --git a/hash.c b/hash.c
index 98bf3427f0..dc7483b771 100644
--- a/hash.c
+++ b/hash.c
@@ -260,6 +260,21 @@ rb_hash_clone(hash)
}
static VALUE
+rb_hash_dup(hash)
+ VALUE hash;
+{
+ VALUE dup = rb_obj_dup(hash);
+
+ if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
+ FL_SET(dup, HASH_PROC_DEFAULT);
+ }
+ if (FL_TEST(hash, HASH_DELETED)) {
+ FL_SET(dup, HASH_DELETED);
+ }
+ return dup;
+}
+
+static VALUE
to_hash(hash)
VALUE hash;
{
@@ -353,6 +368,18 @@ rb_hash_set_default(hash, ifnone)
return ifnone;
}
+static VALUE
+rb_hash_default_proc(hash)
+ VALUE hash;
+{
+ VALUE key;
+
+ if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
+ return RHASH(hash)->ifnone;
+ }
+ return Qnil;
+}
+
static int
index_i(key, value, args)
VALUE key, value;
@@ -448,8 +475,15 @@ rb_hash_shift(hash)
var.stop = 0;
st_foreach(RHASH(hash)->tbl, shift_i, &var);
- if (var.stop == 0) return RHASH(hash)->ifnone;
- return rb_assoc_new(var.key, var.val);
+ if (var.stop) {
+ return rb_assoc_new(var.key, var.val);
+ }
+ else if (FL_TEST(hash, HASH_PROC_DEFAULT)) {
+ return rb_funcall(RHASH(hash)->ifnone, id_yield, 2, hash, Qnil);
+ }
+ else {
+ return RHASH(hash)->ifnone;
+ }
}
static int
@@ -573,6 +607,10 @@ rb_hash_replace(hash, hash2)
hash2 = to_hash(hash2);
rb_hash_clear(hash);
st_foreach(RHASH(hash2)->tbl, replace_i, hash);
+ RHASH(hash)->ifnone = RHASH(hash2)->ifnone;
+ if (FL_TEST(hash2, HASH_PROC_DEFAULT)) {
+ FL_SET(hash, HASH_PROC_DEFAULT);
+ }
return hash;
}
@@ -854,7 +892,8 @@ rb_hash_equal(hash1, hash2)
if (TYPE(hash2) != T_HASH) return Qfalse;
if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
return Qfalse;
- if (!rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone))
+ if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) &&
+ FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
return Qfalse;
data.tbl = RHASH(hash2)->tbl;
@@ -1576,6 +1615,7 @@ Init_Hash()
rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
rb_define_method(rb_cHash,"clone", rb_hash_clone, 0);
+ rb_define_method(rb_cHash,"dup", rb_hash_dup, 0);
rb_define_method(rb_cHash,"rehash", rb_hash_rehash, 0);
rb_define_method(rb_cHash,"to_hash", rb_hash_to_hash, 0);
@@ -1590,6 +1630,7 @@ Init_Hash()
rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
rb_define_method(rb_cHash,"default", rb_hash_default, -1);
rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
+ rb_define_method(rb_cHash,"default_proc", rb_hash_default_proc, 0);
rb_define_method(rb_cHash,"index", rb_hash_index, 1);
rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1);