Add function to split string into list.
- With working unit tests.
This commit is contained in:
parent
39abe6fbfe
commit
89e178e7c9
@ -36,7 +36,7 @@ enum
|
||||
DEFAULT_GROW_BY_SIZE = 10
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
struct list *
|
||||
list_create_sized(unsigned int size)
|
||||
{
|
||||
@ -64,14 +64,14 @@ list_create_sized(unsigned int size)
|
||||
return self;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
struct list *
|
||||
list_create(void)
|
||||
{
|
||||
return list_create_sized(DEFAULT_LIST_SIZE);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
void
|
||||
list_delete(struct list *self)
|
||||
{
|
||||
@ -95,7 +95,7 @@ list_delete(struct list *self)
|
||||
free(self);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
static int
|
||||
grow_list(struct list *self)
|
||||
{
|
||||
@ -128,7 +128,7 @@ list_add_item(struct list *self, tbus item)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
tbus
|
||||
list_get_item(const struct list *self, int index)
|
||||
{
|
||||
@ -140,7 +140,7 @@ list_get_item(const struct list *self, int index)
|
||||
return self->items[index];
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
void
|
||||
list_clear(struct list *self)
|
||||
{
|
||||
@ -161,7 +161,7 @@ list_clear(struct list *self)
|
||||
self->items = (tbus *)realloc(self->items, sizeof(tbus) * self->alloc_size);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
int
|
||||
list_index_of(struct list *self, tbus item)
|
||||
{
|
||||
@ -178,7 +178,7 @@ list_index_of(struct list *self, tbus item)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
void
|
||||
list_remove_item(struct list *self, int index)
|
||||
{
|
||||
@ -201,7 +201,6 @@ list_remove_item(struct list *self, int index)
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
list_insert_item(struct list *self, int index, tbus item)
|
||||
{
|
||||
@ -234,7 +233,7 @@ list_insert_item(struct list *self, int index, tbus item)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
/* append one list to another using strdup for each item in the list */
|
||||
/* begins copy at start_index, a zero based index on the source list */
|
||||
int
|
||||
@ -282,7 +281,7 @@ list_append_list_strdup(struct list *self, struct list *dest, int start_index)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************/
|
||||
void
|
||||
list_dump_items(struct list *self)
|
||||
{
|
||||
@ -298,3 +297,71 @@ list_dump_items(struct list *self)
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "%d: %p", index, (void *) list_get_item(self, index));
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Appends a string fragment to a list
|
||||
* @param[in,out] start Pointer to start of fragment (by reference)
|
||||
* @param end Pointer to one past end of fragment
|
||||
* @param list List to append to
|
||||
* @result 1 for success
|
||||
*
|
||||
* In the event of a memory failure, 0 is returned and the list is deleted.
|
||||
*/
|
||||
int
|
||||
split_string_append_fragment(const char **start, const char *end,
|
||||
struct list *list)
|
||||
{
|
||||
const unsigned int len = end - *start;
|
||||
char *copy = (char *)malloc(len + 1);
|
||||
if (copy == NULL)
|
||||
{
|
||||
list_delete(list);
|
||||
return 0;
|
||||
}
|
||||
g_memcpy(copy, *start, len);
|
||||
copy[len] = '\0';
|
||||
if (!list_add_item(list, (tintptr)copy))
|
||||
{
|
||||
g_free(copy);
|
||||
list_delete(list);
|
||||
return 0;
|
||||
}
|
||||
*start = end + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
struct list *
|
||||
split_string_into_list(const char *str, char character)
|
||||
{
|
||||
struct list *result = list_create();
|
||||
if (result == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
result->auto_free = 1;
|
||||
|
||||
if (str == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *p;
|
||||
while ((p = g_strchr(str, character)) != NULL)
|
||||
{
|
||||
if (!split_string_append_fragment(&str, p, result))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (*str != '\0')
|
||||
{
|
||||
if (!split_string_append_fragment(&str, str + g_strlen(str), result))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -95,4 +95,22 @@ list_append_list_strdup(struct list *self, struct list *dest, int start_index);
|
||||
void
|
||||
list_dump_items(struct list *self);
|
||||
|
||||
/**
|
||||
* Splits a string on a separation character and then returns a list of
|
||||
* the string split by the character, without the character contained within
|
||||
* the pieces.
|
||||
*
|
||||
* The list must be disposed of by the caller.
|
||||
*
|
||||
* @param str String to split.
|
||||
* @param character Character used as the delimiter between strings.
|
||||
* @param start_index Index to start on the source list (zero based)
|
||||
*
|
||||
* @result 0 if a memory allocation failure occurred.
|
||||
*
|
||||
* String fragments in the list are created with strdup()
|
||||
*/
|
||||
struct list *
|
||||
split_string_into_list(const char *str, char character);
|
||||
|
||||
#endif
|
||||
|
@ -1142,3 +1142,4 @@ g_charstr_to_bitmask(const char *str, const struct bitmask_char bitdefs[],
|
||||
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config_ac.h"
|
||||
#endif
|
||||
@ -112,8 +111,49 @@ START_TEST(test_list__simple_append_list)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
split_string_append_fragment(const char **start, const char *end,
|
||||
struct list *list);
|
||||
|
||||
START_TEST(test_list__append_fragment)
|
||||
{
|
||||
struct list *l = list_create();
|
||||
l->auto_free = 1;
|
||||
|
||||
const char *test_string = "split this";
|
||||
|
||||
int fragment_ret = split_string_append_fragment(&test_string,
|
||||
test_string + 5, l);
|
||||
ck_assert_int_eq(fragment_ret, 1);
|
||||
ck_assert_str_eq((const char *)l->items[0], "split");
|
||||
|
||||
fragment_ret = split_string_append_fragment(&test_string,
|
||||
test_string + 1000, l);
|
||||
ck_assert_int_eq(fragment_ret, 1);
|
||||
ck_assert_str_eq((const char *)l->items[1], "this");
|
||||
|
||||
list_delete(l);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_list__split_string_into_list)
|
||||
{
|
||||
struct list *l = split_string_into_list("The fat cat sat on my hat.", ' ');
|
||||
|
||||
ck_assert_int_eq(l->count, 7);
|
||||
ck_assert_str_eq((const char *)l->items[0], "The");
|
||||
ck_assert_str_eq((const char *)l->items[1], "fat");
|
||||
ck_assert_str_eq((const char *)l->items[2], "cat");
|
||||
ck_assert_str_eq((const char *)l->items[3], "sat");
|
||||
ck_assert_str_eq((const char *)l->items[4], "on");
|
||||
ck_assert_str_eq((const char *)l->items[5], "my");
|
||||
ck_assert_str_eq((const char *)l->items[6], "hat.");
|
||||
|
||||
list_delete(l);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/******************************************************************************/
|
||||
Suite *
|
||||
make_suite_test_list(void)
|
||||
{
|
||||
@ -127,6 +167,8 @@ make_suite_test_list(void)
|
||||
tcase_add_test(tc_simple, test_list__simple);
|
||||
tcase_add_test(tc_simple, test_list__simple_auto_free);
|
||||
tcase_add_test(tc_simple, test_list__simple_append_list);
|
||||
tcase_add_test(tc_simple, test_list__append_fragment);
|
||||
tcase_add_test(tc_simple, test_list__split_string_into_list);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user