]> git.ipfire.org Git - thirdparty/git.git/commitdiff
string-list: unify string_list_split* functions
authorJunio C Hamano <gitster@pobox.com>
Fri, 1 Aug 2025 22:04:19 +0000 (15:04 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 3 Aug 2025 05:33:12 +0000 (22:33 -0700)
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>
string-list.c

index 2284a009cba6a221c97caabc035802c326228856..65b6ceb259128080ad9f0a1aebb3fb131902d200 100644 (file)
@@ -276,55 +276,71 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
        list->nr--;
 }
 
-int string_list_split(struct string_list *list, const char *string,
-                     const char *delim, int maxsplit)
+/*
+ * append a substring [p..end] to list; return number of things it
+ * appended to the list.
+ */
+static int append_one(struct string_list *list,
+                     const char *p, const char *end,
+                     int in_place)
+{
+       if (!end)
+               end = p + strlen(p);
+
+       if (in_place) {
+               *((char *)end) = '\0';
+               string_list_append(list, p);
+       } else {
+               string_list_append_nodup(list, xmemdupz(p, end - p));
+       }
+       return 1;
+}
+
+/*
+ * Unfortunately this cannot become a public interface, as _in_place()
+ * wants to have "const char *string" while the other variant wants to
+ * have "char *string" for type safety.
+ *
+ * This accepts "const char *string" to allow both wrappers to use it;
+ * it internally casts away the constness when in_place is true by
+ * taking advantage of strpbrk() that takes a "const char *" arg and
+ * returns "char *" pointer into that const string.  Yucky but works ;-).
+ */
+static int split_string(struct string_list *list, const char *string, const char *delim,
+                       int maxsplit, int in_place)
 {
        int count = 0;
-       const char *p = string, *end;
+       const char *p = string;
+
+       if (in_place && list->strdup_strings)
+               BUG("string_list_split_in_place() called with strdup_strings");
+       else if (!in_place && !list->strdup_strings)
+               BUG("string_list_split() called without strdup_strings");
 
-       if (!list->strdup_strings)
-               BUG("internal error in string_list_split(): "
-                   "list->strdup_strings must be set");
        for (;;) {
-               count++;
-               if (maxsplit >= 0 && count > maxsplit) {
-                       string_list_append(list, p);
-                       return count;
-               }
-               end = strpbrk(p, delim);
-               if (end) {
-                       string_list_append_nodup(list, xmemdupz(p, end - p));
-                       p = end + 1;
-               } else {
-                       string_list_append(list, p);
+               char *end;
+
+               if (0 <= maxsplit && maxsplit <= count)
+                       end = NULL;
+               else
+                       end = strpbrk(p, delim);
+
+               count += append_one(list, p, end, in_place);
+
+               if (!end)
                        return count;
-               }
+               p = end + 1;
        }
 }
 
+int string_list_split(struct string_list *list, const char *string,
+                     const char *delim, int maxsplit)
+{
+       return split_string(list, string, delim, maxsplit, 0);
+}
+
 int string_list_split_in_place(struct string_list *list, char *string,
                               const char *delim, int maxsplit)
 {
-       int count = 0;
-       char *p = string, *end;
-
-       if (list->strdup_strings)
-               BUG("internal error in string_list_split_in_place(): "
-                   "list->strdup_strings must not be set");
-       for (;;) {
-               count++;
-               if (maxsplit >= 0 && count > maxsplit) {
-                       string_list_append(list, p);
-                       return count;
-               }
-               end = strpbrk(p, delim);
-               if (end) {
-                       *end = '\0';
-                       string_list_append(list, p);
-                       p = end + 1;
-               } else {
-                       string_list_append(list, p);
-                       return count;
-               }
-       }
+       return split_string(list, string, delim, maxsplit, 1);
 }