git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v1 2/2] list-objects-filter-options: avoid strbuf_split_str()

From
Deveshi Dwivedi <deveshigurgaon@gmail.com>
Date
Mar 8, 2026, 18:03 UTC
Message-ID
<20260308180359.31188-3-deveshigurgaon@gmail.com>
In-Reply-To
<20260308180359.31188-1-deveshigurgaon@gmail.com>

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>
---
 list-objects-filter-options.c | 40 +++++++++++++++++------------------
 1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index 7f3e7b8f50..f536085a7c 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -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;
-- 
2.52.0.230.gd8af7cadaa
Previous: Jeff KingNext: Junio C Hamano
Message 5 of 8 in “avoid unnecessary strbuf_split*() and strbuf-by-value usage”
  1. 0/2 avoid unnecessary strbuf_split*() and strbuf-by-value usageDeveshi Dwivedi, Mar 8, 2026
  2. 1/2 worktree: do not pass strbuf by valueDeveshi Dwivedi, Mar 8, 2026
  3. Junio C HamanoMar 9, 2026
  4. coccinelle to catch pass-by-value?, was: [PATCH v1 1/2] worktree: do not pass strbuf by valueJeff King, Mar 9, 2026
  5. 2/2 list-objects-filter-options: avoid strbuf_split_str()Deveshi Dwivedi, Mar 8, 2026
  6. Junio C HamanoMar 9, 2026
  7. Jeff KingMar 9, 2026
  8. Jeff KingMar 9, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.