* 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
@ -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
84
hash.c
@ -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);
|
||||||
|
14
object.c
14
object.c
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user