mirror of
https://github.com/jqlang/jq.git
synced 2026-10-12 02:16:58 +00:00
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:
+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