[前][次][番号順一覧][スレッド一覧]

ruby-changes:4587

From: ko1@a...
Date: Sat, 19 Apr 2008 20:11:42 +0900 (JST)
Subject: [ruby-changes:4587] knu - Ruby:r16081 (ruby_1_8): * array.c (rb_ary_equal, rb_ary_eql, rb_ary_hash, rb_ary_cmp):

knu	2008-04-19 20:11:25 +0900 (Sat, 19 Apr 2008)

  New Revision: 16081

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/NEWS
    branches/ruby_1_8/array.c
    branches/ruby_1_8/hash.c

  Log:
    * array.c (rb_ary_equal, rb_ary_eql, rb_ary_hash, rb_ary_cmp):
      Make Array#eql?, #hash, #== and #<=> use rb_exec_recursive() and
      handle recursive data properly.
    
    * hash.c (hash_equal, rb_hash_hash): Make Hash#eql?, #hash and #==
      use rb_exec_recursive() and handle recursive data properly.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/ChangeLog?r1=16081&r2=16080&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/hash.c?r1=16081&r2=16080&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/array.c?r1=16081&r2=16080&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/NEWS?r1=16081&r2=16080&diff_format=u

Index: ruby_1_8/array.c
===================================================================
--- ruby_1_8/array.c	(revision 16080)
+++ ruby_1_8/array.c	(revision 16081)
@@ -2595,6 +2595,22 @@
     return Qnil;
 }
 
+static VALUE recursive_equal _((VALUE, VALUE, int));
+static VALUE
+recursive_equal(ary1, ary2, recur)
+    VALUE ary1, ary2;
+    int recur;
+{
+    long i;
+
+    if (recur) return Qfalse;
+    for (i=0; i<RARRAY(ary1)->len; i++) {
+	if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+	    return Qfalse;
+    }
+    return Qtrue;
+}
+
 /* 
  *  call-seq:
  *     array == other_array   ->   bool
@@ -2613,8 +2629,6 @@
 rb_ary_equal(ary1, ary2)
     VALUE ary1, ary2;
 {
-    long i;
-
     if (ary1 == ary2) return Qtrue;
     if (TYPE(ary2) != T_ARRAY) {
 	if (!rb_respond_to(ary2, rb_intern("to_ary"))) {
@@ -2623,8 +2637,20 @@
 	return rb_equal(ary2, ary1);
     }
     if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
+    return rb_exec_recursive(recursive_equal, ary1, ary2);
+}
+
+static VALUE recursive_eql _((VALUE, VALUE, int));
+static VALUE
+recursive_eql(ary1, ary2, recur)
+    VALUE ary1, ary2;
+    int recur;
+{
+    long i;
+
+    if (recur) return Qfalse;
     for (i=0; i<RARRAY(ary1)->len; i++) {
-	if (!rb_equal(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
+	if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
 	    return Qfalse;
     }
     return Qtrue;
@@ -2642,33 +2668,26 @@
 rb_ary_eql(ary1, ary2)
     VALUE ary1, ary2;
 {
-    long i;
-
     if (ary1 == ary2) return Qtrue;
     if (TYPE(ary2) != T_ARRAY) return Qfalse;
     if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
-    for (i=0; i<RARRAY(ary1)->len; i++) {
-	if (!rb_eql(rb_ary_elt(ary1, i), rb_ary_elt(ary2, i)))
-	    return Qfalse;
-    }
-    return Qtrue;
+    return rb_exec_recursive(recursive_eql, ary1, ary2);
 }
 
-/*
- *  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 recursive_hash _((VALUE, VALUE, int));
 static VALUE
-rb_ary_hash(ary)
+recursive_hash(ary, dummy, recur)
     VALUE ary;
+    VALUE dummy;
+    int recur;
 {
     long i, h;
     VALUE n;
 
+    if (recur) {
+	return LONG2FIX(0);
+    }
+
     h = RARRAY(ary)->len;
     for (i=0; i<RARRAY(ary)->len; i++) {
 	h = (h << 1) | (h<0 ? 1 : 0);
@@ -2680,6 +2699,21 @@
 
 /*
  *  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_ary_hash(ary)
+    VALUE ary;
+{
+    return rb_exec_recursive(recursive_hash, ary, 0);
+}
+
+/*
+ *  call-seq:
  *     array.include?(obj)   -> true or false
  *  
  *  Returns <code>true</code> if the given object is present in
@@ -2707,6 +2741,29 @@
 }
 
 
+static VALUE recursive_cmp _((VALUE, VALUE, int));
+static VALUE
+recursive_cmp(ary1, ary2, recur)
+    VALUE ary1;
+    VALUE ary2;
+    int recur;
+{
+    long i, len;
+
+    if (recur) return Qnil;
+    len = RARRAY(ary1)->len;
+    if (len > RARRAY(ary2)->len) {
+	len = RARRAY(ary2)->len;
+    }
+    for (i=0; i<len; i++) {
+	VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
+	if (v != INT2FIX(0)) {
+	    return v;
+	}
+    }
+    return Qundef;
+}
+
 /* 
  *  call-seq:
  *     array <=> other_array   ->  -1, 0, +1
@@ -2731,19 +2788,13 @@
 rb_ary_cmp(ary1, ary2)
     VALUE ary1, ary2;
 {
-    long i, len;
+    long len;
+    VALUE v;
 
     ary2 = to_ary(ary2);
-    len = RARRAY(ary1)->len;
-    if (len > RARRAY(ary2)->len) {
-	len = RARRAY(ary2)->len;
-    }
-    for (i=0; i<len; i++) {
-	VALUE v = rb_funcall(rb_ary_elt(ary1, i), id_cmp, 1, rb_ary_elt(ary2, i));
-	if (v != INT2FIX(0)) {
-	    return v;
-	}
-    }
+    if (ary1 == ary2) return INT2FIX(0);
+    v = rb_exec_recursive(recursive_cmp, ary1, ary2);
+    if (v != Qundef) return v;
     len = RARRAY(ary1)->len - RARRAY(ary2)->len;
     if (len == 0) return INT2FIX(0);
     if (len > 0) return INT2FIX(1);
Index: ruby_1_8/hash.c
===================================================================
--- ruby_1_8/hash.c	(revision 16080)
+++ ruby_1_8/hash.c	(revision 16081)
@@ -1501,11 +1501,13 @@
 struct equal_data {
     int result;
     st_table *tbl;
+    int eql;
 };
 
 static int
-equal_i(key, val1, data)
-    VALUE key, val1;
+eql_i(key, val1, data)
+    VALUE key;
+    VALUE val1;
     struct equal_data *data;
 {
     VALUE val2;
@@ -1515,14 +1517,31 @@
 	data->result = Qfalse;
 	return ST_STOP;
     }
-    if (!rb_equal(val1, val2)) {
+    if (!(data->eql ? rb_eql(val1, val2) : rb_equal(val1, val2))) {
 	data->result = Qfalse;
 	return ST_STOP;
     }
     return ST_CONTINUE;
 }
 
+static VALUE recursive_eql _((VALUE, VALUE, int));
 static VALUE
+recursive_eql(hash, dt, recur)
+    VALUE hash;
+    VALUE dt;
+    int recur;
+{
+    struct equal_data *data;
+
+    if (recur) return Qfalse;
+    data = (struct equal_data*)dt;
+    data->result = Qtrue;
+    rb_hash_foreach(hash, eql_i, (st_data_t)data);
+
+    return data->result;
+}
+
+static VALUE
 hash_equal(hash1, hash2, eql)
     VALUE hash1, hash2;
     int eql;			/* compare default value if true */
