string.c: chompped_length chomp_rs
* string.c (chompped_length, chomp_rs): extract from rb_str_chomp_bang to share with rb_str_chomp. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48756 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
d5b5338421
commit
516b9026fd
168
string.c
168
string.c
@ -7044,33 +7044,21 @@ rb_str_chop(VALUE str)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* str.chomp!(separator=$/) -> str or nil
|
||||
*
|
||||
* Modifies <i>str</i> in place as described for <code>String#chomp</code>,
|
||||
* returning <i>str</i>, or <code>nil</code> if no modifications were made.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
|
||||
static long
|
||||
chompped_length(VALUE str, VALUE rs)
|
||||
{
|
||||
rb_encoding *enc;
|
||||
VALUE rs;
|
||||
int newline;
|
||||
char *p, *pp, *e;
|
||||
long len, rslen;
|
||||
char *pp, *e, *rsptr;
|
||||
long rslen;
|
||||
char *const p = RSTRING_PTR(str);
|
||||
long len = RSTRING_LEN(str);
|
||||
|
||||
str_modify_keep_cr(str);
|
||||
len = RSTRING_LEN(str);
|
||||
if (len == 0) return Qnil;
|
||||
p = RSTRING_PTR(str);
|
||||
if (len == 0) return 0;
|
||||
e = p + len;
|
||||
if (argc == 0) {
|
||||
rs = rb_rs;
|
||||
enc = rb_enc_get(str);
|
||||
if (rs == rb_default_rs) {
|
||||
smart_chomp:
|
||||
enc = rb_enc_get(str);
|
||||
if (rb_enc_mbminlen(enc) > 1) {
|
||||
pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
|
||||
if (rb_enc_is_newline(pp, e, enc)) {
|
||||
@ -7083,72 +7071,116 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
|
||||
e = pp;
|
||||
}
|
||||
}
|
||||
if (e == RSTRING_END(str)) {
|
||||
return Qnil;
|
||||
}
|
||||
len = e - RSTRING_PTR(str);
|
||||
STR_SET_LEN(str, len);
|
||||
}
|
||||
else {
|
||||
if (RSTRING_PTR(str)[len-1] == '\n') {
|
||||
STR_DEC_LEN(str);
|
||||
if (RSTRING_LEN(str) > 0 &&
|
||||
RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\r') {
|
||||
STR_DEC_LEN(str);
|
||||
switch (*(e-1)) { /* not e[-1] to get rid of VC bug */
|
||||
case '\n':
|
||||
if (--e > p && *(e-1) == '\r') {
|
||||
--e;
|
||||
}
|
||||
break;
|
||||
case '\r':
|
||||
--e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (RSTRING_PTR(str)[len-1] == '\r') {
|
||||
STR_DEC_LEN(str);
|
||||
return e - p;
|
||||
}
|
||||
else {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
|
||||
return str;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rb_scan_args(argc, argv, "01", &rs);
|
||||
}
|
||||
if (NIL_P(rs)) return Qnil;
|
||||
StringValue(rs);
|
||||
rslen = RSTRING_LEN(rs);
|
||||
|
||||
RSTRING_GETMEM(rs, rsptr, rslen);
|
||||
if (rslen == 0) {
|
||||
while (len>0 && p[len-1] == '\n') {
|
||||
len--;
|
||||
if (len>0 && p[len-1] == '\r')
|
||||
len--;
|
||||
if (rb_enc_mbminlen(enc) > 1) {
|
||||
while (e > p) {
|
||||
pp = rb_enc_left_char_head(p, e-rb_enc_mbminlen(enc), e, enc);
|
||||
if (!rb_enc_is_newline(pp, e, enc)) break;
|
||||
e = pp;
|
||||
pp -= rb_enc_mbminlen(enc);
|
||||
if (pp >= p) {
|
||||
pp = rb_enc_left_char_head(p, pp, e, enc);
|
||||
if (rb_enc_ascget(pp, e, 0, enc) == '\r') {
|
||||
e = pp;
|
||||
}
|
||||
if (len < RSTRING_LEN(str)) {
|
||||
STR_SET_LEN(str, len);
|
||||
RSTRING_PTR(str)[len] = '\0';
|
||||
return str;
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
if (rslen > len) return Qnil;
|
||||
newline = RSTRING_PTR(rs)[rslen-1];
|
||||
if (rslen == 1 && newline == '\n')
|
||||
goto smart_chomp;
|
||||
}
|
||||
else {
|
||||
while (e > p && *(e-1) == '\n') {
|
||||
--e;
|
||||
if (e > p && *(e-1) == '\r')
|
||||
--e;
|
||||
}
|
||||
}
|
||||
return e - p;
|
||||
}
|
||||
if (rslen > len) return len;
|
||||
|
||||
enc = rb_enc_check(str, rs);
|
||||
if (is_broken_string(rs)) {
|
||||
return Qnil;
|
||||
return len;
|
||||
}
|
||||
newline = rsptr[rslen-1];
|
||||
if (rslen == rb_enc_mbminlen(enc)) {
|
||||
if (rslen == 1) {
|
||||
if (newline == '\n')
|
||||
goto smart_chomp;
|
||||
}
|
||||
else {
|
||||
if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
|
||||
goto smart_chomp;
|
||||
}
|
||||
}
|
||||
|
||||
pp = e - rslen;
|
||||
if (p[len-1] == newline &&
|
||||
(rslen <= 1 ||
|
||||
memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
|
||||
if (rb_enc_left_char_head(p, pp, e, enc) != pp)
|
||||
return Qnil;
|
||||
memcmp(rsptr, pp, rslen) == 0)) {
|
||||
if (rb_enc_left_char_head(p, pp, e, enc) == pp)
|
||||
return len - rslen;
|
||||
RB_GC_GUARD(rs);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
chomp_rs(int argc, const VALUE *argv)
|
||||
{
|
||||
rb_check_arity(argc, 0, 1);
|
||||
if (argc > 0) {
|
||||
VALUE rs = argv[0];
|
||||
if (!NIL_P(rs)) StringValue(rs);
|
||||
return rs;
|
||||
}
|
||||
else {
|
||||
return rb_rs;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* str.chomp!(separator=$/) -> str or nil
|
||||
*
|
||||
* Modifies <i>str</i> in place as described for <code>String#chomp</code>,
|
||||
* returning <i>str</i>, or <code>nil</code> if no modifications were made.
|
||||
*/
|
||||
|
||||
static VALUE
|
||||
rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
|
||||
{
|
||||
VALUE rs;
|
||||
long olen;
|
||||
str_modify_keep_cr(str);
|
||||
if ((olen = RSTRING_LEN(str)) > 0 && !NIL_P(rs = chomp_rs(argc, argv))) {
|
||||
long len;
|
||||
len = chompped_length(str, rs);
|
||||
if (len < olen) {
|
||||
STR_SET_LEN(str, len);
|
||||
RSTRING_PTR(str)[len] = '\0';
|
||||
if (ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
|
||||
ENC_CODERANGE_CLEAR(str);
|
||||
}
|
||||
STR_SET_LEN(str, RSTRING_LEN(str) - rslen);
|
||||
RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
|
||||
return str;
|
||||
}
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@ -7178,9 +7210,9 @@ rb_str_chomp_bang(int argc, VALUE *argv, VALUE str)
|
||||
static VALUE
|
||||
rb_str_chomp(int argc, VALUE *argv, VALUE str)
|
||||
{
|
||||
str = rb_str_dup(str);
|
||||
rb_str_chomp_bang(argc, argv, str);
|
||||
return str;
|
||||
VALUE rs = chomp_rs(argc, argv);
|
||||
if (NIL_P(rs)) return rb_str_dup(str);
|
||||
return rb_str_subseq(str, 0, chompped_length(str, rs));
|
||||
}
|
||||
|
||||
static long
|
||||
|
Loading…
x
Reference in New Issue
Block a user