aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2025-08-01 15:04:19 -0700
committerJunio C Hamano <gitster@pobox.com>2025-08-02 22:33:12 -0700
commit527535fcdd2d9dec56877435f609852d0f2bf163 (patch)
tree6b4659ef3e35df1f0570d105925c4d266dcc348a
parent9f6dfe43c8a55b833ae16486bcafe29b543461f9 (diff)
downloadgit-527535fcdd2d9dec56877435f609852d0f2bf163.tar.gz
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>
-rw-r--r--string-list.c96
1 files changed, 56 insertions, 40 deletions
diff --git a/string-list.c b/string-list.c
index 2284a009cb..65b6ceb259 100644
--- a/string-list.c
+++ b/string-list.c
@@ -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);
}