value: Add 64-bit bitmask type
authorSebastian Dröge <sebastian.droege@collabora.co.uk>
Fri, 16 Dec 2011 11:32:26 +0000 (12:32 +0100)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 5 Jan 2012 09:24:14 +0000 (10:24 +0100)
gst/gstvalue.c
gst/gstvalue.h

index 3646ca4..0cafa4a 100644 (file)
@@ -3831,9 +3831,11 @@ gst_value_register_subtract_func (GType minuend_type, GType subtrahend_type,
 {
   GstValueSubtractInfo info;
 
-  /* one type must be unfixed, other subtractions can be done as comparisons */
-  g_return_if_fail (!gst_type_is_fixed (minuend_type)
-      || !gst_type_is_fixed (subtrahend_type));
+  /* one type must be unfixed, other subtractions can be done as comparisons,
+   * special case: bitmasks */
+  if (minuend_type != GST_TYPE_BITMASK)
+    g_return_if_fail (!gst_type_is_fixed (minuend_type)
+        || !gst_type_is_fixed (subtrahend_type));
 
   info.minuend = minuend_type;
   info.subtrahend = subtrahend_type;
@@ -4647,6 +4649,207 @@ gst_value_transform_string_date (const GValue * src_value, GValue * dest_value)
   gst_value_deserialize_date (dest_value, src_value->data[0].v_pointer);
 }
 
+
+/************
+ * bitmask *
+ ************/
+
+/* helper functions */
+static void
+gst_value_init_bitmask (GValue * value)
+{
+  value->data[0].v_uint64 = 0;
+}
+
+static void
+gst_value_copy_bitmask (const GValue * src_value, GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static gchar *
+gst_value_collect_bitmask (GValue * value, guint n_collect_values,
+    GTypeCValue * collect_values, guint collect_flags)
+{
+  if (n_collect_values != 1)
+    return g_strdup_printf ("not enough value locations for `%s' passed",
+        G_VALUE_TYPE_NAME (value));
+
+  gst_value_set_bitmask (value, (guint64) collect_values[0].v_int64);
+
+  return NULL;
+}
+
+static gchar *
+gst_value_lcopy_bitmask (const GValue * value, guint n_collect_values,
+    GTypeCValue * collect_values, guint collect_flags)
+{
+  guint64 *bitmask = collect_values[0].v_pointer;
+
+  if (!bitmask)
+    return g_strdup_printf ("value for `%s' passed as NULL",
+        G_VALUE_TYPE_NAME (value));
+
+  *bitmask = value->data[0].v_uint64;
+
+  return NULL;
+}
+
+/**
+ * gst_value_set_bitmask:
+ * @value: a GValue initialized to #GST_TYPE_FRACTION
+ * @bitmask: the bitmask
+ *
+ * Sets @value to the bitmask specified by @bitmask.
+ */
+void
+gst_value_set_bitmask (GValue * value, guint64 bitmask)
+{
+  g_return_if_fail (GST_VALUE_HOLDS_BITMASK (value));
+
+  value->data[0].v_uint64 = bitmask;
+}
+
+/**
+ * gst_value_get_bitmask:
+ * @value: a GValue initialized to #GST_TYPE_FRACTION
+ *
+ * Gets the bitmask specified by @value.
+ *
+ * Returns: the bitmask.
+ */
+guint64
+gst_value_get_bitmask (const GValue * value)
+{
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (value), 0);
+
+  return value->data[0].v_uint64;
+}
+
+static gchar *
+gst_value_serialize_bitmask (const GValue * value)
+{
+  guint64 bitmask = value->data[0].v_uint64;
+
+  return g_strdup_printf ("0x%016" G_GINT64_MODIFIER "x", bitmask);
+}
+
+static gboolean
+gst_value_deserialize_bitmask (GValue * dest, const gchar * s)
+{
+  gchar *endptr = NULL;
+  guint64 val;
+
+  if (G_UNLIKELY (s == NULL))
+    return FALSE;
+
+  if (G_UNLIKELY (dest == NULL || !GST_VALUE_HOLDS_BITMASK (dest)))
+    return FALSE;
+
+  val = g_ascii_strtoull (s, &endptr, 16);
+  if (val == G_MAXUINT64 && (errno == ERANGE || errno == EINVAL))
+    return FALSE;
+  if (val == 0 && endptr == s)
+    return FALSE;
+
+  gst_value_set_bitmask (dest, val);
+
+  return TRUE;
+}
+
+static void
+gst_value_transform_bitmask_string (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_pointer = gst_value_serialize_bitmask (src_value);
+}
+
+static void
+gst_value_transform_string_bitmask (const GValue * src_value,
+    GValue * dest_value)
+{
+  if (!gst_value_deserialize_bitmask (dest_value, src_value->data[0].v_pointer))
+    gst_value_set_bitmask (dest_value, 0);
+}
+
+static void
+gst_value_transform_uint64_bitmask (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static void
+gst_value_transform_bitmask_uint64 (const GValue * src_value,
+    GValue * dest_value)
+{
+  dest_value->data[0].v_uint64 = src_value->data[0].v_uint64;
+}
+
+static gboolean
+gst_value_intersect_bitmask_bitmask (GValue * dest, const GValue * src1,
+    const GValue * src2)
+{
+  guint64 s1, s2;
+
+  s1 = gst_value_get_bitmask (src1);
+  s2 = gst_value_get_bitmask (src2);
+
+  g_value_init (dest, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (dest, s1 & s2);
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_union_bitmask_bitmask (GValue * dest, const GValue * src1,
+    const GValue * src2)
+{
+  guint64 s1, s2;
+
+  s1 = gst_value_get_bitmask (src1);
+  s2 = gst_value_get_bitmask (src2);
+
+  g_value_init (dest, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (dest, s1 | s2);
+
+  return TRUE;
+}
+
+static gboolean
+gst_value_subtract_bitmask_bitmask (GValue * dest,
+    const GValue * minuend, const GValue * subtrahend)
+{
+  guint64 m, s, r;
+
+  g_return_val_if_fail (dest != NULL, FALSE);
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (minuend), FALSE);
+  g_return_val_if_fail (GST_VALUE_HOLDS_BITMASK (subtrahend), FALSE);
+
+  m = minuend->data[0].v_uint64;
+  s = subtrahend->data[0].v_uint64;
+  r = m & (~s);
+
+  g_value_init (dest, GST_TYPE_BITMASK);
+  gst_value_set_bitmask (dest, r);
+
+  return (r != 0);
+}
+
+static gint
+gst_value_compare_bitmask (const GValue * value1, const GValue * value2)
+{
+  guint64 v1, v2;
+
+  v1 = value1->data[0].v_uint64;
+  v2 = value2->data[0].v_uint64;
+
+  if (v1 == v2)
+    return GST_VALUE_EQUAL;
+
+  return GST_VALUE_UNORDERED;
+}
+
 static void
 gst_value_transform_object_string (const GValue * src_value,
     GValue * dest_value)
@@ -4824,6 +5027,19 @@ gst_date_time_get_type (void)
   return gst_date_time_type;
 }
 
+static const GTypeValueTable _gst_bitmask_value_table = {
+  gst_value_init_bitmask,
+  NULL,
+  gst_value_copy_bitmask,
+  NULL,
+  (char *) "q",
+  gst_value_collect_bitmask,
+  (char *) "p",
+  gst_value_lcopy_bitmask
+};
+
+FUNC_VALUE_GET_TYPE (bitmask, "GstBitmask");
+
 
 void
 _priv_gst_value_initialize (void)
@@ -4988,6 +5204,18 @@ _priv_gst_value_initialize (void)
     gst_value_register (&gst_value);
   }
 
+  {
+    static GstValueTable gst_value = {
+      0,
+      gst_value_compare_bitmask,
+      gst_value_serialize_bitmask,
+      gst_value_deserialize_bitmask,
+    };
+
+    gst_value.type = gst_bitmask_get_type ();
+    gst_value_register (&gst_value);
+  }
+
   REGISTER_SERIALIZATION (G_TYPE_DOUBLE, double);
   REGISTER_SERIALIZATION (G_TYPE_FLOAT, float);
 
@@ -5038,6 +5266,14 @@ _priv_gst_value_initialize (void)
       gst_value_transform_string_date);
   g_value_register_transform_func (GST_TYPE_OBJECT, G_TYPE_STRING,
       gst_value_transform_object_string);
+  g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_UINT64,
+      gst_value_transform_bitmask_uint64);
+  g_value_register_transform_func (GST_TYPE_BITMASK, G_TYPE_STRING,
+      gst_value_transform_bitmask_string);
+  g_value_register_transform_func (G_TYPE_UINT64, GST_TYPE_BITMASK,
+      gst_value_transform_uint64_bitmask);
+  g_value_register_transform_func (G_TYPE_STRING, GST_TYPE_BITMASK,
+      gst_value_transform_string_bitmask);
 
   gst_value_register_intersect_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_intersect_int_int_range);
