mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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: svn+ssh://ci.ruby-lang.org/ruby/trunk@23951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e972280921
commit
9d9986d25c
3 changed files with 111 additions and 31 deletions
|
@ -79,6 +79,15 @@ Wed Jul 1 06:47:09 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
|||
|
||||
* enum.c (enum_grep): gets rid of type-punning calls.
|
||||
|
||||
Wed Jul 1 06:36:28 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* 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.
|
||||
|
||||
Tue Jun 30 18:19:07 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
|
||||
|
||||
* hash.c (rb_hash_hash): documentation fix. a patch from
|
||||
|
|
121
array.c
121
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<max; i++) {
|
||||
val = RARRAY_PTR(ary)[i];
|
||||
if (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<RARRAY_LEN(ary); i++) {
|
||||
if (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<RARRAY_LEN(ary); i++) {
|
||||
tmp = rb_check_string_type(RARRAY_PTR(ary)[i]);
|
||||
len += NIL_P(tmp) ? 10 : RSTRING_LEN(tmp);
|
||||
}
|
||||
if (!NIL_P(sep)) {
|
||||
StringValue(sep);
|
||||
len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
|
||||
}
|
||||
result = rb_str_buf_new(len);
|
||||
for (i=0; i<RARRAY_LEN(ary); i++) {
|
||||
tmp = RARRAY_PTR(ary)[i];
|
||||
switch (TYPE(tmp)) {
|
||||
case T_STRING:
|
||||
break;
|
||||
case T_ARRAY:
|
||||
if (tmp == ary) {
|
||||
tmp = rb_usascii_str_new2("[...]");
|
||||
}
|
||||
else {
|
||||
VALUE args[2];
|
||||
val = RARRAY_PTR(ary)[i];
|
||||
tmp = rb_check_string_type(val);
|
||||
|
||||
args[0] = tmp;
|
||||
args[1] = sep;
|
||||
tmp = rb_exec_recursive(recursive_join, ary, (VALUE)args);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tmp = rb_obj_as_string(tmp);
|
||||
if (NIL_P(tmp) || tmp != val) {
|
||||
result = rb_str_buf_new(len + (RARRAY_LEN(ary)-i)*10);
|
||||
if (taint) OBJ_TAINT(result);
|
||||
if (untrust) OBJ_UNTRUST(result);
|
||||
ary_join_0(ary, sep, i, result);
|
||||
ary_join_1(ary, sep, i, result);
|
||||
return result;
|
||||
}
|
||||
if (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;
|
||||
}
|
||||
|
||||
|
|
12
enum.c
12
enum.c
|
@ -1803,6 +1803,17 @@ enum_cycle(int argc, VALUE *argv, VALUE obj)
|
|||
return Qnil; /* not reached */
|
||||
}
|
||||
|
||||
static VALUE
|
||||
enum_join(int argc, VALUE *argv, VALUE obj)
|
||||
{
|
||||
VALUE sep;
|
||||
|
||||
rb_scan_args(argc, argv, "01", &sep);
|
||||
if (NIL_P(sep)) sep = rb_output_fs;
|
||||
|
||||
return rb_ary_join(enum_to_a(0, 0, obj), sep);
|
||||
}
|
||||
|
||||
/*
|
||||
* The <code>Enumerable</code> mixin provides collection classes with
|
||||
* several traversal and searching methods, and with the ability to
|
||||
|
@ -1862,6 +1873,7 @@ Init_Enumerable(void)
|
|||
rb_define_method(rb_mEnumerable, "drop", enum_drop, 1);
|
||||
rb_define_method(rb_mEnumerable, "drop_while", enum_drop_while, 0);
|
||||
rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
|
||||
rb_define_method(rb_mEnumerable, "join", enum_join, -1);
|
||||
|
||||
id_eqq = rb_intern("===");
|
||||
id_each = rb_intern("each");
|
||||
|
|
Loading…
Reference in a new issue