Skip to content

Commit 5eff15d

Browse files
author
ngoto
committed
* 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 ruby#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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55575 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent a3ca2c7 commit 5eff15d

File tree

4 files changed

+69
-26
lines changed

4 files changed

+69
-26
lines changed

Diff for: ChangeLog

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
Tue Jul 5 19:39:49 2016 Naohisa Goto <[email protected]>
2+
3+
* string.c (rb_str_change_terminator_length): New function to change
4+
termlen and resize heap for the terminator. This is split from
5+
rb_str_fill_terminator (str_fill_term) because filling terminator
6+
and changing terminator length are different things. [Bug #12536]
7+
8+
* internal.h: declaration for rb_str_change_terminator_length.
9+
10+
* string.c (str_fill_term): Simplify only to zero-fill the terminator.
11+
For non-shared strings, it assumes that (capa + termlen) bytes of
12+
heap is allocated. This partially reverts r55557.
13+
14+
* encoding.c (rb_enc_associate_index): rb_str_change_terminator_length
15+
is used, and it should be called whenever the termlen is changed.
16+
17+
* string.c (str_capacity): New static function to return capacity
18+
of a string with the given termlen, because the termlen may
19+
sometimes be different from TERM_LEN(str) especially during
20+
changing termlen or filling terminator with specific termlen.
21+
22+
* string.c (rb_str_capacity): Use str_capacity.
23+
124
Tue Jul 5 11:07:14 2016 NARUSE, Yui <[email protected]>
225

326
* pack.c (pack_pack): use union instead of bare variable to ease

Diff for: encoding.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -843,8 +843,8 @@ rb_enc_associate_index(VALUE obj, int idx)
843843
}
844844
termlen = rb_enc_mbminlen(enc);
845845
oldtermlen = rb_enc_mbminlen(rb_enc_from_index(oldidx));
846-
if (oldtermlen < termlen && RB_TYPE_P(obj, T_STRING)) {
847-
rb_str_fill_terminator(obj, termlen);
846+
if (oldtermlen != termlen && RB_TYPE_P(obj, T_STRING)) {
847+
rb_str_change_terminator_length(obj, oldtermlen, termlen);
848848
}
849849
enc_set_index(obj, idx);
850850
return obj;

Diff for: internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,7 @@ VALUE rb_id_quote_unprintable(ID);
13561356
#define QUOTE(str) rb_str_quote_unprintable(str)
13571357
#define QUOTE_ID(id) rb_id_quote_unprintable(id)
13581358
char *rb_str_fill_terminator(VALUE str, const int termlen);
1359+
void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen);
13591360
VALUE rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg);
13601361
#ifdef RUBY_ENCODING_H
13611362
VALUE rb_external_str_with_enc(VALUE str, rb_encoding *eenc);

Diff for: string.c

+43-24
Original file line numberDiff line numberDiff line change
@@ -646,11 +646,11 @@ str_mod_check(VALUE s, const char *p, long len)
646646
}
647647
}
648648

649-
size_t
650-
rb_str_capacity(VALUE str)
649+
static size_t
650+
str_capacity(VALUE str, const int termlen)
651651
{
652652
if (STR_EMBED_P(str)) {
653-
return (RSTRING_EMBED_LEN_MAX + 1 - TERM_LEN(str));
653+
return (RSTRING_EMBED_LEN_MAX + 1 - termlen);
654654
}
655655
else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
656656
return RSTRING(str)->as.heap.len;
@@ -660,6 +660,12 @@ rb_str_capacity(VALUE str)
660660
}
661661
}
662662

663+
size_t
664+
rb_str_capacity(VALUE str)
665+
{
666+
return str_capacity(str, TERM_LEN(str));
667+
}
668+
663669
static inline void
664670
must_not_null(const char *ptr)
665671
{
@@ -2021,42 +2027,55 @@ str_null_char(const char *s, long len, const int minlen, rb_encoding *enc)
20212027
static char *
20222028
str_fill_term(VALUE str, char *s, long len, int termlen)
20232029
{
2024-
long capa = rb_str_capacity(str);
2025-
/* This function could be called during the encoding changing procedure.
2026-
* If so, the termlen may be different from current TERM_LEN(str).
2030+
long capa = str_capacity(str, termlen);
2031+
2032+
/* This function assumes that (capa + termlen) bytes of memory
2033+
* is allocated, like many other functions in this file.
20272034
*/
2028-
const int oldtermlen = TERM_LEN(str);
20292035

2030-
if (capa < len + termlen - 1) { /* assumes oldtermlen is 1 here */
2036+
if (capa < len) {
20312037
rb_check_lockedtmp(str);
20322038
str_make_independent_expand(str, len, 0L, termlen);
20332039
}
20342040
else if (str_dependent_p(str)) {
2035-
if ((termlen > oldtermlen) || !zero_filled(s + len, termlen))
2041+
if (!zero_filled(s + len, termlen))
20362042
str_make_independent_expand(str, len, 0L, termlen);
20372043
}
20382044
else {
2039-
if (termlen > oldtermlen) {
2040-
if (!STR_EMBED_P(str)) {
2041-
const int d = termlen - oldtermlen;
2042-
if (capa > len + d) {
2043-
/* decrease capa for the new termlen */
2044-
capa -= d;
2045-
assert(capa >= 1);
2046-
assert(!FL_TEST((str), STR_SHARED));
2047-
RSTRING(str)->as.heap.aux.capa = capa;
2048-
} else {
2049-
assert(capa >= len);
2050-
RESIZE_CAPA_TERM(str, capa, termlen);
2051-
}
2052-
}
2053-
}
20542045
TERM_FILL(s + len, termlen);
20552046
return s;
20562047
}
20572048
return RSTRING_PTR(str);
20582049
}
20592050

2051+
void
2052+
rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen)
2053+
{
2054+
long capa = str_capacity(str, oldtermlen);
2055+
long len = RSTRING_LEN(str);
2056+
2057+
if (capa < len + termlen - oldtermlen) {
2058+
rb_check_lockedtmp(str);
2059+
str_make_independent_expand(str, len, 0L, termlen);
2060+
}
2061+
else if (str_dependent_p(str)) {
2062+
if (termlen > oldtermlen)
2063+
str_make_independent_expand(str, len, 0L, termlen);
2064+
}
2065+
else {
2066+
if (!STR_EMBED_P(str)) {
2067+
/* modify capa instead of realloc */
2068+
assert(!FL_TEST((str), STR_SHARED));
2069+
RSTRING(str)->as.heap.aux.capa = capa - (termlen - oldtermlen);
2070+
}
2071+
if (termlen > oldtermlen) {
2072+
TERM_FILL(RSTRING_PTR(str) + len, termlen);
2073+
}
2074+
}
2075+
2076+
return;
2077+
}
2078+
20602079
char *
20612080
rb_string_value_cstr(volatile VALUE *ptr)
20622081
{

0 commit comments

Comments
 (0)