summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarrett Regier <garrettregier@gmail.com>2015-05-14 03:09:30 -0700
committerPhilip Withnall <withnall@endlessm.com>2017-03-30 09:52:28 +0100
commit6c95cd22e99380a62090fd3d6c010c40563137e5 (patch)
treeece5d1152b1ff4310a3d9243a371a18e3488565c
parent625936343d9009ad54d1de6d9084a017c0bf689b (diff)
downloadglib-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.txt2
-rw-r--r--gobject/genums.c127
-rw-r--r--gobject/genums.h6
-rw-r--r--gobject/gvaluetransform.c18
-rw-r--r--gobject/tests/enums.c44
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);
}