[gimp] libgimpbase: add GimpObjectArray and GimpParamSpecObjectArray



commit 0fefb7e922fea17f4f65aa40385cb3ca31e4baac
Author: Michael Natterer <mitch gimp org>
Date:   Wed Sep 4 22:25:21 2019 +0200

    libgimpbase: add GimpObjectArray and GimpParamSpecObjectArray

 libgimpbase/gimpparamspecs.c | 355 +++++++++++++++++++++++++++++++++++++++++++
 libgimpbase/gimpparamspecs.h |  68 +++++++++
 2 files changed, 423 insertions(+)
---
diff --git a/libgimpbase/gimpparamspecs.c b/libgimpbase/gimpparamspecs.c
index f1daa6fee7..23a4e03768 100644
--- a/libgimpbase/gimpparamspecs.c
+++ b/libgimpbase/gimpparamspecs.c
@@ -1281,3 +1281,358 @@ gimp_value_take_rgb_array (GValue  *value,
   gimp_value_take_array (value, (guint8 *) data,
                          length * sizeof (GimpRGB));
 }
+
+
+/*
+ * GIMP_TYPE_OBJECT_ARRAY
+ */
+
+/**
+ * gimp_object_array_new:
+ * @data:        (array length=length) (transfer none): an array of objects.
+ * @length:      the length of @data.
+ * @static_data: whether the objects in @data are static objects and don't
+ *               need to be copied.
+ *
+ * Creates a new #GimpObjectArray containing object pointers, of size @length.
+ *
+ * If @static_data is %TRUE, @data is used as-is.
+ *
+ * If @static_data is %FALSE, the object and array will be re-allocated,
+ * hence you are expected to free your input data after.
+ *
+ * Returns: (transfer full): a new #GimpObjectArray.
+ */
+GimpObjectArray *
+gimp_object_array_new (GType     object_type,
+                       GObject **data,
+                       gsize     length,
+                       gboolean  static_data)
+{
+  GimpObjectArray *array;
+
+  g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
+  g_return_val_if_fail ((data == NULL && length == 0) ||
+                        (data != NULL && length  > 0), NULL);
+
+  array = g_slice_new0 (GimpObjectArray);
+
+  array->object_type = object_type;
+
+  if (! static_data && data)
+    {
+      GObject **tmp = g_new0 (GObject *, length);
+      gint      i;
+
+      for (i = 0; i < length; i++)
+        tmp[i] = g_object_ref (data[i]);
+
+      array->data = tmp;
+    }
+  else
+    {
+      array->data = data;
+    }
+
+  array->length      = length;
+  array->static_data = static_data;
+
+  return array;
+}
+
+/**
+ * gimp_object_array_copy:
+ * @array: an original #GimpObjectArray of objects.
+ *
+ * Creates a new #GimpObjectArray containing a deep copy of @array.
+ *
+ * Returns: (transfer full): a new #GimpObjectArray.
+ **/
+GimpObjectArray *
+gimp_object_array_copy (const GimpObjectArray *array)
+{
+  if (array)
+    return gimp_object_array_new (array->object_type,
+                                  array->data,
+                                  array->length, FALSE);
+
+  return NULL;
+}
+
+void
+gimp_object_array_free (GimpObjectArray *array)
+{
+  if (array)
+    {
+      if (! array->static_data)
+        {
+          GObject **tmp = array->data;
+          gint      i;
+
+          for (i = 0; i < array->length; i++)
+            g_object_unref (tmp[i]);
+
+          g_free (array->data);
+        }
+
+      g_slice_free (GimpObjectArray, array);
+    }
+}
+
+GType
+gimp_object_array_get_type (void)
+{
+  static GType type = 0;
+
+  if (! type)
+    type = g_boxed_type_register_static ("GimpObjectArray",
+                                         (GBoxedCopyFunc) gimp_object_array_copy,
+                                         (GBoxedFreeFunc) gimp_object_array_free);
+
+  return type;
+}
+
+
+/*
+ * GIMP_TYPE_PARAM_OBJECT_ARRAY
+ */
+
+static void       gimp_param_object_array_class_init  (GParamSpecClass *klass);
+static void       gimp_param_object_array_init        (GParamSpec      *pspec);
+static gboolean   gimp_param_object_array_validate    (GParamSpec      *pspec,
+                                                       GValue          *value);
+static gint       gimp_param_object_array_values_cmp  (GParamSpec      *pspec,
+                                                       const GValue    *value1,
+                                                       const GValue    *value2);
+
+GType
+gimp_param_object_array_get_type (void)
+{
+  static GType type = 0;
+
+  if (! type)
+    {
+      const GTypeInfo info =
+      {
+        sizeof (GParamSpecClass),
+        NULL, NULL,
+        (GClassInitFunc) gimp_param_object_array_class_init,
+        NULL, NULL,
+        sizeof (GimpParamSpecArray),
+        0,
+        (GInstanceInitFunc) gimp_param_object_array_init
+      };
+
+      type = g_type_register_static (G_TYPE_PARAM_BOXED,
+                                     "GimpParamObjectArray", &info, 0);
+    }
+
+  return type;
+}
+
+static void
+gimp_param_object_array_class_init (GParamSpecClass *klass)
+{
+  klass->value_type     = GIMP_TYPE_OBJECT_ARRAY;
+  klass->value_validate = gimp_param_object_array_validate;
+  klass->values_cmp     = gimp_param_object_array_values_cmp;
+}
+
+static void
+gimp_param_object_array_init (GParamSpec *pspec)
+{
+}
+
+static gboolean
+gimp_param_object_array_validate (GParamSpec *pspec,
+                                  GValue     *value)
+{
+  GimpParamSpecObjectArray *array_spec = GIMP_PARAM_SPEC_OBJECT_ARRAY (pspec);
+  GimpObjectArray          *array      = value->data[0].v_pointer;
+
+  if (array)
+    {
+      gint i;
+
+      if ((array->data == NULL && array->length != 0) ||
+          (array->data != NULL && array->length == 0))
+        {
+          g_value_set_boxed (value, NULL);
+          return TRUE;
+        }
+
+      if (! g_type_is_a (array->object_type, array_spec->object_type))
+        {
+          g_value_set_boxed (value, NULL);
+          return TRUE;
+        }
+
+      for (i = 0; i < array->length; i++)
+        {
+          if (array->data[i] && ! g_type_is_a (G_OBJECT_TYPE (array->data[i]),
+                                               array_spec->object_type))
+            {
+              g_value_set_boxed (value, NULL);
+              return TRUE;
+            }
+        }
+    }
+
+  return FALSE;
+}
+
+static gint
+gimp_param_object_array_values_cmp (GParamSpec   *pspec,
+                                    const GValue *value1,
+                                    const GValue *value2)
+{
+  GimpObjectArray *array1 = value1->data[0].v_pointer;
+  GimpObjectArray *array2 = value2->data[0].v_pointer;
+
+  /*  try to return at least *something*, it's useless anyway...  */
+
+  if (! array1)
+    return array2 != NULL ? -1 : 0;
+  else if (! array2)
+    return array1 != NULL ? 1 : 0;
+  else if (array1->length < array2->length)
+    return -1;
+  else if (array1->length > array2->length)
+    return 1;
+
+  return 0;
+}
+
+/**
+ * gimp_param_spec_object_array:
+ * @name:  Canonical name of the property specified.
+ * @nick:  Nick name of the property specified.
+ * @blurb: Description of the property specified.
+ * @flags: Flags for the property specified.
+ *
+ * Creates a new #GimpParamSpecObjectArray specifying a
+ * #GIMP_TYPE_OBJECT_ARRAY property.
+ *
+ * See g_param_spec_internal() for details on property names.
+ *
+ * Returns: (transfer full): The newly created #GimpParamSpecObjectArray.
+ *
+ * Since: 3.0
+ **/
+GParamSpec *
+gimp_param_spec_object_array (const gchar *name,
+                              const gchar *nick,
+                              const gchar *blurb,
+                              GType        object_type,
+                              GParamFlags  flags)
+{
+  GimpParamSpecObjectArray *array_spec;
+
+  g_return_val_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT), NULL);
+
+  array_spec = g_param_spec_internal (GIMP_TYPE_PARAM_OBJECT_ARRAY,
+                                      name, nick, blurb, flags);
+
+  array_spec->object_type = object_type;
+
+  return G_PARAM_SPEC (array_spec);
+}
+
+/**
+ * gimp_value_get_object_array:
+ * @value: a #GValue holding a object #GimpObjectArray.
+ *
+ * Returns: (transfer none): the internal array of objects.
+ */
+GObject **
+gimp_value_get_object_array (const GValue *value)
+{
+  GimpObjectArray *array;
+
+  g_return_val_if_fail (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value), NULL);
+
+  array = value->data[0].v_pointer;
+
+  if (array)
+    return array->data;
+
+  return NULL;
+}
+
+/**
+ * gimp_value_dup_object_array:
+ * @value: a #GValue holding a object #GimpObjectArray.
+ *
+ * Returns: (transfer full): a deep copy of the array of objects.
+ */
+GObject **
+gimp_value_dup_object_array (const GValue *value)
+{
+  GimpObjectArray *array;
+
+  g_return_val_if_fail (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value), NULL);
+
+  array = value->data[0].v_pointer;
+
+  if (array)
+    {
+      GObject **ret = g_memdup (array->data, (array->length) * sizeof (GObject *));
+      gint    i;
+
+      for (i = 0; i < array->length; i++)
+        g_object_ref (ret[i]);
+
+      return ret;
+    }
+
+  return NULL;
+}
+
+void
+gimp_value_set_object_array (GValue   *value,
+                             GType     object_type,
+                             GObject **data,
+                             gsize     length)
+{
+  GimpObjectArray *array;
+
+  g_return_if_fail (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value));
+  g_return_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT));
+
+  array = gimp_object_array_new (object_type, data, length, FALSE);
+
+  g_value_take_boxed (value, array);
+}
+
+void
+gimp_value_set_static_object_array (GValue   *value,
+                                    GType     object_type,
+                                    GObject **data,
+                                    gsize     length)
+{
+  GimpObjectArray *array;
+
+  g_return_if_fail (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value));
+  g_return_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT));
+
+  array = gimp_object_array_new (object_type, data, length, TRUE);
+
+  g_value_take_boxed (value, array);
+}
+
+void
+gimp_value_take_object_array (GValue   *value,
+                              GType     object_type,
+                              GObject **data,
+                              gsize     length)
+{
+  GimpObjectArray *array;
+
+  g_return_if_fail (GIMP_VALUE_HOLDS_OBJECT_ARRAY (value));
+  g_return_if_fail (g_type_is_a (object_type, G_TYPE_OBJECT));
+
+  array = gimp_object_array_new (object_type, data, length, TRUE);
+  array->static_data = FALSE;
+
+  g_value_take_boxed (value, array);
+}
diff --git a/libgimpbase/gimpparamspecs.h b/libgimpbase/gimpparamspecs.h
index ae12246981..6514e5ab7a 100644
--- a/libgimpbase/gimpparamspecs.h
+++ b/libgimpbase/gimpparamspecs.h
@@ -407,6 +407,74 @@ void            gimp_value_take_rgb_array       (GValue        *value,
                                                  gsize          length);
 
 
