Skip to content

Commit 341babc

Browse files
authored
jinja : fix split and replace with empty first arg (ggml-org#24574)
* fix split and replace with empty first arg * fix reserve size
1 parent 1a7718b commit 341babc

2 files changed

Lines changed: 29 additions & 4 deletions

File tree

common/jinja/value.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,9 @@ const func_builtins & value_string_t::get_builtins() const {
673673
std::string str = val_input->as_string().str();
674674
// FIXME: Support non-specified delimiter (split on consecutive (no leading or trailing) whitespace)
675675
std::string delim = (args.count() > 1) ? args.get_pos(1)->as_string().str() : " ";
676+
if (delim.empty()) {
677+
throw raised_exception("empty separator");
678+
}
676679
int64_t maxsplit = (args.count() > 2) ? args.get_pos(2)->as_int() : -1;
677680
auto result = mk_val<value_array>();
678681
size_t pos = 0;
@@ -697,6 +700,9 @@ const func_builtins & value_string_t::get_builtins() const {
697700
std::string str = val_input->as_string().str();
698701
// FIXME: Support non-specified delimiter (split on consecutive (no leading or trailing) whitespace)
699702
std::string delim = (args.count() > 1) ? args.get_pos(1)->as_string().str() : " ";
703+
if (delim.empty()) {
704+
throw raised_exception("empty separator");
705+
}
700706
int64_t maxsplit = (args.count() > 2) ? args.get_pos(2)->as_int() : -1;
701707
auto result = mk_val<value_array>();
702708
size_t pos = 0;
@@ -722,10 +728,23 @@ const func_builtins & value_string_t::get_builtins() const {
722728
if (count > 0) {
723729
throw not_implemented_exception("String replace with count argument not implemented");
724730
}
725-
size_t pos = 0;
726-
while ((pos = str.find(old_str, pos)) != std::string::npos) {
727-
str.replace(pos, old_str.length(), new_str);
728-
pos += new_str.length();
731+
if (old_str != new_str) {
732+
size_t pos = 0;
733+
if (old_str.empty()) {
734+
std::string new_res;
735+
new_res.reserve(str.length() + new_str.length() * (str.length() + 1));
736+
new_res += new_str;
737+
for (const char c : str) {
738+
new_res.push_back(c);
739+
new_res += new_str;
740+
}
741+
str = new_res;
742+
} else {
743+
while ((pos = str.find(old_str, pos)) != std::string::npos) {
744+
str.replace(pos, old_str.length(), new_str);
745+
pos += new_str.length();
746+
}
747+
}
729748
}
730749
auto res = mk_val<value_string>(str);
731750
res->val_str.mark_input_based_on(args.get_pos(0)->val_str);

tests/test-jinja.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,12 @@ static void test_string_methods(testing & t) {
13201320
"hello jinja"
13211321
);
13221322

1323+
test_template(t, "string.replace() empty",
1324+
"{{ s.replace('', '.') }}",
1325+
{{"s", "hello world"}},
1326+
".h.e.l.l.o. .w.o.r.l.d."
1327+
);
1328+
13231329
test_template(t, "string.replace() with count",
13241330
"{{ s.replace('a', 'X', 2) }}",
13251331
{{"s", "banana"}},

0 commit comments

Comments
 (0)