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:
1 parent
5df471fa5b
commit
dc849e9bb7
4 files changed
+41
-13
No files matched your search
+2
-13
@@ -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 {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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"]]
|
||||
|
||||
Reference in new issue
Block a user