string-list: optionally trim string pieces split by string_list_split*()
Teach the unified split_string() to take an optional "flags" word, and define the first flag STRING_LIST_SPLIT_TRIM to cause the split pieces to be trimmed before they are placed in the string list. Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@@ -282,11 +282,18 @@ void unsorted_string_list_delete_item(struct string_list *list, int i, int free_
|
|||||||
*/
|
*/
|
||||||
static int append_one(struct string_list *list,
|
static int append_one(struct string_list *list,
|
||||||
const char *p, const char *end,
|
const char *p, const char *end,
|
||||||
int in_place)
|
int in_place, unsigned flags)
|
||||||
{
|
{
|
||||||
if (!end)
|
if (!end)
|
||||||
end = p + strlen(p);
|
end = p + strlen(p);
|
||||||
|
|
||||||
|
if ((flags & STRING_LIST_SPLIT_TRIM)) {
|
||||||
|
/* rtrim */
|
||||||
|
for (; p < end; end--)
|
||||||
|
if (!isspace(end[-1]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (in_place) {
|
if (in_place) {
|
||||||
*((char *)end) = '\0';
|
*((char *)end) = '\0';
|
||||||
string_list_append(list, p);
|
string_list_append(list, p);
|
||||||
@@ -307,7 +314,7 @@ static int append_one(struct string_list *list,
|
|||||||
* returns "char *" pointer into that const string. Yucky but works ;-).
|
* returns "char *" pointer into that const string. Yucky but works ;-).
|
||||||
*/
|
*/
|
||||||
static int split_string(struct string_list *list, const char *string, const char *delim,
|
static int split_string(struct string_list *list, const char *string, const char *delim,
|
||||||
int maxsplit, int in_place)
|
int maxsplit, int in_place, unsigned flags)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
const char *p = string;
|
const char *p = string;
|
||||||
@@ -320,12 +327,18 @@ static int split_string(struct string_list *list, const char *string, const char
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
char *end;
|
char *end;
|
||||||
|
|
||||||
|
if (flags & STRING_LIST_SPLIT_TRIM) {
|
||||||
|
/* ltrim */
|
||||||
|
while (*p && isspace(*p))
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 <= maxsplit && maxsplit <= count)
|
if (0 <= maxsplit && maxsplit <= count)
|
||||||
end = NULL;
|
end = NULL;
|
||||||
else
|
else
|
||||||
end = strpbrk(p, delim);
|
end = strpbrk(p, delim);
|
||||||
|
|
||||||
count += append_one(list, p, end, in_place);
|
count += append_one(list, p, end, in_place, flags);
|
||||||
|
|
||||||
if (!end)
|
if (!end)
|
||||||
return count;
|
return count;
|
||||||
@@ -336,11 +349,23 @@ static int split_string(struct string_list *list, const char *string, const char
|
|||||||
int string_list_split(struct string_list *list, const char *string,
|
int string_list_split(struct string_list *list, const char *string,
|
||||||
const char *delim, int maxsplit)
|
const char *delim, int maxsplit)
|
||||||
{
|
{
|
||||||
return split_string(list, string, delim, maxsplit, 0);
|
return split_string(list, string, delim, maxsplit, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int string_list_split_in_place(struct string_list *list, char *string,
|
int string_list_split_in_place(struct string_list *list, char *string,
|
||||||
const char *delim, int maxsplit)
|
const char *delim, int maxsplit)
|
||||||
{
|
{
|
||||||
return split_string(list, string, delim, maxsplit, 1);
|
return split_string(list, string, delim, maxsplit, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int string_list_split_f(struct string_list *list, const char *string,
|
||||||
|
const char *delim, int maxsplit, unsigned flags)
|
||||||
|
{
|
||||||
|
return split_string(list, string, delim, maxsplit, 0, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int string_list_split_in_place_f(struct string_list *list, char *string,
|
||||||
|
const char *delim, int maxsplit, unsigned flags)
|
||||||
|
{
|
||||||
|
return split_string(list, string, delim, maxsplit, 1, flags);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,4 +281,19 @@ int string_list_split(struct string_list *list, const char *string,
|
|||||||
*/
|
*/
|
||||||
int string_list_split_in_place(struct string_list *list, char *string,
|
int string_list_split_in_place(struct string_list *list, char *string,
|
||||||
const char *delim, int maxsplit);
|
const char *delim, int maxsplit);
|
||||||
|
|
||||||
|
/* Flag bits for split_f and split_in_place_f functions */
|
||||||
|
enum {
|
||||||
|
/*
|
||||||
|
* trim whitespaces around resulting string piece before adding
|
||||||
|
* it to the list
|
||||||
|
*/
|
||||||
|
STRING_LIST_SPLIT_TRIM = (1 << 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
int string_list_split_f(struct string_list *, const char *string,
|
||||||
|
const char *delim, int maxsplit, unsigned flags);
|
||||||
|
|
||||||
|
int string_list_split_in_place_f(struct string_list *, char *string,
|
||||||
|
const char *delim, int maxsplit, unsigned flags);
|
||||||
#endif /* STRING_LIST_H */
|
#endif /* STRING_LIST_H */
|
||||||
|
|||||||
@@ -63,6 +63,70 @@ static void t_string_list_split(const char *data, const char *delim, int maxspli
|
|||||||
string_list_clear(&list, 0);
|
string_list_clear(&list, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void t_string_list_split_f(const char *data, const char *delim,
|
||||||
|
int maxsplit, unsigned flags, ...)
|
||||||
|
{
|
||||||
|
struct string_list expected_strings = STRING_LIST_INIT_DUP;
|
||||||
|
struct string_list list = STRING_LIST_INIT_DUP;
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, flags);
|
||||||
|
t_vcreate_string_list_dup(&expected_strings, 0, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
string_list_clear(&list, 0);
|
||||||
|
len = string_list_split_f(&list, data, delim, maxsplit, flags);
|
||||||
|
cl_assert_equal_i(len, expected_strings.nr);
|
||||||
|
t_string_list_equal(&list, &expected_strings);
|
||||||
|
|
||||||
|
string_list_clear(&expected_strings, 0);
|
||||||
|
string_list_clear(&list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_list__split_f(void)
|
||||||
|
{
|
||||||
|
t_string_list_split_f("::foo:bar:baz:", ":", -1, 0,
|
||||||
|
"", "", "foo", "bar", "baz", "", NULL);
|
||||||
|
t_string_list_split_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
|
||||||
|
"foo", "bar", "baz", NULL);
|
||||||
|
t_string_list_split_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM,
|
||||||
|
"a", "b c", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void t_string_list_split_in_place_f(const char *data_, const char *delim,
|
||||||
|
int maxsplit, unsigned flags, ...)
|
||||||
|
{
|
||||||
|
struct string_list expected_strings = STRING_LIST_INIT_DUP;
|
||||||
|
struct string_list list = STRING_LIST_INIT_NODUP;
|
||||||
|
char *data = xstrdup(data_);
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, flags);
|
||||||
|
t_vcreate_string_list_dup(&expected_strings, 0, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
string_list_clear(&list, 0);
|
||||||
|
len = string_list_split_in_place_f(&list, data, delim, maxsplit, flags);
|
||||||
|
cl_assert_equal_i(len, expected_strings.nr);
|
||||||
|
t_string_list_equal(&list, &expected_strings);
|
||||||
|
|
||||||
|
free(data);
|
||||||
|
string_list_clear(&expected_strings, 0);
|
||||||
|
string_list_clear(&list, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_string_list__split_in_place_f(void)
|
||||||
|
{
|
||||||
|
t_string_list_split_in_place_f("::foo:bar:baz:", ":", -1, 0,
|
||||||
|
"", "", "foo", "bar", "baz", "", NULL);
|
||||||
|
t_string_list_split_in_place_f(" foo:bar : baz", ":", -1, STRING_LIST_SPLIT_TRIM,
|
||||||
|
"foo", "bar", "baz", NULL);
|
||||||
|
t_string_list_split_in_place_f(" a b c ", " ", 1, STRING_LIST_SPLIT_TRIM,
|
||||||
|
"a", "b c", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void test_string_list__split(void)
|
void test_string_list__split(void)
|
||||||
{
|
{
|
||||||
t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL);
|
t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user