diff options
-rw-r--r-- | string.c | 23 | ||||
-rw-r--r-- | test/ruby/test_string.rb | 5 |
2 files changed, 24 insertions, 4 deletions
@@ -2903,15 +2903,30 @@ rb_str_append(VALUE str, VALUE str2) return rb_str_buf_append(str, str2); } +#define MIN_PRE_ALLOC_SIZE 48 + VALUE rb_str_concat_literals(size_t num, const VALUE *strary) { VALUE str; - size_t i; + size_t i, s; + long len = 1; + + if (UNLIKELY(!num)) return rb_str_new(0, 0); + if (UNLIKELY(num == 1)) return rb_str_resurrect(strary[0]); + + for (i = 0; i < num; ++i) { len += RSTRING_LEN(strary[i]); } + if (LIKELY(len < MIN_PRE_ALLOC_SIZE)) { + str = rb_str_resurrect(strary[0]); + s = 1; + } + else { + str = rb_str_buf_new(len); + rb_enc_copy(str, strary[0]); + s = 0; + } - if (!num) return rb_str_new(0, 0); - str = rb_str_resurrect(strary[0]); - for (i = 1; i < num; ++i) { + for (i = s; i < num; ++i) { const VALUE v = strary[i]; int encidx = ENCODING_GET(v); diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb index b6c6214364..ed95d8013d 100644 --- a/test/ruby/test_string.rb +++ b/test/ruby/test_string.rb @@ -620,6 +620,11 @@ CODE assert_raise(RuntimeError) { 'foo'.freeze.concat('bar') } end + def test_concat_literals + s="." * 50 + assert_equal(Encoding::UTF_8, "#{s}x".encoding) + end + def test_count a = S("hello world") assert_equal(5, a.count(S("lo"))) |