From d32b853e4502e385372e5ae45503290df824518e Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 3 Jul 2009 18:14:33 +0000 Subject: * enum.c (enum_join): add Enumerable#join. * array.c (ary_join_1): recursive join for Enumerators (and objects with #to_a). * array.c (rb_ary_join): performance tune. git-svn-id: http://svn.ruby-lang.org/repos/ruby/trunk@23951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- array.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 32 deletions(-) (limited to 'array.c') diff --git a/array.c b/array.c index cb37a2ead..059574026 100644 --- a/array.c +++ b/array.c @@ -1519,14 +1519,86 @@ rb_ary_resurrect(VALUE ary) extern VALUE rb_output_fs; +static void ary_join_1(VALUE ary, VALUE sep, long i, VALUE result); + static VALUE -recursive_join(VALUE ary, VALUE argp, int recur) +recursive_join(VALUE obj, VALUE argp, int recur) { VALUE *arg = (VALUE *)argp; + VALUE ary = arg[0]; + VALUE sep = arg[1]; + VALUE result = arg[2]; + if (recur) { - return rb_usascii_str_new2("[...]"); + rb_str_buf_cat_ascii(result, "[...]"); + } + else { + ary_join_1(ary, sep, 0, result); + } + return Qnil; +} + +static void +ary_join_0(VALUE ary, VALUE sep, long max, VALUE result) +{ + long i; + VALUE val; + + for (i=0; i 0 && !NIL_P(sep)) + rb_str_buf_append(result, sep); + rb_str_buf_append(result, val); + if (OBJ_TAINTED(val)) OBJ_TAINT(result); + if (OBJ_UNTRUSTED(val)) OBJ_TAINT(result); + } +} + +static void +ary_join_1(VALUE ary, VALUE sep, long i, VALUE result) +{ + VALUE val, tmp; + + for (; i 0 && !NIL_P(sep)) + rb_str_buf_append(result, sep); + + val = RARRAY_PTR(ary)[i]; + switch (TYPE(val)) { + case T_STRING: + str_join: + rb_str_buf_append(result, val); + break; + case T_ARRAY: + ary_join: + if (val == ary) { + val = rb_usascii_str_new2("[...]"); + goto str_join; + } + else { + VALUE args[3]; + + args[0] = val; + args[1] = sep; + args[2] = result; + rb_exec_recursive(recursive_join, ary, (VALUE)args); + } + break; + default: + tmp = rb_check_string_type(val); + if (!NIL_P(tmp)) { + val = tmp; + goto str_join; + } + tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a"); + if (!NIL_P(tmp)) { + val = tmp; + goto ary_join; + } + val = rb_obj_as_string(val); + goto str_join; + } } - return rb_ary_join(arg[0], arg[1]); } VALUE @@ -1535,50 +1607,37 @@ rb_ary_join(VALUE ary, VALUE sep) long len = 1, i; int taint = Qfalse; int untrust = Qfalse; - VALUE result, tmp; + VALUE val, tmp, result; if (RARRAY_LEN(ary) == 0) return rb_str_new(0, 0); if (OBJ_TAINTED(ary) || OBJ_TAINTED(sep)) taint = Qtrue; if (OBJ_UNTRUSTED(ary) || OBJ_UNTRUSTED(sep)) untrust = Qtrue; - for (i=0; i 0 && !NIL_P(sep)) - rb_str_buf_append(result, sep); - rb_str_buf_append(result, tmp); - if (OBJ_TAINTED(tmp)) taint = Qtrue; - if (OBJ_UNTRUSTED(tmp)) untrust = Qtrue; + + len += RSTRING_LEN(tmp); } + result = rb_str_buf_new(len); if (taint) OBJ_TAINT(result); if (untrust) OBJ_UNTRUST(result); + ary_join_0(ary, sep, RARRAY_LEN(ary), result); + return result; } -- cgit