Project

General

Profile

Feature #14916 ยป array_eqq.patch

Support `to_ary` - osyo (manga osyo), 08/09/2018 02:22 AM

View differences:

array.c
3957 3957
    return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
3958 3958
}
3959 3959

  
3960
static VALUE
3961
recursive_eqq(VALUE ary1, VALUE ary2, int recur)
3962
{
3963
    long i, len1;
3964
    const VALUE *p1, *p2;
3965

  
3966
    if (recur) return Qtrue; /* Subtle! */
3967

  
3968
    p1 = RARRAY_CONST_PTR(ary1);
3969
    p2 = RARRAY_CONST_PTR(ary2);
3970
    len1 = RARRAY_LEN(ary1);
3971

  
3972
    for (i = 0; i < len1; i++) {
3973
	if (*p1 != *p2) {
3974
	    if (rb_funcall(*p1, idEqq, 1, *p2) || rb_equal(*p1, *p2)) {
3975
		len1 = RARRAY_LEN(ary1);
3976
		if (len1 != RARRAY_LEN(ary2))
3977
		    return Qfalse;
3978
		if (len1 < i)
3979
		    return Qtrue;
3980
		p1 = RARRAY_CONST_PTR(ary1) + i;
3981
		p2 = RARRAY_CONST_PTR(ary2) + i;
3982
	    }
3983
	    else {
3984
		return Qfalse;
3985
	    }
3986
	}
3987
	p1++;
3988
	p2++;
3989
    }
3990
    return Qtrue;
3991
}
3992

  
3993
/*
3994
 *  call-seq:
3995
 *     ary == other_ary   ->   bool
3996
 *
3997
 *  Equality(===) --- Two arrays are equal if they contain the same number of
3998
 *  elements and if each element is equal to (according to Object#==) the
3999
 *  corresponding element in +other_ary+.
4000
 *
4001
 *     [ String, /\w/ ]          === [ "a", "c", 7 ]   # => false
4002
 *     [ String, /\w/, (1..10) ] === [ "a", "c", 7 ]   # => true
4003
 *     [ String, /\w/, (1..10) ] === [ "a", "!", 42 ]  # => false
4004
 *
4005
 */
4006

  
4007
static VALUE
4008
rb_ary_eqq(VALUE ary1, VALUE ary2)
4009
{
4010
    if (ary1 == ary2) return Qtrue;
4011
    if (!RB_TYPE_P(ary2, T_ARRAY)) {
4012
	if (rb_respond_to(ary2, idTo_ary)) {
4013
	    return rb_ary_eqq(ary1, to_ary(ary2));
4014
	}
4015
	else {
4016
	    return Qfalse;
4017
	}
4018
    }
4019
    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
4020
    if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
4021
    return rb_exec_recursive_paired(recursive_eqq, ary1, ary2, ary2);
4022
}
4023

  
3960 4024
/*
3961 4025
 *  call-seq:
3962 4026
 *     ary.hash   -> integer
......
6272 6336
    rb_define_method(rb_cArray, "to_ary", rb_ary_to_ary_m, 0);
6273 6337

  
6274 6338
    rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
6339
    rb_define_method(rb_cArray, "===", rb_ary_eqq, 1);
6275 6340
    rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
6276 6341
    rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
6277 6342

  
test/ruby/test_array.rb
2389 2389
    assert_not_equal([0, 1, 2], [0, 1, 3])
2390 2390
  end
2391 2391

  
2392
  def test_eqq
2393
    o = Object.new
2394
    def o.==(x); false; end
2395
    def o.===(x); true; end
2396
    assert_operator([o, o, o], :===, [0, 1, 2])
2397
    assert_operator([0, 1, 2], :===, [0, 1, 2])
2398
    assert_operator([], :===, [])
2399
    a = [1, 2, 3]
2400
    a[0] = a
2401
    assert_operator(a, :===, a)
2402
    b = [1, 2, 3]
2403
    b[0] = b
2404
    assert_operator(a, :===, b)
2405

  
2406
    o2 = Object.new
2407
    def o2.==(x); true; end
2408
    def o2.===(x); false; end
2409
    assert_operator([o2], :===, [1])
2410

  
2411
    o3 = Object.new
2412
    def o3.to_ary
2413
      [1]
2414
    end
2415
    assert_operator([Integer], :===, o3)
2416

  
2417
    assert_not_operator([o, o], :===, [0, 1, 2])
2418
    assert_not_operator([o, o, o], :===, [0, 1])
2419
    assert_not_operator([0, 1, 2], :===, [o, o, o])
2420
    assert_not_operator([1], :===, [])
2421
    assert_not_operator([], :===, [1])
2422
    assert_not_operator([0, 1, 2], :===, 42)
2423
    assert_not_operator([], :===, 42)
2424

  
2425
    c = [1, 3, 2]
2426
    c[0] = c
2427
    assert_not_operator(a, :===, c)
2428
  end
2429

  
2392 2430
  A = Array.new(3, &:to_s)
2393 2431
  B = A.dup
2394 2432