Feature #5970 ยป enumerable_join.patch
enum.c | ||
---|---|---|
#include "ruby/ruby.h"
|
||
#include "ruby/util.h"
|
||
#include "ruby/encoding.h"
|
||
#include "node.h"
|
||
#include "id.h"
|
||
#include "internal.h"
|
||
... | ... | |
}
|
||
static VALUE
|
||
enum_join_i(VALUE obj, VALUE *params, int argc, VALUE *argv)
|
||
{
|
||
VALUE *param = (VALUE *)params;
|
||
VALUE sep = param[0];
|
||
VALUE result = param[1];
|
||
int *first = (int *)param[2];
|
||
ID join = rb_intern("join");
|
||
VALUE tmp;
|
||
switch (TYPE(obj)) {
|
||
case T_STRING:
|
||
str_join:
|
||
if (!NIL_P(sep) && !*first)
|
||
rb_str_buf_append(result, sep);
|
||
if (*first)
|
||
rb_enc_copy(result, obj);
|
||
rb_str_buf_append(result, obj);
|
||
*first = FALSE;
|
||
break;
|
||
default:
|
||
if (rb_respond_to(obj, join)) {
|
||
obj = rb_funcall(obj, join, 1, sep);
|
||
}
|
||
else {
|
||
obj = rb_obj_as_string(obj);
|
||
}
|
||
rb_enc_copy(obj, result);
|
||
goto str_join;
|
||
}
|
||
return result;
|
||
}
|
||
/*
|
||
* call-seq:
|
||
* enum.join(sep=$,) -> str
|
||
*
|
||
* Returns a string created by converting each element of the
|
||
* <i>enum</i> to a string, separated by <i>sep</i>.
|
||
*
|
||
* (1..3).join #=> "123"
|
||
* (1..3).join("-") #=> "1-2-3"
|
||
*/
|
||
static VALUE
|
||
enum_join(int argc, VALUE *argv, VALUE obj)
|
||
{
|
||
VALUE sep;
|
||
VALUE result;
|
||
VALUE args[3];
|
||
int first = TRUE;
|
||
int taint = FALSE;
|
||
int untrust = FALSE;
|
||
if (!enum_any(obj))
|
||
return rb_usascii_str_new(0, 0);
|
||
rb_scan_args(argc, argv, "01", &sep);
|
||
if (NIL_P(sep)) sep = rb_output_fs;
|
||
if (!NIL_P(sep)) StringValue(sep);
|
||
if (OBJ_TAINTED(obj) || OBJ_TAINTED(sep)) taint = TRUE;
|
||
if (OBJ_UNTRUSTED(obj) || OBJ_UNTRUSTED(sep)) untrust = TRUE;
|
||
result = rb_usascii_str_new(0, 0);
|
||
if (taint) OBJ_TAINT(result);
|
||
if (untrust) OBJ_UNTRUST(result);
|
||
args[0] = sep;
|
||
args[1] = result;
|
||
args[2] = (VALUE)&first;
|
||
rb_block_call(obj, id_each, 0, 0, enum_join_i, (VALUE)args);
|
||
return result;
|
||
}
|
||
static VALUE
|
||
cycle_i(VALUE i, VALUE ary, int argc, VALUE *argv)
|
||
{
|
||
ENUM_WANT_SVALUE();
|
||
... | ... | |
rb_define_method(rb_mEnumerable, "cycle", enum_cycle, -1);
|
||
rb_define_method(rb_mEnumerable, "chunk", enum_chunk, -1);
|
||
rb_define_method(rb_mEnumerable, "slice_before", enum_slice_before, -1);
|
||
rb_define_method(rb_mEnumerable, "join", enum_join, -1);
|
||
id_next = rb_intern("next");
|
||
}
|
test/ruby/test_enum.rb | ||
---|---|---|
assert_equal([1, 2, 3, 1, 2], @obj.to_a)
|
||
end
|
||
def test_join
|
||
assert_equal('123', (1..3).join )
|
||
@speach = Object.new
|
||
class << @speach
|
||
attr_writer :statements
|
||
include Enumerable
|
||
def each
|
||
@statements.each{|s| yield s }
|
||
end
|
||
end
|
||
@speach.statements = [1,2,3,1,2]
|
||
assert_equal('12312', @speach.join )
|
||
assert_equal('1;2;3;1;2', @speach.join(';') )
|
||
@speach.statements = [ [9,8,7], 'ohai', @obj ]
|
||
assert_equal('9;8;7;ohai;1;2;3;1;2', @speach.join(';') )
|
||
@speach.statements = []
|
||
assert_equal('', @speach.join )
|
||
["", ":", nil].each do |output_fs|
|
||
$, = output_fs
|
||
assert_equal("", @speach.join)
|
||
assert_equal("", @speach.join(','))
|
||
assert_equal(Encoding::US_ASCII, @speach.join.encoding)
|
||
end
|
||
@speach.statements = [1,2,3,1,2]
|
||
["", ":", nil].each do |output_fs|
|
||
assert_equal("1,2,3,1,2", @speach.join(','))
|
||
end
|
||
$, = ":"
|
||
assert_equal("1:2:3:1:2", @speach.join)
|
||
$, = nil
|
||
assert_equal("12312", @speach.join)
|
||
@speach.taint
|
||
@speach.untrust
|
||
s = @speach.join
|
||
assert_equal(true, s.tainted?)
|
||
assert_equal(true, s.untrusted?)
|
||
e = ''.force_encoding('EUC-JP')
|
||
u = ''.force_encoding('UTF-8')
|
||
assert_equal(Encoding::US_ASCII, @speach.join.encoding)
|
||
@speach.statements = [1, [u]]
|
||
assert_equal(Encoding::US_ASCII, @speach.join.encoding)
|
||
@speach.statements = [u, [e]]
|
||
assert_equal(Encoding::UTF_8, @speach.join.encoding)
|
||
@speach.statements = [u, [1]]
|
||
assert_equal(Encoding::UTF_8, @speach.join.encoding)
|
||
bug5379 = '[ruby-core:39776]'
|
||
@speach.statements = [[], u, nil]
|
||
assert_equal(Encoding::US_ASCII, @speach.join.encoding, bug5379)
|
||
@speach.statements = [[], "\u3042", nil]
|
||
assert_equal(Encoding::UTF_8, @speach.join.encoding, bug5379)
|
||
@nested = Object.new
|
||
class << @nested
|
||
include Enumerable
|
||
class Nested
|
||
include Enumerable
|
||
def each
|
||
yield Nested.new
|
||
end
|
||
end
|
||
def each
|
||
yield Nested.new
|
||
end
|
||
end
|
||
assert_raise(SystemStackError){ @nested.join }
|
||
ensure
|
||
$, = nil
|
||
end
|
||
def test_inject
|
||
assert_equal(12, @obj.inject {|z, x| z * x })
|
||
assert_equal(48, @obj.inject {|z, x| z * 2 + x })
|