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/