Port gtk-doc comments to their equivalent markdown syntax
[platform/upstream/gstreamer.git] / gst / gststructure.c
index ad42d3a..8166e47 100644 (file)
@@ -21,6 +21,7 @@
 
 /**
  * SECTION:gststructure
+ * @title: GstStructure
  * @short_description: Generic structure containing fields of names and values
  * @see_also: #GstCaps, #GstMessage, #GstEvent, #GstQuery
  *
@@ -619,7 +620,8 @@ gst_structure_set_valist_internal (GstStructure * structure,
  * @fieldname: the name of the field to set
  * @...: variable arguments
  *
- * Parses the variable arguments and sets fields accordingly.
+ * Parses the variable arguments and sets fields accordingly. Fields that
+ * weren't already part of the structure are added as needed.
  * Variable arguments should be in the form field name, field type
  * (as a GType), value(s).  The last variable argument should be %NULL.
  */
@@ -1100,7 +1102,8 @@ gst_structure_nth_field_name (const GstStructure * structure, guint index)
  * @user_data: (closure): private data
  *
  * Calls the provided function once for each field in the #GstStructure. The
- * function must not modify the fields. Also see gst_structure_map_in_place().
+ * function must not modify the fields. Also see gst_structure_map_in_place()
+ * and gst_structure_filter_and_map_in_place().
  *
  * Returns: %TRUE if the supplied function returns %TRUE For each of the fields,
  * %FALSE otherwise.
@@ -1167,6 +1170,51 @@ gst_structure_map_in_place (GstStructure * structure,
 }
 
 /**
+ * gst_structure_filter_and_map_in_place:
+ * @structure: a #GstStructure
+ * @func: (scope call): a function to call for each field
+ * @user_data: (closure): private data
+ *
+ * Calls the provided function once for each field in the #GstStructure. In
+ * contrast to gst_structure_foreach(), the function may modify the fields.
+ * In contrast to gst_structure_map_in_place(), the field is removed from
+ * the structure if %FALSE is returned from the function.
+ * The structure must be mutable.
+ *
+ * Since: 1.6
+ */
+void
+gst_structure_filter_and_map_in_place (GstStructure * structure,
+    GstStructureFilterMapFunc func, gpointer user_data)
+{
+  guint i, len;
+  GstStructureField *field;
+  gboolean ret;
+
+  g_return_if_fail (structure != NULL);
+  g_return_if_fail (IS_MUTABLE (structure));
+  g_return_if_fail (func != NULL);
+  len = GST_STRUCTURE_FIELDS (structure)->len;
+
+  for (i = 0; i < len;) {
+    field = GST_STRUCTURE_FIELD (structure, i);
+
+    ret = func (field->name, &field->value, user_data);
+
+    if (!ret) {
+      if (G_IS_VALUE (&field->value)) {
+        g_value_unset (&field->value);
+      }
+      GST_STRUCTURE_FIELDS (structure) =
+          g_array_remove_index (GST_STRUCTURE_FIELDS (structure), i);
+      len = GST_STRUCTURE_FIELDS (structure)->len;
+    } else {
+      i++;
+    }
+  }
+}
+
+/**
  * gst_structure_id_has_field:
  * @structure: a #GstStructure
  * @field: #GQuark of the field name
@@ -1674,6 +1722,44 @@ gst_structure_get_fraction (const GstStructure * structure,
   return TRUE;
 }
 
+/**
+ * gst_structure_get_flagset:
+ * @structure: a #GstStructure
+ * @fieldname: the name of a field
+ * @value_flags: (out) (allow-none): a pointer to a guint for the flags field
+ * @value_mask: (out) (allow-none): a pointer to a guint for the mask field
+ *
+ * Read the GstFlagSet flags and mask out of the structure into the
+ * provided pointers.
+ *
+ * Returns: %TRUE if the values could be set correctly. If there was no field
+ * with @fieldname or the existing field did not contain a GstFlagSet, this
+ * function returns %FALSE.
+ *
+ * Since: 1.6
+ */
+gboolean
+gst_structure_get_flagset (const GstStructure * structure,
+    const gchar * fieldname, guint * value_flags, guint * value_mask)
+{
+  GstStructureField *field;
+
+  g_return_val_if_fail (structure != NULL, FALSE);
+  g_return_val_if_fail (fieldname != NULL, FALSE);
+
+  field = gst_structure_get_field (structure, fieldname);
+
+  if (field == NULL || !GST_VALUE_HOLDS_FLAG_SET (&field->value))
+    return FALSE;
+
+  if (value_flags)
+    *value_flags = gst_value_get_flagset_flags (&field->value);
+  if (value_mask)
+    *value_mask = gst_value_get_flagset_mask (&field->value);
+
+  return TRUE;
+}
+
 typedef struct _GstStructureAbbreviation
 {
   const gchar *type_name;
@@ -1736,6 +1822,8 @@ gst_structure_get_abbrs (gint * n_abbrs)
       {"sample", GST_TYPE_SAMPLE}
       ,
       {"taglist", GST_TYPE_TAG_LIST}
+      ,
+      {"type", G_TYPE_GTYPE}
     };
     _num = G_N_ELEMENTS (dyn_abbrs);
     /* permanently allocate and copy the array now */
