Skip to content

Commit c7922b3

Browse files
committed
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 <[email protected]>
1 parent cc80bac commit c7922b3

File tree

1 file changed

+56
-40
lines changed

1 file changed

+56
-40
lines changed

string-list.c

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -276,55 +276,71 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
276276
list->nr--;
277277
}
278278

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)
281311
{
282312
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");
284319

285-
if (!list->strdup_strings)
286-
BUG("internal error in string_list_split(): "
287-
"list->strdup_strings must be set");
288320
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)
300331
return count;
301-
}
332+
p = end + 1;
302333
}
303334
}
304335

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+
305342
int string_list_split_in_place(struct string_list *list, char *string,
306343
const char *delim, int maxsplit)
307344
{
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);
330346
}

0 commit comments

Comments
 (0)