diff options
author | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-09-22 08:36:02 +0000 |
---|---|---|
committer | matz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2006-09-22 08:36:02 +0000 |
commit | 70360efac388686eb848b5bfbbb3be7a755451c6 (patch) | |
tree | 09b95c12a0d418145b7070a895ac8f9e35bb84f6 /hash.c | |
parent | 51281b961be085be5a29088ada5118699035306b (diff) |
* hash.c (rb_hash_eql): new method to be used by Hash.
* hash.c (rb_hash_hash): ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@10993 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 84 |
1 files changed, 77 insertions, 7 deletions
@@ -1304,6 +1304,23 @@ struct equal_data { }; static int +eql_i(VALUE key, VALUE val1, struct equal_data *data) +{ + VALUE val2; + + if (key == Qundef) return ST_CONTINUE; + if (!st_lookup(data->tbl, key, &val2)) { + data->result = Qfalse; + return ST_STOP; + } + if (!rb_eql(val1, val2)) { + data->result = Qfalse; + return ST_STOP; + } + return ST_CONTINUE; +} + +static int equal_i(VALUE key, VALUE val1, struct equal_data *data) { VALUE val2; @@ -1321,7 +1338,7 @@ equal_i(VALUE key, VALUE val1, struct equal_data *data) } static VALUE -hash_equal(VALUE hash1, VALUE hash2, int eql /* compare default value if true */) +hash_equal(VALUE hash1, VALUE hash2, int eql) { struct equal_data data; @@ -1334,15 +1351,15 @@ hash_equal(VALUE hash1, VALUE hash2, int eql /* compare default value if true */ } if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) return Qfalse; - if (eql) { - if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) && - FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT))) - return Qfalse; - } +#if 0 + if (!(rb_equal(RHASH(hash1)->ifnone, RHASH(hash2)->ifnone) && + FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT))) + return Qfalse; +#endif data.tbl = RHASH(hash2)->tbl; data.result = Qtrue; - rb_hash_foreach(hash1, equal_i, (st_data_t)&data); + rb_hash_foreach(hash1, eql ? eql_i : equal_i, (st_data_t)&data); return data.result; } @@ -1372,6 +1389,57 @@ rb_hash_equal(VALUE hash1, VALUE hash2) return hash_equal(hash1, hash2, Qfalse); } +/* + * call-seq: + * hash.eql?(other) -> true or false + * + * Returns <code>true</code> if <i>hash</i> and <i>other</i> are + * both hashes with the same content. + */ + +static VALUE +rb_hash_eql(VALUE hash1, VALUE hash2) +{ + return hash_equal(hash1, hash2, Qfalse); +} + +static int +hash_i(VALUE key, VALUE val, int *hval) +{ + if (key == Qundef) return ST_CONTINUE; + *hval ^= rb_hash(key); + *hval ^= rb_hash(val); + return ST_CONTINUE; +} + +static VALUE +recursive_hash(VALUE hash, VALUE dummy, int recur) +{ + int hval; + VALUE n; + + if (recur) { + return LONG2FIX(0); + } + hval = RHASH(hash)->tbl->num_entries; + rb_hash_foreach(hash, hash_i, (st_data_t)&hval); + return INT2FIX(hval); +} + +/* + * call-seq: + * array.hash -> fixnum + * + * Compute a hash-code for this array. Two arrays with the same content + * will have the same hash code (and will compare using <code>eql?</code>). + */ + +static VALUE +rb_hash_hash(VALUE hash) +{ + return rb_exec_recursive(recursive_hash, hash, 0); +} + static int rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) { @@ -2330,6 +2398,8 @@ Init_Hash(void) rb_define_method(rb_cHash,"==", rb_hash_equal, 1); rb_define_method(rb_cHash,"[]", rb_hash_aref, 1); + rb_define_method(rb_cHash,"hash", rb_hash_hash, 0); + rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1); rb_define_method(rb_cHash,"fetch", rb_hash_fetch, -1); rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2); rb_define_method(rb_cHash,"store", rb_hash_aset, 2); |