aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmm-common/mm-common-helpers.c145
-rw-r--r--libmm-common/mm-common-helpers.h9
2 files changed, 153 insertions, 1 deletions
diff --git a/libmm-common/mm-common-helpers.c b/libmm-common/mm-common-helpers.c
index 1d3361e1..98f85bc5 100644
--- a/libmm-common/mm-common-helpers.c
+++ b/libmm-common/mm-common-helpers.c
@@ -10,9 +10,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2011 - Google, Inc.
+ * Copyright (C) 2011 - 2012 Google, Inc.
*/
+#include <string.h>
#include <gio/gio.h>
#include <ModemManager.h>
@@ -314,3 +315,145 @@ mm_common_build_bands_any (void)
g_variant_new_uint32 (MM_MODEM_BAND_ANY));
return g_variant_builder_end (&builder);
}
+
+/* Expecting input as:
+ * key1=string,key2=true,key3=false...
+ * Strings may also be passed enclosed between double or single quotes, like:
+ * key1="this is a string", key2='and so is this'
+ */
+gboolean
+mm_common_parse_key_value_string (const gchar *str,
+ GError **error,
+ MMParseKeyValueForeachFn callback,
+ gpointer user_data)
+{
+ GError *inner_error = NULL;
+ gchar *dup, *p, *key, *key_end, *value, *value_end, quote;
+
+ g_return_val_if_fail (callback != NULL, FALSE);
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ dup = g_strdup (str);
+
+ p = dup;
+
+ while (TRUE) {
+ gboolean keep_iteration = FALSE;
+
+ /* Skip leading spaces */
+ while (*p && g_ascii_isspace (*p))
+ p++;
+
+ /* Key start */
+ key = p;
+ if (!g_ascii_isalnum (*key)) {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Key must start with alpha/num, starts with '%c'",
+ *key);
+ break;
+ }
+
+ /* Key end */
+ while (g_ascii_isalnum (*p) || (*p == '-') || (*p == '_'))
+ p++;
+ key_end = p;
+ if (key_end == key) {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't find a proper key");
+ break;
+ }
+
+ /* Skip whitespaces, if any */
+ while (*p && g_ascii_isspace (*p))
+ p++;
+
+ /* Equal sign must be here */
+ if (*p != '=') {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't find equal sign separator");
+ break;
+ }
+ /* Skip the equal */
+ p++;
+
+ /* Skip whitespaces, if any */
+ while (*p && g_ascii_isspace (*p))
+ p++;
+
+ /* Do we have a quote-enclosed string? */
+ if (*p == '\"' || *p == '\'') {
+ quote = *p;
+ /* Skip the quote */
+ p++;
+ /* Value start */
+ value = p;
+ /* Find the closing quote */
+ p = strchr (p, quote);
+ if (!p) {
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Unmatched quotes in string value");
+ break;
+ }
+
+ /* Value end */
+ value_end = p;
+ /* Skip the quote */
+ p++;
+ } else {
+ /* Value start */
+ value = p;
+
+ /* Value end */
+ while ((*p != ',') && (*p != '\0') && !g_ascii_isspace (*p))
+ p++;
+ value_end = p;
+ }
+
+ /* Note that we allow value == value_end here */
+
+ /* Skip whitespaces, if any */
+ while (*p && g_ascii_isspace (*p))
+ p++;
+
+ /* If a comma is found, we should keep the iteration */
+ if (*p == ',') {
+ /* skip the comma */
+ p++;
+ keep_iteration = TRUE;
+ }
+
+ /* Got key and value, prepare them and run the callback */
+ *value_end = '\0';
+ *key_end = '\0';
+ if (!callback (key, value, user_data)) {
+ /* We were told to abort */
+ break;
+ }
+
+ if (keep_iteration)
+ continue;
+
+ /* Check if no more key/value pairs expected */
+ if (*p == '\0')
+ break;
+
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Unexpected content (%s) after value",
+ p);
+ break;
+ }
+
+ g_free (dup);
+
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/libmm-common/mm-common-helpers.h b/libmm-common/mm-common-helpers.h
index e7ed4197..44625386 100644
--- a/libmm-common/mm-common-helpers.h
+++ b/libmm-common/mm-common-helpers.h
@@ -46,4 +46,13 @@ GVariant *mm_common_bands_garray_to_variant (GArray *array);
GVariant *mm_common_build_bands_any (void);
GVariant *mm_common_build_bands_unknown (void);
+typedef gboolean (*MMParseKeyValueForeachFn) (const gchar *key,
+ const gchar *value,
+ gpointer user_data);
+gboolean mm_common_parse_key_value_string (const gchar *str,
+ GError **error,
+ MMParseKeyValueForeachFn callback,
+ gpointer user_data);
+
+
#endif /* MM_COMMON_HELPERS_H */