@@ -1756,6 +1844,7 @@ gst_structure_gtype_from_abbr (const char *type_name)
   int i;
   GstStructureAbbreviation *abbrs;
   gint n_abbrs;
+  GType ret;
 
   g_return_val_if_fail (type_name != NULL, G_TYPE_INVALID);
 
@@ -1768,7 +1857,11 @@ gst_structure_gtype_from_abbr (const char *type_name)
   }
 
   /* this is the fallback */
-  return g_type_from_name (type_name);
+  ret = g_type_from_name (type_name);
+  /* If not found, try it as a dynamic type */
+  if (G_UNLIKELY (ret == 0))
+    ret = gst_dynamic_type_factory_load (type_name);
+  return ret;
 }
 
 static const char *
@@ -1792,7 +1885,7 @@ gst_structure_to_abbr (GType type)
 }
 
 static GType
-gst_structure_value_get_generic_type (GValue * val)
+gst_structure_value_get_generic_type (const GValue * val)
 {
   if (G_VALUE_TYPE (val) == GST_TYPE_LIST
       || G_VALUE_TYPE (val) == GST_TYPE_ARRAY) {
@@ -1842,14 +1935,69 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
     g_string_append_len (s, "=(", 2);
     g_string_append (s, gst_structure_to_abbr (type));
     g_string_append_c (s, ')');
-    g_string_append (s, t == NULL ? "NULL" : t);
-    g_free (t);
+    if (t) {
+      g_string_append (s, t);
+      g_free (t);
+    } else {
+      GST_WARNING ("No value transform to serialize field '%s' of type '%s'",
+          g_quark_to_string (field->name), gst_structure_to_abbr (type));
+      g_string_append (s, "NULL");
+    }
   }
 
   g_string_append_c (s, ';');
   return TRUE;
 }
 
+gboolean
+priv__gst_structure_append_template_to_gstring (GQuark field_id,
+    const GValue * value, gpointer user_data)
+{
+  GType type = gst_structure_value_get_generic_type (value);
+  GString *s = (GString *) user_data;
+
+  g_string_append_len (s, ", ", 2);
+  /* FIXME: do we need to escape fieldnames? */
+  g_string_append (s, g_quark_to_string (field_id));
+  g_string_append_len (s, "=(", 2);
+  g_string_append (s, gst_structure_to_abbr (type));
+  g_string_append_c (s, ')');
+
+  //TODO(ensonic): table like GstStructureAbbreviation (or extend it)
+  if (type == G_TYPE_INT) {
+    g_string_append_len (s, "%i", 2);
+  } else if (type == G_TYPE_UINT) {
+    g_string_append_len (s, "%u", 2);
+  } else if (type == G_TYPE_FLOAT) {
+    g_string_append_len (s, "%f", 2);
+  } else if (type == G_TYPE_DOUBLE) {
+    g_string_append_len (s, "%lf", 3);
+  } else if (type == G_TYPE_STRING) {
+    g_string_append_len (s, "%s", 2);
+  } else if (type == G_TYPE_BOOLEAN) {
+    /* we normally store this as a string, but can parse it also from an int */
+    g_string_append_len (s, "%i", 2);
+  } else if (type == G_TYPE_INT64) {
+    g_string_append (s, "%" G_GINT64_FORMAT);
+  } else if (type == G_TYPE_UINT64) {
+    g_string_append (s, "%" G_GUINT64_FORMAT);
+  } else if (type == GST_TYPE_STRUCTURE) {
+    g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT);
+  } else if (g_type_is_a (type, G_TYPE_ENUM)
+      || g_type_is_a (type, G_TYPE_FLAGS)) {
+    g_string_append_len (s, "%i", 2);
+  } else if (type == G_TYPE_GTYPE) {
+    g_string_append_len (s, "%s", 2);
+  } else if (type == G_TYPE_POINTER) {
+    g_string_append_len (s, "%p", 2);
+  } else {
+    GST_WARNING ("unhandled type: %s", g_type_name (type));
+    g_string_append (s, "%" GST_WRAPPED_PTR_FORMAT);
+  }
+
+  return TRUE;
+}
+
 /**
  * gst_structure_to_string:
  * @structure: a #GstStructure
@@ -1857,7 +2005,7 @@ priv_gst_structure_append_to_gstring (const GstStructure * structure,
  * Converts @structure to a human-readable string representation.
  *
  * For debugging purposes its easier to do something like this:
- * |[
+ * |[<!-- language="C" -->
  * GST_LOG ("structure is %" GST_PTR_FORMAT, structure);
  * ]|
  * This prints the structure in human readable form.
@@ -1892,11 +2040,19 @@ gst_structure_to_string (const GstStructure * structure)
 }
 
 /*
- * r will still point to the string. if end == next, the string will not be
+ * gst_structure_parse_string:
+ * @s: string to parse
+ * @end: out-pointer to char behind end of string
+ * @next: out-pointer to start of unread data
+ * @unescape: @TRUE if the substring is escaped.
+ *
+ * Find the end of a sub-string. If end == next, the string will not be
  * null-terminated. In all other cases it will be.
- * end = pointer to char behind end of string, next = pointer to start of
- * unread data.
- * THIS FUNCTION MODIFIES THE STRING AND DETECTS INSIDE A NONTERMINATED STRING
+ *
+ * Note: This function modifies the string in @s (if unescape == @TRUE).
+ *
+ * Returns: @TRUE if a sub-string was found and @FALSE if the string is not
+ * terminated.
  */
 static gboolean
 gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
