Skip to content

Commit

Permalink
rb_str_resize: Only clear coderange on truncation
Browse files Browse the repository at this point in the history
If we are expanding the string or only stripping extra capacity
then coderange won't change, so clearing it is wasteful.
  • Loading branch information
byroot committed Aug 18, 2022
1 parent fe61cad commit b0b9f72
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 8 deletions.
3 changes: 3 additions & 0 deletions file.c
Expand Up @@ -4090,6 +4090,9 @@ static VALUE
str_shrink(VALUE str)
{
rb_str_resize(str, RSTRING_LEN(str));
// expand_path on Windows can sometimes mutate the string
// without clearing its coderange
ENC_CODERANGE_CLEAR(str);
return str;
}

Expand Down
5 changes: 4 additions & 1 deletion sprintf.c
Expand Up @@ -937,6 +937,8 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
}
rb_str_resize(result, blen);
// rb_str_format mutates the string without updating coderange
ENC_CODERANGE_CLEAR(result);

return result;
}
Expand Down Expand Up @@ -1163,6 +1165,8 @@ ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
buffer.value = 0;
BSD_vfprintf(&f, fmt, ap);
RBASIC_SET_CLASS_RAW(result, klass);
// vfprintf mutates the string without updating coderange
ENC_CODERANGE_CLEAR(result);
rb_str_resize(result, (char *)f._p - RSTRING_PTR(result));
#undef f
}
Expand All @@ -1183,7 +1187,6 @@ rb_enc_vsprintf(rb_encoding *enc, const char *fmt, va_list ap)
rb_enc_associate(result, enc);
}
ruby_vsprintf0(result, RSTRING_PTR(result), fmt, ap);

return result;
}

Expand Down
13 changes: 6 additions & 7 deletions string.c
Expand Up @@ -2498,7 +2498,6 @@ rb_str_modify_expand(VALUE str, long expand)
else if (expand > 0) {
RESIZE_CAPA_TERM(str, len + expand, termlen);
}
ENC_CODERANGE_CLEAR(str);
}

/* As rb_str_modify(), but don't clear coderange */
Expand Down Expand Up @@ -3073,16 +3072,16 @@ rb_str_set_len(VALUE str, long len)
VALUE
rb_str_resize(VALUE str, long len)
{
long slen;
int independent;

if (len < 0) {
rb_raise(rb_eArgError, "negative string size (or size too big)");
}

independent = str_independent(str);
ENC_CODERANGE_CLEAR(str);
slen = RSTRING_LEN(str);
int independent = str_independent(str);
long slen = RSTRING_LEN(str);

if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
ENC_CODERANGE_CLEAR(str);
}

{
long capa;
Expand Down
10 changes: 10 additions & 0 deletions test/ruby/test_sprintf.rb
Expand Up @@ -507,6 +507,16 @@ def test_named_typed_enc
end
end

def test_coderange
format_str = "wrong constant name %s"
interpolated_str = "\u3042"
assert_predicate format_str, :ascii_only?
refute_predicate interpolated_str, :ascii_only?

str = format_str % interpolated_str
refute_predicate str, :ascii_only?
end

def test_named_default
h = Hash.new('world')
assert_equal("hello world", "hello %{location}" % h)
Expand Down

0 comments on commit b0b9f72

Please sign in to comment.