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

ruby-changes:43948

From: nobu <ko1@a...>
Date: Sat, 27 Aug 2016 10:26:23 +0900 (JST)
Subject: [ruby-changes:43948] nobu:r56021 (trunk): multiple arguments

nobu	2016-08-27 10:26:17 +0900 (Sat, 27 Aug 2016)

  New Revision: 56021

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=56021

  Log:
    multiple arguments
    
    * array.c (rb_ary_concat_multi): take multiple arguments.  based
      on the patch by Satoru Horie.  [Feature #12333]
    * string.c (rb_str_concat_multi, rb_str_prepend_multi): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/array.c
    trunk/string.c
    trunk/test/ruby/test_array.rb
    trunk/test/ruby/test_string.rb
Index: string.c
===================================================================
--- string.c	(revision 56020)
+++ string.c	(revision 56021)
@@ -2798,20 +2798,43 @@ rb_str_concat_literals(size_t num, const https://github.com/ruby/ruby/blob/trunk/string.c#L2798
 
 /*
  *  call-seq:
- *     str << integer       -> str
- *     str.concat(integer)  -> str
- *     str << obj           -> str
- *     str.concat(obj)      -> str
+ *     str << integer                      -> str
+ *     str.concat(integer1, integer2,...)  -> str
+ *     str << obj                          -> str
+ *     str.concat(obj1, obj2,...)          -> str
  *
  *  Append---Concatenates the given object to <i>str</i>. If the object is an
  *  <code>Integer</code>, it is considered as a codepoint, and is converted
- *  to a character before concatenation.
+ *  to a character before concatenation. Concat can take multiple arguments.
+ *  All the arguments are concatenated in order.
  *
  *     a = "hello "
  *     a << "world"   #=> "hello world"
  *     a.concat(33)   #=> "hello world!"
+ *     a              #=> "hollo world!"
+ *
+ *     b = "sn"
+ *     b.concat(b, b)    #=> "snsnsn"
  */
 
+static VALUE
+rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
+{
+    str_modifiable(str);
+
+    if (argc > 0) {
+	int i;
+	VALUE arg_str = rb_str_tmp_new(0);
+	rb_enc_copy(arg_str, str);
+	for (i = 0; i < argc; i++) {
+	    rb_str_concat(arg_str, argv[i]);
+	}
+	rb_str_buf_append(str, arg_str);
+    }
+
+    return str;
+}
+
 VALUE
 rb_str_concat(VALUE str1, VALUE str2)
 {
@@ -2878,21 +2901,32 @@ rb_str_concat(VALUE str1, VALUE str2) https://github.com/ruby/ruby/blob/trunk/string.c#L2901
 
 /*
  *  call-seq:
- *     str.prepend(other_str)  -> str
+ *     str.prepend(other_str1, other_str2,...)  -> str
+ *
+ *  Prepend---Prepend the given strings to <i>str</i>.
  *
- *  Prepend---Prepend the given string to <i>str</i>.
+ *     a = "!"
+ *     a.prepend("hello ", "world") #=> "hello world!"
+ *     a                            #=> "hello world!"
  *
- *     a = "world"
- *     a.prepend("hello ") #=> "hello world"
- *     a                   #=> "hello world"
+ *  See also String#concat.
  */
 
 static VALUE
-rb_str_prepend(VALUE str, VALUE str2)
+rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
 {
-    StringValue(str2);
-    StringValue(str);
-    rb_str_update(str, 0L, 0L, str2);
+    str_modifiable(str);
+
+    if (argc > 0) {
+	int i;
+	VALUE arg_str = rb_str_tmp_new(0);
+	rb_enc_copy(arg_str, str);
+	for (i = 0; i < argc; i++) {
+	    rb_str_append(arg_str, argv[i]);
+	}
+	rb_str_update(str, 0L, 0L, arg_str);
+    }
+
     return str;
 }
 
@@ -9826,9 +9860,9 @@ Init_String(void) https://github.com/ruby/ruby/blob/trunk/string.c#L9860
     rb_define_method(rb_cString, "codepoints", rb_str_codepoints, 0);
     rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
     rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
-    rb_define_method(rb_cString, "concat", rb_str_concat, 1);
+    rb_define_method(rb_cString, "concat", rb_str_concat_multi, -1);
     rb_define_method(rb_cString, "<<", rb_str_concat, 1);
-    rb_define_method(rb_cString, "prepend", rb_str_prepend, 1);
+    rb_define_method(rb_cString, "prepend", rb_str_prepend_multi, -1);
     rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
     rb_define_method(rb_cString, "intern", rb_str_intern, 0); /* in symbol.c */
     rb_define_method(rb_cString, "to_sym", rb_str_intern, 0); /* in symbol.c */
Index: test/ruby/test_string.rb
===================================================================
--- test/ruby/test_string.rb	(revision 56020)
+++ test/ruby/test_string.rb	(revision 56021)
@@ -495,6 +495,8 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L495
   def test_concat
     assert_equal(S("world!"), S("world").concat(33))
     assert_equal(S("world!"), S("world").concat(S('!')))
+    b = S("sn")
+    assert_equal(S("snsnsn"), b.concat(b, b))
 
     bug7090 = '[ruby-core:47751]'
     result = S("").force_encoding(Encoding::UTF_16LE)
@@ -502,6 +504,7 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L504
     expected = S("\u0300".encode(Encoding::UTF_16LE))
     assert_equal(expected, result, bug7090)
     assert_raise(TypeError) { 'foo' << :foo }
+    assert_raise(RuntimeError) { 'foo'.freeze.concat('bar') }
   end
 
   def test_count
@@ -2313,7 +2316,9 @@ CODE https://github.com/ruby/ruby/blob/trunk/test/ruby/test_string.rb#L2316
   end
 
   def test_prepend
-    assert_equal(S("hello world!"), "world!".prepend("hello "))
+    assert_equal(S("hello world!"), "!".prepend("hello ", "world"))
+    b = S("ue")
+    assert_equal(S("ueueue"), b.prepend(b, b))
 
     foo = Object.new
     def foo.to_str
Index: test/ruby/test_array.rb
===================================================================
--- test/ruby/test_array.rb	(revision 56020)
+++ test/ruby/test_array.rb	(revision 56021)
@@ -556,7 +556,9 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L556
   def test_concat
     assert_equal(@cls[1, 2, 3, 4],     @cls[1, 2].concat(@cls[3, 4]))
     assert_equal(@cls[1, 2, 3, 4],     @cls[].concat(@cls[1, 2, 3, 4]))
+    assert_equal(@cls[1, 2, 3, 4],     @cls[1].concat(@cls[2, 3], [4]))
     assert_equal(@cls[1, 2, 3, 4],     @cls[1, 2, 3, 4].concat(@cls[]))
+    assert_equal(@cls[1, 2, 3, 4],     @cls[1, 2, 3, 4].concat())
     assert_equal(@cls[],               @cls[].concat(@cls[]))
     assert_equal(@cls[@cls[1, 2], @cls[3, 4]], @cls[@cls[1, 2]].concat(@cls[@cls[3, 4]]))
 
@@ -564,6 +566,10 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L566
     a.concat(a)
     assert_equal([1, 2, 3, 1, 2, 3], a)
 
+    b = @cls[4, 5]
+    b.concat(b, b)
+    assert_equal([4, 5, 4, 5, 4, 5], b)
+
     assert_raise(TypeError) { [0].concat(:foo) }
     assert_raise(RuntimeError) { [0].freeze.concat(:foo) }
   end
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 56020)
+++ ChangeLog	(revision 56021)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Aug 27 10:26:14 2016  Nobuyoshi Nakada  <nobu@r...>
+
+	* array.c (rb_ary_concat_multi): take multiple arguments.  based
+	  on the patch by Satoru Horie.  [Feature #12333]
+
+	* string.c (rb_str_concat_multi, rb_str_prepend_multi): ditto.
+
 Thu Aug 25 00:42:31 2016  Nobuyoshi Nakada  <nobu@r...>
 
 	* win32/file.c (append_wstr): remove a codepage argument, and use
Index: array.c
===================================================================
--- array.c	(revision 56020)
+++ array.c	(revision 56021)
@@ -3623,31 +3623,58 @@ rb_ary_plus(VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/array.c#L3623
     return z;
 }
 
+static VALUE
+ary_append(VALUE x, VALUE y)
+{
+    long n = RARRAY_LEN(y);
+    if (n > 0) {
+	rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), n);
+    }
+    return x;
+}
+
 /*
  *  call-seq:
- *     ary.concat(other_ary)   -> ary
+ *     ary.concat(other_ary1, other_ary2,...)   -> ary
  *
- *  Appends the elements of +other_ary+ to +self+.
+ *  Appends the elements of +other_ary+s to +self+.
  *
  *     [ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
+ *     [ "a" ].concat( ["b"], ["c", "d"] ) #=> [ "a", "b", "c", "d" ]
+ *     [ "a" ].concat #=> [ "a" ]
+ *
  *     a = [ 1, 2, 3 ]
  *     a.concat( [ 4, 5 ] )
  *     a                                 #=> [ 1, 2, 3, 4, 5 ]
  *
+ *     a = [ 1, 2 ]
+ *     a.concat(a, a)                    #=> [1, 2, 1, 2, 1, 2]
+ *
  *  See also Array#+.
  */
 
-VALUE
-rb_ary_concat(VALUE x, VALUE y)
+static VALUE
+rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
 {
-    rb_ary_modify_check(x);
-    y = to_ary(y);
-    if (RARRAY_LEN(y) > 0) {
-	rb_ary_splice(x, RARRAY_LEN(x), 0, RARRAY_CONST_PTR(y), RARRAY_LEN(y));
+    rb_ary_modify_check(ary);
+
+    if (argc > 0) {
+	int i;
+	VALUE args = rb_ary_tmp_new(argc);
+	for (i = 0; i < argc; i++) {
+	    rb_ary_concat(args, argv[i]);
+	}
+	ary_append(ary, args);
     }
-    return x;
+
+    return ary;
 }
 
+VALUE
+rb_ary_concat(VALUE x, VALUE y)
+{
+    return ary_append(x, to_ary(y));
+}
 
 /*
  *  call-seq:
@@ -6073,7 +6100,7 @@ Init_Array(void) https://github.com/ruby/ruby/blob/trunk/array.c#L6100
     rb_define_method(rb_cArray, "fetch", rb_ary_fetch, -1);
     rb_define_method(rb_cArray, "first", rb_ary_first, -1);
     rb_define_method(rb_cArray, "last", rb_ary_last, -1);
-    rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
+    rb_define_method(rb_cArray, "concat", rb_ary_concat_multi, -1);
     rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
     rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
     rb_define_method(rb_cArray, "pop", rb_ary_pop_m, -1);

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

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