aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--string-list.c35
-rw-r--r--string-list.h15
-rw-r--r--t/unit-tests/u-string-list.c64
3 files changed, 109 insertions, 5 deletions
diff --git a/string-list.c b/string-list.c
index 65b6ceb259..86a309f8fb 100644
--- a/string-list.c
+++ b/string-list.c
@@ -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,
const char *p, const char *end,
- int in_place)
+ int in_place, unsigned flags)
{
if (!end)
end = p + strlen(p);
+ if ((flags & STRING_LIST_SPLIT_TRIM)) {
+ /* rtrim */
+ for (; p < end; end--)
+ if (!isspace(end[-1]))
+ break;
+ }
+
if (in_place) {
*((char *)end) = '\0';
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 ;-).
*/
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;
const char *p = string;
@@ -320,12 +327,18 @@ static int split_string(struct string_list *list, const char *string, const char
for (;;) {
char *end;
+ if (flags & STRING_LIST_SPLIT_TRIM) {
+ /* ltrim */
+ while (*p && isspace(*p))
+ p++;
+ }
+
if (0 <= maxsplit && maxsplit <= count)
end = NULL;
else
end = strpbrk(p, delim);
- count += append_one(list, p, end, in_place);
+ count += append_one(list, p, end, in_place, flags);
if (!end)
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,
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,
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);
}
diff --git a/string-list.h b/string-list.h
index 6c8650efde..40e148712d 100644
--- a/string-list.h
+++ b/string-list.h
@@ -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,
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 */
diff --git a/t/unit-tests/u-string-list.c b/t/unit-tests/u-string-list.c
index 150a5f505f..daa9307e45 100644
--- a/t/unit-tests/u-string-list.c
+++ b/t/unit-tests/u-string-list.c
@@ -63,6 +63,70 @@ static void t_string_list_split(const char *data, const char *delim, int maxspli
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)
{
t_string_list_split("foo:bar:baz", ":", -1, "foo", "bar", "baz", NULL);