[glib-controller] Add iterable and iterator types



commit 8b671e53b2c3dca2708284b885200187eee3e1c5
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Wed Mar 7 16:21:29 2012 +0000

    Add iterable and iterator types

 Makefile.am                             |    4 +
 examples/simple-model.c                 |   92 +++++++--
 glib-controller/gcontrollertypes.h      |   18 ++-
 glib-controller/gcontrollerversion.h.in |    4 -
 glib-controller/giterable.c             |   41 ++++
 glib-controller/giterable.h             |   27 +++
 glib-controller/giterator.c             |  345 +++++++++++++++++++++++++++++++
 glib-controller/giterator.h             |   70 +++++++
 glib-controller/glib-controller.h       |    3 +
 9 files changed, 584 insertions(+), 20 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index a5d9886..21db805 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,6 +41,8 @@ source_c = \
 	glib-controller/gcontrollerevent.c	\
 	glib-controller/gcontroller.c 		\
 	glib-controller/ghashcontroller.c	\
+	glib-controller/giterable.c		\
+	glib-controller/giterator.c		\
 	glib-controller/gptrarraycontroller.c	\
 	$(NULL)
 
@@ -50,6 +52,8 @@ source_public_h = \
 	glib-controller/gcontrollertypes.h	\
 	glib-controller/gcontroller.h		\
 	glib-controller/ghashcontroller.h	\
+	glib-controller/giterable.h		\
+	glib-controller/giterator.h		\
 	glib-controller/gptrarraycontroller.h	\
 	$(NULL)
 
diff --git a/examples/simple-model.c b/examples/simple-model.c
index ec373a7..d2f2825 100644
--- a/examples/simple-model.c
+++ b/examples/simple-model.c
@@ -33,7 +33,24 @@ G_END_DECLS
 
 /* implementation */
 
-G_DEFINE_TYPE (MySimpleModel, my_simple_model, G_TYPE_OBJECT);
+typedef struct _MySimpleIter {
+  GIterator parent_instance;
+
+  int size;
+  int last_pos;
+} MySimpleIter;
+
+typedef struct _GIteratorClass  MySimpleIterClass;
+
+GType my_simple_iter_get_type (void) G_GNUC_CONST;
+
+static void g_iterable_iface_init (GIterableInterface *iface);
+
+G_DEFINE_TYPE (MySimpleIter, my_simple_iter, G_TYPE_ITERATOR)
+
+G_DEFINE_TYPE_WITH_CODE (MySimpleModel, my_simple_model, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ITERABLE,
+                                                g_iterable_iface_init))
 
 static void
 my_simple_model_dispose (GObject *gobject)
@@ -68,6 +85,51 @@ my_simple_model_init (MySimpleModel *model)
   model->array = array;
 }
 
