gststructure: Inline gst_structure_intersect()
authorEdward Hervey <edward@centricular.com>
Mon, 23 Mar 2020 07:06:26 +0000 (08:06 +0100)
committerSebastian Dröge <slomo@coaxion.net>
Tue, 5 May 2020 10:17:49 +0000 (10:17 +0000)
Having direct access to the iteration allows tighter code and
also being able to stop earlier.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/453>

gst/gststructure.c

index d5dc4f6..8df6c12 100644 (file)
@@ -2982,45 +2982,6 @@ gst_structure_is_equal (const GstStructure * structure1,
       (gpointer) structure2);
 }
 
-
-typedef struct
-{
-  GstStructure *dest;
-  const GstStructure *intersect;
-}
-IntersectData;
-
-static gboolean
-gst_structure_intersect_field1 (GQuark id, const GValue * val1, gpointer data)
-{
-  IntersectData *idata = (IntersectData *) data;
-  const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
-  if (G_UNLIKELY (val2 == NULL)) {
-    gst_structure_id_set_value (idata->dest, id, val1);
-  } else {
-    GValue dest_value = { 0 };
-    if (gst_value_intersect (&dest_value, val1, val2)) {
-      gst_structure_id_take_value (idata->dest, id, &dest_value);
-    } else {
-      return FALSE;
-    }
-  }
-  return TRUE;
-}
-
-static gboolean
-gst_structure_intersect_field2 (GQuark id, const GValue * val1, gpointer data)
-{
-  IntersectData *idata = (IntersectData *) data;
-  const GValue *val2 = gst_structure_id_get_value (idata->intersect, id);
-
-  if (G_UNLIKELY (val2 == NULL)) {
-    gst_structure_id_set_value (idata->dest, id, val1);
-  }
-  return TRUE;
-}
-
 /**
  * gst_structure_intersect:
  * @struct1: a #GstStructure
@@ -3034,7 +2995,8 @@ GstStructure *
 gst_structure_intersect (const GstStructure * struct1,
     const GstStructure * struct2)
 {
-  IntersectData data;
+  guint it1, len1, it2, len2;
+  GstStructure *dest;
 
   g_assert (struct1 != NULL);
   g_assert (struct2 != NULL);
@@ -3042,24 +3004,59 @@ gst_structure_intersect (const GstStructure * struct1,
   if (G_UNLIKELY (struct1->name != struct2->name))
     return NULL;
 
+  len1 = GST_STRUCTURE_LEN (struct1);
+  len2 = GST_STRUCTURE_LEN (struct2);
+
+  /* Resulting structure will be at most the size of the smallest structure */
+  dest = gst_structure_new_id_empty_with_size (struct1->name, MIN (len1, len2));
+
   /* copy fields from struct1 which we have not in struct2 to target
    * intersect if we have the field in both */
-  data.dest = gst_structure_new_id_empty (struct1->name);
-  data.intersect = struct2;
-  if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct1,
-              gst_structure_intersect_field1, &data)))
-    goto error;
+  for (it1 = 0; it1 < len1; it1++) {
+    GstStructureField *field1 = GST_STRUCTURE_FIELD (struct1, it1);
+    gboolean seenother = FALSE;
+    for (it2 = 0; it2 < len2; it2++) {
+      GstStructureField *field2 = GST_STRUCTURE_FIELD (struct2, it2);
+      if (field1->name == field2->name) {
+        GValue dest_value = { 0 };
+        seenother = TRUE;
+        /* Get the intersection if any */
+        if (gst_value_intersect (&dest_value, &field1->value, &field2->value)) {
+          gst_structure_id_take_value (dest, field1->name, &dest_value);
+          break;
+        } else {
+          /* No intersection, return nothing */
+          goto error;
+        }
+      }
+    }
+    /* Field1 was only present in struct1, copy it over */
+    if (!seenother)
+      gst_structure_id_set_value (dest, field1->name, &field1->value);
+  }
 
-  /* copy fields from struct2 which we have not in struct1 to target */
-  data.intersect = struct1;
-  if (G_UNLIKELY (!gst_structure_foreach ((GstStructure *) struct2,
-              gst_structure_intersect_field2, &data)))
-    goto error;
+  /* Now iterate over the 2nd struct and copy over everything which
+   * isn't present in the 1st struct (we've already taken care of
+   * values being present in both just above) */
+  for (it2 = 0; it2 < len2; it2++) {
+    GstStructureField *field2 = GST_STRUCTURE_FIELD (struct2, it2);
+    gboolean seenother = FALSE;
+    for (it1 = 0; it1 < len1; it1++) {
+      GstStructureField *field1 = GST_STRUCTURE_FIELD (struct1, it1);
+      if (field1->name == field2->name) {
+        seenother = TRUE;
+        break;
+      }
+    }
+    if (!seenother)
+      gst_structure_id_set_value (dest, field2->name, &field2->value);
+
+  }
 
-  return data.dest;
+  return dest;
 
 error:
-  gst_structure_free (data.dest);
+  gst_structure_free (dest);
   return NULL;
 }