Merge branch 'wip/gvariant-builder-init-unset' into 'main'

gvariant: Introduce G_VARIANT_BUILDER_INIT_UNSET

See merge request GNOME/glib!4377
This commit is contained in:
Philip Withnall 2024-11-04 16:11:52 +00:00
commit a33f26ff58
2 changed files with 69 additions and 13 deletions

View File

@ -344,23 +344,25 @@ GQuark g_variant_parse_error_quark (void);
* G_VARIANT_BUILDER_INIT:
* @variant_type: a const GVariantType*
*
* A stack-allocated #GVariantBuilder must be initialized if it is
* used together with g_auto() to avoid warnings or crashes if
* function returns before g_variant_builder_init() is called on the
* builder.
* A stack-allocated [struct@GLib.VariantBuilder] must be initialized
* if it is used together with
* [`g_auto()`](auto-cleanup.html#variable-declaration). This macro can
* be used as initializer when declaring the builder, but it cannot be
* assigned to a variable.
*
* This macro can be used as initializer instead of an
* explicit zeroing a variable when declaring it and a following
* g_variant_builder_init(), but it cannot be assigned to a variable.
* The effects of initializing the builder with
* `G_VARIANT_BUILDER_INIT` is the same as initializing it with
* [func@GLib.VARIANT_BUILDER_INIT_UNSET], followed by a call to
* [method@GLib.VariantBuilder.init].
*
* The passed @variant_type should be a static GVariantType to avoid
* lifetime issues, as copying the @variant_type does not happen in
* the G_VARIANT_BUILDER_INIT() call, but rather in functions that
* make sure that #GVariantBuilder is valid.
* The passed @variant_type should be a static [type@GLib.VariantType]
* to avoid lifetime issues, as copying the @variant_type does not
* happen in the `G_VARIANT_BUILDER_INIT` call, but rather in functions
* that make sure that [struct@GLib.VariantBuilder] is valid.
*
* |[<!-- language="C" -->
* ```c
* g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_BYTESTRING);
* ]|
* ```
*
* Since: 2.50
*/
@ -373,6 +375,38 @@ GQuark g_variant_parse_error_quark (void);
} \
}
/**
* G_VARIANT_BUILDER_INIT_UNSET:
*
* A stack-allocated [struct@GLib.VariantBuilder] must be initialized
* if it is used together with
* [`g_auto()`](auto-cleanup.html#variable-declaration). This macro can
* be used as initializer when declaring the builder, but it cannot be
* assigned to a variable.
*
* The builder can be initialized to a specific [type@GLib.VariantType]
* later with [method@GLib.VariantBuilder.init].
*
* Use [func@GLib.VARIANT_BUILDER_INIT] to directly initialize the
* builder with a specific [type@GLib.VariantType].
*
* ```c
* g_auto(GVariantBuilder) builder = G_VARIANT_BUILDER_INIT_UNSET ();
*
* if (condition)
* return NULL;
*
* g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{su}"));
* return g_variant_ref_sink (g_variant_builder_end (&builder));
* ```
*
* Since: 2.84
*/
#define G_VARIANT_BUILDER_INIT_UNSET() \
{ \
0, \
} GLIB_AVAILABLE_MACRO_IN_2_84
GLIB_AVAILABLE_IN_ALL
GVariantBuilder * g_variant_builder_new (const GVariantType *type);
GLIB_AVAILABLE_IN_ALL

View File

@ -5106,6 +5106,27 @@ test_stack_builder_init_static (void)
g_variant_unref (variant);
}
static void
test_stack_builder_init_unset (void)
{
GVariantBuilder builder1 = G_VARIANT_BUILDER_INIT_UNSET ();
GVariantBuilder builder2 = G_VARIANT_BUILDER_INIT_UNSET ();
GVariantBuilder builder3 = G_VARIANT_BUILDER_INIT_UNSET ();
GVariant *variant;
g_variant_builder_clear (&builder1);
g_variant_builder_init_static (&builder2, G_VARIANT_TYPE_BYTESTRING);
g_variant_builder_add_value (&builder2, g_variant_new_byte ('\0'));
variant = g_variant_ref_sink (g_variant_builder_end (&builder2));
g_assert_nonnull (variant);
g_variant_unref (variant);
g_variant_builder_clear (&builder2);
g_variant_builder_init (&builder3, G_VARIANT_TYPE_BYTESTRING);
g_variant_builder_clear (&builder3);
}
static GVariant *
get_asv (void)
{
@ -5973,6 +5994,7 @@ main (int argc, char **argv)
g_test_add_func ("/gvariant/stack-builder-init", test_stack_builder_init);
g_test_add_func ("/gvariant/stack-builder-init-static", test_stack_builder_init_static);
g_test_add_func ("/gvariant/stack-builder-init-unset", test_stack_builder_init_unset);
g_test_add_func ("/gvariant/stack-dict-init", test_stack_dict_init);
g_test_add_func ("/gvariant/normal-checking/tuples",