summaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/hash.c b/hash.c
index f3cf068fa22..16f63259555 100644
--- a/hash.c
+++ b/hash.c
@@ -1497,6 +1497,49 @@ rb_hash_eql(hash1, hash2)
return hash_equal(hash1, hash2, Qtrue);
}
+
+rb_hash_hash_i(key, value, hp)
+ VALUE key, value;
+ long *hp;
+{
+ long h = *hp;
+ VALUE n;
+
+ h = (h << 1) | (h<0 ? 1 : 0);
+ n = rb_hash(key);
+ h ^= NUM2LONG(n);
+ h = (h << 1) | (h<0 ? 1 : 0);
+ n = rb_hash(value);
+ h ^= NUM2LONG(n);
+
+ *hp = h;
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * hash.hash -> fixnum
+ *
+ * Compute a hash-code for this hash. Two hashes with the same content
+ * will have the same hash code (and will compare using <code>eql?</code>).
+ */
+
+static VALUE
+rb_hash_hash(hash)
+ VALUE hash;
+{
+ long h;
+ VALUE n;
+
+ h = RHASH(hash)->tbl->num_entries;
+ rb_hash_foreach(hash, rb_hash_hash_i, (VALUE)&h);
+ h = (h << 1) | (h<0 ? 1 : 0);
+ n = rb_hash(RHASH(hash)->ifnone);
+ h ^= NUM2LONG(n);
+
+ return LONG2FIX(h);
+}
+
static int
rb_hash_invert_i(key, value, hash)
VALUE key, value;
@@ -2430,6 +2473,7 @@ Init_Hash()
rb_define_method(rb_cHash,"==", rb_hash_equal, 1);
rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
+ rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
rb_define_method(rb_cHash,"[]", rb_hash_aref, 1);
rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);