structure: Add GST_SERIALIZE_FLAG_STRICT

It makes serialization succeed only if all values have a type that can
be deserialized.

Sponsored-by: Netflix Inc.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
This commit is contained in:
Xavier Claessens 2023-09-20 15:34:40 -04:00 committed by GStreamer Marge Bot
parent 899d08722a
commit 9501d64ccd
3 changed files with 46 additions and 2 deletions

View file

@ -2033,6 +2033,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
guint i, len;
gboolean nested_structs_brackets =
!(flags & GST_SERIALIZE_FLAG_BACKWARD_COMPAT);
gboolean strict = (flags & GST_SERIALIZE_FLAG_STRICT) != 0;
g_return_val_if_fail (s != NULL, FALSE);
@ -2069,7 +2070,8 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
g_string_append_c (s, '[');
g_string_append (s, g_quark_to_string (substruct->name));
priv_gst_structure_append_to_gstring (substruct, s, flags);
if (!priv_gst_structure_append_to_gstring (substruct, s, flags))
return FALSE;
g_string_append_c (s, ']');
} else if (nested_structs_brackets
&& G_VALUE_TYPE (&field->value) == GST_TYPE_CAPS) {
@ -2081,9 +2083,13 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
} else if (t) {
g_string_append (s, t);
g_free (t);
if (strict && G_VALUE_HOLDS_OBJECT (&field->value))
return FALSE;
} else if (G_TYPE_CHECK_VALUE_TYPE (&field->value, G_TYPE_POINTER)) {
gpointer ptr = g_value_get_pointer (&field->value);
if (strict)
return FALSE;
if (!ptr)
g_string_append (s, "NULL");
else
@ -2093,6 +2099,8 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
g_quark_to_string (field->name),
_priv_gst_value_gtype_to_abbr (type));
if (strict)
return FALSE;
/* TODO(ensonic): don't print NULL if field->value is not empty */
g_string_append (s, "NULL");
}
@ -2168,7 +2176,10 @@ structure_serialize (const GstStructure * structure, GstSerializeFlags flags)
* avoid unnecessary reallocs within GString */
s = g_string_sized_new (STRUCTURE_ESTIMATED_STRING_LEN (structure));
g_string_append (s, g_quark_to_string (structure->name));
priv_gst_structure_append_to_gstring (structure, s, flags);
if (!priv_gst_structure_append_to_gstring (structure, s, flags)) {
g_string_free (s, TRUE);
return NULL;
}
return g_string_free (s, FALSE);
}

View file

@ -32,11 +32,23 @@ GST_API GType _gst_structure_type;
typedef struct _GstStructure GstStructure;
/**
* GST_SERIALIZE_FLAG_STRICT:
*
* Serialization fails if a value cannot be serialized instead of using
* placeholder "NULL" value (e.g. pointers, objects).
*
* Since: 1.24
*/
/**
* GstSerializeFlags:
* @GST_SERIALIZE_FLAG_NONE: No special flags specified.
* @GST_SERIALIZE_FLAG_BACKWARD_COMPAT: Serialize using the old format for
* nested structures.
* @GST_SERIALIZE_FLAG_STRICT: Serialization fails if a value cannot be
* serialized instead of using placeholder "NULL" value (e.g. pointers,
* objects). (Since 1.24)
*
* Since: 1.20
*/
@ -44,6 +56,7 @@ typedef enum
{
GST_SERIALIZE_FLAG_NONE = 0,
GST_SERIALIZE_FLAG_BACKWARD_COMPAT = (1 << 0),
GST_SERIALIZE_FLAG_STRICT = (1 << 1),
} GstSerializeFlags;
#define GST_TYPE_STRUCTURE (_gst_structure_type)

View file

@ -1034,6 +1034,25 @@ GST_START_TEST (test_flags)
GST_END_TEST;
GST_START_TEST (test_strict)
{
GstStructure *s;
GstElement *bin = gst_bin_new ("mybin");
s = gst_structure_new ("test-struct", "obj", GST_TYPE_BIN, bin, NULL);
fail_unless (s);
fail_if (gst_structure_serialize (s, GST_SERIALIZE_FLAG_STRICT));
gst_structure_free (s);
gst_object_unref (bin);
s = gst_structure_new ("test-struct", "ptr", G_TYPE_POINTER, NULL, NULL);
fail_unless (s);
fail_if (gst_structure_serialize (s, GST_SERIALIZE_FLAG_STRICT));
gst_structure_free (s);
}
GST_END_TEST;
static Suite *
gst_structure_suite (void)
{
@ -1067,6 +1086,7 @@ gst_structure_suite (void)
tcase_add_test (tc_chain, test_filter_and_map_in_place);
tcase_add_test (tc_chain, test_flagset);
tcase_add_test (tc_chain, test_flags);
tcase_add_test (tc_chain, test_strict);
return s;
}