string-list: unify string_list_split* functions
Thanks to the previous step, the only difference between these two related functions is that string_list_split() works on a string without modifying its contents (i.e. taking "const char *") and the resulting pieces of strings are their own copies in a string list, while string_list_split_in_place() works on a mutable string and the resulting pieces of strings come from the original string. Consolidate their implementations into a single helper function, and make them a thin wrapper around it. We can later add an extra flags parameter to extend both of these functions by updating only the internal helper function. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Junio C Hamano committed
Aug 1, 2025 at 15:04 UTC
527535fcdd2d9dec56877435f609852d0f2bf163
1 file changed
+56
-40
string-list.c
+56
-40
@@ -276,55 +276,71 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
276
list->nr--;
277
}
278
279
-int string_list_split(struct string_list *list, const char *string,
280
- const char *delim, int maxsplit)
279
+/*
280
+ * append a substring [p..end] to list; return number of things it
281
+ * appended to the list.
282
+ */
283
+static int append_one(struct string_list *list,
284
+ const char *p, const char *end,
285
+ int in_place)
286
+{
287
+ if (!end)
288
+ end = p + strlen(p);
289
+
290
+ if (in_place) {
291
+ *((char *)end) = '\0';
292
+ string_list_append(list, p);
293
+ } else {
294
+ string_list_append_nodup(list, xmemdupz(p, end - p));
295
+ }
296
+ return 1;
297
+}
298
+
299
+/*
300
+ * Unfortunately this cannot become a public interface, as _in_place()
301
+ * wants to have "const char *string" while the other variant wants to
302
+ * have "char *string" for type safety.
303
+ *
304
+ * This accepts "const char *string" to allow both wrappers to use it;
305
+ * it internally casts away the constness when in_place is true by
306
+ * taking advantage of strpbrk() that takes a "const char *" arg and
307
+ * returns "char *" pointer into that const string. Yucky but works ;-).
308
+ */
309
+static int split_string(struct string_list *list, const char *string, const char *delim,
310
+ int maxsplit, int in_place)
311
{
312
int count = 0;
283
- const char *p = string, *end;
313
+ const char *p = string;
314
+
315
+ if (in_place && list->strdup_strings)
316
+ BUG("string_list_split_in_place() called with strdup_strings");
317
+ else if (!in_place && !list->strdup_strings)
318
+ BUG("string_list_split() called without strdup_strings");
319
285
- if (!list->strdup_strings)
286
- BUG("internal error in string_list_split(): "
287
- "list->strdup_strings must be set");
320
for (;;) {
289
- count++;
290
- if (maxsplit >= 0 && count > maxsplit) {
291
- string_list_append(list, p);
292
- return count;
293
- }
294
- end = strpbrk(p, delim);
295
- if (end) {
296
- string_list_append_nodup(list, xmemdupz(p, end - p));
297
- p = end + 1;
298
- } else {
299
- string_list_append(list, p);
321
+ char *end;
322
+
323
+ if (0 <= maxsplit && maxsplit <= count)
324
+ end = NULL;
325
+ else
326
+ end = strpbrk(p, delim);
327
+
328
+ count += append_one(list, p, end, in_place);
329
+
330
+ if (!end)
331
return count;
301
- }
332
+ p = end + 1;
333
}
334
}
335
336
+int string_list_split(struct string_list *list, const char *string,
337
+ const char *delim, int maxsplit)
338
+{
339
+ return split_string(list, string, delim, maxsplit, 0);
340
+}
341
+
342
int string_list_split_in_place(struct string_list *list, char *string,
343
const char *delim, int maxsplit)
344
{
308
- int count = 0;
309
- char *p = string, *end;
310
-
311
- if (list->strdup_strings)
312
- BUG("internal error in string_list_split_in_place(): "
313
- "list->strdup_strings must not be set");
314
- for (;;) {
315
- count++;
316
- if (maxsplit >= 0 && count > maxsplit) {
317
- string_list_append(list, p);
318
- return count;
319
- }
320
- end = strpbrk(p, delim);
321
- if (end) {
322
- *end = '\0';
323
- string_list_append(list, p);
324
- p = end + 1;
325
- } else {
326
- string_list_append(list, p);
327
- return count;
328
- }
329
- }
345
+ return split_string(list, string, delim, maxsplit, 1);
346
}