modem-helpers: new uint list parser, including interval support
This commit is contained in:
@@ -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
|
guint
|
||||||
mm_count_bits_set (gulong number)
|
mm_count_bits_set (gulong number)
|
||||||
{
|
{
|
||||||
|
@@ -53,6 +53,9 @@ const gchar *mm_strip_tag (const gchar *str,
|
|||||||
|
|
||||||
gchar **mm_split_string_groups (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);
|
guint mm_count_bits_set (gulong number);
|
||||||
|
|
||||||
gchar *mm_create_device_identifier (guint vid,
|
gchar *mm_create_device_identifier (guint vid,
|
||||||
|
@@ -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
|
void
|
||||||
_mm_log (const char *loc,
|
_mm_log (const char *loc,
|
||||||
const char *func,
|
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_cgcontrdp_response, NULL));
|
||||||
|
|
||||||
|
g_test_suite_add (suite, TESTCASE (test_parse_uint_list, NULL));
|
||||||
|
|
||||||
result = g_test_run ();
|
result = g_test_run ();
|
||||||
|
|
||||||
reg_test_data_free (reg_data);
|
reg_test_data_free (reg_data);
|
||||||
|
Reference in New Issue
Block a user