diff options
author | Guido Günther <agx@sigxcpu.org> | 2025-03-28 16:49:57 +0100 |
---|---|---|
committer | Dan Williams <dan@ioncontrol.co> | 2025-03-29 22:19:17 +0000 |
commit | 4414344d828bb59e6ef1389a08a4e8699628e7ef (patch) | |
tree | 0781b294c1937b5c92f5bfb723eba6fd3243cd62 | |
parent | d00ff2d0a127bbe2fc3d73b7e10d3aa65675c1a6 (diff) |
libmm-glib,helpers: Add helpers to parse CB channels in and out of strings
Signed-off-by: Guido Günther <agx@sigxcpu.org>
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 114 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 6 | ||||
-rw-r--r-- | libmm-glib/tests/test-common-helpers.c | 86 |
3 files changed, 206 insertions, 0 deletions
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c index e249a2fc..12796429 100644 --- a/libmm-glib/mm-common-helpers.c +++ b/libmm-glib/mm-common-helpers.c @@ -174,6 +174,36 @@ mm_common_build_mode_combinations_string (const MMModemModeCombination *modes, return g_string_free (str, FALSE); } +gchar * +mm_common_build_channels_string (const MMCellBroadcastChannels *channels, + guint n_channels) +{ + gboolean first = TRUE; + GString *str; + guint i; + + if (!channels || !n_channels) + return g_strdup ("none"); + + str = g_string_new (""); + for (i = 0; i < n_channels; i++) { + if (channels[i].start == channels[i].end) { + g_string_append_printf (str, "%s%u", + first ? "" : ",", + channels[i].start); + } else { + g_string_append_printf (str, "%s%u-%u", + first ? "" : ",", + channels[i].start, channels[i].end); + } + + if (first) + first = FALSE; + } + + return g_string_free (str, FALSE); +} + /******************************************************************************/ /* String to enums/flags parsers */ @@ -738,6 +768,90 @@ mm_common_get_profile_source_from_string (const gchar *str, error); } +gboolean +mm_common_get_cell_broadcast_channels_from_string (const gchar *str, + MMCellBroadcastChannels **channels, + guint *n_channels, + GError **error) +{ + GError *inner_error = NULL; + GArray *array; + g_auto(GStrv) channel_strings = NULL; + + array = g_array_new (FALSE, FALSE, sizeof (MMCellBroadcastChannels)); + + channel_strings = g_strsplit (str, ",", -1); + + if (channel_strings) { + guint i; + + for (i = 0; channel_strings[i]; i++) { + char *startptr, *endptr; + gint64 start; + + startptr = channel_strings[i]; + start = g_ascii_strtoll (startptr, &endptr, 10); + if (startptr == endptr || start > G_MAXUINT16 || start < 0) { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Couldn't parse '%s' as MMCellBroadcastChannel start value", + channel_strings[i]); + break; + } + if (*endptr == '\0') { + MMCellBroadcastChannels ch; + + ch.start = start; + ch.end = start; + g_array_append_val (array, ch); + } else if (*endptr == '-') { + gint64 end; + + startptr = endptr + 1; + end = g_ascii_strtoll (startptr, &endptr, 10); + if (startptr == endptr || end > G_MAXUINT16 || end < 0) { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Couldn't parse '%s' as MMCellBroadcastChannel end value", + channel_strings[i]); + break; + } + if (*endptr == '\0') { + MMCellBroadcastChannels ch; + + ch.start = start; + ch.end = end; + g_array_append_val (array, ch); + } else { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Couldn't parse '%s' as MMCellBroadcastChannel end value", + channel_strings[i]); + break; + } + } else { + inner_error = g_error_new (MM_CORE_ERROR, + MM_CORE_ERROR_INVALID_ARGS, + "Couldn't parse '%s' as MMCellBroadcastChannel value", + channel_strings[i]); + break; + } + } + } + + if (inner_error) { + g_propagate_error (error, inner_error); + g_array_free (array, TRUE); + *n_channels = 0; + *channels = NULL; + return FALSE; + } + + *n_channels = array->len; + *channels = (MMCellBroadcastChannels *)g_array_free (array, FALSE); + return TRUE; +} + /******************************************************************************/ /* MMModemPortInfo array management */ diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h index bea220e0..d3b2a0fb 100644 --- a/libmm-glib/mm-common-helpers.h +++ b/libmm-glib/mm-common-helpers.h @@ -46,6 +46,8 @@ gchar *mm_common_build_sms_storages_string (const MMSmsStorage *s guint n_storages); gchar *mm_common_build_mode_combinations_string (const MMModemModeCombination *modes, guint n_modes); +gchar *mm_common_build_channels_string (const MMCellBroadcastChannels *channels, + guint n_channels); /******************************************************************************/ /* String to enums/flags parsers */ @@ -102,6 +104,10 @@ MMBearerAccessTypePreference mm_common_get_access_type_preference_from_string GError **error); MMBearerProfileSource mm_common_get_profile_source_from_string (const gchar *str, GError **error); +gboolean mm_common_get_cell_broadcast_channels_from_string (const gchar *str, + MMCellBroadcastChannels **channels, + guint *n_channels, + GError **error); /******************************************************************************/ diff --git a/libmm-glib/tests/test-common-helpers.c b/libmm-glib/tests/test-common-helpers.c index 7ee69687..a84314ba 100644 --- a/libmm-glib/tests/test-common-helpers.c +++ b/libmm-glib/tests/test-common-helpers.c @@ -762,6 +762,28 @@ sms_storages_to_string (void) } static void +cell_broadcast_channels_to_string (void) +{ + gchar *channels_str = NULL; + MMCellBroadcastChannels channels[] = { + { .start = 4383, .end = 4383 }, + { .start = 4380, .end = 4382 } + }; + + channels_str = mm_common_build_channels_string (NULL, 0); + g_assert_cmpstr (channels_str, ==, "none"); + g_clear_pointer (&channels_str, g_free); + + channels_str = mm_common_build_channels_string (channels, 1); + g_assert_cmpstr (channels_str, ==, "4383"); + g_clear_pointer (&channels_str, g_free); + + channels_str = mm_common_build_channels_string (channels, 2); + g_assert_cmpstr (channels_str, ==, "4383,4380-4382"); + g_clear_pointer (&channels_str, g_free); +} + +static void capabilities_from_string (void) { MMModemCapability capability = MM_MODEM_CAPABILITY_ANY; @@ -1275,6 +1297,68 @@ profile_source_from_string (void) g_assert (profile_source == MM_BEARER_PROFILE_SOURCE_MODEM); } +static void +cell_broadcast_channels_from_string (void) +{ + MMCellBroadcastChannels *channels = NULL; + guint n_channels = 0; + gboolean ret = FALSE; + GError *error = NULL; + + ret = mm_common_get_cell_broadcast_channels_from_string ("not found", &channels, &n_channels, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_false (ret); + g_assert_cmpuint (n_channels, ==, 0); + g_assert_null (channels); + g_clear_error (&error); + + ret = mm_common_get_cell_broadcast_channels_from_string ("4370", &channels, &n_channels, &error); + g_assert_no_error (error); + g_assert_true (ret); + g_assert_cmpuint (n_channels, ==, 1); + g_assert_cmpuint (channels[0].start, ==, 4370); + g_assert_cmpuint (channels[0].end, ==, 4370); + g_clear_pointer(&channels, g_free); + + ret = mm_common_get_cell_broadcast_channels_from_string ("4370,4371-abc", &channels, &n_channels, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_false (ret); + g_assert_cmpuint (n_channels, ==, 0); + g_assert_null (channels); + g_clear_error (&error); + + ret = mm_common_get_cell_broadcast_channels_from_string ("4370,,4371-5000", &channels, &n_channels, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_false (ret); + g_assert_cmpuint (n_channels, ==, 0); + g_assert_null (channels); + g_clear_error (&error); + + ret = mm_common_get_cell_broadcast_channels_from_string ("4370,,-5000", &channels, &n_channels, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_false (ret); + g_assert_cmpuint (n_channels, ==, 0); + g_assert_null (channels); + g_clear_error (&error); + + ret = mm_common_get_cell_broadcast_channels_from_string ("65537", &channels, &n_channels, &error); + g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS); + g_assert_false (ret); + g_assert_cmpuint (n_channels, ==, 0); + g_assert_null (channels); + g_clear_error (&error); + + ret = mm_common_get_cell_broadcast_channels_from_string ("4370,4371-5000", &channels, &n_channels, &error); + g_assert_no_error (error); + g_assert_true (ret); + g_assert_cmpuint (n_channels, ==, 2); + g_assert_cmpuint (channels[0].start, ==, 4370); + g_assert_cmpuint (channels[0].end, ==, 4370); + g_assert_cmpuint (channels[1].start, ==, 4371); + g_assert_cmpuint (channels[1].end, ==, 5000); + g_clear_pointer(&channels, g_free); +} + /**************************************************************/ int main (int argc, char **argv) @@ -1328,6 +1412,7 @@ int main (int argc, char **argv) g_test_add_func ("/MM/Common/StrConvTo/mode-combinations", mode_combinations_to_string); g_test_add_func ("/MM/Common/StrConvTo/ports", ports_to_string); g_test_add_func ("/MM/Common/StrConvTo/sms-storages", sms_storages_to_string); + g_test_add_func ("/MM/Common/StrConvTo/cb-channels", cell_broadcast_channels_to_string); g_test_add_func ("/MM/Common/StrConvFrom/capabilities", capabilities_from_string); g_test_add_func ("/MM/Common/StrConvFrom/modes", modes_from_string); @@ -1354,6 +1439,7 @@ int main (int argc, char **argv) g_test_add_func ("/MM/Common/StrConvFrom/3gpp_drx_cycle", _3gpp_drx_cycle_from_string); g_test_add_func ("/MM/Common/StrConvFrom/access_type", access_type_preference_from_string); g_test_add_func ("/MM/Common/StrConvFrom/profile_source", profile_source_from_string); + g_test_add_func ("/MM/Common/StrConvFrom/cb_channels", cell_broadcast_channels_from_string); return g_test_run (); } |