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

ruby-changes:43502

From: ngoto <ko1@a...>
Date: Tue, 5 Jul 2016 19:45:30 +0900 (JST)
Subject: [ruby-changes:43502] ngoto:r55575 (trunk): * string.c (rb_str_change_terminator_length): New function to change

ngoto	2016-07-05 19:45:23 +0900 (Tue, 05 Jul 2016)

  New Revision: 55575

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

  Log:
    * string.c (rb_str_change_terminator_length): New function to change
      termlen and resize heap for the terminator. This is split from
      rb_str_fill_terminator (str_fill_term) because filling terminator
      and changing terminator length are different things. [Bug #12536]
    
    * internal.h: declaration for rb_str_change_terminator_length.
    
    * string.c (str_fill_term): Simplify only to zero-fill the terminator.
      For non-shared strings, it assumes that (capa + termlen) bytes of
      heap is allocated. This partially reverts r55557.
    
    * encoding.c (rb_enc_associate_index): rb_str_change_terminator_length
      is used, and it should be called whenever the termlen is changed.
    
    * string.c (str_capacity): New static function to return capacity
      of a string with the given termlen, because the termlen may
      sometimes be different from TERM_LEN(str) especially during
      changing termlen or filling terminator with specific termlen.
    
    * string.c (rb_str_capacity): Use str_capacity.

  Modified files:
    trunk/ChangeLog
    trunk/encoding.c
    trunk/internal.h
    trunk/string.c
Index: string.c
===================================================================
--- string.c	(revision 55574)
+++ string.c	(revision 55575)
@@ -646,11 +646,11 @@ str_mod_check(VALUE s, const char *p, lo https://github.com/ruby/ruby/blob/trunk/string.c#L646
     }
 }
 
-size_t
-rb_str_capacity(VALUE str)
+static size_t
+str_capacity(VALUE str, const int termlen)
 {
     if (STR_EMBED_P(str)) {
-	return (RSTRING_EMBED_LEN_MAX + 1 - TERM_LEN(str));
+	return (RSTRING_EMBED_LEN_MAX + 1 - termlen);
     }
     else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
 	return RSTRING(str)->as.heap.len;
@@ -660,6 +660,12 @@ rb_str_capacity(VALUE str) https://github.com/ruby/ruby/blob/trunk/string.c#L660
     }
 }
 
