Subject: [RFC PATCH v2 1/3] ref filter: add multiple-option parsing functions

From: Kousik Sanagavarapu <[email-masked]>
Date: Sat, 15 Jul 2023 00:50:26 +0530

The functions

	match_placeholder_arg_value()
	match_placeholder_bool_arg()

were added in pretty (4f732e0fd7 (pretty: allow %(trailers) options
with explicit value, 2019-01-29)) to parse multiple options in an
argument to --pretty. For example,

	git log --pretty="%(trailers:key=Signed-Off-By,separator=%x2C )"

will output all the trailers matching the key and seperates them by
commas per commit.

Add similar functions,

	match_atom_arg_value()
	match_atom_bool_arg()

in ref-filter. A particular use of this can be seen in the subsequent
commit where we parse the options given to a new atom "describe".

Mentored-by: Christian Couder <[email-masked]>
Mentored-by: Hariom Verma <[email-masked]>
Signed-off-by: Kousik Sanagavarapu <[email-masked]>
---
 ref-filter.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/ref-filter.c b/ref-filter.c
index e0d03a9f8e..b170994d9d 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -251,6 +251,65 @@ static int err_bad_arg(struct strbuf *sb, const char *name, const char *arg)
 	return -1;
 }
 
+static int match_atom_arg_value(const char *to_parse, const char *candidate,
+				const char **end, const char **valuestart,
+				size_t *valuelen)
+{
+	const char *atom;
+
+	if (!(skip_prefix(to_parse, candidate, &atom)))
+		return 0;
+	if (valuestart) {
+		if (*atom == '=') {
+			*valuestart = atom + 1;
+			*valuelen = strcspn(*valuestart, ",\0");
+			atom = *valuestart + *valuelen;
+		} else {
+			if (*atom != ',' && *atom != '\0')
+				return 0;
+			*valuestart = NULL;
+			*valuelen = 0;
+		}
+	}
+	if (*atom == ',') {
+		*end = atom + 1;
+		return 1;
+	}
+	if (*atom == '\0') {
+		*end = atom;
+		return 1;
+	}
+	return 0;
+}
+
+static int match_atom_bool_arg(const char *to_parse, const char *candidate,
+				const char **end, int *val)
+{
+	const char *argval;
+	char *strval;
+	size_t arglen;
+	int v;
+
+	if (!match_atom_arg_value(to_parse, candidate, end, &argval, &arglen))
+		return 0;
+
+	if (!argval) {
+		*val = 1;
+		return 1;
+	}
+
+	strval = xstrndup(argval, arglen);
+	v = git_parse_maybe_bool(strval);
+	free(strval);
+
+	if (v == -1)
+		return 0;
+
+	*val = v;
+
+	return 1;
+}
+
 static int color_atom_parser(struct ref_format *format, struct used_atom *atom,
 			     const char *color_value, struct strbuf *err)
 {
-- 
2.41.0.321.g26b82700c0.dirty