mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
structure: add gst_structure_*_get*() vararg functions
Add a bunch of vararg getter convenience functions to complement the vararg setter functions, and a basic unit test. Fixes #534208. API: gst_structure_get() API: gst_structure_id_get() API: gst_structure_get_valist() API: gst_structure_id_get_valist()
This commit is contained in:
parent
26b201273a
commit
cdd47a37e9
5 changed files with 373 additions and 0 deletions
|
@ -2012,8 +2012,12 @@ gst_structure_get_name
|
||||||
gst_structure_has_name
|
gst_structure_has_name
|
||||||
gst_structure_set_name
|
gst_structure_set_name
|
||||||
gst_structure_get_name_id
|
gst_structure_get_name_id
|
||||||
|
gst_structure_id_get
|
||||||
|
gst_structure_id_get_valist
|
||||||
gst_structure_id_get_value
|
gst_structure_id_get_value
|
||||||
gst_structure_id_set_value
|
gst_structure_id_set_value
|
||||||
|
gst_structure_get
|
||||||
|
gst_structure_get_valist
|
||||||
gst_structure_get_value
|
gst_structure_get_value
|
||||||
gst_structure_set_value
|
gst_structure_set_value
|
||||||
gst_structure_set
|
gst_structure_set
|
||||||
|
|
|
@ -2342,3 +2342,250 @@ gst_structure_fixate_field_nearest_fraction (GstStructure * structure,
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* our very own version of G_VALUE_LCOPY that allows NULL return locations
|
||||||
|
* (useful for message parsing functions where the return location is user
|
||||||
|
* supplied and the user may pass NULL if the value isn't of interest) */
|
||||||
|
#define GST_VALUE_LCOPY(value, var_args, flags, __error, fieldname) \
|
||||||
|
G_STMT_START { \
|
||||||
|
const GValue *_value = (value); \
|
||||||
|
guint _flags = (flags); \
|
||||||
|
GType _value_type = G_VALUE_TYPE (_value); \
|
||||||
|
GTypeValueTable *_vtable = g_type_value_table_peek (_value_type); \
|
||||||
|
gchar *_lcopy_format = _vtable->lcopy_format; \
|
||||||
|
GTypeCValue _cvalues[G_VALUE_COLLECT_FORMAT_MAX_LENGTH] = { { 0, }, }; \
|
||||||
|
guint _n_values = 0; \
|
||||||
|
\
|
||||||
|
while (*_lcopy_format != '\0') { \
|
||||||
|
g_assert (*_lcopy_format == G_VALUE_COLLECT_POINTER); \
|
||||||
|
_cvalues[_n_values++].v_pointer = va_arg ((var_args), gpointer); \
|
||||||
|
_lcopy_format++; \
|
||||||
|
} \
|
||||||
|
if (_n_values == 2 && !!_cvalues[0].v_pointer != !!_cvalues[1].v_pointer) { \
|
||||||
|
*(__error) = g_strdup_printf ("either all or none of the return " \
|
||||||
|
"locations for field '%s' need to be NULL", fieldname); \
|
||||||
|
} else if (_cvalues[0].v_pointer != NULL) { \
|
||||||
|
*(__error) = _vtable->lcopy_value (_value, _n_values, _cvalues, _flags); \
|
||||||
|
} \
|
||||||
|
} G_STMT_END
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_structure_get_valist:
|
||||||
|
* @structure: a #GstStructure
|
||||||
|
* @first_fieldname: the name of the first field to read
|
||||||
|
* @valist: variable arguments
|
||||||
|
*
|
||||||
|
* Parses the variable arguments and reads fields from @structure accordingly.
|
||||||
|
* valist-variant of gst_structure_get(). Look at the documentation of
|
||||||
|
* gst_structure_get() for more details.
|
||||||
|
*
|
||||||
|
* Returns: TRUE, or FALSE if there was a problem reading any of the fields
|
||||||
|
*
|
||||||
|
* Since: 0.10.24
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_structure_get_valist (GstStructure * structure,
|
||||||
|
const char *first_fieldname, va_list args)
|
||||||
|
{
|
||||||
|
const char *field_name;
|
||||||
|
GType expected_type = G_TYPE_INVALID;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
|
||||||
|
g_return_val_if_fail (first_fieldname != NULL, FALSE);
|
||||||
|
|
||||||
|
field_name = first_fieldname;
|
||||||
|
while (field_name) {
|
||||||
|
const GValue *val = NULL;
|
||||||
|
gchar *err = NULL;
|
||||||
|
|
||||||
|
expected_type = va_arg (args, GType);
|
||||||
|
|
||||||
|
val = gst_structure_get_value (structure, field_name);
|
||||||
|
|
||||||
|
if (val == NULL)
|
||||||
|
goto no_such_field;
|
||||||
|
|
||||||
|
if (G_VALUE_TYPE (val) != expected_type)
|
||||||
|
goto wrong_type;
|
||||||
|
|
||||||
|
GST_VALUE_LCOPY (val, args, 0, &err, field_name);
|
||||||
|
if (err) {
|
||||||
|
g_warning ("%s: %s", G_STRFUNC, err);
|
||||||
|
g_free (err);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_name = va_arg (args, const gchar *);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_such_field:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
|
||||||
|
field_name, structure);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wrong_type:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
|
||||||
|
"field was of type '%s': %" GST_PTR_FORMAT, field_name,
|
||||||
|
GST_STR_NULL (g_type_name (expected_type)),
|
||||||
|
G_VALUE_TYPE_NAME (gst_structure_get_value (structure, field_name)),
|
||||||
|
structure);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_structure_id_get_valist:
|
||||||
|
* @structure: a #GstStructure
|
||||||
|
* @first_field_id: the quark of the first field to read
|
||||||
|
* @valist: variable arguments
|
||||||
|
*
|
||||||
|
* Parses the variable arguments and reads fields from @structure accordingly.
|
||||||
|
* valist-variant of gst_structure_id_get(). Look at the documentation of
|
||||||
|
* gst_structure_id_get() for more details.
|
||||||
|
*
|
||||||
|
* Returns: TRUE, or FALSE if there was a problem reading any of the fields
|
||||||
|
*
|
||||||
|
* Since: 0.10.24
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_structure_id_get_valist (GstStructure * structure, GQuark first_field_id,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
GQuark field_id;
|
||||||
|
GType expected_type = G_TYPE_INVALID;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
|
||||||
|
g_return_val_if_fail (first_field_id != 0, FALSE);
|
||||||
|
|
||||||
|
field_id = first_field_id;
|
||||||
|
while (field_id) {
|
||||||
|
const GValue *val = NULL;
|
||||||
|
gchar *err = NULL;
|
||||||
|
|
||||||
|
expected_type = va_arg (args, GType);
|
||||||
|
|
||||||
|
val = gst_structure_id_get_value (structure, field_id);
|
||||||
|
|
||||||
|
if (val == NULL)
|
||||||
|
goto no_such_field;
|
||||||
|
|
||||||
|
if (G_VALUE_TYPE (val) != expected_type)
|
||||||
|
goto wrong_type;
|
||||||
|
|
||||||
|
GST_VALUE_LCOPY (val, args, 0, &err, g_quark_to_string (field_id));
|
||||||
|
if (err) {
|
||||||
|
g_warning ("%s: %s", G_STRFUNC, err);
|
||||||
|
g_free (err);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
field_id = va_arg (args, GQuark);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_such_field:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Expected field '%s' in structure: %" GST_PTR_FORMAT,
|
||||||
|
GST_STR_NULL (g_quark_to_string (field_id)), structure);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
wrong_type:
|
||||||
|
{
|
||||||
|
GST_WARNING ("Expected field '%s' in structure to be of type '%s', but "
|
||||||
|
"field was of type '%s': %" GST_PTR_FORMAT,
|
||||||
|
g_quark_to_string (field_id),
|
||||||
|
GST_STR_NULL (g_type_name (expected_type)),
|
||||||
|
G_VALUE_TYPE_NAME (gst_structure_id_get_value (structure, field_id)),
|
||||||
|
structure);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_structure_get:
|
||||||
|
* @structure: a #GstStructure
|
||||||
|
* @first_fieldname: the name of the first field to read
|
||||||
|
* @...: variable arguments
|
||||||
|
*
|
||||||
|
* Parses the variable arguments and reads fields from @structure accordingly.
|
||||||
|
* Variable arguments should be in the form field name, field type
|
||||||
|
* (as a GType), pointer(s) to a variable(s) to hold the return value(s).
|
||||||
|
* The last variable argument should be NULL.
|
||||||
|
*
|
||||||
|
* For refcounted (mini)objects you will acquire your own reference which
|
||||||
|
* you must release with a suitable _unref() when no longer needed. For
|
||||||
|
* strings and boxed types you will acquire a copy which you will need to
|
||||||
|
* release with either g_free() or the suiteable function for the boxed type.
|
||||||
|
*
|
||||||
|
* Returns: FALSE if there was a problem reading any of the fields (e.g.
|
||||||
|
* because the field requested did not exist, or was of a type other
|
||||||
|
* than the type specified), otherwise TRUE.
|
||||||
|
*
|
||||||
|
* Since: 0.10.24
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_structure_get (GstStructure * structure, const char *first_fieldname, ...)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
|
||||||
|
g_return_val_if_fail (first_fieldname != NULL, FALSE);
|
||||||
|
|
||||||
|
va_start (args, first_fieldname);
|
||||||
|
ret = gst_structure_get_valist (structure, first_fieldname, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_structure_id_get:
|
||||||
|
* @structure: a #GstStructure
|
||||||
|
* @first_field_id: the quark of the first field to read
|
||||||
|
* @...: variable arguments
|
||||||
|
*
|
||||||
|
* Parses the variable arguments and reads fields from @structure accordingly.
|
||||||
|
* Variable arguments should be in the form field id quark, field type
|
||||||
|
* (as a GType), pointer(s) to a variable(s) to hold the return value(s).
|
||||||
|
* The last variable argument should be NULL (technically it should be a
|
||||||
|
* 0 quark, but we require NULL so compilers that support it can check for
|
||||||
|
* the NULL terminator and warn if it's not there).
|
||||||
|
*
|
||||||
|
* This function is just like gst_structure_get() only that it is slightly
|
||||||
|
* more efficient since it saves the string-to-quark lookup in the global
|
||||||
|
* quark hashtable.
|
||||||
|
*
|
||||||
|
* For refcounted (mini)objects you will acquire your own reference which
|
||||||
|
* you must release with a suitable _unref() when no longer needed. For
|
||||||
|
* strings and boxed types you will acquire a copy which you will need to
|
||||||
|
* release with either g_free() or the suiteable function for the boxed type.
|
||||||
|
*
|
||||||
|
* Returns: FALSE if there was a problem reading any of the fields (e.g.
|
||||||
|
* because the field requested did not exist, or was of a type other
|
||||||
|
* than the type specified), otherwise TRUE.
|
||||||
|
*
|
||||||
|
* Since: 0.10.24
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_structure_id_get (GstStructure * structure, GQuark first_field_id, ...)
|
||||||
|
{
|
||||||
|
gboolean ret;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GST_IS_STRUCTURE (structure), FALSE);
|
||||||
|
g_return_val_if_fail (first_field_id != 0, FALSE);
|
||||||
|
|
||||||
|
va_start (args, first_field_id);
|
||||||
|
ret = gst_structure_id_get_valist (structure, first_field_id, args);
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
|
@ -132,6 +132,21 @@ void gst_structure_id_set_valist (GstStructure
|
||||||
GQuark fieldname,
|
GQuark fieldname,
|
||||||
va_list varargs);
|
va_list varargs);
|
||||||
|
|
||||||
|
gboolean gst_structure_get_valist (GstStructure *structure,
|
||||||
|
const char *first_fieldname,
|
||||||
|
va_list args);
|
||||||
|
|
||||||
|
gboolean gst_structure_get (GstStructure *structure,
|
||||||
|
const char *first_fieldname,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
gboolean gst_structure_id_get_valist (GstStructure *structure,
|
||||||
|
GQuark first_field_id,
|
||||||
|
va_list args);
|
||||||
|
|
||||||
|
gboolean gst_structure_id_get (GstStructure *structure,
|
||||||
|
GQuark first_field_id,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
G_CONST_RETURN GValue * gst_structure_id_get_value (const GstStructure *structure,
|
G_CONST_RETURN GValue * gst_structure_id_get_value (const GstStructure *structure,
|
||||||
GQuark field);
|
GQuark field);
|
||||||
|
|
|
@ -433,6 +433,108 @@ GST_START_TEST (test_empty_string_fields)
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (test_vararg_getters)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
GstBuffer *buf, *buf2;
|
||||||
|
gboolean ret;
|
||||||
|
GstCaps *caps, *caps2;
|
||||||
|
gdouble d;
|
||||||
|
gint64 i64;
|
||||||
|
gchar *c;
|
||||||
|
gint i, num, denom;
|
||||||
|
|
||||||
|
buf = gst_buffer_new_and_alloc (3);
|
||||||
|
GST_BUFFER_DATA (buf)[0] = 0xf0;
|
||||||
|
GST_BUFFER_DATA (buf)[1] = 0x66;
|
||||||
|
GST_BUFFER_DATA (buf)[2] = 0x0d;
|
||||||
|
|
||||||
|
caps = gst_caps_new_simple ("video/x-foo", NULL);
|
||||||
|
|
||||||
|
s = gst_structure_new ("test", "int", G_TYPE_INT, 12345678, "string",
|
||||||
|
G_TYPE_STRING, "Hello World!", "buf", GST_TYPE_BUFFER, buf, "caps",
|
||||||
|
GST_TYPE_CAPS, caps, "int64", G_TYPE_INT64, G_GINT64_CONSTANT (-99),
|
||||||
|
"double", G_TYPE_DOUBLE, G_MAXDOUBLE, "frag", GST_TYPE_FRACTION, 39, 14,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/* first the plain one */
|
||||||
|
ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, &d, "string",
|
||||||
|
G_TYPE_STRING, &c, "caps", GST_TYPE_CAPS, &caps2, "buf",
|
||||||
|
GST_TYPE_BUFFER, &buf2, "frag", GST_TYPE_FRACTION, &num, &denom, "int",
|
||||||
|
G_TYPE_INT, &i, "int64", G_TYPE_INT64, &i64, NULL);
|
||||||
|
|
||||||
|
fail_unless (ret);
|
||||||
|
fail_unless_equals_string (c, "Hello World!");
|
||||||
|
fail_unless_equals_int (i, 12345678);
|
||||||
|
fail_unless_equals_float (d, G_MAXDOUBLE);
|
||||||
|
fail_unless_equals_int (num, 39);
|
||||||
|
fail_unless_equals_int (denom, 14);
|
||||||
|
fail_unless (i64 == -99);
|
||||||
|
fail_unless (caps == caps2);
|
||||||
|
fail_unless (buf == buf2);
|
||||||
|
|
||||||
|
/* expected failures */
|
||||||
|
ASSERT_CRITICAL (gst_structure_get (s, NULL, G_TYPE_INT, &i, NULL));
|
||||||
|
fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "double",
|
||||||
|
G_TYPE_FLOAT, &d, NULL));
|
||||||
|
fail_if (gst_structure_get (s, "int", G_TYPE_INT, &i, "dooble",
|
||||||
|
G_TYPE_DOUBLE, &d, NULL));
|
||||||
|
|
||||||
|
g_free (c);
|
||||||
|
c = NULL;
|
||||||
|
gst_caps_unref (caps2);
|
||||||
|
caps2 = NULL;
|
||||||
|
gst_buffer_unref (buf2);
|
||||||
|
buf2 = NULL;
|
||||||
|
|
||||||
|
/* and now the _id variant */
|
||||||
|
ret = gst_structure_id_get (s, g_quark_from_static_string ("double"),
|
||||||
|
G_TYPE_DOUBLE, &d, g_quark_from_static_string ("string"), G_TYPE_STRING,
|
||||||
|
&c, g_quark_from_static_string ("caps"), GST_TYPE_CAPS, &caps2,
|
||||||
|
g_quark_from_static_string ("buf"), GST_TYPE_BUFFER, &buf2,
|
||||||
|
g_quark_from_static_string ("int"), G_TYPE_INT, &i,
|
||||||
|
g_quark_from_static_string ("int64"), G_TYPE_INT64, &i64, NULL);
|
||||||
|
|
||||||
|
fail_unless (ret);
|
||||||
|
fail_unless_equals_string (c, "Hello World!");
|
||||||
|
fail_unless_equals_int (i, 12345678);
|
||||||
|
fail_unless_equals_float (d, G_MAXDOUBLE);
|
||||||
|
fail_unless (i64 == -99);
|
||||||
|
fail_unless (caps == caps2);
|
||||||
|
fail_unless (buf == buf2);
|
||||||
|
|
||||||
|
/* expected failures */
|
||||||
|
ASSERT_CRITICAL (gst_structure_get (s, 0, G_TYPE_INT, &i, NULL));
|
||||||
|
fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
|
||||||
|
G_TYPE_INT, &i, g_quark_from_static_string ("double"), G_TYPE_FLOAT,
|
||||||
|
&d, NULL));
|
||||||
|
fail_if (gst_structure_id_get (s, g_quark_from_static_string ("int"),
|
||||||
|
G_TYPE_INT, &i, g_quark_from_static_string ("dooble"), G_TYPE_DOUBLE,
|
||||||
|
&d, NULL));
|
||||||
|
|
||||||
|
g_free (c);
|
||||||
|
gst_caps_unref (caps2);
|
||||||
|
gst_buffer_unref (buf2);
|
||||||
|
|
||||||
|
/* finally make sure NULL as return location is handled gracefully */
|
||||||
|
ret = gst_structure_get (s, "double", G_TYPE_DOUBLE, NULL, "string",
|
||||||
|
G_TYPE_STRING, NULL, "caps", GST_TYPE_CAPS, NULL, "buf",
|
||||||
|
GST_TYPE_BUFFER, NULL, "int", G_TYPE_INT, &i, "frag", GST_TYPE_FRACTION,
|
||||||
|
NULL, NULL, "int64", G_TYPE_INT64, &i64, NULL);
|
||||||
|
|
||||||
|
ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, NULL,
|
||||||
|
&denom, NULL));
|
||||||
|
ASSERT_WARNING (gst_structure_get (s, "frag", GST_TYPE_FRACTION, &num,
|
||||||
|
NULL, NULL));
|
||||||
|
|
||||||
|
/* clean up */
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
gst_structure_free (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
static Suite *
|
static Suite *
|
||||||
gst_structure_suite (void)
|
gst_structure_suite (void)
|
||||||
{
|
{
|
||||||
|
@ -451,6 +553,7 @@ gst_structure_suite (void)
|
||||||
tcase_add_test (tc_chain, test_structure_nested);
|
tcase_add_test (tc_chain, test_structure_nested);
|
||||||
tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
|
tcase_add_test (tc_chain, test_structure_nested_from_and_to_string);
|
||||||
tcase_add_test (tc_chain, test_empty_string_fields);
|
tcase_add_test (tc_chain, test_empty_string_fields);
|
||||||
|
tcase_add_test (tc_chain, test_vararg_getters);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -866,6 +866,7 @@ EXPORTS
|
||||||
gst_structure_foreach
|
gst_structure_foreach
|
||||||
gst_structure_free
|
gst_structure_free
|
||||||
gst_structure_from_string
|
gst_structure_from_string
|
||||||
|
gst_structure_get
|
||||||
gst_structure_get_boolean
|
gst_structure_get_boolean
|
||||||
gst_structure_get_clock_time
|
gst_structure_get_clock_time
|
||||||
gst_structure_get_date
|
gst_structure_get_date
|
||||||
|
@ -880,11 +881,14 @@ EXPORTS
|
||||||
gst_structure_get_string
|
gst_structure_get_string
|
||||||
gst_structure_get_type
|
gst_structure_get_type
|
||||||
gst_structure_get_uint
|
gst_structure_get_uint
|
||||||
|
gst_structure_get_valist
|
||||||
gst_structure_get_value
|
gst_structure_get_value
|
||||||
gst_structure_has_field
|
gst_structure_has_field
|
||||||
gst_structure_has_field_typed
|
gst_structure_has_field_typed
|
||||||
gst_structure_has_name
|
gst_structure_has_name
|
||||||
gst_structure_id_empty_new
|
gst_structure_id_empty_new
|
||||||
|
gst_structure_id_get
|
||||||
|
gst_structure_id_get_valist
|
||||||
gst_structure_id_get_value
|
gst_structure_id_get_value
|
||||||
gst_structure_id_new
|
gst_structure_id_new
|
||||||
gst_structure_id_set
|
gst_structure_id_set
|
||||||
|
|
Loading…
Reference in a new issue