+size_t
+rb_str_capacity(VALUE str)
+{
+    return str_capacity(str, TERM_LEN(str));
+}
+
 static inline void
 must_not_null(const char *ptr)
 {
@@ -2021,42 +2027,55 @@ str_null_char(const char *s, long len, c https://github.com/ruby/ruby/blob/trunk/string.c#L2027
 static char *
 str_fill_term(VALUE str, char *s, long len, int termlen)
 {
-    long capa = rb_str_capacity(str);
-    /* This function could be called during the encoding changing procedure.
-     * If so, the termlen may be different from current TERM_LEN(str).
+    long capa = str_capacity(str, termlen);
+
+    /* This function assumes that (capa + termlen) bytes of memory
+     * is allocated, like many other functions in this file.
      */
-    const int oldtermlen = TERM_LEN(str);
 
-    if (capa < len + termlen - 1) { /* assumes oldtermlen is 1 here */
+    if (capa < len) {
 	rb_check_lockedtmp(str);
 	str_make_independent_expand(str, len, 0L, termlen);
     }
     else if (str_dependent_p(str)) {
-	if ((termlen > oldtermlen) || !zero_filled(s + len, termlen))
+	if (!zero_filled(s + len, termlen))
 	    str_make_independent_expand(str, len, 0L, termlen);
     }
     else {
-	if (termlen > oldtermlen) {
-	    if (!STR_EMBED_P(str)) {
-		const int d = termlen - oldtermlen;
-		if (capa > len + d) {
-		    /* decrease capa for the new termlen */
-		    capa -= d;
-		    assert(capa >= 1);
-		    assert(!FL_TEST((str), STR_SHARED));
-		    RSTRING(str)->as.heap.aux.capa = capa;
-		} else {
-		    assert(capa >= len);
-		    RESIZE_CAPA_TERM(str, capa, termlen);
-		}
-	    }
-	}
 	TERM_FILL(s + len, termlen);
 	return s;
     }
     return RSTRING_PTR(str);
 }
 
+void
+rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen)
+{
+    long capa = str_capacity(str, oldtermlen);
+    long len = RSTRING_LEN(str);
+
+    if (capa < len + termlen - oldtermlen) {
+	rb_check_lockedtmp(str);
+	str_make_independent_expand(str, len, 0L, termlen);
+    }
+    else if (str_dependent_p(str)) {
+	if (termlen > oldtermlen)
+	    str_make_independent_expand(str, len, 0L, termlen);
+    }
+    else {
+	if (!STR_EMBED_P(str)) {
+	    /* modify capa instead of realloc */
+	    assert(!FL_TEST((str), STR_SHARED));
+	    RSTRING(str)->as.heap.aux.capa = capa - (termlen - oldtermlen);
+	}
+	if (termlen > oldtermlen) {
+	    TERM_FILL(RSTRING_PTR(str) + len, termlen);
+	}
+    }
+
+    return;
+}
+
 char *
 rb_string_value_cstr(volatile VALUE *ptr)
 {
Index: encoding.c
===================================================================
--- encoding.c	(revision 55574)
+++ encoding.c	(revision 55575)
@@ -843,8 +843,8 @@ rb_enc_associate_index(VALUE obj, int id https://github.com/ruby/ruby/blob/trunk/encoding.c#L843
     }
     termlen = rb_enc_mbminlen(enc);
     oldtermlen = rb_enc_mbminlen(rb_enc_from_index(oldidx));
-    if (oldtermlen < termlen && RB_TYPE_P(obj, T_STRING)) {
-	rb_str_fill_terminator(obj, termlen);
+    if (oldtermlen != termlen && RB_TYPE_P(obj, T_STRING)) {
+	rb_str_change_terminator_length(obj, oldtermlen, termlen);
     }
     enc_set_index(obj, idx);
     return obj;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 55574)
+++ ChangeLog	(revision 55575)
@@ -1,3 +1,26 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Jul  5 19:39:49 2016  Naohisa Goto  <ngotogenome@g...>
+
+	* string.c (rb_str_change_terminator_length): New function to change
+	  termlen and resize heap for the terminator. This is split from
+	  rb_str_fill_terminator (str_fill_term) because filling terminator
+	  and changing terminator length are different things. [Bug #12536]
+
+	* internal.h: declaration for rb_str_change_terminator_length.
+
+	* string.c (str_fill_term): Simplify only to zero-fill the terminator.
+	  For non-shared strings, it assumes that (capa + termlen) bytes of
+	  heap is allocated. This partially reverts r55557.
+
+	* encoding.c (rb_enc_associate_index): rb_str_change_terminator_length
+	  is used, and it should be called whenever the termlen is changed.
+
+	* string.c (str_capacity): New static function to return capacity
+	  of a string with the given termlen, because the termlen may
+	  sometimes be different from TERM_LEN(str) especially during
+	  changing termlen or filling terminator with specific termlen.
+
+	* string.c (rb_str_capacity): Use str_capacity.
+
 Tue Jul  5 11:07:14 2016  NARUSE, Yui  <naruse@r...>
 
 	* pack.c (pack_pack): use union instead of bare variable to ease
Index: internal.h
===================================================================
--- internal.h	(revision 55574)
+++ internal.h	(revision 55575)
@@ -1356,6 +1356,7 @@ VALUE rb_id_quote_unprintable(ID); https://github.com/ruby/ruby/blob/trunk/internal.h#L1356
 #define QUOTE(str) rb_str_quote_unprintable(str)
 #define QUOTE_ID(id) rb_id_quote_unprintable(id)
 char *rb_str_fill_terminator(VALUE str, const int termlen);
+void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen);
 VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
 #ifdef RUBY_ENCODING_H
 VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc);

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

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