--- a/gstreamer_core/gst/gststructure.c Wed Mar 31 22:03:18 2010 +0300
+++ b/gstreamer_core/gst/gststructure.c Tue Aug 31 15:30:33 2010 +0300
@@ -49,7 +49,10 @@
* Fields can be removed with gst_structure_remove_field() or
* gst_structure_remove_fields().
*
- * Last reviewed on 2007-10-16 (0.10.15)
+ * Strings in structures must be ASCII or UTF-8 encoded. Other encodings are
+ * not allowed. Strings must not be empty either, but may be NULL.
+ *
+ * Last reviewed on 2009-06-08 (0.10.23)
*/
#ifdef HAVE_CONFIG_H
@@ -59,6 +62,7 @@
#include <string.h>
#include "gst_private.h"
+#include "gstquark.h"
#include <gst/gst.h>
#include <gobject/gvaluecollector.h>
@@ -81,6 +85,9 @@
(!(structure)->parent_refcount || \
g_atomic_int_get ((structure)->parent_refcount) == 1)
+#define IS_TAGLIST(structure) \
+ (structure->name == GST_QUARK (TAGLIST))
+
static void gst_structure_set_field (GstStructure * structure,
GstStructureField * field);
static GstStructureField *gst_structure_get_field (const GstStructure *
@@ -121,11 +128,12 @@
{
GstStructure *structure;
- structure = g_new0 (GstStructure, 1);
+ structure = g_slice_new (GstStructure);
structure->type = gst_structure_get_type ();
structure->name = quark;
+ structure->parent_refcount = NULL;
structure->fields =
- g_array_sized_new (FALSE, TRUE, sizeof (GstStructureField), prealloc);
+ g_array_sized_new (FALSE, FALSE, sizeof (GstStructureField), prealloc);
return structure;
}
@@ -150,6 +158,7 @@
return gst_structure_id_empty_new_with_size (quark, 0);
}
+#ifndef G_DISABLE_CHECKS
static gboolean
gst_structure_validate_name (const gchar * name)
{
@@ -158,7 +167,7 @@
g_return_val_if_fail (name != NULL, FALSE);
/* FIXME 0.11: use g_ascii_isalpha() */
- if (!g_ascii_isalnum (*name)) {
+ if (G_UNLIKELY (!g_ascii_isalnum (*name))) {
GST_WARNING ("Invalid character '%c' at offset 0 in structure name: %s",
*name, name);
return FALSE;
@@ -169,7 +178,7 @@
s = &name[1];
while (*s && (g_ascii_isalnum (*s) || strchr ("/-_.:+ ", *s) != NULL))
s++;
- if (*s != '\0') {
+ if (G_UNLIKELY (*s != '\0')) {
GST_WARNING ("Invalid character '%c' at offset %lu in structure name: %s",
*s, ((gulong) s - (gulong) name), name);
return FALSE;
@@ -177,6 +186,7 @@
return TRUE;
}
+#endif
/**
* gst_structure_empty_new:
@@ -282,7 +292,7 @@
#endif
void
-gst_structure_set_parent_refcount (GstStructure * structure, int *refcount)
+gst_structure_set_parent_refcount (GstStructure * structure, gint * refcount)
{
g_return_if_fail (structure != NULL);
@@ -313,7 +323,7 @@
{
GstStructure *new_structure;
GstStructureField *field;
- guint i;
+ guint i, len;
g_return_val_if_fail (structure != NULL, NULL);
@@ -321,7 +331,8 @@
gst_structure_id_empty_new_with_size (structure->name,
structure->fields->len);
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+ for (i = 0; i < len; i++) {
GstStructureField new_field = { 0 };
field = GST_STRUCTURE_FIELD (structure, i);
@@ -349,12 +360,13 @@
gst_structure_free (GstStructure * structure)
{
GstStructureField *field;
- guint i;
+ guint i, len;
g_return_if_fail (structure != NULL);
g_return_if_fail (structure->parent_refcount == NULL);
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+ for (i = 0; i < len; i++) {
field = GST_STRUCTURE_FIELD (structure, i);
if (G_IS_VALUE (&field->value)) {
@@ -365,7 +377,7 @@
#ifdef USE_POISONING
memset (structure, 0xff, sizeof (GstStructure));
#endif
- g_free (structure);
+ g_slice_free (GstStructure, structure);
}
/**
@@ -484,17 +496,6 @@
g_return_if_fail (G_IS_VALUE (value));
g_return_if_fail (IS_MUTABLE (structure));
- if (G_VALUE_HOLDS_STRING (value)) {
- const gchar *s;
-
- s = g_value_get_string (value);
- if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
- g_warning ("Trying to set string field '%s' on structure, but string is "
- "not valid UTF-8. Please file a bug.", g_quark_to_string (field));
- return;
- }
- }
-
gsfield.name = field;
gst_value_init_and_copy (&gsfield.value, value);
@@ -540,7 +541,7 @@
*/
#ifdef __SYMBIAN32__
EXPORT_C
-#endif
+#endif
void
gst_structure_set (GstStructure * structure, const gchar * field, ...)
{
@@ -584,14 +585,14 @@
type = va_arg (varargs, GType);
- if (type == G_TYPE_DATE) {
+ if (G_UNLIKELY (type == G_TYPE_DATE)) {
g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
type = GST_TYPE_DATE;
}
g_value_init (&field.value, type);
G_VALUE_COLLECT (&field.value, varargs, 0, &err);
- if (err) {
+ if (G_UNLIKELY (err)) {
g_critical ("%s", err);
return;
}
@@ -662,14 +663,14 @@
type = va_arg (varargs, GType);
- if (type == G_TYPE_DATE) {
+ if (G_UNLIKELY (type == G_TYPE_DATE)) {
g_warning ("Don't use G_TYPE_DATE, use GST_TYPE_DATE instead\n");
type = GST_TYPE_DATE;
}
g_value_init (&field.value, type);
G_VALUE_COLLECT (&field.value, varargs, 0, &err);
- if (err) {
+ if (G_UNLIKELY (err)) {
g_critical ("%s", err);
return;
}
@@ -679,6 +680,51 @@
}
}
+/**
+ * gst_structure_id_new:
+ * @name_quark: name of new structure
+ * @field_quark: the GQuark for the name of the field to set
+ * @...: variable arguments
+ *
+ * Creates a new #GstStructure with the given name as a GQuark, followed by
+ * fieldname quark, GType, argument(s) "triplets" in the same format as
+ * gst_structure_id_set(). Basically a convenience wrapper around
+ * gst_structure_id_empty_new() and gst_structure_id_set().
+ *
+ * The last variable argument must be NULL (or 0).
+ *
+ * Returns: a new #GstStructure
+ *
+ * Since: 0.10.24
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+GstStructure *
+gst_structure_id_new (GQuark name_quark, GQuark field_quark, ...)
+{
+ GstStructure *s;
+ va_list varargs;
+
+ g_return_val_if_fail (name_quark != 0, NULL);
+ g_return_val_if_fail (field_quark != 0, NULL);
+
+ s = gst_structure_id_empty_new (name_quark);
+
+ va_start (varargs, field_quark);
+ gst_structure_id_set_valist (s, field_quark, varargs);
+ va_end (varargs);
+
+ return s;
+}
+
+#if GST_VERSION_NANO == 1
+#define GIT_G_WARNING g_warning
+#else
+#define GIT_G_WARNING GST_WARNING
+#endif
+
/* If the structure currently contains a field with the same name, it is
* replaced with the provided field. Otherwise, the field is added to the
* structure. The field's value is not deeply copied.
@@ -687,12 +733,41 @@
gst_structure_set_field (GstStructure * structure, GstStructureField * field)
{
GstStructureField *f;
- guint i;
-
- for (i = 0; i < structure->fields->len; i++) {
+ guint i, len = structure->fields->len;
+
+ if (G_UNLIKELY (G_VALUE_HOLDS_STRING (&field->value))) {
+ const gchar *s;
+
+ s = g_value_get_string (&field->value);
+ /* only check for NULL strings in taglists, as they are allowed in message
+ * structs, e.g. error message debug strings */
+ if (G_UNLIKELY (IS_TAGLIST (structure) && (s == NULL || *s == '\0'))) {
+ if (s == NULL) {
+ GIT_G_WARNING ("Trying to set NULL string on field '%s' on taglist. "
+ "Please file a bug.", g_quark_to_string (field->name));
+ g_value_unset (&field->value);
+ return;
+ } else {
+ /* empty strings never make sense */
+ GIT_G_WARNING ("Trying to set empty string on taglist field '%s'. "
+ "Please file a bug.", g_quark_to_string (field->name));
+ g_value_unset (&field->value);
+ return;
+ }
+ } else if (G_UNLIKELY (s != NULL && !g_utf8_validate (s, -1, NULL))) {
+ g_warning ("Trying to set string on %s field '%s', but string is not "
+ "valid UTF-8. Please file a bug.",
+ IS_TAGLIST (structure) ? "taglist" : "structure",
+ g_quark_to_string (field->name));
+ g_value_unset (&field->value);
+ return;
+ }
+ }
+
+ for (i = 0; i < len; i++) {
f = GST_STRUCTURE_FIELD (structure, i);
- if (f->name == field->name) {
+ if (G_UNLIKELY (f->name == field->name)) {
g_value_unset (&f->value);
memcpy (f, field, sizeof (GstStructureField));
return;
@@ -708,14 +783,15 @@
gst_structure_id_get_field (const GstStructure * structure, GQuark field_id)
{
GstStructureField *field;
- guint i;
-
+ guint i, len;
+
+ len = structure->fields->len;
g_return_val_if_fail (structure != NULL, NULL);
- for (i = 0; i < structure->fields->len; i++) {
+ for (i = 0; i < len; i++) {
field = GST_STRUCTURE_FIELD (structure, i);
- if (field->name == field_id)
+ if (G_UNLIKELY (field->name == field_id))
return field;
}
@@ -809,15 +885,16 @@
{
GstStructureField *field;
GQuark id;
- guint i;
+ guint i, len;
g_return_if_fail (structure != NULL);
g_return_if_fail (fieldname != NULL);
g_return_if_fail (IS_MUTABLE (structure));
id = g_quark_from_string (fieldname);
-
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+
+ for (i = 0; i < len; i++) {
field = GST_STRUCTURE_FIELD (structure, i);
if (field->name == id) {
@@ -1014,18 +1091,20 @@
gst_structure_foreach (const GstStructure * structure,
GstStructureForeachFunc func, gpointer user_data)
{
- guint i;
+ guint i, len;
GstStructureField *field;
gboolean ret;
g_return_val_if_fail (structure != NULL, FALSE);
g_return_val_if_fail (func != NULL, FALSE);
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+
+ for (i = 0; i < len; i++) {
field = GST_STRUCTURE_FIELD (structure, i);
ret = func (field->name, &field->value, user_data);
- if (!ret)
+ if (G_UNLIKELY (!ret))
return FALSE;
}
@@ -1053,15 +1132,16 @@
gst_structure_map_in_place (GstStructure * structure,
GstStructureMapFunc func, gpointer user_data)
{
- guint i;
+ guint i, len;
GstStructureField *field;
gboolean ret;
g_return_val_if_fail (structure != NULL, FALSE);
g_return_val_if_fail (IS_MUTABLE (structure), FALSE);
g_return_val_if_fail (func != NULL, FALSE);
-
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+
+ for (i = 0; i < len; i++) {
field = GST_STRUCTURE_FIELD (structure, i);
ret = func (field->name, &field->value, user_data);
@@ -1303,6 +1383,11 @@
* given field. Caller is responsible for making sure the field exists
* and has the correct type.
*
+ * On success @value will point to a newly-allocated copy of the date which
+ * should be freed with g_date_free() when no longer needed (note: this is
+ * inconsistent with e.g. gst_structure_get_string() which doesn't return a
+ * copy of the string).
+ *
* Returns: TRUE if the value could be set correctly. If there was no field
* with @fieldname or the existing field did not contain a data, this function
* returns FALSE.
@@ -1328,6 +1413,7 @@
if (!GST_VALUE_HOLDS_DATE (&field->value))
return FALSE;
+ /* FIXME: 0.11 g_value_dup_boxed() -> g_value_get_boxed() */
*value = g_value_dup_boxed (&field->value);
return TRUE;
@@ -1540,7 +1626,7 @@
typedef struct _GstStructureAbbreviation
{
- char *type_name;
+ gchar *type_name;
GType type;
}
GstStructureAbbreviation;
@@ -1555,7 +1641,7 @@
if (abbrs == NULL) {
/* dynamically generate the array */
- #ifdef __SYMBIAN32__
+#ifdef __SYMBIAN32__
GstStructureAbbreviation dyn_abbrs[] = {
@@ -1715,27 +1801,23 @@
}
return G_VALUE_TYPE (val);
}
-
-/* keep in sync with gstvalue.c */
-#define GST_ASCII_IS_STRING(c) (g_ascii_isalnum((c)) || ((c) == '_') || \
- ((c) == '-') || ((c) == '+') || ((c) == '/') || ((c) == ':') || \
- ((c) == '.'))
-
#ifdef __SYMBIAN32__
EXPORT_C
#endif
+
gboolean
priv_gst_structure_append_to_gstring (const GstStructure * structure,
GString * s)
{
GstStructureField *field;
- guint i;
+ guint i, len;
g_return_val_if_fail (s != NULL, FALSE);
g_string_append (s, g_quark_to_string (structure->name));
- for (i = 0; i < structure->fields->len; i++) {
+ len = structure->fields->len;
+ for (i = 0; i < len; i++) {
char *t;
GType type;
@@ -1750,7 +1832,7 @@
g_string_append_len (s, "=(", 2);
g_string_append (s, gst_structure_to_abbr (type));
g_string_append_c (s, ')');
- g_string_append (s, GST_STR_NULL (t));
+ g_string_append (s, t == NULL ? "NULL" : t);
g_free (t);
}
@@ -1764,13 +1846,18 @@
*
* Converts @structure to a human-readable string representation.
*
+ * For debugging purposes its easier to do something like this:
+ * |[
+ * GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
+ * ]|
+ * This prints the structure in human readble form.
+ *
* Returns: a pointer to string allocated by g_malloc(). g_free() after
* usage.
*/
#ifdef __SYMBIAN32__
EXPORT_C
#endif
-
gchar *
gst_structure_to_string (const GstStructure * structure)
{
@@ -1799,7 +1886,8 @@
* THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING
*/
static gboolean
-gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next)
+gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
+ gboolean unescape)
{
gchar *w;
@@ -1815,21 +1903,32 @@
return ret;
}
- w = s;
- s++;
- while (*s != '"') {
- if (*s == 0)
- return FALSE;
-
- if (*s == '\\') {
+ if (unescape) {
+ w = s;
+ s++;
+ while (*s != '"') {
+ if (G_UNLIKELY (*s == 0))
+ return FALSE;
+ if (G_UNLIKELY (*s == '\\'))
+ s++;
+ *w = *s;
+ w++;
s++;
}
-
- *w = *s;
- w++;
+ s++;
+ } else {
+ /* Find the closing quotes */
s++;
+ while (*s != '"') {
+ if (G_UNLIKELY (*s == 0))
+ return FALSE;
+ if (G_UNLIKELY (*s == '\\'))
+ s++;
+ s++;
+ }
+ s++;
+ w = s;
}
- s++;
*end = w;
*next = s;
@@ -1976,7 +2075,7 @@
{
char *s = str;
- while (GST_ASCII_IS_STRING (*s)) {
+ while (G_LIKELY (GST_ASCII_IS_STRING (*s))) {
s++;
}
@@ -1999,23 +2098,24 @@
while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
s++;
name = s;
- if (!gst_structure_parse_simple_string (s, &name_end))
+ if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &name_end)))
return FALSE;
s = name_end;
while (g_ascii_isspace (*s) || (s[0] == '\\' && g_ascii_isspace (s[1])))
s++;
- if (*s != '=')
+ if (G_UNLIKELY (*s != '='))
return FALSE;
s++;
c = *name_end;
- *name_end = 0;
+ *name_end = '\0';
field->name = g_quark_from_string (name);
*name_end = c;
- if (!gst_structure_parse_value (s, &s, &field->value, G_TYPE_INVALID))
+ if (G_UNLIKELY (!gst_structure_parse_value (s, &s, &field->value,
+ G_TYPE_INVALID)))
return FALSE;
*after = s;
@@ -2038,7 +2138,6 @@
#endif
GType type = default_type;
-
s = str;
while (g_ascii_isspace (*s))
s++;
@@ -2046,18 +2145,16 @@
/* check if there's a (type_name) 'cast' */
type_name = NULL;
if (*s == '(') {
- type = G_TYPE_INVALID;
-
s++;
while (g_ascii_isspace (*s))
s++;
type_name = s;
- if (!gst_structure_parse_simple_string (s, &type_end))
+ if (G_UNLIKELY (!gst_structure_parse_simple_string (s, &type_end)))
return FALSE;
s = type_end;
while (g_ascii_isspace (*s))
s++;
- if (*s != ')')
+ if (G_UNLIKELY (*s != ')'))
return FALSE;
s++;
while (g_ascii_isspace (*s))
@@ -2068,7 +2165,7 @@
type = gst_structure_gtype_from_abbr (type_name);
*type_end = c;
- if (type == G_TYPE_INVALID)
+ if (G_UNLIKELY (type == G_TYPE_INVALID))
return FALSE;
}
@@ -2082,12 +2179,8 @@
ret = gst_structure_parse_array (s, &s, value, type);
} else {
value_s = s;
- if (!gst_structure_parse_string (s, &value_end, &s))
- return FALSE;
-
- c = *value_end;
- *value_end = 0;
- if (type == G_TYPE_INVALID) {
+
+ if (G_UNLIKELY (type == G_TYPE_INVALID)) {
#ifdef __SYMBIAN32__
GType try_types[] =
{ G_TYPE_INT, G_TYPE_DOUBLE, G_TYPE_INVALID, G_TYPE_STRING };
@@ -2099,6 +2192,12 @@
int i;
#endif
+ if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s, TRUE)))
+ return FALSE;
+ /* Set NULL terminator for deserialization */
+ c = *value_end;
+ *value_end = '\0';
+
for (i = 0; i < G_N_ELEMENTS (try_types); i++) {
g_value_init (value, try_types[i]);
ret = gst_value_deserialize (value, value_s);
@@ -2109,7 +2208,16 @@
} else {
g_value_init (value, type);
+ if (G_UNLIKELY (!gst_structure_parse_string (s, &value_end, &s,
+ (type != G_TYPE_STRING))))
+ return FALSE;
+ /* Set NULL terminator for deserialization */
+ c = *value_end;
+ *value_end = '\0';
+
ret = gst_value_deserialize (value, value_s);
+ if (G_UNLIKELY (!ret))
+ g_value_unset (value);
}
*value_end = c;
}
@@ -2144,7 +2252,7 @@
char *r;
char save;
GstStructure *structure = NULL;
- GstStructureField field = { 0 };
+ GstStructureField field;
g_return_val_if_fail (string != NULL, NULL);
@@ -2157,17 +2265,17 @@
r++;
name = r;
- if (!gst_structure_parse_string (r, &w, &r)) {
+ if (G_UNLIKELY (!gst_structure_parse_string (r, &w, &r, TRUE))) {
GST_WARNING ("Failed to parse structure string");
goto error;
}
save = *w;
- *w = 0;
+ *w = '\0';
structure = gst_structure_empty_new (name);
*w = save;
- if (structure == NULL)
+ if (G_UNLIKELY (structure == NULL))
goto error;
do {
@@ -2183,7 +2291,7 @@
/* accept \0 as end delimiter */
break;
}
- if (*r != ',') {
+ if (G_UNLIKELY (*r != ',')) {
GST_WARNING ("Failed to find delimiter, r=%s", r);
goto error;
}
@@ -2193,10 +2301,9 @@
r++;
memset (&field, 0, sizeof (field));
- if (!gst_structure_parse_field (r, &r, &field))
+ if (G_UNLIKELY (!gst_structure_parse_field (r, &r, &field)))
goto error;
gst_structure_set_field (structure, &field);
-
} while (TRUE);
if (end)
@@ -2483,16 +2590,13 @@
const GValue *list_value;
int i, n;
const GValue *best = NULL;
- GValue best_diff = { 0 };
- GValue cur_diff = { 0 };
- GValue target = { 0 };
- gboolean res = FALSE;
-
- g_value_init (&best_diff, GST_TYPE_FRACTION);
- g_value_init (&cur_diff, GST_TYPE_FRACTION);
- g_value_init (&target, GST_TYPE_FRACTION);
-
- gst_value_set_fraction (&target, target_numerator, target_denominator);
+ gdouble target;
+ gdouble cur_diff;
+ gdouble best_diff = G_MAXDOUBLE;
+
+ target = (gdouble) target_numerator / (gdouble) target_denominator;
+
+ GST_DEBUG ("target %g, best %g", target, best_diff);
best = NULL;
@@ -2500,28 +2604,295 @@
for (i = 0; i < n; i++) {
list_value = gst_value_list_get_value (value, i);
if (G_VALUE_TYPE (list_value) == GST_TYPE_FRACTION) {
-
- if (gst_value_compare (list_value, &target) == GST_VALUE_LESS_THAN)
- gst_value_fraction_subtract (&cur_diff, &target, list_value);
- else
- gst_value_fraction_subtract (&cur_diff, list_value, &target);
-
- if (!best
- || gst_value_compare (&cur_diff,
- &best_diff) == GST_VALUE_LESS_THAN) {
+ gint num, denom;
+ gdouble list_double;
+
+ num = gst_value_get_fraction_numerator (list_value);
+ denom = gst_value_get_fraction_denominator (list_value);
+
+ list_double = ((gdouble) num / (gdouble) denom);
+ cur_diff = target - list_double;
+
+ GST_DEBUG ("curr diff %g, list %g", cur_diff, list_double);
+
+ if (cur_diff < 0)
+ cur_diff = -cur_diff;
+
+ if (!best || cur_diff < best_diff) {
+ GST_DEBUG ("new best %g", list_double);
best = list_value;
- g_value_copy (&cur_diff, &best_diff);
+ best_diff = cur_diff;
}
}
}
if (best != NULL) {
gst_structure_set_value (structure, field_name, best);
- res = TRUE;
+ return TRUE;
}
- g_value_unset (&best_diff);
- g_value_unset (&cur_diff);
- g_value_unset (&target);
- return res;
}
+
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
+ * @args: 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
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+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
+ * @args: 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
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+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
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+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
+ */
+#ifdef __SYMBIAN32__
+EXPORT_C
+#endif
+
+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;
+}