@@ -1545,10 +1564,8 @@
     }
 
     data.tbl = RHASH(hash2)->tbl;
-    data.result = Qtrue;
-    rb_hash_foreach(hash1, equal_i, (st_data_t)&data);
-
-    return data.result;
+    data.eql = eql;
+    return rb_exec_recursive(recursive_eql, hash1, (VALUE)&data);
 }
 
 /*
@@ -1578,6 +1595,66 @@
 }
 
 static int
+hash_i(key, val, hval)
+    VALUE key;
+    VALUE val;
+    int *hval;
+{
+    if (key == Qundef) return ST_CONTINUE;
+    *hval ^= rb_hash(key);
+    *hval *= 137;
+    *hval ^= rb_hash(val);
+    return ST_CONTINUE;
+}
+
+static VALUE
+recursive_hash(hash, dummy, recur)
+    VALUE hash;
+    VALUE dummy;
+    int recur;
+{
+    int hval;
+
+    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(hash)
+    VALUE hash;
+{
+    return rb_exec_recursive(recursive_hash, hash, 0);
+}
+
+
+/*
+ *  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(hash1, hash2)
+    VALUE hash1, hash2;
+{
+    return hash_equal(hash1, hash2, Qtrue);
+}
+
+static int
 rb_hash_invert_i(key, value, hash)
     VALUE key, value;
     VALUE hash;
@@ -2545,6 +2622,8 @@
 
     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);
Index: ruby_1_8/NEWS
===================================================================
--- ruby_1_8/NEWS	(revision 16080)
+++ ruby_1_8/NEWS	(revision 16081)
@@ -27,6 +27,13 @@
     Takes an optional argument that determines the level of recursion
     to flatten.
 
+  * Array#eql?
+  * Array#hash
+  * Array#==
+  * Array#<=>
+
+    Handle recursive data properly.
+
   * Array#index
   * Array#rindex
 
@@ -122,6 +129,12 @@
 
     New alias to #inject.
 
+  * Hash#eql?
+  * Hash#hash
+  * Hash#==
+
+    Handle recursive data properly.
+
   * Hash#delete_if
   * Hash#each
   * Hash#each_key
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 16080)
+++ ruby_1_8/ChangeLog	(revision 16081)
@@ -1,3 +1,12 @@
+Sat Apr 19 20:05:39 2008  Akinori MUSHA  <knu@i...>
+
+	* array.c (rb_ary_equal, rb_ary_eql, rb_ary_hash, rb_ary_cmp):
+	  Make Array#eql?, #hash, #== and #<=> use rb_exec_recursive() and
+	  handle recursive data properly.
+
+	* hash.c (hash_equal, rb_hash_hash): Make Hash#eql?, #hash and #==
+	  use rb_exec_recursive() and handle recursive data properly.
+
 Sat Apr 19 19:26:09 2008  Akinori MUSHA  <knu@i...>
 
 	* intern.h, eval.c (rb_exec_recursive): New internal function to

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]