@@ -5058,6 +5294,8 @@ _priv_gst_value_initialize (void)
   gst_value_register_intersect_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_intersect_fraction_range_fraction_range);
+  gst_value_register_intersect_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_intersect_bitmask_bitmask);
 
   gst_value_register_subtract_func (G_TYPE_INT, GST_TYPE_INT_RANGE,
       gst_value_subtract_int_int_range);
@@ -5077,7 +5315,6 @@ _priv_gst_value_initialize (void)
       gst_value_subtract_double_range_double);
   gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE,
       GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_range_double_range);
-
   gst_value_register_subtract_func (GST_TYPE_FRACTION, GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_fraction_range);
   gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE, GST_TYPE_FRACTION,
@@ -5085,6 +5322,8 @@ _priv_gst_value_initialize (void)
   gst_value_register_subtract_func (GST_TYPE_FRACTION_RANGE,
       GST_TYPE_FRACTION_RANGE,
       gst_value_subtract_fraction_range_fraction_range);
+  gst_value_register_subtract_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_subtract_bitmask_bitmask);
 
   /* see bug #317246, #64994, #65041 */
   {
@@ -5097,6 +5336,8 @@ _priv_gst_value_initialize (void)
       gst_value_union_int_int_range);
   gst_value_register_union_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE,
       gst_value_union_int_range_int_range);
