Merge branch 'backport-3213-variant-text-performance-glib-2-74' into 'glib-2-74'

Backport !3213 “gvariant: Optimise g_variant_print() for nested maybes” to glib-2-74

See merge request GNOME/glib!3214
This commit is contained in:
Philip Withnall 2023-01-18 12:46:35 +00:00
commit 788e1cf888
3 changed files with 45 additions and 26 deletions

View File

@ -1138,11 +1138,13 @@ GVariant *
g_variant_get_child_value (GVariant *value, g_variant_get_child_value (GVariant *value,
gsize index_) gsize index_)
{ {
g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
g_return_val_if_fail (value->depth < G_MAXSIZE, NULL); g_return_val_if_fail (value->depth < G_MAXSIZE, NULL);
if (~g_atomic_int_get (&value->state) & STATE_SERIALISED) if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
{ {
/* g_variant_serialised_get_child() does its own checks on index_ */
g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
g_variant_lock (value); g_variant_lock (value);
if (~value->state & STATE_SERIALISED) if (~value->state & STATE_SERIALISED)
@ -1233,11 +1235,13 @@ GVariant *
g_variant_maybe_get_child_value (GVariant *value, g_variant_maybe_get_child_value (GVariant *value,
gsize index_) gsize index_)
{ {
g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
g_return_val_if_fail (value->depth < G_MAXSIZE, NULL); g_return_val_if_fail (value->depth < G_MAXSIZE, NULL);
if (~g_atomic_int_get (&value->state) & STATE_SERIALISED) if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
{ {
/* g_variant_serialised_get_child() does its own checks on index_ */
g_return_val_if_fail (index_ < g_variant_n_children (value), NULL);
g_variant_lock (value); g_variant_lock (value);
if (~value->state & STATE_SERIALISED) if (~value->state & STATE_SERIALISED)

View File

@ -2213,20 +2213,22 @@ g_variant_print_string (GVariant *value,
GString *string, GString *string,
gboolean type_annotate) gboolean type_annotate)
{ {
const gchar *value_type_string = g_variant_get_type_string (value);
if G_UNLIKELY (string == NULL) if G_UNLIKELY (string == NULL)
string = g_string_new (NULL); string = g_string_new (NULL);
switch (g_variant_classify (value)) switch (value_type_string[0])
{ {
case G_VARIANT_CLASS_MAYBE: case G_VARIANT_CLASS_MAYBE:
if (type_annotate) if (type_annotate)
g_string_append_printf (string, "@%s ", g_string_append_printf (string, "@%s ", value_type_string);
g_variant_get_type_string (value));
if (g_variant_n_children (value)) if (g_variant_n_children (value))
{ {
gchar *printed_child; const GVariantType *base_type;
GVariant *element; guint i, depth;
GVariant *element = NULL;
/* Nested maybes: /* Nested maybes:
* *
@ -2240,19 +2242,36 @@ g_variant_print_string (GVariant *value,
* "just" is actually exactly the case where we have a nested * "just" is actually exactly the case where we have a nested
* Nothing. * Nothing.
* *
* Instead of searching for that nested Nothing, we just print * Search for the nested Nothing, to save a lot of recursion if there
* the contained value into a separate string and see if we * are multiple levels of maybes.
* end up with "nothing" at the end of it. If so, we need to
* add "just" at our level.
*/ */
element = g_variant_get_child_value (value, 0); for (depth = 0, base_type = g_variant_get_type (value);
printed_child = g_variant_print (element, FALSE); g_variant_type_is_maybe (base_type);
g_variant_unref (element); depth++, base_type = g_variant_type_element (base_type));
if (g_str_has_suffix (printed_child, "nothing")) element = g_variant_ref (value);
g_string_append (string, "just "); for (i = 0; i < depth && element != NULL; i++)
g_string_append (string, printed_child); {
g_free (printed_child); GVariant *new_element = g_variant_n_children (element) ? g_variant_get_child_value (element, 0) : NULL;
g_variant_unref (element);
element = g_steal_pointer (&new_element);
}
if (element == NULL)
{
/* One of the maybes was Nothing, so print out the right number of
* justs. */
for (; i > 1; i--)
g_string_append (string, "just ");
g_string_append (string, "nothing");
}
else
{
/* There are no Nothings, so print out the child with no prefixes. */
g_variant_print_string (element, string, FALSE);
}
g_clear_pointer (&element, g_variant_unref);
} }
else else
g_string_append (string, "nothing"); g_string_append (string, "nothing");
@ -2265,7 +2284,7 @@ g_variant_print_string (GVariant *value,
* if the first two characters are 'ay' then it's a bytestring. * if the first two characters are 'ay' then it's a bytestring.
* under certain conditions we print those as strings. * under certain conditions we print those as strings.
*/ */
if (g_variant_get_type_string (value)[1] == 'y') if (value_type_string[1] == 'y')
{ {
const gchar *str; const gchar *str;
gsize size; gsize size;
@ -2307,7 +2326,7 @@ g_variant_print_string (GVariant *value,
* dictionary entries (ie: a dictionary) so we print that * dictionary entries (ie: a dictionary) so we print that
* differently. * differently.
*/ */
if (g_variant_get_type_string (value)[1] == '{') if (value_type_string[1] == '{')
/* dictionary */ /* dictionary */
{ {
const gchar *comma = ""; const gchar *comma = "";
@ -2316,8 +2335,7 @@ g_variant_print_string (GVariant *value,
if ((n = g_variant_n_children (value)) == 0) if ((n = g_variant_n_children (value)) == 0)
{ {
if (type_annotate) if (type_annotate)
g_string_append_printf (string, "@%s ", g_string_append_printf (string, "@%s ", value_type_string);
g_variant_get_type_string (value));
g_string_append (string, "{}"); g_string_append (string, "{}");
break; break;
} }
@ -2353,8 +2371,7 @@ g_variant_print_string (GVariant *value,
if ((n = g_variant_n_children (value)) == 0) if ((n = g_variant_n_children (value)) == 0)
{ {
if (type_annotate) if (type_annotate)
g_string_append_printf (string, "@%s ", g_string_append_printf (string, "@%s ", value_type_string);
g_variant_get_type_string (value));
g_string_append (string, "[]"); g_string_append (string, "[]");
break; break;
} }

View File

@ -247,8 +247,6 @@ g_variant_type_info_query (GVariantTypeInfo *info,
guint *alignment, guint *alignment,
gsize *fixed_size) gsize *fixed_size)
{ {
g_variant_type_info_check (info, 0);
if (alignment) if (alignment)
*alignment = info->alignment; *alignment = info->alignment;