diff options
Diffstat (limited to 'string.c')
-rw-r--r-- | string.c | 30 |
1 files changed, 13 insertions, 17 deletions
@@ -2161,30 +2161,26 @@ str_fill_term(VALUE str, char *s, long len, int termlen) void rb_str_change_terminator_length(VALUE str, const int oldtermlen, const int termlen) { - long capa = str_capacity(str, oldtermlen) + oldtermlen; + int diff = termlen - oldtermlen; long len = RSTRING_LEN(str); - assert(capa >= len); - if (capa - len < termlen) { - rb_check_lockedtmp(str); - str_make_independent_expand(str, len, 0L, termlen); - } - else if (str_dependent_p(str)) { - if (termlen > oldtermlen) + if (diff > 0) { + if (str_dependent_p(str)) { + rb_check_lockedtmp(str); 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; } - if (termlen > oldtermlen) { + else if (str_capacity(str, oldtermlen) - len < (size_t)diff) { + rb_check_lockedtmp(str); + RESIZE_CAPA_TERM(str, len, termlen); + } + else { TERM_FILL(RSTRING_PTR(str) + len, termlen); } } - - return; + else if (diff < 0 && + FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) { + RSTRING(str)->as.heap.aux.capa += -diff; + } } static char * |