Feature #14869 » hash_eqq.patch
hash.c | ||
---|---|---|
return hash_equal(hash1, hash2, TRUE);
|
||
}
|
||
static int
|
||
eqq_i(VALUE key, VALUE val1, VALUE arg)
|
||
{
|
||
struct equal_data *data = (struct equal_data *)arg;
|
||
st_data_t val2;
|
||
if (!st_lookup(data->tbl, key, &val2)) {
|
||
data->result = Qfalse;
|
||
return ST_STOP;
|
||
}
|
||
if (!rb_funcall(val1, idEqq, 1, (VALUE)val2)) {
|
||
data->result = Qfalse;
|
||
return ST_STOP;
|
||
}
|
||
return ST_CONTINUE;
|
||
}
|
||
static VALUE
|
||
recursive_eqq(VALUE hash, VALUE dt, int recur)
|
||
{
|
||
struct equal_data *data;
|
||
if (recur) return Qtrue; /* Subtle! */
|
||
data = (struct equal_data*)dt;
|
||
data->result = Qtrue;
|
||
rb_hash_foreach(hash, eqq_i, dt);
|
||
return data->result;
|
||
}
|
||
/*
|
||
* call-eqq:
|
||
* hsh === other_hash -> true or false
|
||
*
|
||
* Equality(===)---Two hashes are equal if they each contain the same number
|
||
* of keys and if each key-value pair is equal to (according to
|
||
* <code>Object#===</code>) the corresponding elements in the other
|
||
* hash.
|
||
*
|
||
* h1 = { "a" => "hoge", "b" => 2 }
|
||
* h2 = { "a" => 1, "b" => 2, "c" => 35 }
|
||
* { "a" => String, "c" => Integer } === h1 #=> true
|
||
* { "a" => String } === h1 #=> true
|
||
* { "a" => Integer, "c" => String } === h1 #=> false
|
||
* { "b" => Integer, "c" => (1..100) } === h2 #=> true
|
||
*
|
||
*/
|
||
static VALUE
|
||
rb_hash_eqq(VALUE hash1, VALUE hash2)
|
||
{
|
||
struct equal_data data;
|
||
if (hash1 == hash2) return Qtrue;
|
||
if (!RB_TYPE_P(hash2, T_HASH)) {
|
||
if (rb_respond_to(hash2, idTo_hash)) {
|
||
return rb_hash_eqq(hash1, to_hash(hash2));
|
||
}
|
||
else {
|
||
return Qfalse;
|
||
}
|
||
}
|
||
if (RHASH_EMPTY_P(hash1))
|
||
return RHASH_EMPTY_P(hash2) ? Qtrue : Qfalse;
|
||
if (RHASH_SIZE(hash1) > RHASH_SIZE(hash2))
|
||
return Qfalse;
|
||
if (!RHASH(hash1)->ntbl || !RHASH(hash2)->ntbl)
|
||
return Qtrue;
|
||
if (RHASH(hash1)->ntbl->type != RHASH(hash2)->ntbl->type)
|
||
return Qfalse;
|
||
data.tbl = RHASH(hash2)->ntbl;
|
||
return rb_exec_recursive_paired(recursive_eqq, hash1, hash2, (VALUE)&data);
|
||
}
|
||
static int
|
||
hash_i(VALUE key, VALUE val, VALUE arg)
|
||
{
|
||
... | ... | |
rb_define_method(rb_cHash, "to_proc", rb_hash_to_proc, 0);
|
||
rb_define_method(rb_cHash, "==", rb_hash_equal, 1);
|
||
rb_define_method(rb_cHash, "===", rb_hash_eqq, 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);
|
test/ruby/test_hash.rb | ||
---|---|---|
assert_not_send([@cls[], :eql?, o])
|
||
end
|
||
def test_eqq
|
||
user = { id: 1, name: "homu", age: 14 }
|
||
assert_operator({ id: 1 }, :===, user)
|
||
assert_operator({ id: 1, age: 14 }, :===, user)
|
||
assert_operator({ id: Integer }, :===, user)
|
||
assert_operator({ name: String, age: Integer }, :===, user)
|
||
assert_operator({ name: /m/ }, :===, user)
|
||
assert_operator({ number: nil }, :===, { number: nil })
|
||
assert_operator({}, :===, {})
|
||
obj = Object.new
|
||
def obj.=== other
|
||
true
|
||
end
|
||
assert_operator({ id: obj }, :===, user)
|
||
a = { name: String }
|
||
a[:a] = a
|
||
assert_operator(a, :===, a)
|
||
b = { name: "homu" }
|
||
b[:a] = b
|
||
assert_operator(a, :===, b)
|
||
o2 = Object.new
|
||
def o2.to_hash
|
||
{ name: "homu", age: 14 }
|
||
end
|
||
assert_operator({ name: /^h/ }, :===, o2)
|
||
assert_not_operator({ id: 2 }, :===, user)
|
||
assert_not_operator({ name: Integer }, :===, user)
|
||
assert_not_operator({ number: 42 }, :===, user)
|
||
assert_not_operator({ number: nil }, :===, {})
|
||
assert_not_operator({ number: 42 }, :===, {})
|
||
assert_not_operator({ number: 42 }, :===, 42)
|
||
assert_not_operator({ number: 42 }, :===, [])
|
||
assert_not_operator({}, :===, user)
|
||
assert_not_operator({}, :===, 42)
|
||
assert_not_operator({}, :===, { name: "homu" })
|
||
obj2 = Object.new
|
||
def obj2.=== other
|
||
false
|
||
end
|
||
assert_not_operator({ id: obj2 }, :===, user)
|
||
a = { name: Integer }
|
||
a[:a] = a
|
||
b = { name: "homu" }
|
||
b[:a] = b
|
||
assert_not_operator(a, :===, b)
|
||
end
|
||
def test_hash2
|
||
assert_kind_of(Integer, @cls[].hash)
|
||
h = @cls[1=>2]
|
- « Previous
- 1
- 2
- Next »