diff options
Diffstat (limited to 'shared/nm-glib-aux/nm-enum-utils.c')
| -rw-r--r-- | shared/nm-glib-aux/nm-enum-utils.c | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/shared/nm-glib-aux/nm-enum-utils.c b/shared/nm-glib-aux/nm-enum-utils.c deleted file mode 100644 index b06f2bb2..00000000 --- a/shared/nm-glib-aux/nm-enum-utils.c +++ /dev/null @@ -1,368 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -/* - * Copyright (C) 2017 Red Hat, Inc. - */ - -#include "nm-glib-aux/nm-default-glib-i18n-lib.h" - -#include "nm-enum-utils.h" -#include "nm-str-buf.h" - -/*****************************************************************************/ - -#define IS_FLAGS_SEPARATOR(ch) (NM_IN_SET((ch), ' ', '\t', ',', '\n', '\r')) - -static void -_ASSERT_enum_values_info(GType type, const NMUtilsEnumValueInfo *value_infos) -{ -#if NM_MORE_ASSERTS > 5 - nm_auto_unref_gtypeclass GTypeClass *klass = NULL; - gs_unref_hashtable GHashTable *ht = NULL; - - klass = g_type_class_ref(type); - - g_assert(G_IS_ENUM_CLASS(klass) || G_IS_FLAGS_CLASS(klass)); - - if (!value_infos) - return; - - ht = g_hash_table_new(g_str_hash, g_str_equal); - - for (; value_infos->nick; value_infos++) { - g_assert(value_infos->nick[0]); - - /* duplicate nicks make no sense!! */ - g_assert(!g_hash_table_contains(ht, value_infos->nick)); - g_hash_table_add(ht, (gpointer) value_infos->nick); - - if (G_IS_ENUM_CLASS(klass)) { - GEnumValue *enum_value; - - enum_value = g_enum_get_value_by_nick(G_ENUM_CLASS(klass), value_infos->nick); - if (enum_value) { - /* we do allow specifying the same name via @value_infos and @type. - * That might make sense, if @type comes from a library where older versions - * of the library don't yet support the value. In this case, the caller can - * provide the nick via @value_infos, to support the older library version. - * And then, when actually running against a newer library version where - * @type knows the nick, we have this situation. - * - * Another reason for specifying a nick both in @value_infos and @type, - * is to specify an alias which is not used with highest preference. For - * example, if you add an alias "disabled" for "none" (both numerically - * equal), then the first alias in @value_infos will be preferred over - * the name from @type. So, to still use "none" as preferred name, you may - * explicitly specify the "none" alias in @value_infos before "disabled". - * - * However, what never is allowed, is to use a name (nick) to re-number - * the value. That is, if both @value_infos and @type contain a particular - * nick, their numeric values must agree as well. - * Allowing this, would be very confusing, because the name would have a different - * value from the regular GLib GEnum API. - */ - g_assert(enum_value->value == value_infos->value); - } - } else { - GFlagsValue *flags_value; - - flags_value = g_flags_get_value_by_nick(G_FLAGS_CLASS(klass), value_infos->nick); - if (flags_value) { - /* see ENUM case above. */ - g_assert(flags_value->value == (guint) value_infos->value); - } - } - } -#endif -} - -static gboolean -_is_hex_string(const char *str, gboolean allow_sign) -{ - if (allow_sign && str[0] == '-') - str++; - return str[0] == '0' && str[1] == 'x' && str[2] - && NM_STRCHAR_ALL(&str[2], ch, g_ascii_isxdigit(ch)); -} - -static gboolean -_is_dec_string(const char *str, gboolean allow_sign) -{ - if (allow_sign && str[0] == '-') - str++; - return str[0] && NM_STRCHAR_ALL(&str[0], ch, g_ascii_isdigit(ch)); -} - -static gboolean -_enum_is_valid_enum_nick(const char *str) -{ - return str[0] && !NM_STRCHAR_ANY(str, ch, g_ascii_isspace(ch)) && !_is_dec_string(str, TRUE) - && !_is_hex_string(str, TRUE); -} - -static gboolean -_enum_is_valid_flags_nick(const char *str) -{ - return str[0] && !NM_STRCHAR_ANY(str, ch, IS_FLAGS_SEPARATOR(ch)) && !_is_dec_string(str, FALSE) - && !_is_hex_string(str, FALSE); -} - -char * -_nm_utils_enum_to_str_full(GType type, - int value, - const char * flags_separator, - const NMUtilsEnumValueInfo *value_infos) -{ - nm_auto_unref_gtypeclass GTypeClass *klass = NULL; - - _ASSERT_enum_values_info(type, value_infos); - - if (flags_separator - && (!flags_separator[0] || NM_STRCHAR_ANY(flags_separator, ch, !IS_FLAGS_SEPARATOR(ch)))) - g_return_val_if_reached(NULL); - - klass = g_type_class_ref(type); - - if (G_IS_ENUM_CLASS(klass)) { - GEnumValue *enum_value; - - for (; value_infos && value_infos->nick; value_infos++) { - if (value_infos->value == value) - return g_strdup(value_infos->nick); - } - - enum_value = g_enum_get_value(G_ENUM_CLASS(klass), value); - if (!enum_value || !_enum_is_valid_enum_nick(enum_value->value_nick)) - return g_strdup_printf("%d", value); - else - return g_strdup(enum_value->value_nick); - } else if (G_IS_FLAGS_CLASS(klass)) { - unsigned uvalue = (unsigned) value; - GFlagsValue *flags_value; - NMStrBuf strbuf; - - flags_separator = flags_separator ?: " "; - - nm_str_buf_init(&strbuf, 16, FALSE); - - for (; value_infos && value_infos->nick; value_infos++) { - nm_assert(_enum_is_valid_flags_nick(value_infos->nick)); - - if (uvalue == 0) { - if (value_infos->value != 0) - continue; - } else { - if (!NM_FLAGS_ALL(uvalue, (unsigned) value_infos->value)) - continue; - } - - if (strbuf.len) - nm_str_buf_append(&strbuf, flags_separator); - nm_str_buf_append(&strbuf, value_infos->nick); - uvalue &= ~((unsigned) value_infos->value); - if (uvalue == 0) { - /* we printed all flags. Done. */ - goto flags_done; - } - } - - do { - flags_value = g_flags_get_first_value(G_FLAGS_CLASS(klass), uvalue); - if (strbuf.len) - nm_str_buf_append(&strbuf, flags_separator); - if (!flags_value || !_enum_is_valid_flags_nick(flags_value->value_nick)) { - if (uvalue) - nm_str_buf_append_printf(&strbuf, "0x%x", uvalue); - break; - } - nm_str_buf_append(&strbuf, flags_value->value_nick); - uvalue &= ~flags_value->value; - } while (uvalue); - -flags_done: - return nm_str_buf_finalize(&strbuf, NULL); - } - - g_return_val_if_reached(NULL); -} - -static const NMUtilsEnumValueInfo * -_find_value_info(const NMUtilsEnumValueInfo *value_infos, const char *needle) -{ - if (value_infos) { - for (; value_infos->nick; value_infos++) { - if (nm_streq(needle, value_infos->nick)) - return value_infos; - } - } - return NULL; -} - -gboolean -_nm_utils_enum_from_str_full(GType type, - const char * str, - int * out_value, - char ** err_token, - const NMUtilsEnumValueInfo *value_infos) -{ - nm_auto_unref_gtypeclass GTypeClass *klass = NULL; - gboolean ret = FALSE; - int value = 0; - gs_free char * str_clone = NULL; - char * s; - gint64 v64; - const NMUtilsEnumValueInfo * nick; - - g_return_val_if_fail(str, FALSE); - - _ASSERT_enum_values_info(type, value_infos); - - s = nm_strdup_maybe_a(300, nm_str_skip_leading_spaces(str), &str_clone); - g_strchomp(s); - - klass = g_type_class_ref(type); - - if (G_IS_ENUM_CLASS(klass)) { - GEnumValue *enum_value; - - G_STATIC_ASSERT(G_MAXINT < G_MAXINT64); - G_STATIC_ASSERT(G_MININT > G_MININT64); - - if (s[0]) { - if (_is_hex_string(s, TRUE)) { - if (s[0] == '-') { - v64 = _nm_utils_ascii_str_to_int64(&s[3], - 16, - -((gint64) G_MAXINT), - -((gint64) G_MININT), - G_MAXINT64); - if (v64 != G_MAXINT64) { - value = (int) (-v64); - ret = TRUE; - } - } else { - v64 = _nm_utils_ascii_str_to_int64(&s[2], 16, G_MININT, G_MAXINT, G_MAXINT64); - if (v64 != G_MAXINT64) { - value = (int) v64; - ret = TRUE; - } - } - } else if (_is_dec_string(s, TRUE)) { - v64 = _nm_utils_ascii_str_to_int64(s, 10, G_MININT, G_MAXINT, G_MAXINT64); - if (v64 != G_MAXINT64) { - value = (int) v64; - ret = TRUE; - } - } else if ((nick = _find_value_info(value_infos, s))) { - value = nick->value; - ret = TRUE; - } else if ((enum_value = g_enum_get_value_by_nick(G_ENUM_CLASS(klass), s))) { - value = enum_value->value; - ret = TRUE; - } - } - } else if (G_IS_FLAGS_CLASS(klass)) { - GFlagsValue *flags_value; - unsigned uvalue = 0; - - ret = TRUE; - while (s[0]) { - char *s_end; - - for (s_end = s; s_end[0]; s_end++) { - if (IS_FLAGS_SEPARATOR(s_end[0])) { - s_end[0] = '\0'; - s_end++; - break; - } - } - - if (s[0]) { - if (_is_hex_string(s, FALSE)) { - v64 = _nm_utils_ascii_str_to_int64(&s[2], 16, 0, G_MAXUINT, -1); - if (v64 == -1) { - ret = FALSE; - break; - } - uvalue |= (unsigned) v64; - } else if (_is_dec_string(s, FALSE)) { - v64 = _nm_utils_ascii_str_to_int64(s, 10, 0, G_MAXUINT, -1); - if (v64 == -1) { - ret = FALSE; - break; - } - uvalue |= (unsigned) v64; - } else if ((nick = _find_value_info(value_infos, s))) - uvalue |= (unsigned) nick->value; - else if ((flags_value = g_flags_get_value_by_nick(G_FLAGS_CLASS(klass), s))) - uvalue |= flags_value->value; - else { - ret = FALSE; - break; - } - } - - s = s_end; - } - - value = (int) uvalue; - } else - g_return_val_if_reached(FALSE); - - NM_SET_OUT(err_token, !ret && s[0] ? g_strdup(s) : NULL); - NM_SET_OUT(out_value, ret ? value : 0); - return ret; -} - -const char ** -_nm_utils_enum_get_values(GType type, int from, int to) -{ - GTypeClass *klass; - GPtrArray * array; - int i; - char sbuf[64]; - - klass = g_type_class_ref(type); - array = g_ptr_array_new(); - - if (G_IS_ENUM_CLASS(klass)) { - GEnumClass *enum_class = G_ENUM_CLASS(klass); - GEnumValue *enum_value; - - for (i = 0; i < enum_class->n_values; i++) { - enum_value = &enum_class->values[i]; - if (enum_value->value >= from && enum_value->value <= to) { - if (_enum_is_valid_enum_nick(enum_value->value_nick)) - g_ptr_array_add(array, (gpointer) enum_value->value_nick); - else - g_ptr_array_add( - array, - (gpointer) g_intern_string(nm_sprintf_buf(sbuf, "%d", enum_value->value))); - } - } - } else if (G_IS_FLAGS_CLASS(klass)) { - GFlagsClass *flags_class = G_FLAGS_CLASS(klass); - GFlagsValue *flags_value; - - for (i = 0; i < flags_class->n_values; i++) { - flags_value = &flags_class->values[i]; - if (flags_value->value >= (guint) from && flags_value->value <= (guint) to) { - if (_enum_is_valid_flags_nick(flags_value->value_nick)) - g_ptr_array_add(array, (gpointer) flags_value->value_nick); - else - g_ptr_array_add( - array, - (gpointer) g_intern_string( - nm_sprintf_buf(sbuf, "0x%x", (unsigned) flags_value->value))); - } - } - } else { - g_type_class_unref(klass); - g_ptr_array_free(array, TRUE); - g_return_val_if_reached(NULL); - } - - g_type_class_unref(klass); - g_ptr_array_add(array, NULL); - - return (const char **) g_ptr_array_free(array, FALSE); -} |