aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2016-08-08 09:40:17 +0200
committerAleksander Morgado <aleksander@aleksander.es>2016-10-12 11:29:52 +0200
commit3a886d848dadd98eda8dff354c1d10450d7613fe (patch)
tree94e5b92cb513f3aa595a28c5c7c1f95ef3edca9f
parent37bd61421245de87d2c04852109d2a1b14d338cb (diff)
modem-helpers: new uint list parser, including interval support
-rw-r--r--src/mm-modem-helpers.c99
-rw-r--r--src/mm-modem-helpers.h3
-rw-r--r--src/tests/test-modem-helpers.c45
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);