+/*
+ * GIMP_TYPE_OBJECT_ARRAY
+ */
+
+typedef struct _GimpObjectArray GimpObjectArray;
+
+struct _GimpObjectArray
+{
+  GType     object_type;
+  GObject **data;
+  gsize     length;
+  gboolean  static_data;
+};
+
+GimpObjectArray * gimp_object_array_new  (GType                  object_type,
+                                          GObject              **data,
+                                          gsize                  length,
+                                          gboolean               static_data);
+GimpObjectArray * gimp_object_array_copy (const GimpObjectArray  *array);
+void              gimp_object_array_free (GimpObjectArray        *array);
+
+#define GIMP_TYPE_OBJECT_ARRAY               (gimp_object_array_get_type ())
+#define GIMP_VALUE_HOLDS_OBJECT_ARRAY(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GIMP_TYPE_OBJECT_ARRAY))
+
+GType   gimp_object_array_get_type           (void) G_GNUC_CONST;
+
+
+/*
+ * GIMP_TYPE_PARAM_OBJECT_ARRAY
+ */
+
+#define GIMP_TYPE_PARAM_OBJECT_ARRAY           (gimp_param_object_array_get_type ())
+#define GIMP_PARAM_SPEC_OBJECT_ARRAY(pspec)    (G_TYPE_CHECK_INSTANCE_CAST ((pspec), 
GIMP_TYPE_PARAM_OBJECT_ARRAY, GimpParamSpecObjectArray))
+#define GIMP_IS_PARAM_SPEC_OBJECT_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), 
GIMP_TYPE_PARAM_OBJECT_ARRAY))
+
+typedef struct _GimpParamSpecObjectArray GimpParamSpecObjectArray;
+
+struct _GimpParamSpecObjectArray
+{
+  GParamSpecBoxed parent_instance;
+
+  GType           object_type;
+};
+
+GType         gimp_param_object_array_get_type   (void) G_GNUC_CONST;
+
+GParamSpec  * gimp_param_spec_object_array       (const gchar   *name,
+                                                  const gchar   *nick,
+                                                  const gchar   *blurb,
+                                                  GType          object_type,
+                                                  GParamFlags    flags);
+
+GObject    ** gimp_value_get_object_array        (const GValue  *value);
+GObject    ** gimp_value_dup_object_array        (const GValue  *value);
+void          gimp_value_set_object_array        (GValue        *value,
+                                                  GType          object_type,
+                                                  GObject      **array,
+                                                  gsize          length);
+void          gimp_value_set_static_object_array (GValue        *value,
+                                                  GType          object_type,
+                                                  GObject      **array,
+                                                  gsize          length);
+void          gimp_value_take_object_array       (GValue        *value,
+                                                  GType          object_type,
+                                                  GObject      **array,
+                                                  gsize          length);
+
+
 G_END_DECLS
 
 #endif  /*  __GIMP_PARAM_SPECS_H__  */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]