[glib-controller] Add iterable and iterator types
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-controller] Add iterable and iterator types
- Date: Wed, 7 Mar 2012 16:23:51 +0000 (UTC)
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]