list-objects-filter-options: avoid strbuf_split_str()

parse_combine_filter() splits a combine: filter spec at '+' using
strbuf_split_str(), which yields an array of strbufs with the
delimiter left at the end of each non-final piece.  The code then
mutates each non-final piece to strip the trailing '+' before parsing.

Allocating an array of strbufs is unnecessary.  The function processes
one sub-spec at a time and does not use strbuf editing on the pieces.
The two helpers it calls, has_reserved_character() and
parse_combine_subfilter(), only read the string content of the strbuf
they receive.

Walk the input string directly with strchr() to find each '+'.  Copy
each sub-spec into a temporary buffer and strip the '+' only when
another sub-spec follows.  Change the helpers to take const char *
instead of struct strbuf *.

Signed-off-by: Deveshi Dwivedi <deveshigurgaon@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Deveshi Dwivedi
2026-03-08 18:03:59 +00:00
committed by Junio C Hamano
parent 5ad63f32da
commit 2e01626d33

View File

@@ -125,9 +125,9 @@ int gently_parse_list_objects_filter(
static const char *RESERVED_NON_WS = "~`!@#$^&*()[]{}\\;'\",<>?";
static int has_reserved_character(
struct strbuf *sub_spec, struct strbuf *errbuf)
const char *sub_spec, struct strbuf *errbuf)
{
const char *c = sub_spec->buf;
const char *c = sub_spec;
while (*c) {
if (*c <= ' ' || strchr(RESERVED_NON_WS, *c)) {
strbuf_addf(
@@ -144,7 +144,7 @@ static int has_reserved_character(
static int parse_combine_subfilter(
struct list_objects_filter_options *filter_options,
struct strbuf *subspec,
const char *subspec,
struct strbuf *errbuf)
{
size_t new_index = filter_options->sub_nr;
@@ -155,7 +155,7 @@ static int parse_combine_subfilter(
filter_options->sub_alloc);
list_objects_filter_init(&filter_options->sub[new_index]);
decoded = url_percent_decode(subspec->buf);
decoded = url_percent_decode(subspec);
result = has_reserved_character(subspec, errbuf);
if (result)
@@ -182,34 +182,34 @@ static int parse_combine_filter(
const char *arg,
struct strbuf *errbuf)
{
struct strbuf **subspecs = strbuf_split_str(arg, '+', 0);
size_t sub;
const char *p = arg;
int result = 0;
if (!subspecs[0]) {
if (!*p) {
strbuf_addstr(errbuf, _("expected something after combine:"));
result = 1;
goto cleanup;
}
for (sub = 0; subspecs[sub] && !result; sub++) {
if (subspecs[sub + 1]) {
/*
* This is not the last subspec. Remove trailing "+" so
* we can parse it.
*/
size_t last = subspecs[sub]->len - 1;
assert(subspecs[sub]->buf[last] == '+');
strbuf_remove(subspecs[sub], last, 1);
}
result = parse_combine_subfilter(
filter_options, subspecs[sub], errbuf);
while (*p && !result) {
const char *sep = strchr(p, '+');
size_t len = sep ? (size_t)(sep - p + 1) : strlen(p);
char *sub = xmemdupz(p, len);
/* strip '+' separator, but only when more sub-specs follow */
if (sep && *(sep + 1))
sub[len - 1] = '\0';
result = parse_combine_subfilter(filter_options, sub, errbuf);
free(sub);
if (!sep)
break;
p = sep + 1;
}
filter_options->choice = LOFC_COMBINE;
cleanup:
strbuf_list_free(subspecs);
if (result)
list_objects_filter_release(filter_options);
return result;