+static GIterator *
+my_simple_model_create_iterator (GIterable *iterable)
+{
+  MySimpleModel *self = MY_SIMPLE_MODEL (iterable);
+  MySimpleIter *iter = g_iterator_create (my_simple_iter_get_type ());
+
+  iter->size = self->array->len;
+  iter->last_pos = -1;
+
+  return G_ITERATOR (iter);
+}
+
+static void
+g_iterable_iface_init (GIterableInterface *iface)
+{
+  iface->create_iterator = my_simple_model_create_iterator;
+}
+
+static gboolean
+my_simple_iter_next (GIterator *iter)
+{
+  MySimpleIter *self = (MySimpleIter *) iter;
+
+  if (self->last_pos + 1 < self->size)
+    {
+      self->last_pos += 1;
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static void
+my_simple_iter_class_init (MySimpleIterClass *klass)
+{
+  G_ITERATOR_CLASS (klass)->next = my_simple_iter_next;
+}
+
+static void
+my_simple_iter_init (MySimpleIter *self)
+{
+  self->last_pos = -1;
+}
+
 MySimpleModel *
 my_simple_model_new (void)
 {
@@ -251,8 +313,8 @@ int
 main (int argc, char *argv[])
 {
   MySimpleModel *model;
-  const gchar **items;
-  gint n_items, i;
+  GIterator *iter;
+  gint i;
 
   g_type_init ();
 
@@ -266,21 +328,25 @@ main (int argc, char *argv[])
   my_simple_model_add_text (model, "bar");
   my_simple_model_add_text (model, "baz");
 
-  items = my_simple_model_get_items (model);
-  n_items = my_simple_model_get_size (model);
-
+  i = 0;
   g_print ("Model contents:\n");
-  for (i = 0; i < n_items; i++)
-    g_print ("\trow[%d] = '%s'\n", i, items[i]);
+  iter = g_iterable_create_iterator (G_ITERABLE (model));
+  while (g_iterator_next (iter))
+    {
+      g_print ("\trow[%d] = '%s'\n", i, my_simple_model_get_text (model, i));
+      i += 1;
+    }
 
   my_simple_model_remove_text (model, "baz");
 
-  items = my_simple_model_get_items (model);
-  n_items = my_simple_model_get_size (model);
-
+  i = 0;
   g_print ("Model contents:\n");
-  for (i = 0; i < n_items; i++)
-    g_print ("\trow[%d] = '%s'\n", i, items[i]);
+  iter = g_iterable_create_iterator (G_ITERABLE (model));
+  while (g_iterator_next (iter))
+    {
+      g_print ("\trow[%d] = '%s'\n", i, my_simple_model_get_text (model, i));
+      i += 1;
+    }
 
   my_simple_model_clear (model);
 
diff --git a/glib-controller/gcontrollertypes.h b/glib-controller/gcontrollertypes.h
index eaabc64..6b82dff 100644
--- a/glib-controller/gcontrollertypes.h
+++ b/glib-controller/gcontrollertypes.h
@@ -9,9 +9,21 @@
 
 G_BEGIN_DECLS
 
-#define G_TYPE_CONTROLLER       (g_controller_get_type ())
-#define G_CONTROLLER(obj)       (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_CONTROLLER, GController))
-#define G_IS_CONTROLLER(obj)    (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_CONTROLLER))
+#define G_TYPE_ITERATOR                 (g_iterator_get_type ())
+#define G_ITERATOR(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ITERATOR, GIterator))
+#define G_IS_ITERATOR(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ITERATOR))
+
+typedef struct _GIterator               GIterator;
+
+#define G_TYPE_ITERABLE                 (g_iterable_get_type ())
+#define G_ITERABLE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_ITERABLE, GIterable))
+#define G_IS_ITERABLE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_ITERABLE))
+
+typedef struct _GIterable               GIterable;
+
+#define G_TYPE_CONTROLLER               (g_controller_get_type ())
+#define G_CONTROLLER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_CONTROLLER, GController))
+#define G_IS_CONTROLLER(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_CONTROLLER))
 
 /**
  * GController:
diff --git a/glib-controller/gcontrollerversion.h.in b/glib-controller/gcontrollerversion.h.in
index 15b6a9a..5267001 100644
--- a/glib-controller/gcontrollerversion.h.in
+++ b/glib-controller/gcontrollerversion.h.in
@@ -13,8 +13,4 @@
 
 #define G_CONTROLLER_VERSION_S          "@GCONTROLLER_VERSION@"
 
-#define G_CONTROLLER_VERSION_HEX        (G_CONTROLLER_MAJOR_VERSION << 24 | \
-                                         G_CONTROLLER_MINOR_VERSION << 16 | \
-                                         G_CONTROLLER_MICRO_VERSION <<  8)
-
 #endif /* __G_CONTROLLER_VERSION_H__ */
diff --git a/glib-controller/giterable.c b/glib-controller/giterable.c
new file mode 100644
index 0000000..6070df4
--- /dev/null
+++ b/glib-controller/giterable.c
@@ -0,0 +1,41 @@
+#include "config.h"
+
+#include "giterable.h"
+#include "giterator.h"
+
+G_DEFINE_INTERFACE (GIterable, g_iterable, G_TYPE_OBJECT)
+
+static GIterator *
+g_iterable_real_create_iterator (GIterable *iterable)
+{
+  GIterableInterface *iface = G_ITERABLE_GET_INTERFACE (iterable);
+
+  if (iface->iterator_type != G_TYPE_INVALID &&
+      g_type_is_a (iface->iterator_type, G_TYPE_ITERATOR))
+    return g_iterator_create (iface->iterator_type);
+
+  return NULL;
+}
+
+static void
+g_iterable_default_init (GIterableInterface *iface)
+{
+  iface->iterator_type = G_TYPE_INVALID;
+  iface->create_iterator = g_iterable_real_create_iterator;
+}
+
+/**
+ * g_iterable_create_iterator:
+ * @iterable: FIXME
+ *
+ * FIXME
+ *
+ * Return value: (transfer full): FIXME
+ */
+GIterator *
+g_iterable_create_iterator (GIterable *iterable)
+{
+  g_return_val_if_fail (G_IS_ITERABLE (iterable), NULL);
+
+  return G_ITERABLE_GET_INTERFACE (iterable)->create_iterator (iterable);
+}
diff --git a/glib-controller/giterable.h b/glib-controller/giterable.h
new file mode 100644
index 0000000..6a09573
--- /dev/null
+++ b/glib-controller/giterable.h
@@ -0,0 +1,27 @@
+#ifndef __G_ITERABLE_H__
+#define __G_ITERABLE_H__
+
+#include <glib-controller/gcontrollertypes.h>
+
+G_BEGIN_DECLS
+
+#define G_ITERABLE_GET_INTERFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_ITERABLE, GIterableInterface))
+
+typedef struct _GIterableInterface      GIterableInterface;
+
+struct _GIterableInterface
+{
+  GTypeInterface g_iface;
+
+  GType iterator_type;
+
+  GIterator *(* create_iterator) (GIterable *iterable);
+};
+
+GType g_iterable_get_type (void) G_GNUC_CONST;
+
+GIterator *     g_iterable_create_iterator      (GIterable *iterable);
+
+G_END_DECLS
+
+#endif /* __G_ITERABLE_H__ */
diff --git a/glib-controller/giterator.c b/glib-controller/giterator.c
new file mode 100644
index 0000000..3e1f8f0
--- /dev/null
+++ b/glib-controller/giterator.c
@@ -0,0 +1,345 @@
+#include "config.h"
+
+#include "giterator.h"
+
+#include <gobject/gvaluecollector.h>
+
+static void
+value_iter_init_value (GValue *value)
+{
+  value->data[0].v_pointer = NULL;
+}
+
+static void
+value_iter_free_value (GValue *value)
+{
+  if (value->data[0].v_pointer != NULL)
+    g_iterator_unref (value->data[0].v_pointer);
+}
+
+static void
+value_iter_copy_value (const GValue *src,
+                       GValue       *dst)
+{
+  if (src->data[0].v_pointer != NULL)
+    dst->data[0].v_pointer = g_iterator_ref (src->data[0].v_pointer);
+  else
+    dst->data[0].v_pointer = NULL;
+}
+
+static gpointer
+value_iter_peek_pointer (const GValue *value)
+{
+  return value->data[0].v_pointer;
+}
+
+static gchar *
+value_iter_collect_value (GValue *value,
+                          guint n_collect_values,
+                          GTypeCValue *collect_values,
+                          guint collect_flags)
+{
+  GIterator *iter;
+
+  iter = collect_values[0].v_pointer;
+
+  if (iter == NULL)
+    {
+      value->data[0].v_pointer = NULL;
+      return NULL;
+    }
+
+  if (iter->parent_instance.g_class == NULL)
+    return g_strconcat ("invalid unclassed GIterator pointer for value type '",
+                        G_VALUE_TYPE_NAME (value),
+                        "'",
+                        NULL);
+
+  value->data[0].v_pointer = g_iterator_ref (iter);
+
+  return NULL;
+}
+
+static gchar *
+value_iter_lcopy_value (const GValue *value,
+                        guint n_collect_values,
+                        GTypeCValue *collect_values,
+                        guint collect_flags)
+{
+  GIterator **iter_p = collect_values[0].v_pointer;
+
+  if (iter_p == NULL)
+    return g_strconcat ("value location for '",
+                        G_VALUE_TYPE_NAME (value),
+                        "' passed as NULL",
+                        NULL);
+
+  if (value->data[0].v_pointer == NULL)
+    *iter_p = NULL;
+  else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
+    *iter_p = value->data[0].v_pointer;
+  else
+    *iter_p = g_iterator_ref (value->data[0].v_pointer);
+
+  return NULL;
+}
+
+static const GTypeValueTable value_table = {
+  value_iter_init_value,
+  value_iter_free_value,
+  value_iter_copy_value,
+  value_iter_peek_pointer,
+  (char *) "p",
+  value_iter_collect_value,
+  (char *) "p",
+  value_iter_lcopy_value,
+};
+
+static void
+g_iterator_class_base_finalize (GIteratorClass *klass)
+{
+}
+
+static void
+g_iterator_class_base_init (GIteratorClass *klass)
+{
+}
+
+static gboolean
+g_iterator_real_next (GIterator *iterator)
+{
+  g_warning ("The iterator of type '%s' does not implement the GIterator::next virtual function",
+             g_type_name (G_TYPE_FROM_INSTANCE (iterator)));
+
+  return FALSE;
+}
+
+static void
+g_iterator_real_destroy (GIterator *iterator)
+{
+}
+
+static void
+g_iterator_class_init (GIteratorClass *klass)
+{
+  klass->next = g_iterator_real_next;
+  klass->destroy = g_iterator_real_destroy;
+}
+
+static void
+g_iterator_init (GIterator *iter)
+{
+  iter->ref_count = 1;
+}
+
+static const GTypeFundamentalInfo fundamental_info = {
+  (G_TYPE_FLAG_CLASSED |
+   G_TYPE_FLAG_INSTANTIATABLE |
+   G_TYPE_FLAG_DERIVABLE |
+   G_TYPE_FLAG_DEEP_DERIVABLE),
+};
+
+GType
+g_iterator_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      const GTypeInfo iter_info = {
+        sizeof (GIteratorClass),
+
+        (GBaseInitFunc) g_iterator_class_base_init,
+        (GBaseFinalizeFunc) g_iterator_class_base_finalize,
+        (GClassInitFunc) g_iterator_class_init,
+        (GClassFinalizeFunc) NULL,
+        NULL,
+
+        sizeof (GIterator),
+        0,
+
+        (GInstanceInitFunc) g_iterator_init,
+
+        &value_table,
+      };
+
+      GType g_define_type_id =
+        g_type_register_fundamental (g_type_fundamental_next (),
+                                     g_intern_static_string ("GIterator"),
+                                     &iter_info,
+                                     &fundamental_info,
+                                     G_TYPE_FLAG_ABSTRACT);
+
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+
+/**
+ * g_iterator_create:
+ * @iter_type: FIXME
+ *
+ * FIXME
+ *
+ * Return value: (type GIterator) (transfer full): FIXME
+ */
+gpointer
+g_iterator_create (GType iter_type)
+{
+  g_return_val_if_fail (g_type_is_a (iter_type, G_TYPE_ITERATOR), NULL);
+
+  return (gpointer) g_type_create_instance (iter_type);
+}
+
+/**
+ * g_iterator_ref:
+ * @iter: (type GIterator): FIXME
+ *
+ * FIXME
+ *
+ * Return value: (transfer none): FIXME
+ */
+gpointer
+g_iterator_ref (gpointer iter)
+{
+  GIterator *iterator = iter;
+
+  g_return_val_if_fail (G_IS_ITERATOR (iter), NULL);
+
+  g_atomic_int_inc (&iterator->ref_count);
+
+  return iter;
+}
+
+/**
+ * g_iterator_unref:
+ * @iter: FIXME
+ *
+ * FIXME
+ */
+void
+g_iterator_unref (gpointer iter)
+{
+  GIterator *iterator = iter;
+
+  g_return_if_fail (G_IS_ITERATOR (iter));
+
+  if (g_atomic_int_dec_and_test (&iterator->ref_count))
+    {
+      G_ITERATOR_GET_CLASS (iterator)->destroy (iterator);
+
+      g_type_free_instance ((GTypeInstance *) iterator);
+    }
+}
+
+/**
+ * g_iterator_next:
+ * @iter: (type GIterator): FIXME
+ *
+ * FIXME
+ *
+ * Return value: FIXME
+ */
+gboolean
+g_iterator_next (gpointer iter)
+{
+  g_return_val_if_fail (G_IS_ITERATOR (iter), FALSE);
+
+  return G_ITERATOR_GET_CLASS (iter)->next (iter);
+}
+
+/**
+ * g_value_set_iterator:
+ * @value: FIXME
+ * @iter: (type GIterator): FIXME
+ *
+ * FIXME
+ */
+void
+g_value_set_iterator (GValue *value,
+                      gpointer iter)
+{
+  GIterator *old_iter;
+
+  g_return_if_fail (G_VALUE_HOLDS_ITERATOR (value));
+
+  old_iter = value->data[0].v_pointer;
+
+  if (iter != NULL)
+    {
+      g_return_if_fail (G_IS_ITERATOR (iter));
+
+      value->data[0].v_pointer = g_iterator_ref (iter);
+    }
+  else
+    value->data[0].v_pointer = NULL;
+
+  if (old_iter != NULL)
+    g_iterator_unref (old_iter);
+}
+
+/**
+ * g_value_take_iterator:
+ * @value: FIXME
+ * @iter: (type GIterator) (transfer none): FIXME
+ *
+ * FIXME
+ */
+void
+g_value_take_iterator (GValue *value,
+                       gpointer iter)
+{
+  GIterator *old_iter;
+
+  g_return_if_fail (G_VALUE_HOLDS_ITERATOR (value));
+
+  old_iter = value->data[0].v_pointer;
+
+  if (iter != NULL)
+    {
+      g_return_if_fail (G_IS_ITERATOR (iter));
+
+      value->data[0].v_pointer = iter;
+    }
+  else
+    value->data[0].v_pointer = NULL;
+
+  if (old_iter != NULL)
+    g_iterator_unref (old_iter);
+}
+
+/**
+ * g_value_get_iterator:
+ * @value: FIXME
+ *
+ * FIXME
+ *
+ * Return value: (transfer none): FIXME
+ */
+gpointer
+g_value_get_iterator (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS_ITERATOR (value), NULL);
+
+  return value->data[0].v_pointer;
+}
+
+/**
+ * g_value_dup_iterator:
+ * @value: FIXME
+ *
+ * FIXME
+ *
+ * Return value: (type GIterator) (transfer full): FIXME
+ */
+gpointer
+g_value_dup_iterator (const GValue *value)
+{
+  g_return_val_if_fail (G_VALUE_HOLDS_ITERATOR (value), NULL);
+
+  if (value->data[0].v_pointer != NULL)
+    return g_iterator_ref (value->data[0].v_pointer);
+
+  return NULL;
+}
diff --git a/glib-controller/giterator.h b/glib-controller/giterator.h
new file mode 100644
index 0000000..a4b1e72
--- /dev/null
+++ b/glib-controller/giterator.h
@@ -0,0 +1,70 @@
+#ifndef __G_ITERATOR_H__
+#define __G_ITERATOR_H__
+
+#include <glib-controller/gcontrollertypes.h>
+
+G_BEGIN_DECLS
+
+#define G_ITERATOR_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), G_TYPE_ITERATOR, GIteratorClass))
+#define G_IS_ITERATOR_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), G_TYPE_ITERATOR))
+#define G_ITERATOR_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_ITERATOR, GIteratorClass))
+
+typedef struct _GIteratorClass          GIteratorClass;
+
+/**
+ * GIterator:
+ *
+ * Ref Func: g_iterator_ref
+ * Unref Func: g_iterator_unref
+ * Set Value Func: g_value_set_iterator
+ * Get Value Func: g_value_get_iterator
+ */
+struct _GIterator
+{
+  /*< private >*/
+  GTypeInstance parent_instance;
+
+  volatile int ref_count;
+};
+
+/**
+ * GIteratorClass:
+ * @next:
+ * @destroy:
+ *
+ */
+struct _GIteratorClass
+{
+  /*< private >*/
+  GTypeClass parent_class;
+
+  /*< public >*/
+  gboolean (* next) (GIterator *iter);
+
+  void (* destroy) (GIterator *iter);
+
+  /*< private >*/
+  gpointer _padding[2];
+};
+
+GType g_iterator_get_type (void) G_GNUC_CONST;
+
+gpointer        g_iterator_create       (GType      iter_type);
+
+gpointer        g_iterator_ref          (gpointer   iter);
+void            g_iterator_unref        (gpointer   iter);
+
+gboolean        g_iterator_next         (gpointer   iter);
+
+#define G_VALUE_HOLDS_ITERATOR(v)       (G_VALUE_HOLDS (v, G_TYPE_ITERATOR))
+
+void            g_value_set_iterator    (GValue       *value,
+                                         gpointer      iter);
+void            g_value_take_iterator   (GValue       *value,
+                                         gpointer      iter);
+gpointer        g_value_get_iterator    (const GValue *value);
+gpointer        g_value_dup_iterator    (const GValue *value);
+
+G_END_DECLS
+
+#endif /* __G_ITERATOR_H__ */
diff --git a/glib-controller/glib-controller.h b/glib-controller/glib-controller.h
index 9eba4b1..59e9fdc 100644
--- a/glib-controller/glib-controller.h
+++ b/glib-controller/glib-controller.h
@@ -7,6 +7,9 @@
 #include "gcontrollerevent.h"
 #include "gcontroller.h"
 
+#include "giterable.h"
+#include "giterator.h"
+
 #include "garraycontroller.h"
 #include "ghashcontroller.h"
 #include "gptrarraycontroller.h"



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