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/