зеркало из https://github.com/github/ruby.git
string.c: chomp option
* string.c (rb_str_enumerate_lines): implement chomp option. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56972 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
9fa8006a01
Коммит
d95f5bc81a
53
string.c
53
string.c
|
@ -7376,22 +7376,41 @@ rb_str_split(VALUE str, const char *sep0)
|
||||||
return rb_str_split_m(1, &sep, str);
|
return rb_str_split_m(1, &sep, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
chomp_newline(const char *p, const char *e, rb_encoding *enc)
|
||||||
|
{
|
||||||
|
const char *prev = rb_enc_prev_char(p, e, e, enc);
|
||||||
|
if (rb_enc_is_newline(prev, e, enc)) {
|
||||||
|
e = prev;
|
||||||
|
prev = rb_enc_prev_char(p, e, e, enc);
|
||||||
|
if (rb_enc_ascget(prev, e, NULL, enc) == '\r')
|
||||||
|
e = prev;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, int wantarray)
|
rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, int wantarray)
|
||||||
{
|
{
|
||||||
rb_encoding *enc;
|
rb_encoding *enc;
|
||||||
VALUE line, rs, orig = str;
|
VALUE line, rs, orig = str, opts = Qnil, chomp = Qfalse;
|
||||||
const char *ptr, *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
|
const char *ptr, *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
|
||||||
long pos, len, rslen;
|
long pos, len, rslen;
|
||||||
int paragraph_mode = 0;
|
int paragraph_mode = 0;
|
||||||
|
int rsnewline = 0;
|
||||||
|
|
||||||
VALUE MAYBE_UNUSED(ary);
|
VALUE MAYBE_UNUSED(ary);
|
||||||
|
|
||||||
if (argc == 0)
|
if (rb_scan_args(argc, argv, "01:", &rs, &opts) == 0)
|
||||||
rs = rb_rs;
|
rs = rb_rs;
|
||||||
else
|
if (!NIL_P(opts)) {
|
||||||
rb_scan_args(argc, argv, "01", &rs);
|
static ID keywords[1];
|
||||||
|
if (!keywords[0]) {
|
||||||
|
keywords[0] = rb_intern_const("chomp");
|
||||||
|
}
|
||||||
|
rb_get_kwargs(opts, keywords, 0, 1, &chomp);
|
||||||
|
chomp = (chomp != Qundef && RTEST(chomp));
|
||||||
|
}
|
||||||
|
|
||||||
if (rb_block_given_p()) {
|
if (rb_block_given_p()) {
|
||||||
if (wantarray) {
|
if (wantarray) {
|
||||||
|
@ -7438,9 +7457,14 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, int wantarray)
|
||||||
rsptr = "\n\n";
|
rsptr = "\n\n";
|
||||||
rslen = 2;
|
rslen = 2;
|
||||||
paragraph_mode = 1;
|
paragraph_mode = 1;
|
||||||
|
rsnewline = 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rsptr = RSTRING_PTR(rs);
|
rsptr = RSTRING_PTR(rs);
|
||||||
|
if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
|
||||||
|
rb_enc_is_newline(rsptr, rsptr + RSTRING_LEN(rs), enc)) {
|
||||||
|
rsnewline = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rs == rb_default_rs || paragraph_mode) && !rb_enc_asciicompat(enc)) {
|
if ((rs == rb_default_rs || paragraph_mode) && !rb_enc_asciicompat(enc)) {
|
||||||
|
@ -7461,10 +7485,24 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, int wantarray)
|
||||||
}
|
}
|
||||||
subend = hit + rslen;
|
subend = hit + rslen;
|
||||||
if (paragraph_mode) {
|
if (paragraph_mode) {
|
||||||
while (subend < pend && rb_enc_is_newline(subend, pend, enc)) {
|
while (subend < pend) {
|
||||||
|
int n;
|
||||||
|
if (rb_enc_ascget(subend, pend, &n, enc) != '\r')
|
||||||
|
n = 0;
|
||||||
|
if (!rb_enc_is_newline(subend + n, pend, enc)) break;
|
||||||
|
subend += n;
|
||||||
subend += rb_enc_mbclen(subend, pend, enc);
|
subend += rb_enc_mbclen(subend, pend, enc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hit = subend;
|
||||||
|
if (chomp) {
|
||||||
|
if (rsnewline) {
|
||||||
|
subend = chomp_newline(subptr, subend, enc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subend -= rslen;
|
||||||
|
}
|
||||||
|
}
|
||||||
line = rb_str_subseq(str, subptr - ptr, subend - subptr);
|
line = rb_str_subseq(str, subptr - ptr, subend - subptr);
|
||||||
if (wantarray) {
|
if (wantarray) {
|
||||||
rb_ary_push(ary, line);
|
rb_ary_push(ary, line);
|
||||||
|
@ -7473,10 +7511,13 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, int wantarray)
|
||||||
rb_yield(line);
|
rb_yield(line);
|
||||||
str_mod_check(str, ptr, len);
|
str_mod_check(str, ptr, len);
|
||||||
}
|
}
|
||||||
subptr = subend;
|
subptr = hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subptr != pend) {
|
if (subptr != pend) {
|
||||||
|
if (chomp && paragraph_mode) {
|
||||||
|
pend = chomp_newline(subptr, pend, enc);
|
||||||
|
}
|
||||||
line = rb_str_subseq(str, subptr - ptr, pend - subptr);
|
line = rb_str_subseq(str, subptr - ptr, pend - subptr);
|
||||||
if (wantarray)
|
if (wantarray)
|
||||||
rb_ary_push(ary, line);
|
rb_ary_push(ary, line);
|
||||||
|
|
|
@ -816,6 +816,35 @@ CODE
|
||||||
$/ = save
|
$/ = save
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_each_line_chomp
|
||||||
|
res = []
|
||||||
|
S("hello\nworld").each_line("\n", chomp: true) {|x| res << x}
|
||||||
|
assert_equal(S("hello"), res[0])
|
||||||
|
assert_equal(S("world"), res[1])
|
||||||
|
|
||||||
|
res = []
|
||||||
|
S("hello\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
|
||||||
|
assert_equal(S("hello\n\n"), res[0])
|
||||||
|
assert_equal(S("world"), res[1])
|
||||||
|
|
||||||
|
res = []
|
||||||
|
S("hello!world").each_line(S('!'), chomp: true) {|x| res << x}
|
||||||
|
assert_equal(S("hello"), res[0])
|
||||||
|
assert_equal(S("world"), res[1])
|
||||||
|
|
||||||
|
res = []
|
||||||
|
S("a").each_line(S('ab'), chomp: true).each {|x| res << x}
|
||||||
|
assert_equal(1, res.size)
|
||||||
|
assert_equal(S("a"), res[0])
|
||||||
|
|
||||||
|
s = nil
|
||||||
|
"foo\nbar".each_line(nil, chomp: true) {|s2| s = s2 }
|
||||||
|
assert_equal("foo\nbar", s)
|
||||||
|
|
||||||
|
assert_equal "hello", S("hello\nworld").each_line(chomp: true).next
|
||||||
|
assert_equal "hello\nworld", S("hello\nworld").each_line(nil, chomp: true).next
|
||||||
|
end
|
||||||
|
|
||||||
def test_lines
|
def test_lines
|
||||||
s = S("hello\nworld")
|
s = S("hello\nworld")
|
||||||
assert_equal ["hello\n", "world"], s.lines
|
assert_equal ["hello\n", "world"], s.lines
|
||||||
|
|
Загрузка…
Ссылка в новой задаче