mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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:
parent
51281b961b
commit
70360efac3
3 changed files with 90 additions and 14 deletions
|
@ -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>
|
||||
|
||||
* bignum.c (rb_big_hash): use rb_memhash().
|
||||
|
|
84
hash.c
84
hash.c
|
@ -1303,6 +1303,23 @@ struct equal_data {
|
|||
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
|
||||
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
|
||||
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);
|
||||
|
|
14
object.c
14
object.c
|
@ -76,13 +76,13 @@ rb_eql(VALUE obj1, VALUE obj2)
|
|||
* object as <code>b</code>).
|
||||
*
|
||||
* The <code>eql?</code> method returns <code>true</code> if
|
||||
<i>obj</i> and <i>anObject</i> have the
|
||||
* same value. Used by <code>Hash</code> to test members for equality.
|
||||
* For objects of class <code>Object</code>, <code>eql?</code> is
|
||||
* synonymous with <code>==</code>. Subclasses normally continue this
|
||||
* tradition, but there are exceptions. <code>Numeric</code> types, for
|
||||
* example, perform type conversion across <code>==</code>, but not
|
||||
* across <code>eql?</code>, so:
|
||||
* <i>obj</i> and <i>anObject</i> have the same value. Used by
|
||||
* <code>Hash</code> to test members for equality. For objects of
|
||||
* class <code>Object</code>, <code>eql?</code> is synonymous with
|
||||
* <code>==</code>. Subclasses normally continue this tradition, but
|
||||
* there are exceptions. <code>Numeric</code> types, for example,
|
||||
* perform type conversion across <code>==</code>, but not across
|
||||
* <code>eql?</code>, so:
|
||||
*
|
||||
* 1 == 1.0 #=> true
|
||||
* 1.eql? 1.0 #=> false
|
||||
|
|
Loading…
Reference in a new issue