* 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:
matz 2009-07-03 18:14:33 +00:00
Родитель e972280921
Коммит 9d9986d25c
3 изменённых файлов: 111 добавлений и 31 удалений

Просмотреть файл

@ -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
Просмотреть файл

@ -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
Просмотреть файл

@ -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");