diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-06-17 17:22:21 +0200 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-06-17 17:22:21 +0200 |
commit | 6751167f52d9056d6ac9770323658f4904db3afd (patch) | |
tree | 67140893c207ddf9a5e834beb030b11a8c1663eb | |
parent | d4dfc2f4546a837824b872ad05b67531a795bd8d (diff) | |
download | experiment-player-6751167f52d9056d6ac9770323658f4904db3afd.tar.gz |
use closure objects internally in libexperiment-reader instead of plain C callbacks
* has the advantage that it will be easier to port libexperiment-reader to other languages (by using its closures and marshallers)
-rw-r--r-- | lib/experiment-reader/Makefile.am | 14 | ||||
-rw-r--r-- | lib/experiment-reader/cclosure-marshallers.list | 2 | ||||
-rw-r--r-- | lib/experiment-reader/experiment-reader.c | 81 | ||||
-rw-r--r-- | lib/experiment-reader/experiment-reader.h | 1 |
4 files changed, 84 insertions, 14 deletions
diff --git a/lib/experiment-reader/Makefile.am b/lib/experiment-reader/Makefile.am index fc06aac..dc2c231 100644 --- a/lib/experiment-reader/Makefile.am +++ b/lib/experiment-reader/Makefile.am @@ -4,8 +4,11 @@ SUBDIRS = . tests reader_datadir = @datarootdir@/libexperiment-reader +BUILT_SOURCES = cclosure-marshallers.c cclosure-marshallers.h + lib_LTLIBRARIES = libexperiment-reader.la libexperiment_reader_la_SOURCES = experiment-reader.c experiment-reader.h +nodist_libexperiment_reader_la_SOURCES = $(BUILT_SOURCES) libexperiment_reader_la_CFLAGS = $(AM_CFLAGS) libexperiment_reader_la_CPPFLAGS = @@ -21,3 +24,14 @@ libexperiment_reader_la_LIBADD += @LIBXML2_LIBS@ include_HEADERS = experiment-reader.h dist_reader_data_DATA = session.dtd + +dist_noinst_DATA = cclosure-marshallers.list +CLEANFILES = $(BUILT_SOURCES) + +MARSHAL_PREFIX = experiment_reader_marshal + +cclosure-marshallers.c : cclosure-marshallers.list + @GLIB_GENMARSHAL@ --prefix $(MARSHAL_PREFIX) --body $< >$@ + +cclosure-marshallers.h : cclosure-marshallers.list + @GLIB_GENMARSHAL@ --prefix $(MARSHAL_PREFIX) --header $< >$@ diff --git a/lib/experiment-reader/cclosure-marshallers.list b/lib/experiment-reader/cclosure-marshallers.list new file mode 100644 index 0000000..70ffabb --- /dev/null +++ b/lib/experiment-reader/cclosure-marshallers.list @@ -0,0 +1,2 @@ +# ExperimentReaderTopicCallback marshaller +VOID:STRING,INT64,INT64 diff --git a/lib/experiment-reader/experiment-reader.c b/lib/experiment-reader/experiment-reader.c index aca1d97..6384adc 100644 --- a/lib/experiment-reader/experiment-reader.c +++ b/lib/experiment-reader/experiment-reader.c @@ -28,6 +28,7 @@ #include <string.h> #include <assert.h> +#include <glib-object.h> #include <glib.h> #include <glib/gprintf.h> @@ -36,6 +37,7 @@ #include <libxml/xpath.h> #include <libxml/xpathInternals.h> +#include "cclosure-marshallers.h" #include "experiment-reader.h" static void experiment_reader_class_init(ExperimentReaderClass *klass); @@ -46,9 +48,15 @@ static gint64 get_timepoint_by_ref(xmlDoc *doc, xmlChar *ref); static xmlNode *get_first_element(xmlNode *children, const gchar *name); static xmlNode *get_last_element(xmlNode *children, const gchar *name); +static GClosure *experiment_reader_topic_callback_new(ExperimentReaderTopicCallback, + gpointer); +static void experiment_reader_topic_callback_invoke(ExperimentReader *reader, + GClosure *closure, + const gchar *topic_id, + gint64 start_time, + gint64 end_time); static gboolean generic_foreach_topic(ExperimentReader *reader, xmlNodeSet *nodes, - ExperimentReaderTopicCallback callback, - gpointer data); + GClosure *closure); static gint experiment_reader_contrib_cmp(const ExperimentReaderContrib *a, const ExperimentReaderContrib *b); @@ -161,9 +169,47 @@ get_last_element(xmlNode *children, const gchar *name) return ret; } +static GClosure * +experiment_reader_topic_callback_new(ExperimentReaderTopicCallback callback, + gpointer data) +{ + GClosure *closure = g_cclosure_new(G_CALLBACK(callback), data, NULL); + + g_closure_set_marshal(closure, + experiment_reader_marshal_VOID__STRING_INT64_INT64); + g_closure_ref(closure); + g_closure_sink(closure); + + return closure; +} + +static void +experiment_reader_topic_callback_invoke(ExperimentReader *reader, + GClosure *closure, + const gchar *topic_id, + gint64 start_time, gint64 end_time) +{ + GValue params[4]; + + memset(params, 0, sizeof(params)); + g_value_init(params + 0, G_TYPE_OBJECT); + g_value_set_object(params + 0, reader); + g_value_init(params + 1, G_TYPE_STRING); + g_value_set_string(params + 1, topic_id); + g_value_init(params + 2, G_TYPE_INT64); + g_value_set_int64(params + 2, start_time); + g_value_init(params + 3, G_TYPE_INT64); + g_value_set_int64(params + 3, end_time); + + g_closure_invoke(closure, NULL, G_N_ELEMENTS(params), params, NULL); + + for (gint i = 0; i < G_N_ELEMENTS(params); i++) + g_value_unset(params + i); +} + static gboolean generic_foreach_topic(ExperimentReader *reader, xmlNodeSet *nodes, - ExperimentReaderTopicCallback callback, gpointer data) + GClosure *closure) { if (nodes == NULL) return TRUE; @@ -200,8 +246,9 @@ generic_foreach_topic(ExperimentReader *reader, xmlNodeSet *nodes, xmlFree(contrib_end_ref); } - callback(reader, (const gchar *)topic_id, - start_time, end_time, data); + experiment_reader_topic_callback_invoke(reader, closure, + (const gchar *)topic_id, + start_time, end_time); xmlFree(topic_id); } @@ -444,13 +491,15 @@ experiment_reader_foreach_greeting_topic(ExperimentReader *reader, { xmlXPathContext *xpathCtx; xmlXPathObject *xpathObj; + GClosure *closure; xpathCtx = xmlXPathNewContext(reader->priv->doc); xpathObj = xmlXPathEvalExpression(XML_CHAR("/session/greeting/topic"), xpathCtx); - generic_foreach_topic(reader, xpathObj->nodesetval, - callback, userdata); + closure = experiment_reader_topic_callback_new(callback, userdata); + generic_foreach_topic(reader, xpathObj->nodesetval, closure); + g_closure_unref(closure); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); @@ -473,14 +522,16 @@ experiment_reader_foreach_exp_initial_narrative_topic(reader, callback, userdata { xmlXPathContext *xpathCtx; xmlXPathObject *xpathObj; + GClosure *closure; xpathCtx = xmlXPathNewContext(reader->priv->doc); xpathObj = xmlXPathEvalExpression(XML_CHAR("/session/experiment/" "initial-narrative/topic"), xpathCtx); - generic_foreach_topic(reader, xpathObj->nodesetval, - callback, userdata); + closure = experiment_reader_topic_callback_new(callback, userdata); + generic_foreach_topic(reader, xpathObj->nodesetval, closure); + g_closure_unref(closure); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); @@ -505,6 +556,7 @@ experiment_reader_foreach_exp_last_minute_phase_topic(reader, phase, callback, u { xmlXPathContext *xpathCtx; xmlXPathObject *xpathObj; + GClosure *closure; xmlChar expr[255]; @@ -517,8 +569,9 @@ experiment_reader_foreach_exp_last_minute_phase_topic(reader, phase, callback, u phase); xpathObj = xmlXPathEvalExpression(expr, xpathCtx); - generic_foreach_topic(reader, xpathObj->nodesetval, - callback, userdata); + closure = experiment_reader_topic_callback_new(callback, userdata); + generic_foreach_topic(reader, xpathObj->nodesetval, closure); + g_closure_unref(closure); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); @@ -539,13 +592,15 @@ experiment_reader_foreach_farewell_topic(ExperimentReader *reader, { xmlXPathContext *xpathCtx; xmlXPathObject *xpathObj; + GClosure *closure; xpathCtx = xmlXPathNewContext(reader->priv->doc); xpathObj = xmlXPathEvalExpression(XML_CHAR("/session/farewell/topic"), xpathCtx); - generic_foreach_topic(reader, xpathObj->nodesetval, - callback, userdata); + closure = experiment_reader_topic_callback_new(callback, userdata); + generic_foreach_topic(reader, xpathObj->nodesetval, closure); + g_closure_unref(closure); xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); diff --git a/lib/experiment-reader/experiment-reader.h b/lib/experiment-reader/experiment-reader.h index 6df8b77..ae2fc95 100644 --- a/lib/experiment-reader/experiment-reader.h +++ b/lib/experiment-reader/experiment-reader.h @@ -81,7 +81,6 @@ GType experiment_reader_get_type(void); * @param end_time End of last \b contribution in \e topic (milliseconds) * @param data Callback user data */ -/** @todo Perhaps we should use CClosures */ typedef void (*ExperimentReaderTopicCallback)(ExperimentReader *reader, const gchar *topic_id, gint64 start_time, |