diff options
author | Garrett Regier <garrettregier@gmail.com> | 2015-05-14 03:09:30 -0700 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2017-03-30 09:52:28 +0100 |
commit | 6c95cd22e99380a62090fd3d6c010c40563137e5 (patch) | |
tree | ece5d1152b1ff4310a3d9243a371a18e3488565c | |
parent | 625936343d9009ad54d1de6d9084a017c0bf689b (diff) | |
download | glib-6c95cd22e99380a62090fd3d6c010c40563137e5.tar.gz |
gobject: Add to_string() functions for Enum and Flags types
These are useful for debugging.
https://bugzilla.gnome.org/show_bug.cgi?id=447907
-rw-r--r-- | docs/reference/gobject/gobject-sections.txt | 2 | ||||
-rw-r--r-- | gobject/genums.c | 127 | ||||
-rw-r--r-- | gobject/genums.h | 6 | ||||
-rw-r--r-- | gobject/gvaluetransform.c | 18 | ||||
-rw-r--r-- | gobject/tests/enums.c | 44 |
5 files changed, 186 insertions, 11 deletions
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 0f14f93fe..be95c1c82 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -351,9 +351,11 @@ GFlagsValue g_enum_get_value g_enum_get_value_by_name g_enum_get_value_by_nick +g_enum_to_string g_flags_get_first_value g_flags_get_value_by_name g_flags_get_value_by_nick +g_flags_to_string g_enum_register_static g_flags_register_static g_enum_complete_type_info diff --git a/gobject/genums.c b/gobject/genums.c index a4f22c98a..469f79806 100644 --- a/gobject/genums.c +++ b/gobject/genums.c @@ -567,6 +567,133 @@ g_flags_get_first_value (GFlagsClass *flags_class, } /** + * g_enum_to_string: + * @g_enum_type: the type identifier of a #GEnumClass type + * @value: the value + * + * Pretty-prints @value in the form of the enum’s name. + * + * This is intended to be used for debugging purposes. The format of the output + * may change in the future. + * + * Returns: (transfer full): a newly-allocated text string + * + * Since: 2.54 + */ +gchar * +g_enum_to_string (GType g_enum_type, + gint value) +{ + gchar *result; + GEnumClass *enum_class; + GEnumValue *enum_value; + + g_return_val_if_fail (G_TYPE_IS_ENUM (g_enum_type), NULL); + + enum_class = g_type_class_ref (g_enum_type); + + /* Already warned */ + if (enum_class == NULL) + return g_strdup_printf ("%d", value); + + enum_value = g_enum_get_value (enum_class, value); + + if (enum_value == NULL) + result = g_strdup_printf ("%d", value); + else + result = g_strdup (enum_value->value_name); + + g_type_class_unref (enum_class); + return result; +} + +/* + * g_flags_get_value_string: + * @flags_class: a #GFlagsClass + * @value: the value + * + * Pretty-prints @value in the form of the flag names separated by ` | ` and + * sorted. Any extra bits will be shown at the end as a hexadecimal number. + * + * This is intended to be used for debugging purposes. The format of the output + * may change in the future. + * + * Returns: (transfer full): a newly-allocated text string + * + * Since: 2.54 + */ +static gchar * +g_flags_get_value_string (GFlagsClass *flags_class, + guint value) +{ + GString *str; + GFlagsValue *flags_value; + + g_return_val_if_fail (G_IS_FLAGS_CLASS (flags_class), NULL); + + str = g_string_new (NULL); + + while ((str->len == 0 || value != 0) && + (flags_value = g_flags_get_first_value (flags_class, value)) != NULL) + { + if (str->len > 0) + g_string_append (str, " | "); + + g_string_append (str, flags_value->value_name); + + value &= ~flags_value->value; + } + + /* Show the extra bits */ + if (value != 0 || str->len == 0) + { + if (str->len > 0) + g_string_append (str, " | "); + + g_string_append_printf (str, "0x%x", value); + } + + return g_string_free (str, FALSE); +} + +/** + * g_flags_to_string: + * @flags_type: the type identifier of a #GFlagsClass type + * @value: the value + * + * Pretty-prints @value in the form of the flag names separated by ` | ` and + * sorted. Any extra bits will be shown at the end as a hexadecimal number. + * + * This is intended to be used for debugging purposes. The format of the output + * may change in the future. + * + * Returns: (transfer full): a newly-allocated text string + * + * Since: 2.54 + */ +gchar * +g_flags_to_string (GType flags_type, + guint value) +{ + gchar *result; + GFlagsClass *flags_class; + + g_return_val_if_fail (G_TYPE_IS_FLAGS (flags_type), NULL); + + flags_class = g_type_class_ref (flags_type); + + /* Already warned */ + if (flags_class == NULL) + return NULL; + + result = g_flags_get_value_string (flags_class, value); + + g_type_class_unref (flags_class); + return result; +} + + +/** * g_value_set_enum: * @value: a valid #GValue whose type is derived from %G_TYPE_ENUM * @v_enum: enum value to be set diff --git a/gobject/genums.h b/gobject/genums.h index 15c9d81fd..109d79809 100644 --- a/gobject/genums.h +++ b/gobject/genums.h @@ -233,6 +233,12 @@ GFlagsValue* g_flags_get_value_by_name (GFlagsClass *flags_class, GLIB_AVAILABLE_IN_ALL GFlagsValue* g_flags_get_value_by_nick (GFlagsClass *flags_class, const gchar *nick); +GLIB_AVAILABLE_IN_2_54 +gchar *g_enum_to_string (GType g_enum_type, + gint value); +GLIB_AVAILABLE_IN_2_54 +gchar *g_flags_to_string (GType flags_type, + guint value); GLIB_AVAILABLE_IN_ALL void g_value_set_enum (GValue *value, gint v_enum); diff --git a/gobject/gvaluetransform.c b/gobject/gvaluetransform.c index 5579e7f41..48051f871 100644 --- a/gobject/gvaluetransform.c +++ b/gobject/gvaluetransform.c @@ -183,15 +183,10 @@ static void value_transform_enum_string (const GValue *src_value, GValue *dest_value) { - GEnumClass *class = g_type_class_ref (G_VALUE_TYPE (src_value)); - GEnumValue *enum_value = g_enum_get_value (class, src_value->data[0].v_long); - - if (enum_value) - dest_value->data[0].v_pointer = g_strdup (enum_value->value_name); - else - dest_value->data[0].v_pointer = g_strdup_printf ("%ld", src_value->data[0].v_long); - - g_type_class_unref (class); + gint v_enum = src_value->data[0].v_long; + gchar *str = g_enum_to_string (G_VALUE_TYPE (src_value), v_enum); + + dest_value->data[0].v_pointer = str; } static void value_transform_flags_string (const GValue *src_value, @@ -199,7 +194,10 @@ value_transform_flags_string (const GValue *src_value, { GFlagsClass *class = g_type_class_ref (G_VALUE_TYPE (src_value)); GFlagsValue *flags_value = g_flags_get_first_value (class, src_value->data[0].v_ulong); - + + /* Note: this does not use g_flags_to_string() + * to keep backwards compatibility. + */ if (flags_value) { GString *gstring = g_string_new (NULL); diff --git a/gobject/tests/enums.c b/gobject/tests/enums.c index 84ffed7aa..3b9641790 100644 --- a/gobject/tests/enums.c +++ b/gobject/tests/enums.c @@ -15,6 +15,7 @@ test_enum_basic (void) GEnumClass *class; GEnumValue *val; GValue value = G_VALUE_INIT; + gchar *to_string; type = g_enum_register_static ("MyEnum", my_enum_values); @@ -49,6 +50,14 @@ test_enum_basic (void) val = g_enum_get_value_by_nick (class, "purple"); g_assert (val == NULL); + to_string = g_enum_to_string (type, 2); + g_assert_cmpstr (to_string, ==, "the second value"); + g_free (to_string); + + to_string = g_enum_to_string (type, 15); + g_assert_cmpstr (to_string, ==, "15"); + g_free (to_string); + g_type_class_unref (class); } @@ -61,6 +70,12 @@ static const GFlagsValue my_flag_values[] = { 0, NULL, NULL } }; +static const GFlagsValue no_default_flag_values[] = +{ + { 1, "the first flag", "one" }, + { 0, NULL, NULL } +}; + static void test_flags_transform_to_string (const GValue *value) { @@ -74,12 +89,15 @@ test_flags_transform_to_string (const GValue *value) static void test_flags_basic (void) { - GType type; + GType type, no_default_type; GFlagsClass *class; GFlagsValue *val; GValue value = G_VALUE_INIT; + gchar *to_string; type = g_flags_register_static ("MyFlags", my_flag_values); + no_default_type = g_flags_register_static ("NoDefaultFlags", + no_default_flag_values); g_value_init (&value, type); g_assert (G_VALUE_HOLDS_FLAGS (&value)); @@ -113,6 +131,30 @@ test_flags_basic (void) test_flags_transform_to_string (&value); g_value_unset (&value); + to_string = g_flags_to_string (type, 1|8); + g_assert_cmpstr (to_string, ==, "the first flag | the third flag"); + g_free (to_string); + + to_string = g_flags_to_string (type, 0); + g_assert_cmpstr (to_string, ==, "no flags"); + g_free (to_string); + + to_string = g_flags_to_string (type, 16); + g_assert_cmpstr (to_string, ==, "0x10"); + g_free (to_string); + + to_string = g_flags_to_string (type, 1|16); + g_assert_cmpstr (to_string, ==, "the first flag | 0x10"); + g_free (to_string); + + to_string = g_flags_to_string (no_default_type, 0); + g_assert_cmpstr (to_string, ==, "0x0"); + g_free (to_string); + + to_string = g_flags_to_string (no_default_type, 16); + g_assert_cmpstr (to_string, ==, "0x10"); + g_free (to_string); + g_type_class_unref (class); } |