+  gst_value_register_union_func (GST_TYPE_BITMASK,
+      GST_TYPE_BITMASK, gst_value_union_bitmask_bitmask);
 
 #if 0
   /* Implement these if needed */
index 6db9640..ab5d355 100644 (file)
@@ -196,6 +196,14 @@ G_BEGIN_DECLS
 #define GST_VALUE_HOLDS_DATE_TIME(x)    (G_VALUE_HOLDS((x), gst_date_time_get_type ()))
 
 /**
+ * GST_VALUE_HOLDS_BITMASK:
+ * @x: the #GValue to check
+ *
+ * Checks if the given #GValue contains a #GST_TYPE_BITMASK value.
+ */
+#define GST_VALUE_HOLDS_BITMASK(x)      (G_VALUE_HOLDS((x), gst_bitmask_get_type ()))
+
+/**
  * GST_TYPE_INT_RANGE:
  *
  * a #GValue type that represents an integer range
@@ -293,6 +301,16 @@ G_BEGIN_DECLS
 #define GST_TYPE_DATE_TIME               gst_date_time_get_type ()
 
 /**
+ * GST_TYPE_BITMASK:
+ *
+ * a #GValue type that represents a 64-bit bitmask.
+ *
+ * Returns: the #GType of GstBitmask (which is not explicitly typed)
+ */
+
+#define GST_TYPE_BITMASK                 gst_bitmask_get_type ()
+
+/**
  * GST_VALUE_LESS_THAN:
  *
  * Indicates that the first value provided to a comparison function
@@ -436,6 +454,7 @@ GType gst_fraction_range_get_type (void);
 GType gst_fraction_get_type (void);
 GType gst_value_list_get_type (void);
 GType gst_value_array_get_type (void);
+GType gst_bitmask_get_type (void);
 
 GType gst_date_get_type (void);
 GType gst_date_time_get_type (void);
@@ -534,6 +553,12 @@ const GDate *   gst_value_get_date              (const GValue   *value);
 void            gst_value_set_date              (GValue         *value,
                                                  const GDate    *date);
 
+
+/* bitmask */
+guint64         gst_value_get_bitmask           (const GValue   *value);
+void            gst_value_set_bitmask           (GValue         *value,
+                                                 guint64         bitmask);
+
 /* compare */
 gint            gst_value_compare               (const GValue   *value1,
                                                  const GValue   *value2);