Improve performance of repeating strings (#3272)

This commit improves the performance of repeating strings, by copying
the result string instead of the string being repeated. Also it adds
an error message when the result string is too long.
This commit is contained in:
itchyny
2025-03-04 22:13:55 +09:00
committed by GitHub
parent 5df471fa5b
commit dc849e9bb7
4 changed files with 41 additions and 13 deletions
+2 -13
View File
@@ -343,21 +343,10 @@ jv binop_multiply(jv a, jv b) {
str = b;
num = a;
}
jv res;
double d = jv_number_value(num);
if (d < 0 || isnan(d)) {
res = jv_null();
} else {
int n = d;
size_t alen = jv_string_length_bytes(jv_copy(str));
res = jv_string_empty(alen * n);
for (; n > 0; n--) {
res = jv_string_append_buf(res, jv_string_value(str), alen);
}
}
jv_free(str);
jv_free(num);
return res;
return jv_string_repeat(str,
d < 0 || isnan(d) ? -1 : d > INT_MAX ? INT_MAX : (int)d);
} else if (ak == JV_KIND_OBJECT && bk == JV_KIND_OBJECT) {
return jv_object_merge_recursive(a, b);
} else {
+26
View File
@@ -1324,6 +1324,32 @@ jv jv_string_indexes(jv j, jv k) {
return a;
}
jv jv_string_repeat(jv j, int n) {
assert(JVP_HAS_KIND(j, JV_KIND_STRING));
if (n < 0) {
jv_free(j);
return jv_null();
}
int len = jv_string_length_bytes(jv_copy(j));
int64_t res_len = (int64_t)len * n;
if (res_len >= INT_MAX) {
jv_free(j);
return jv_invalid_with_msg(jv_string("Repeat string result too long"));
}
if (res_len == 0) {
jv_free(j);
return jv_string("");
}
jv res = jv_string_empty(res_len);
res = jvp_string_append(res, jv_string_value(j), len);
for (int curr = len, grow; curr < res_len; curr += grow) {
grow = MIN(res_len - curr, curr);
res = jvp_string_append(res, jv_string_value(res), grow);
}
jv_free(j);
return res;
}
jv jv_string_split(jv j, jv sep) {
assert(JVP_HAS_KIND(j, JV_KIND_STRING));
assert(JVP_HAS_KIND(sep, JV_KIND_STRING));
+1
View File
@@ -136,6 +136,7 @@ jv jv_string_fmt(const char*, ...) JV_PRINTF_LIKE(1, 2);
jv jv_string_append_codepoint(jv a, uint32_t c);
jv jv_string_append_buf(jv a, const char* buf, int len);
jv jv_string_append_str(jv a, const char* str);
jv jv_string_repeat(jv j, int n);
jv jv_string_split(jv j, jv sep);
jv jv_string_explode(jv j);
jv jv_string_implode(jv j);
+12
View File
@@ -1460,6 +1460,18 @@ indices("o")
"abc"
[null,null]
. * 100000 | [.[:10],.[-10:]]
"abc"
["abcabcabca","cabcabcabc"]
. * 1000000000
""
""
try (. * 1000000000) catch .
"abc"
"Repeat string result too long"
[.[] / ","]
["a, bc, def, ghij, jklmn, a,b, c,d, e,f", "a,b,c,d, e,f,g,h"]
[["a"," bc"," def"," ghij"," jklmn"," a","b"," c","d"," e","f"],["a","b","c","d"," e","f","g","h"]]