quote: make sq_dequote_step() a public function

We provide a function for dequoting an entire string, as well as one for handling a space-separated list of quoted strings. But there's no way for a caller to parse a string like 'foo'='bar', even though it is easy to generate one using sq_quote_buf() or similar. Let's make the single-step function available to callers outside of quote.c. Note that we do need to adjust its implementation slightly: it insists on seeing whitespace between items, and we'd like to be more flexible than that. Since it only has a single caller, we can move that check (and slurping up any extra whitespace) into that caller. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Jan 12, 2021 at 13:26 UTC 13c44953fb0b396d3594b4a712f956ab3a48169e
2 files changed +26 -7
quote.c
+10 -5
@@ -116,7 +116,7 @@ void sq_append_quote_argv_pretty(struct strbuf *dst, const char **argv)
116 }
117 }
118
119 -static char *sq_dequote_step(char *arg, char **next)
119 +char *sq_dequote_step(char *arg, char **next)
120 {
121 char *dst = arg;
122 char *src = arg;
@@ -153,11 +153,8 @@ static char *sq_dequote_step(char *arg, char **next)
153 }
154 /* Fallthrough */
155 default:
156 - if (!next || !isspace(*src))
156 + if (!next)
157 return NULL;
158 - do {
159 - c = *++src;
160 - } while (isspace(c));
158 *dst = 0;
159 *next = src;
160 return arg;
@@ -182,6 +179,14 @@ static int sq_dequote_to_argv_internal(char *arg,
179 char *dequoted = sq_dequote_step(next, &next);
180 if (!dequoted)
181 return -1;
182 + if (next) {
183 + char c;
184 + if (!isspace(*next))
185 + return -1;
186 + do {
187 + c = *++next;
188 + } while (isspace(c));
189 + }
190 if (argv) {
191 ALLOC_GROW(*argv, *nr + 1, *alloc);
192 (*argv)[(*nr)++] = dequoted;
quote.h
+16 -2
@@ -42,12 +42,26 @@ void sq_quote_buf_pretty(struct strbuf *, const char *src);
42 void sq_quote_argv_pretty(struct strbuf *, const char **argv);
43 void sq_append_quote_argv_pretty(struct strbuf *dst, const char **argv);
44
45 -/* This unwraps what sq_quote() produces in place, but returns
45 +/*
46 + * This unwraps what sq_quote() produces in place, but returns
47 * NULL if the input does not look like what sq_quote would have
47 - * produced.
48 + * produced (the full string must be a single quoted item).
49 */
50 char *sq_dequote(char *);
51
52 +/*
53 + * Like sq_dequote(), but dequote a single item, and leave "next" pointing to
54 + * the next character. E.g., in the string:
55 + *
56 + * 'one' 'two' 'three'
57 + *
58 + * after the first call, the return value would be the unquoted string "one",
59 + * with "next" pointing to the space between "one" and "two"). The caller is
60 + * responsible for advancing the pointer to the start of the next item before
61 + * calling sq_dequote_step() again.
62 + */
63 +char *sq_dequote_step(char *src, char **next);
64 +
65 /*
66 * Same as the above, but can be used to unwrap many arguments in the
67 * same string separated by space. Like sq_quote, it works in place,