chomp!(...)
public
Modifies str in place as described for String#chomp,
returning str, or nil if no modifications were made.
Show source
/*
* 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(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE rs;
int newline;
char *p;
long len, rslen;
if (rb_scan_args(argc, argv, "01", &rs) == 0) {
len = RSTRING(str)->len;
if (len == 0) return Qnil;
p = RSTRING(str)->ptr;
rs = rb_rs;
if (rs == rb_default_rs) {
smart_chomp:
rb_str_modify(str);
if (RSTRING(str)->ptr[len-1] == '\n') {
RSTRING(str)->len--;
if (RSTRING(str)->len > 0 &&
RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') {
RSTRING(str)->len--;
}
}
else if (RSTRING(str)->ptr[len-1] == '\r') {
RSTRING(str)->len--;
}
else {
return Qnil;
}
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
return str;
}
}
if (NIL_P(rs)) return Qnil;
StringValue(rs);
len = RSTRING(str)->len;
if (len == 0) return Qnil;
p = RSTRING(str)->ptr;
rslen = RSTRING(rs)->len;
if (rslen == 0) {
while (len>0 && p[len-1] == '\n') {
len--;
if (len>0 && p[len-1] == '\r')
len--;
}
if (len < RSTRING(str)->len) {
rb_str_modify(str);
RSTRING(str)->len = len;
RSTRING(str)->ptr[len] = '\0';
return str;
}
return Qnil;
}
if (rslen > len) return Qnil;
newline = RSTRING(rs)->ptr[rslen-1];
if (rslen == 1 && newline == '\n')
goto smart_chomp;
if (p[len-1] == newline &&
(rslen <= 1 ||
rb_memcmp(RSTRING(rs)->ptr, p+len-rslen, rslen) == 0)) {
rb_str_modify(str);
RSTRING(str)->len -= rslen;
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
return str;
}
return Qnil;
}