[前][次][番号順一覧][スレッド一覧]

ruby-changes:36675

From: nobu <ko1@a...>
Date: Wed, 10 Dec 2014 16:48:35 +0900 (JST)
Subject: [ruby-changes:36675] nobu:r48756 (trunk): string.c: chompped_length chomp_rs

nobu	2014-12-10 16:48:17 +0900 (Wed, 10 Dec 2014)

  New Revision: 48756

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=48756

  Log:
    string.c: chompped_length chomp_rs
    
    * string.c (chompped_length, chomp_rs): extract from
      rb_str_chomp_bang to share with rb_str_chomp.

  Modified files:
    trunk/string.c
Index: string.c
===================================================================
--- string.c	(revision 48755)
+++ string.c	(revision 48756)
@@ -7044,110 +7044,142 @@ rb_str_chop(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L7044
 }
 
 
-/*
- *  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;
-	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)) {
+    enc = rb_enc_get(str);
+    if (rs == rb_default_rs) {
+      smart_chomp:
+	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)) {
+		e = pp;
+	    }
+	    pp = e - 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;
 		}
-		pp = e - rb_enc_mbminlen(enc);
+	    }
+	}
+	else {
+	    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;
+	    }
+	}
+	return e - p;
+    }
+
+    RSTRING_GETMEM(rs, rsptr, rslen);
+    if (rslen == 0) {
+	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 (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);
-		    }
-		}
-		else if (RSTRING_PTR(str)[len-1] == '\r') {
-		    STR_DEC_LEN(str);
-		}
-		else {
-		    return Qnil;
-		}
+	}
+	else {
+	    while (e > p && *(e-1) == '\n') {
+		--e;
+		if (e > p && *(e-1) == '\r')
+		    --e;
 	    }
-	    RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
-	    return str;
 	}
+	return e - p;
     }
-    else {
-	rb_scan_args(argc, argv, "01", &rs);
+    if (rslen > len) return len;
+
+    enc = rb_enc_check(str, rs);
+    if (is_broken_string(rs)) {
+	return len;
     }
-    if (NIL_P(rs)) return Qnil;
-    StringValue(rs);
-    rslen = RSTRING_LEN(rs);
-    if (rslen == 0) {
-	while (len>0 && p[len-1] == '\n') {
-	    len--;
-	    if (len>0 && p[len-1] == '\r')
-		len--;
+    newline = rsptr[rslen-1];
+    if (rslen == rb_enc_mbminlen(enc)) {
+	if (rslen == 1) {
+	    if (newline == '\n')
+		goto smart_chomp;
 	}
-	if (len < RSTRING_LEN(str)) {
-	    STR_SET_LEN(str, len);
-	    RSTRING_PTR(str)[len] = '\0';
-	    return str;
+	else {
+	    if (rb_enc_is_newline(rsptr, rsptr+rslen, enc))
+		goto smart_chomp;
 	}
-	return Qnil;
     }
-    if (rslen > len) return Qnil;
-    newline = RSTRING_PTR(rs)[rslen-1];
-    if (rslen == 1 && newline == '\n')
-	goto smart_chomp;
 
-    enc = rb_enc_check(str, rs);
-    if (is_broken_string(rs)) {
-	return Qnil;
-    }
     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;
-	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;
+	 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);
+	    }
+	    return str;
+	}
     }
     return Qnil;
 }
@@ -7178,9 +7210,9 @@ rb_str_chomp_bang(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/string.c#L7210
 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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]