summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2015-06-04 15:05:33 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2015-07-24 14:02:59 +0200
commit8be981479366f8caeb494471742e5c801a52cfa2 (patch)
tree2cdf54ed59b4378f971e2036949f1baf7c4c8024
parentea58caef36a0c46517c8b2b9ae1beb86288b58af (diff)
downloadNetworkManager-8be981479366f8caeb494471742e5c801a52cfa2.tar.gz
libnm-core: add enum conversion utilities
Add functions nm_utils_enum_to_str() and nm_utils_enum_from_str() which can be used to perform conversions between enum values and strings, passing the GType automatically generated for every enum by glib-mkenums.
-rw-r--r--docs/libnm/Makefile.am3
-rw-r--r--libnm-core/nm-utils.c120
-rw-r--r--libnm-core/nm-utils.h6
-rw-r--r--libnm-core/tests/Makefile.am15
-rw-r--r--libnm-core/tests/test-general-enums.h46
-rw-r--r--libnm-core/tests/test-general.c73
-rw-r--r--libnm/libnm.ver2
7 files changed, 264 insertions, 1 deletions
diff --git a/docs/libnm/Makefile.am b/docs/libnm/Makefile.am
index 28938f89ff..2525856d5f 100644
--- a/docs/libnm/Makefile.am
+++ b/docs/libnm/Makefile.am
@@ -53,7 +53,8 @@ IGNORE_HFILES= \
nm-setting-private.h \
nm-types.h \
nm-utils-private.h \
- nm-vpn-plugin-old.h
+ nm-vpn-plugin-old.h \
+ nm-core-tests-enum-types.h
# Images to copy into HTML directory.
HTML_IMAGES = libnm.png
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index 66878e8cc0..c8b35b1dfb 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -3688,3 +3688,123 @@ int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option)
return -1;
}
+/**
+ * nm_utils_enum_to_str
+ * @type: the %GType of the enum
+ * @value: the value to be translated
+ *
+ * Converts an enum value to its string representation. If the enum is a
+ * %G_TYPE_FLAGS the function returns a comma-separated list of matching values.
+ * If the enum is a %G_TYPE_ENUM and the given value is not valid the
+ * function returns %NULL.
+ *
+ * Returns: a newly allocated string or %NULL
+ *
+ * Since: 1.2
+ */
+char *nm_utils_enum_to_str (GType type, int value)
+{
+ GTypeClass *class;
+ char *ret;
+
+ class = g_type_class_ref (type);
+
+ if (G_IS_ENUM_CLASS (class)) {
+ GEnumValue *enum_value;
+
+ enum_value = g_enum_get_value (G_ENUM_CLASS (class), value);
+ ret = enum_value ? strdup (enum_value->value_nick) : NULL;
+ } else if (G_IS_FLAGS_CLASS (class)) {
+ GFlagsValue *flags_value;
+ GString *str = g_string_new ("");
+ gboolean first = TRUE;
+
+ while (value) {
+ flags_value = g_flags_get_first_value (G_FLAGS_CLASS (class), value);
+ if (!flags_value)
+ break;
+
+ if (!first)
+ g_string_append_c (str, ',');
+ g_string_append (str, flags_value->value_nick);
+
+ value &= ~flags_value->value;
+ first = FALSE;
+ }
+ ret = g_string_free (str, FALSE);
+ } else
+ g_return_if_reached ();
+
+ g_type_class_unref (class);
+ return ret;
+}
+
+/**
+ * nm_utils_enum_from_str
+ * @type: the %GType of the enum
+ * @str: the input string
+ * @out_value: (out) (allow-none) the output value
+ * @err_token: (out) (allow-none) location to store the first unrecognized token
+ *
+ * Converts a string to the matching enum value.
+ *
+ * If the enum is a %G_TYPE_FLAGS the function returns the logical OR of values
+ * matching the comma-separated tokens in the string; if an unknown token is found
+ * the function returns %FALSE and stores a pointer to a newly allocated string
+ * containing the unrecognized token in @err_token.
+ *
+ * Returns: %TRUE if the conversion was successful, %FALSE otherwise
+ *
+ * Since: 1.2
+ */
+gboolean nm_utils_enum_from_str (GType type, const char *str,
+ int *out_value, char **err_token)
+{
+ GTypeClass *class;
+ gboolean ret = FALSE;
+ int value = 0;
+
+ g_return_val_if_fail (str, FALSE);
+ class = g_type_class_ref (type);
+
+ if (G_IS_ENUM_CLASS (class)) {
+ GEnumValue *enum_value;
+
+ enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (class), str);
+ if (enum_value) {
+ value = enum_value->value;
+ ret = TRUE;
+ }
+ } else if (G_IS_FLAGS_CLASS (class)) {
+ GFlagsValue *flags_value;
+ gs_strfreev char **strv = NULL;
+ int i;
+
+ strv = g_strsplit (str, ",", 0);
+ for (i = 0; strv[i]; i++) {
+ if (!strv[i][0])
+ continue;
+
+ flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (class), strv[i]);
+ if (!flags_value)
+ break;
+
+ value |= flags_value->value;
+ }
+
+ if (strv[i]) {
+ if (err_token)
+ *err_token = strdup (strv[i]);
+ value = 0;
+ } else
+ ret = TRUE;
+ } else
+ g_assert_not_reached ();
+
+ if (out_value)
+ *out_value = value;
+
+ g_type_class_unref (class);
+ return ret;
+}
+
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index 727f000568..c9a01d6e6e 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -190,6 +190,12 @@ int nm_utils_bond_mode_string_to_int (const char *mode);
NM_AVAILABLE_IN_1_2
const char *nm_utils_bond_mode_int_to_string (int mode);
+NM_AVAILABLE_IN_1_2
+char *nm_utils_enum_to_str (GType type, int value);
+
+NM_AVAILABLE_IN_1_2
+gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token);
+
G_END_DECLS
#endif /* __NM_UTILS_H__ */
diff --git a/libnm-core/tests/Makefile.am b/libnm-core/tests/Makefile.am
index daa5825b50..dd38b3d685 100644
--- a/libnm-core/tests/Makefile.am
+++ b/libnm-core/tests/Makefile.am
@@ -1,5 +1,14 @@
if ENABLE_TESTS
+include $(GLIB_MAKEFILE)
+
+GLIB_GENERATED = nm-core-tests-enum-types.h nm-core-tests-enum-types.c
+nm_core_tests_enum_types_sources = test-general-enums.h
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+
+BUILT_SOURCES = $(GLIB_GENERATED)
+
certsdir = $(srcdir)/certs
AM_CPPFLAGS = \
@@ -28,6 +37,12 @@ LDADD = \
@VALGRIND_RULES@
TESTS = $(noinst_PROGRAMS)
+test_general_SOURCES = \
+ test-general.c \
+ test-general-enums.h \
+ nm-core-tests-enum-types.c \
+ nm-core-tests-enum-types.h
+
endif
# test-cert.p12 created with:
diff --git a/libnm-core/tests/test-general-enums.h b/libnm-core/tests/test-general-enums.h
new file mode 100644
index 0000000000..d06d6e39ff
--- /dev/null
+++ b/libnm-core/tests/test-general-enums.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2015 Red Hat, Inc.
+ */
+
+#ifndef _NM_TEST_GENERAL_ENUMS_H_
+#define _NM_TEST_GENERAL_ENUMS_H_
+
+typedef enum {
+ NM_TEST_GENERAL_BOOL_ENUM_NO = 0,
+ NM_TEST_GENERAL_BOOL_ENUM_YES = 1,
+ NM_TEST_GENERAL_BOOL_ENUM_MAYBE = 2,
+ NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN = 3,
+ NM_TEST_GENERAL_BOOL_ENUM_INVALID = 4, /*< skip >*/
+} NMTestGeneralBoolEnum;
+
+typedef enum {
+ NM_TEST_GENERAL_META_FLAGS_NONE = 0,
+ NM_TEST_GENERAL_META_FLAGS_FOO = (1 << 0),
+ NM_TEST_GENERAL_META_FLAGS_BAR = (1 << 1),
+ NM_TEST_GENERAL_META_FLAGS_BAZ = (1 << 2),
+} NMTestGeneralMetaFlags;
+
+typedef enum { /*< flags >*/
+ NM_TEST_GENERAL_COLOR_FLAGS_WHITE = 1, /*< skip >*/
+ NM_TEST_GENERAL_COLOR_FLAGS_BLUE = 2,
+ NM_TEST_GENERAL_COLOR_FLAGS_RED = 4,
+ NM_TEST_GENERAL_COLOR_FLAGS_GREEN = 8,
+} NMTestGeneralColorFlags;
+
+#endif /* _NM_TEST_GENERAL_ENUMS_H_ */
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
index 082015c040..a661758d25 100644
--- a/libnm-core/tests/test-general.c
+++ b/libnm-core/tests/test-general.c
@@ -33,6 +33,7 @@
#include "nm-utils.h"
#include "nm-utils-private.h"
#include "nm-core-internal.h"
+#include "nm-core-tests-enum-types.h"
#include "nm-setting-8021x.h"
#include "nm-setting-adsl.h"
@@ -64,6 +65,7 @@
#include "nm-glib-compat.h"
#include "nm-test-utils.h"
+#include "test-general-enums.h"
static void
vpn_check_func (const char *key, const char *value, gpointer user_data)
@@ -4587,7 +4589,76 @@ test_nm_utils_ptrarray_find_binary_search (void)
}
/******************************************************************************/
+static void
+test_nm_utils_enum_from_str_do (GType type, const char *str,
+ gboolean exp_result, int exp_flags,
+ const char *exp_err_token)
+{
+ int flags = 1;
+ char *err_token = NULL;
+ gboolean result;
+
+ result = nm_utils_enum_from_str (type, str, &flags, &err_token);
+
+ g_assert (result == exp_result);
+ g_assert_cmpint (flags, ==, exp_flags);
+ g_assert_cmpstr (err_token, ==, exp_err_token);
+
+ g_free (err_token);
+}
+
+static void
+test_nm_utils_enum_to_str_do (GType type, int flags, const char *exp_str)
+{
+ char *str;
+ str = nm_utils_enum_to_str (type, flags);
+ g_assert_cmpstr (str, ==, exp_str);
+ g_free (str);
+}
+
+static void test_nm_utils_enum (void)
+{
+ GType bool_enum = nm_test_general_bool_enum_get_type();
+ GType meta_flags = nm_test_general_meta_flags_get_type();
+ GType color_flags = nm_test_general_color_flags_get_type();
+
+ test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_YES, "yes");
+ test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_UNKNOWN, "unknown");
+ test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_INVALID, NULL);
+
+ test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "");
+ test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
+ test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
+ NM_TEST_GENERAL_META_FLAGS_BAR |
+ NM_TEST_GENERAL_META_FLAGS_BAZ, "foo,bar,baz");
+
+ test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED, "red");
+ test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_WHITE, "");
+ test_nm_utils_enum_to_str_do (color_flags, NM_TEST_GENERAL_COLOR_FLAGS_RED |
+ NM_TEST_GENERAL_COLOR_FLAGS_GREEN, "red,green");
+
+ test_nm_utils_enum_from_str_do (bool_enum, "", FALSE, 0, NULL);
+ test_nm_utils_enum_from_str_do (bool_enum, "invalid", FALSE, 0, NULL);
+ test_nm_utils_enum_from_str_do (bool_enum, "yes", TRUE, NM_TEST_GENERAL_BOOL_ENUM_YES, NULL);
+ test_nm_utils_enum_from_str_do (bool_enum, "no", TRUE, NM_TEST_GENERAL_BOOL_ENUM_NO, NULL);
+ test_nm_utils_enum_from_str_do (bool_enum, "yes,no", FALSE, 0, NULL);
+
+ test_nm_utils_enum_from_str_do (meta_flags, "", TRUE, 0, NULL);
+ test_nm_utils_enum_from_str_do (meta_flags, "foo", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO, NULL);
+ test_nm_utils_enum_from_str_do (meta_flags, "foo,baz", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
+ NM_TEST_GENERAL_META_FLAGS_BAZ, NULL);
+ test_nm_utils_enum_from_str_do (meta_flags, "foo,,bar", TRUE, NM_TEST_GENERAL_META_FLAGS_FOO |
+ NM_TEST_GENERAL_META_FLAGS_BAR, NULL);
+ test_nm_utils_enum_from_str_do (meta_flags, "foo,baz,quux,bar", FALSE, 0, "quux");
+
+ test_nm_utils_enum_from_str_do (color_flags, "green", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_GREEN, NULL);
+ test_nm_utils_enum_from_str_do (color_flags, "blue,red", TRUE, NM_TEST_GENERAL_COLOR_FLAGS_BLUE |
+ NM_TEST_GENERAL_COLOR_FLAGS_RED, NULL);
+ test_nm_utils_enum_from_str_do (color_flags, "blue,white", FALSE, 0, "white");
+}
+
+/******************************************************************************/
NMTST_DEFINE ();
int main (int argc, char **argv)
@@ -4696,6 +4767,8 @@ int main (int argc, char **argv)
g_test_add_func ("/core/general/_nm_utils_dns_option_validate", test_nm_utils_dns_option_validate);
g_test_add_func ("/core/general/_nm_utils_dns_option_find_idx", test_nm_utils_dns_option_find_idx);
+ g_test_add_func ("/core/general/test_nm_utils_enum", test_nm_utils_enum);
+
return g_test_run ();
}
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 01e01c910a..13111f4837 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -877,4 +877,6 @@ global:
nm_setting_wireless_get_powersave;
nm_utils_bond_mode_int_to_string;
nm_utils_bond_mode_string_to_int;
+ nm_utils_enum_from_str;
+ nm_utils_enum_to_str;
} libnm_1_0_0;