@@ -1908,14 +2064,13 @@ gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
     return FALSE;
 
   if (*s != '"') {
-    int ret;
-
-    ret = gst_structure_parse_simple_string (s, end);
+    int ret = gst_structure_parse_simple_string (s, end);
     *next = *end;
 
     return ret;
   }
 
+  /* Find the closing quotes */
   if (unescape) {
     w = s;
     s++;
@@ -1933,7 +2088,6 @@ gst_structure_parse_string (gchar * s, gchar ** end, gchar ** next,
     }
     s++;
   } else {
-    /* Find the closing quotes */
     s++;
     while (*s != '"') {
       if (G_UNLIKELY (*s == 0))
@@ -1970,7 +2124,7 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
   s++;
 
   ret = gst_structure_parse_value (s, &s, &value1, type);
-  if (ret == FALSE)
+  if (!ret)
     return FALSE;
 
   while (g_ascii_isspace (*s))
@@ -1984,7 +2138,7 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
     s++;
 
   ret = gst_structure_parse_value (s, &s, &value2, type);
-  if (ret == FALSE)
+  if (!ret)
     return FALSE;
 
   while (g_ascii_isspace (*s))
@@ -2000,7 +2154,7 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value,
         s++;
 
       ret = gst_structure_parse_value (s, &s, &value3, type);
-      if (ret == FALSE)
+      if (!ret)
         return FALSE;
 
       while (g_ascii_isspace (*s))
@@ -2084,7 +2238,7 @@ gst_structure_parse_any_list (gchar * s, gchar ** after, GValue * value,
   }
 
   ret = gst_structure_parse_value (s, &s, &list_value, type);
-  if (ret == FALSE)
+  if (!ret)
     return FALSE;
 
   g_array_append_val (array, list_value);
@@ -2102,7 +2256,7 @@ gst_structure_parse_any_list (gchar * s, gchar ** after, GValue * value,
 
     memset (&list_value, 0, sizeof (list_value));
     ret = gst_structure_parse_value (s, &s, &list_value, type);
-    if (ret == FALSE)
+    if (!ret)
       return FALSE;
 
     g_array_append_val (array, list_value);
@@ -2250,8 +2404,8 @@ gst_structure_parse_value (gchar * str,
 
     if (G_UNLIKELY (type == G_TYPE_INVALID)) {
       GType try_types[] =
-          { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, G_TYPE_BOOLEAN,
-        G_TYPE_STRING
+          { G_TYPE_INT, G_TYPE_DOUBLE, GST_TYPE_FRACTION, GST_TYPE_FLAG_SET,
+        G_TYPE_BOOLEAN, G_TYPE_STRING
       };
       int i;