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

ruby-changes:20313

From: nobu <ko1@a...>
Date: Sat, 2 Jul 2011 07:18:01 +0900 (JST)
Subject: [ruby-changes:20313] nobu:r32360 (trunk, ruby_1_8): * array.c (rb_ary_reject_bang, rb_ary_delete_if): rejected

nobu	2011-07-02 07:17:46 +0900 (Sat, 02 Jul 2011)

  New Revision: 32360

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=32360

  Log:
    * array.c (rb_ary_reject_bang, rb_ary_delete_if): rejected
      elements should be removed.  fixed [Bug #2545]

  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/array.c
    branches/ruby_1_8/test/ruby/test_array.rb
    trunk/ChangeLog
    trunk/array.c
    trunk/test/ruby/test_array.rb

Index: array.c
===================================================================
--- array.c	(revision 32359)
+++ array.c	(revision 32360)
@@ -2563,6 +2563,48 @@
     return rb_ary_delete_at(ary, NUM2LONG(arg1));
 }
 
+static VALUE
+ary_reject(VALUE orig, VALUE result)
+{
+    long i;
+    int rejected = 0;
+
+    for (i = 0; i < RARRAY_LEN(orig); i++) {
+	VALUE v = RARRAY_PTR(orig)[i];
+	if (!RTEST(rb_yield(v))) {
+	    rb_ary_push_1(result, v);
+	}
+	else {
+	    rejected = 1;
+	}
+    }
+    return rejected ? result : 0;
+}
+
+static VALUE
+ary_protecting_reject(VALUE arg)
+{
+    VALUE *args = (VALUE *)arg;
+    return ary_reject(args[0], args[1]);
+}
+
+static VALUE
+ary_reject_bang(VALUE ary)
+{
+    VALUE args[2];
+    int state = 0;
+
+    rb_ary_modify_check(ary);
+    args[0] = ary;
+    args[1] = rb_ary_new();
+    if (!rb_protect(ary_protecting_reject, (VALUE)args, &state)) {
+	return Qnil;
+    }
+    rb_ary_replace(ary, args[1]);
+    if (state) rb_jump_tag(state);
+    return ary;
+}
+
 /*
  *  call-seq:
  *     ary.reject! {|item| block }  -> ary or nil
@@ -2580,23 +2622,8 @@
 static VALUE
 rb_ary_reject_bang(VALUE ary)
 {
-    long i1, i2;
-
     RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_modify(ary);
-    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
-	VALUE v = RARRAY_PTR(ary)[i1];
-	if (RTEST(rb_yield(v))) continue;
-	if (i1 != i2) {
-	    rb_ary_store(ary, i2, v);
-	}
-	i2++;
-    }
-
-    if (RARRAY_LEN(ary) == i2) return Qnil;
-    if (i2 < RARRAY_LEN(ary))
-	ARY_SET_LEN(ary, i2);
-    return ary;
+    return ary_reject_bang(ary);
 }
 
 /*
@@ -2615,10 +2642,12 @@
 static VALUE
 rb_ary_reject(VALUE ary)
 {
+    VALUE rejected_ary;
+
     RETURN_ENUMERATOR(ary, 0, 0);
-    ary = rb_ary_dup(ary);
-    rb_ary_reject_bang(ary);
-    return ary;
+    rejected_ary = rb_ary_new();
+    ary_reject(ary, rejected_ary);
+    return rejected_ary;
 }
 
 /*
@@ -2640,7 +2669,7 @@
 rb_ary_delete_if(VALUE ary)
 {
     RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_reject_bang(ary);
+    ary_reject_bang(ary);
     return ary;
 }
 
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 32359)
+++ ChangeLog	(revision 32360)
@@ -1,3 +1,8 @@
+Sat Jul  2 07:17:45 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* array.c (rb_ary_reject_bang, rb_ary_delete_if): rejected
+	  elements should be removed.  fixed [Bug #2545]
+
 Sat Jul  2 01:57:00 2011  Kenta Murata  <mrkn@m...>
 
 	* NEWS: remove a description of Kernel#respond_to? because it has
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 32359)
+++ test/ruby/test_array.rb	(revision 32360)
@@ -607,6 +607,11 @@
     a = @cls[ 1, 2, 3, 4, 5 ]
     assert_equal(a, a.delete_if { |i| i > 3 })
     assert_equal(@cls[1, 2, 3], a)
+
+    bug2545 = '[ruby-core:27366]'
+    a = @cls[ 5, 6, 7, 8, 9, 10 ]
+    assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
+    assert_equal(@cls[7, 8], a, bug2545)
   end
 
   def test_dup
@@ -1087,6 +1092,11 @@
     a = @cls[ 1, 2, 3, 4, 5 ]
     assert_equal(a, a.reject! { |i| i > 3 })
     assert_equal(@cls[1, 2, 3], a)
+
+    bug2545 = '[ruby-core:27366]'
+    a = @cls[ 5, 6, 7, 8, 9, 10 ]
+    assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
+    assert_equal(@cls[7, 8], a, bug2545)
   end
 
   def test_replace
Index: ruby_1_8/array.c
===================================================================
--- ruby_1_8/array.c	(revision 32359)
+++ ruby_1_8/array.c	(revision 32360)
@@ -2200,6 +2200,51 @@
     return rb_ary_delete_at(ary, NUM2LONG(arg1));
 }
 
+static VALUE
+ary_reject(orig, result)
+    VALUE orig, result;
+{
+    long i;
+    int rejected = 0;
+
+    for (i = 0; i < RARRAY_LEN(orig); i++) {
+	VALUE v = RARRAY_PTR(orig)[i];
+	if (!RTEST(rb_yield(v))) {
+	    rb_ary_push_1(result, v);
+	}
+	else {
+	    rejected = 1;
+	}
+    }
+    return rejected ? result : 0;
+}
+
+static VALUE
+ary_protecting_reject(arg)
+    VALUE arg;
+{
+    VALUE *args = (VALUE *)arg;
+    return ary_reject(args[0], args[1]);
+}
+
+static VALUE
+ary_reject_bang(ary)
+    VALUE ary;
+{
+    VALUE args[2];
+    int state = 0;
+
+    rb_ary_modify_check(ary);
+    args[0] = ary;
+    args[1] = rb_ary_new();
+    if (!rb_protect(ary_protecting_reject, (VALUE)args, &state)) {
+	return Qnil;
+    }
+    rb_ary_replace(ary, args[1]);
+    if (state) rb_jump_tag(state);
+    return ary;
+}
+
 /*
  *  call-seq:
  *     array.reject! {|item| block }  -> array or nil
@@ -2214,23 +2259,8 @@
 rb_ary_reject_bang(ary)
     VALUE ary;
 {
-    long i1, i2;
-
     RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_modify(ary);
-    for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
-	VALUE v = RARRAY(ary)->ptr[i1];
-	if (RTEST(rb_yield(v))) continue;
-	if (i1 != i2) {
-	    rb_ary_store(ary, i2, v);
-	}
-	i2++;
-    }
-    if (RARRAY(ary)->len == i2) return Qnil;
-    if (i2 < RARRAY(ary)->len)
-	RARRAY(ary)->len = i2;
-
-    return ary;
+    return ary_reject_bang(ary);
 }
 
 /*
@@ -2245,10 +2275,12 @@
 rb_ary_reject(ary)
     VALUE ary;
 {
+    VALUE rejected_ary;
+
     RETURN_ENUMERATOR(ary, 0, 0);
-    ary = rb_ary_dup(ary);
-    rb_ary_reject_bang(ary);
-    return ary;
+    rejected_ary = rb_ary_new();
+    ary_reject(ary, rejected_ary);
+    return rejected_ary;
 }
 
 /*
@@ -2267,7 +2299,7 @@
     VALUE ary;
 {
     RETURN_ENUMERATOR(ary, 0, 0);
-    rb_ary_reject_bang(ary);
+    ary_reject_bang(ary);
     return ary;
 }
 
Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 32359)
+++ ruby_1_8/ChangeLog	(revision 32360)
@@ -1,3 +1,8 @@
+Sat Jul  2 07:17:45 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* array.c (rb_ary_reject_bang, rb_ary_delete_if): rejected
+	  elements should be removed.  fixed [Bug #2545]
+
 Wed Jun 29 23:17:57 2011  WATANABE Hirofumi  <eban@r...>
 
 	* ext/openssl/ossl.h (OPENSSL_SYS_WIN32): support for mingw(msys).
Index: ruby_1_8/test/ruby/test_array.rb
===================================================================
--- ruby_1_8/test/ruby/test_array.rb	(revision 32359)
+++ ruby_1_8/test/ruby/test_array.rb	(revision 32360)
@@ -597,6 +597,11 @@
     a = @cls[ 1, 2, 3, 4, 5 ]
     assert_equal(a, a.delete_if { |i| i > 3 })
     assert_equal(@cls[1, 2, 3], a)
+
+    bug2545 = '[ruby-core:27366]'
+    a = @cls[ 5, 6, 7, 8, 9, 10 ]
+    assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
+    assert_equal(@cls[7, 8], a, bug2545)
   end
 
   def test_dup
@@ -967,6 +972,11 @@
     a = @cls[ 1, 2, 3, 4, 5 ]
     assert_equal(a, a.reject! { |i| i > 3 })
     assert_equal(@cls[1, 2, 3], a)
+
+    bug2545 = '[ruby-core:27366]'
+    a = @cls[ 5, 6, 7, 8, 9, 10 ]
+    assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
+    assert_equal(@cls[7, 8], a, bug2545)
   end
 
   def test_replace

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

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