* 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
This commit is contained in:
matz 2006-09-22 08:36:02 +00:00
parent 51281b961b
commit 70360efac3
3 changed files with 90 additions and 14 deletions

View File

@ -1,3 +1,9 @@
Fri Sep 22 17:33:29 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* hash.c (rb_hash_eql): new method to be used by Hash.
* hash.c (rb_hash_hash): ditto.
Fri Sep 22 06:53:22 2006 Yukihiro Matsumoto <matz@ruby-lang.org> Fri Sep 22 06:53:22 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* bignum.c (rb_big_hash): use rb_memhash(). * bignum.c (rb_big_hash): use rb_memhash().

84
hash.c
View File

@ -1303,6 +1303,23 @@ struct equal_data {
st_table *tbl; st_table *tbl;
}; };
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 static int
equal_i(VALUE key, VALUE val1, struct equal_data *data) equal_i(VALUE key, VALUE val1, struct equal_data *data)
{ {
@ -1321,7 +1338,7 @@ equal_i(VALUE key, VALUE val1, struct equal_data *data)
} }
static VALUE 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; 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) if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries)
return Qfalse; return Qfalse;
if (eql) { #if 0
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))) FL_TEST(hash1, HASH_PROC_DEFAULT) == FL_TEST(hash2, HASH_PROC_DEFAULT)))
return Qfalse; return Qfalse;
} #endif
data.tbl = RHASH(hash2)->tbl; data.tbl = RHASH(hash2)->tbl;
data.result = Qtrue; 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; return data.result;
} }
@ -1372,6 +1389,57 @@ rb_hash_equal(VALUE hash1, VALUE hash2)
return hash_equal(hash1, hash2, Qfalse); 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 static int
rb_hash_invert_i(VALUE key, VALUE value, VALUE hash) 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_equal, 1);
rb_define_method(rb_cHash,"[]", rb_hash_aref, 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,"fetch", rb_hash_fetch, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2); rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
rb_define_method(rb_cHash,"store", rb_hash_aset, 2); rb_define_method(rb_cHash,"store", rb_hash_aset, 2);

View File

@ -76,13 +76,13 @@ rb_eql(VALUE obj1, VALUE obj2)
* object as <code>b</code>). * object as <code>b</code>).
* *
* The <code>eql?</code> method returns <code>true</code> if * The <code>eql?</code> method returns <code>true</code> if
<i>obj</i> and <i>anObject</i> have the * <i>obj</i> and <i>anObject</i> have the same value. Used by
* same value. Used by <code>Hash</code> to test members for equality. * <code>Hash</code> to test members for equality. For objects of
* For objects of class <code>Object</code>, <code>eql?</code> is * class <code>Object</code>, <code>eql?</code> is synonymous with
* synonymous with <code>==</code>. Subclasses normally continue this * <code>==</code>. Subclasses normally continue this tradition, but
* tradition, but there are exceptions. <code>Numeric</code> types, for * there are exceptions. <code>Numeric</code> types, for example,
* example, perform type conversion across <code>==</code>, but not * perform type conversion across <code>==</code>, but not across
* across <code>eql?</code>, so: * <code>eql?</code>, so:
* *
* 1 == 1.0 #=> true * 1 == 1.0 #=> true
* 1.eql? 1.0 #=> false * 1.eql? 1.0 #=> false