diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2015-06-04 15:05:33 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2015-07-24 14:02:59 +0200 |
commit | 8be981479366f8caeb494471742e5c801a52cfa2 (patch) | |
tree | 2cdf54ed59b4378f971e2036949f1baf7c4c8024 | |
parent | ea58caef36a0c46517c8b2b9ae1beb86288b58af (diff) | |
download | NetworkManager-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.am | 3 | ||||
-rw-r--r-- | libnm-core/nm-utils.c | 120 | ||||
-rw-r--r-- | libnm-core/nm-utils.h | 6 | ||||
-rw-r--r-- | libnm-core/tests/Makefile.am | 15 | ||||
-rw-r--r-- | libnm-core/tests/test-general-enums.h | 46 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 73 | ||||
-rw-r--r-- | libnm/libnm.ver | 2 |
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; |