diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2016-08-08 09:40:17 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2016-10-12 11:29:52 +0200 |
commit | 3a886d848dadd98eda8dff354c1d10450d7613fe (patch) | |
tree | 94e5b92cb513f3aa595a28c5c7c1f95ef3edca9f | |
parent | 37bd61421245de87d2c04852109d2a1b14d338cb (diff) |
modem-helpers: new uint list parser, including interval support
-rw-r--r-- | src/mm-modem-helpers.c | 99 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 3 | ||||
-rw-r--r-- | src/tests/test-modem-helpers.c | 45 |
3 files changed, 147 insertions, 0 deletions
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c index e6e158cc..8b4f0f08 100644 --- a/src/mm-modem-helpers.c +++ b/src/mm-modem-helpers.c @@ -131,6 +131,105 @@ mm_split_string_groups (const gchar *str) /*****************************************************************************/ +static int uint_compare_func (gconstpointer a, gconstpointer b) +{ + return (*(guint *)a - *(guint *)b); +} + +GArray * +mm_parse_uint_list (const gchar *str, + GError **error) +{ + GArray *array; + gchar *dupstr; + gchar *aux; + GError *inner_error = NULL; + + if (!str || !str[0]) + return NULL; + + /* Parses into a GArray of guints, the list of numbers given in the string, + * also supporting number intervals. + * E.g.: + * 1-6 --> 1,2,3,4,5,6 + * 1,2,4-6 --> 1,2,4,5,6 + */ + array = g_array_new (FALSE, FALSE, sizeof (guint)); + aux = dupstr = g_strdup (str); + + while (aux) { + gchar *next; + gchar *interval; + + next = strchr (aux, ','); + if (next) { + *next = '\0'; + next++; + } + + interval = strchr (aux, '-'); + if (interval) { + guint start = 0; + guint stop = 0; + + *interval = '\0'; + interval++; + + if (!mm_get_uint_from_str (aux, &start)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "couldn't parse interval start integer: '%s'", aux); + goto out; + } + if (!mm_get_uint_from_str (interval, &stop)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "couldn't parse interval stop integer: '%s'", interval); + goto out; + } + + if (start > stop) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "interval start (%u) cannot be bigger than interval stop (%u)", start, stop); + goto out; + } + + for (; start <= stop; start++) + g_array_append_val (array, start); + } else { + guint num; + + if (!mm_get_uint_from_str (aux, &num)) { + inner_error = g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED, + "couldn't parse integer: '%s'", aux); + goto out; + } + + g_array_append_val (array, num); + } + + aux = next; + } + + if (!array->len) + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "couldn't parse list of integers: '%s'", str); + else + g_array_sort (array, uint_compare_func); + +out: + g_free (dupstr); + + if (inner_error) { + g_propagate_error (error, inner_error); + g_array_unref (array); + return NULL; + } + + return array; +} + +/*****************************************************************************/ + guint mm_count_bits_set (gulong number) { diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h index c7aba903..21794646 100644 --- a/src/mm-modem-helpers.h +++ b/src/mm-modem-helpers.h @@ -53,6 +53,9 @@ const gchar *mm_strip_tag (const gchar *str, gchar **mm_split_string_groups (const gchar *str); +GArray *mm_parse_uint_list (const gchar *str, + GError **error); + guint mm_count_bits_set (gulong number); gchar *mm_create_device_identifier (guint vid, diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c index c6fef40a..14f32961 100644 --- a/src/tests/test-modem-helpers.c +++ b/src/tests/test-modem-helpers.c @@ -3060,6 +3060,49 @@ test_cgcontrdp_response (void) /*****************************************************************************/ +typedef struct { + gchar *str; + gint expected_number_list[9]; +} TestParseNumberList; + +static const TestParseNumberList test_parse_number_list_item [] = { + { "1-6", { 1, 2, 3, 4, 5, 6, -1 } }, + { "0,1,2,4,6", { 0, 1, 2, 4, 6, -1 } }, + { "1,3-5,7,9-11", { 1, 3, 4, 5, 7, 9, 10, 11, -1 } }, + { "9-11,7,3-5", { 3, 4, 5, 7, 9, 10, 11, -1 } }, + { "", { -1 } }, + { NULL, { -1 } }, +}; + +static void +test_parse_uint_list (void) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (test_parse_number_list_item); i++) { + GArray *array; + GError *error = NULL; + guint j; + + array = mm_parse_uint_list (test_parse_number_list_item[i].str, &error); + g_assert_no_error (error); + if (test_parse_number_list_item[i].expected_number_list[0] == -1) { + g_assert (!array); + continue; + } + + g_assert (array); + for (j = 0; j < array->len; j++) { + g_assert_cmpint (test_parse_number_list_item[i].expected_number_list[j], !=, -1); + g_assert_cmpuint (test_parse_number_list_item[i].expected_number_list[j], ==, g_array_index (array, guint, j)); + } + g_assert_cmpint (test_parse_number_list_item[i].expected_number_list[array->len], ==, -1); + g_array_unref (array); + } +} + +/*****************************************************************************/ + void _mm_log (const char *loc, const char *func, @@ -3245,6 +3288,8 @@ int main (int argc, char **argv) g_test_suite_add (suite, TESTCASE (test_cgcontrdp_response, NULL)); + g_test_suite_add (suite, TESTCASE (test_parse_uint_list, NULL)); + result = g_test_run (); reg_test_data_free (reg_data); |