[yelp/yelp-3-0] [yelp-transform] Adding yelp-transform to libyelp
- From: Shaun McCance <shaunm src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [yelp/yelp-3-0] [yelp-transform] Adding yelp-transform to libyelp
- Date: Mon, 12 Oct 2009 21:48:16 +0000 (UTC)
commit 3a382a0027a627ebd76ed3449df872c73e1874f3
Author: Shaun McCance <shaunm gnome org>
Date: Mon Oct 12 16:45:37 2009 -0500
[yelp-transform] Adding yelp-transform to libyelp
I've changed YelpTransform to be a GObject. This changes considerably the
way we track references to the object to make sure we don't nuke it while
there's still a pending idle function or a running thread.
libyelp/Makefile.am | 2 +
libyelp/yelp-error.h | 3 +-
libyelp/yelp-transform.c | 485 +++++++++++++++++++++++++++++++++++++++
libyelp/yelp-transform.h | 73 ++++++
src/yelp-transform.c | 468 -------------------------------------
src/yelp-transform.h | 86 -------
tests/Makefile.am | 5 +
{src => tests}/test-transform.c | 104 +++++----
8 files changed, 630 insertions(+), 596 deletions(-)
---
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index 89298d6..6599cfd 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -6,12 +6,14 @@ libyelp_la_SOURCES = \
yelp-location-entry.c \
yelp-settings.c \
yelp-simple-document.c \
+ yelp-transform.c \
yelp-uri.c \
yelp-types.c \
yelp-view.c
libyelp_la_CFLAGS = \
$(YELP_CFLAGS) \
+ -DDATADIR=\""$(datadir)"\" \
-DGDU_ICON_PATH=\"$(GDU_ICON_PATH)\"
libyelp_la_LIBADD = \
diff --git a/libyelp/yelp-error.h b/libyelp/yelp-error.h
index 78fbf3d..103f87e 100644
--- a/libyelp/yelp-error.h
+++ b/libyelp/yelp-error.h
@@ -31,7 +31,8 @@ G_BEGIN_DECLS
typedef enum {
YELP_ERROR_NOT_FOUND,
- YELP_ERROR_CANT_READ
+ YELP_ERROR_CANT_READ,
+ YELP_ERROR_PROCESSING
} YelpError;
G_END_DECLS
diff --git a/libyelp/yelp-transform.c b/libyelp/yelp-transform.c
new file mode 100644
index 0000000..919b08a
--- /dev/null
+++ b/libyelp/yelp-transform.c
@@ -0,0 +1,485 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm gnome org>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/xinclude.h>
+#include <libxml/xpathInternals.h>
+#include <libxslt/documents.h>
+#include <libxslt/xslt.h>
+#include <libexslt/exslt.h>
+#include <libxslt/templates.h>
+#include <libxslt/transform.h>
+#include <libxslt/extensions.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/xsltutils.h>
+
+#include "yelp-debug.h"
+#include "yelp-error.h"
+#include "yelp-transform.h"
+
+#define YELP_NAMESPACE "http://www.gnome.org/yelp/ns"
+
+static void yelp_transform_init (YelpTransform *transform);
+static void yelp_transform_class_init (YelpTransformClass *klass);
+static void yelp_transform_dispose (GObject *object);
+static void yelp_transform_finalize (GObject *object);
+
+static void transform_run (YelpTransform *transform);
+static gboolean transform_free (YelpTransform *transform);
+static void transform_set_error (YelpTransform *transform,
+ YelpError *error);
+
+static gboolean transform_chunk (YelpTransform *transform);
+static gboolean transform_error (YelpTransform *transform);
+static gboolean transform_final (YelpTransform *transform);
+
+static void xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+static void xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp);
+static void xslt_yelp_aux (xmlXPathParserContextPtr ctxt,
+ int nargs);
+
+enum {
+ CHUNK_READY,
+ FINISHED,
+ ERROR,
+ LAST_SIGNAL
+};
+static gint signals[LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (YelpTransform, yelp_transform, G_TYPE_OBJECT);
+#define GET_PRIV(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), YELP_TYPE_TRANSFORM, YelpTransformPrivate))
+
+typedef struct _YelpTransformPrivate YelpTransformPrivate;
+struct _YelpTransformPrivate {
+ xmlDocPtr input;
+ xmlDocPtr output;
+ xsltStylesheetPtr stylesheet;
+ xsltTransformContextPtr context;
+
+ xmlDocPtr aux;
+ xsltDocumentPtr aux_xslt;
+
+ gchar **params;
+
+ GThread *thread;
+ GMutex *mutex;
+ GAsyncQueue *queue;
+ GHashTable *chunks;
+
+ gboolean running;
+ gboolean cancelled;
+
+ GError *error;
+
+ /* FIXME: remove
+ YelpTransformFunc func;
+ gpointer user_data;
+ */
+};
+
+/******************************************************************************/
+
+static void
+yelp_transform_init (YelpTransform *transform)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ priv->queue = g_async_queue_new ();
+ priv->chunks = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ NULL);
+}
+
+static void
+yelp_transform_class_init (YelpTransformClass *klass)
+{
+ exsltRegisterAll ();
+
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = yelp_transform_dispose;
+ object_class->finalize = yelp_transform_finalize;
+
+ signals[CHUNK_READY] = g_signal_new ("chunk-ready",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+ signals[FINISHED] = g_signal_new ("finished",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[ERROR] = g_signal_new ("error",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_type_class_add_private (klass, sizeof (YelpTransformPrivate));
+}
+
+static void
+yelp_transform_dispose (GObject *object)
+{
+ YelpTransformPrivate *priv = GET_PRIV (object);
+
+ if (priv->queue) {
+ gchar *chunk_id;
+ while ((chunk_id = (gchar *) g_async_queue_try_pop (priv->queue)))
+ g_free (chunk_id);
+ g_async_queue_unref (priv->queue);
+ priv->queue = NULL;
+ }
+
+ /* FIXME */
+ GHashTable *chunks;
+}
+
+static void
+yelp_transform_finalize (GObject *object)
+{
+ YelpTransformPrivate *priv = GET_PRIV (object);
+ /* We do not free input or aux. They belong to the caller, which
+ must ensure they exist for the lifetime of the transform.
+ */
+ if (priv->output)
+ xmlFreeDoc (priv->output);
+ if (priv->stylesheet)
+ xsltFreeStylesheet (priv->stylesheet);
+ if (priv->context)
+ xsltFreeTransformContext (priv->context);
+ if (priv->aux_xslt)
+ priv->aux_xslt->doc = NULL;
+ if (priv->error)
+ g_error_free (priv->error);
+
+ g_strfreev (priv->params);
+ g_mutex_free (priv->mutex);
+}
+
+/******************************************************************************/
+
+YelpTransform *
+yelp_transform_new ()
+{
+ return (YelpTransform *) g_object_new (YELP_TYPE_TRANSFORM, NULL);
+}
+
+gboolean
+yelp_transform_set_stylesheet (YelpTransform *transform,
+ const gchar *stylesheet,
+ GError **error)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+
+ priv->stylesheet = xsltParseStylesheetFile (BAD_CAST stylesheet);
+ if (priv->stylesheet == NULL) {
+ if (error)
+ g_set_error(error, YELP_ERROR, YELP_ERROR_PROCESSING,
+ _("The XSLT stylesheet â??%sâ?? is either missing or not valid."),
+ stylesheet);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void
+yelp_transform_set_aux (YelpTransform *transform,
+ xmlDocPtr aux)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ priv->aux = aux;
+}
+
+gboolean
+yelp_transform_start (YelpTransform *transform,
+ xmlDocPtr document,
+ const gchar * const *params,
+ GError **error)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+
+ priv->input = document;
+
+ priv->context = xsltNewTransformContext (priv->stylesheet,
+ priv->input);
+ if (priv->context == NULL) {
+ if (error)
+ g_set_error (error, YELP_ERROR, YELP_ERROR_PROCESSING,
+ _("The XSLT stylesheet could not be compiled."));
+ return FALSE;
+ }
+
+ priv->params = g_strdupv ((gchar **) params);
+
+ priv->context->_private = transform;
+ xsltRegisterExtElement (priv->context,
+ BAD_CAST "document",
+ BAD_CAST YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_document);
+ xsltRegisterExtElement (priv->context,
+ BAD_CAST "cache",
+ BAD_CAST YELP_NAMESPACE,
+ (xsltTransformFunction) xslt_yelp_cache);
+ xsltRegisterExtFunction (priv->context,
+ BAD_CAST "aux",
+ BAD_CAST YELP_NAMESPACE,
+ (xmlXPathFunction) xslt_yelp_aux);
+
+ priv->mutex = g_mutex_new ();
+ g_mutex_lock (priv->mutex);
+ priv->running = TRUE;
+ g_object_ref (transform);
+ priv->thread = g_thread_create ((GThreadFunc) transform_run,
+ transform, FALSE, NULL);
+ g_mutex_unlock (priv->mutex);
+
+ return TRUE;
+}
+
+gchar *
+yelp_transform_take_chunk (YelpTransform *transform,
+ const gchar *chunk_id)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ gchar *buf;
+
+ g_mutex_lock (priv->mutex);
+
+ buf = g_hash_table_lookup (priv->chunks, chunk_id);
+ if (buf)
+ g_hash_table_remove (priv->chunks, chunk_id);
+
+ g_mutex_unlock (priv->mutex);
+
+ /* The caller assumes ownership of this memory. */
+ return buf;
+}
+
+void
+yelp_transform_cancel (YelpTransform *transform)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ g_mutex_lock (priv->mutex);
+ if (priv->running) {
+ priv->cancelled = TRUE;
+ priv->context->state = XSLT_STATE_STOPPED;
+ }
+ g_mutex_unlock (priv->mutex);
+}
+
+/******************************************************************************/
+
+static void
+transform_run (YelpTransform *transform)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ priv->output = xsltApplyStylesheetUser (priv->stylesheet,
+ priv->input,
+ (const char **) priv->params,
+ NULL, NULL,
+ priv->context);
+ g_mutex_lock (priv->mutex);
+ priv->running = FALSE;
+ if (!priv->cancelled) {
+ g_idle_add ((GSourceFunc) transform_final, transform);
+ }
+ else {
+ g_object_unref (transform);
+ }
+ g_mutex_unlock (priv->mutex);
+}
+
+static gboolean
+transform_chunk (YelpTransform *transform)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+ gchar *chunk_id;
+
+ if (priv->cancelled)
+ goto done;
+
+ chunk_id = (gchar *) g_async_queue_try_pop (priv->queue);
+
+ g_signal_emit (transform, signals[CHUNK_READY], 0, chunk_id);
+
+ g_free (chunk_id);
+
+ done:
+ g_object_unref (transform);
+ return FALSE;
+}
+
+static gboolean
+transform_final (YelpTransform *transform)
+{
+ YelpTransformPrivate *priv = GET_PRIV (transform);
+
+ if (priv->cancelled)
+ goto done;
+
+ g_signal_emit (transform, signals[FINISHED], 0);
+
+ done:
+ g_object_unref (transform);
+ return FALSE;
+}
+
+/******************************************************************************/
+
+static void
+xslt_yelp_document (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+ YelpTransform *transform;
+ YelpTransformPrivate *priv;
+ xmlChar *page_id = NULL;
+ gchar *temp;
+ xmlChar *page_buf;
+ gint buf_size;
+ xsltStylesheetPtr style = NULL;
+ const char *old_outfile;
+ xmlDocPtr new_doc = NULL;
+ xmlDocPtr old_doc;
+ xmlNodePtr old_insert;
+
+ debug_print (DB_FUNCTION, "entering\n");
+
+ if (ctxt->state == XSLT_STATE_STOPPED)
+ return;
+
+ if (!ctxt || !node || !inst || !comp)
+ return;
+
+ transform = YELP_TRANSFORM (ctxt->_private);
+ priv = GET_PRIV (transform);
+
+ page_id = xsltEvalAttrValueTemplate (ctxt, inst,
+ (const xmlChar *) "href",
+ NULL);
+ if (page_id == NULL || *page_id == '\0') {
+ if (page_id)
+ xmlFree (page_id);
+ else
+ xsltTransformError (ctxt, NULL, inst,
+ _("No href attribute found on "
+ "yelp:document\n"));
+ /* FIXME: put a real error here */
+ goto done;
+ }
+ debug_print (DB_ARG, " page_id = \"%s\"\n", page_id);
+
+ old_outfile = ctxt->outputFile;
+ old_doc = ctxt->output;
+ old_insert = ctxt->insert;
+ ctxt->outputFile = (const char *) page_id;
+
+ style = xsltNewStylesheet ();
+ if (style == NULL) {
+ xsltTransformError (ctxt, NULL, inst,
+ _("Out of memory"));
+ goto done;
+ }
+
+ style->omitXmlDeclaration = TRUE;
+
+ new_doc = xmlNewDoc (BAD_CAST "1.0");
+ new_doc->charset = XML_CHAR_ENCODING_UTF8;
+ new_doc->dict = ctxt->dict;
+ xmlDictReference (new_doc->dict);
+
+ ctxt->output = new_doc;
+ ctxt->insert = (xmlNodePtr) new_doc;
+
+ xsltApplyOneTemplate (ctxt, node, inst->children, NULL, NULL);
+ xsltSaveResultToString (&page_buf, &buf_size, new_doc, style);
+
+ ctxt->outputFile = old_outfile;
+ ctxt->output = old_doc;
+ ctxt->insert = old_insert;
+
+ g_mutex_lock (priv->mutex);
+
+ temp = g_strdup ((gchar *) page_id);
+ xmlFree (page_id);
+
+ g_async_queue_push (priv->queue, g_strdup ((gchar *) temp));
+ g_hash_table_insert (priv->chunks, temp, page_buf);
+
+ g_object_ref (transform);
+ g_idle_add ((GSourceFunc) transform_chunk, transform);
+
+ g_mutex_unlock (priv->mutex);
+
+ done:
+ if (new_doc)
+ xmlFreeDoc (new_doc);
+ if (style)
+ xsltFreeStylesheet (style);
+}
+
+static void
+xslt_yelp_cache (xsltTransformContextPtr ctxt,
+ xmlNodePtr node,
+ xmlNodePtr inst,
+ xsltStylePreCompPtr comp)
+{
+}
+
+static void
+xslt_yelp_aux (xmlXPathParserContextPtr ctxt, int nargs)
+{
+ xsltTransformContextPtr tctxt;
+ xmlXPathObjectPtr ret;
+ YelpTransform *transform;
+ YelpTransformPrivate *priv;
+
+ tctxt = xsltXPathGetTransformContext (ctxt);
+ transform = YELP_TRANSFORM (tctxt->_private);
+ priv = GET_PRIV (transform);
+
+ /* FIXME: pretty sure this eats transform->aux, memory corruption will follow */
+ priv->aux_xslt = xsltNewDocument (tctxt, priv->aux);
+
+ ret = xmlXPathNewNodeSet (xmlDocGetRootElement (priv->aux));
+ xsltExtensionInstructionResultRegister (tctxt, ret);
+ valuePush (ctxt, ret);
+}
diff --git a/libyelp/yelp-transform.h b/libyelp/yelp-transform.h
new file mode 100644
index 0000000..3c738bf
--- /dev/null
+++ b/libyelp/yelp-transform.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Copyright (C) 2003-2007 Shaun McCance <shaunm gnome org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Shaun McCance <shaunm gnome org>
+ */
+
+#ifndef __YELP_TRANSFORM_H__
+#define __YELP_TRANSFORM_H__
+
+#include <glib.h>
+#include <libxml/tree.h>
+#include <libxslt/xslt.h>
+#include <libxslt/transform.h>
+
+/*
+typedef enum {
+ YELP_TRANSFORM_CHUNK,
+ YELP_TRANSFORM_ERROR,
+ YELP_TRANSFORM_FINAL
+} YelpTransformSignal;
+
+typedef void (*YelpTransformFunc) (YelpTransform *transform,
+ YelpTransformSignal signal,
+ gpointer func_data,
+ gpointer user_data);
+*/
+
+#define YELP_TYPE_TRANSFORM (yelp_transform_get_type ())
+#define YELP_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), YELP_TYPE_TRANSFORM, YelpTransform))
+#define YELP_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), YELP_TYPE_TRANSFORM, YelpTransformClass))
+#define YELP_IS_TRANSFORM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), YELP_TYPE_TRANSFORM))
+#define YELP_IS_TRANSFORM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), YELP_TYPE_TRANSFORM))
+
+typedef struct _YelpTransform YelpTransform;
+typedef struct _YelpTransformClass YelpTransformClass;
+struct _YelpTransform {
+ GObject parent;
+};
+struct _YelpTransformClass {
+ GObjectClass parent_class;
+};
+
+YelpTransform * yelp_transform_new (void);
+gboolean yelp_transform_set_stylesheet (YelpTransform *transform,
+ const gchar *stylesheet,
+ GError **error);
+void yelp_transform_set_aux (YelpTransform *transform,
+ xmlDocPtr aux);
+gboolean yelp_transform_start (YelpTransform *transform,
+ xmlDocPtr document,
+ const gchar * const *params,
+ GError **error);
+gchar * yelp_transform_take_chunk (YelpTransform *transform,
+ const gchar *chunk_id);
+void yelp_transform_cancel (YelpTransform *transform);
+
+#endif /* __YELP_TRANSFORM_H__ */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 14d53e2..d305e34 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,6 +2,7 @@ YELP_COMMON_CFLAGS = \
$(YELP_CFLAGS) \
$(AM_CFLAGS) \
$(YELP_DEFINES) \
+ -DDATADIR=\""$(datadir)"\" \
-I$(top_srcdir)/libyelp
YELP_COMMON_LDADD = \
$(YELP_LIBS) \
@@ -10,6 +11,7 @@ YELP_COMMON_LDADD = \
check_PROGRAMS = \
test-location-entry \
test-settings \
+ test-transform \
test-uri \
test-view
@@ -19,6 +21,9 @@ test_location_entry_LDADD = $(YELP_COMMON_LDADD)
test_settings_CFLAGS = $(YELP_COMMON_CFLAGS)
test_settings_LDADD = $(YELP_COMMON_LDADD)
+test_transform_CFLAGS = $(YELP_COMMON_CFLAGS)
+test_transform_LDADD = $(YELP_COMMON_LDADD)
+
test_uri_CFLAGS = $(YELP_COMMON_CFLAGS)
test_uri_LDADD = $(YELP_COMMON_LDADD)
diff --git a/src/test-transform.c b/tests/test-transform.c
similarity index 67%
rename from src/test-transform.c
rename to tests/test-transform.c
index ae659be..efda9b8 100644
--- a/src/test-transform.c
+++ b/tests/test-transform.c
@@ -19,6 +19,8 @@
* Author: Shaun McCance <shaunm gnome org>
*/
+#include <config.h>
+
#include <glib.h>
#include <libxml/parser.h>
#include <libxml/xinclude.h>
@@ -26,6 +28,9 @@
#include "yelp-error.h"
#include "yelp-transform.h"
+static gint num_chunks = 0;
+static gboolean freed;
+
static gint timeout = -1;
static gboolean random_timeout = FALSE;
static gchar **files = NULL;
@@ -46,51 +51,60 @@ static const GOptionEntry options[] = {
GMainLoop *loop;
-static void
+static gboolean
transform_release (YelpTransform *transform)
{
printf ("\nRELEASE\n");
- yelp_transform_release (transform);
- /* Quit after pending things are done. This helps test
- * whether YelpTransform takes its release seriously.
- */
- g_idle_add ((GSourceFunc) g_main_loop_quit, loop);
+ if (!freed) {
+ yelp_transform_cancel (transform);
+ g_object_unref (transform);
+ }
+ freed = TRUE;
+ return FALSE;
}
static void
-transform_func (YelpTransform *transform,
- YelpTransformSignal signal,
- gpointer *func_data,
- gpointer user_data)
+transform_chunk (YelpTransform *transform,
+ const gchar *chunk_id,
+ gpointer user_data)
{
- gchar *chunk_id;
- gchar *chunk_data;
- gchar *chunk_short;
- YelpError *error;
-
- switch (signal) {
- case YELP_TRANSFORM_CHUNK:
- chunk_id = (gchar *) func_data;
- printf ("\nCHUNK: %s\n", chunk_id);
-
- chunk_data = yelp_transform_eat_chunk (transform, chunk_id);
- chunk_short = g_strndup (chunk_data, 300);
- printf ("%s\n", chunk_short);
-
- g_free (chunk_short);
- g_free (chunk_data);
- g_free (chunk_id);
- break;
- case YELP_TRANSFORM_ERROR:
- error = (YelpError *) func_data;
- printf ("\nERROR: %s\n", yelp_error_get_title (error));
- yelp_error_free (error);
- break;
- case YELP_TRANSFORM_FINAL:
- printf ("\nFINAL\n");
- transform_release (transform);
- break;
+ gchar *chunk, *small;
+ num_chunks++;
+ printf ("\nCHUNK %i: %s\n", num_chunks, chunk_id);
+
+ chunk = yelp_transform_take_chunk (transform, chunk_id);
+ small = g_strndup (chunk, 300);
+ printf ("%s\n", small);
+
+ g_free (small);
+ g_free (chunk);
+}
+
+static void
+transform_finished (YelpTransform *transform,
+ gpointer user_data)
+{
+ printf ("\nFINAL\n");
+ if (!freed) {
+ yelp_transform_cancel (transform);
+ g_object_unref (transform);
}
+ freed = TRUE;
+}
+
+static void
+transform_error (YelpTransform *transform,
+ gpointer user_data)
+{
+ printf ("\nERROR\n");
+}
+
+static void
+transform_destroyed (gpointer data,
+ GObject *object)
+{
+ printf ("\nFREED\n");
+ g_main_loop_quit (loop);
}
gint
@@ -104,6 +118,7 @@ main (gint argc, gchar **argv)
gchar *stylesheet;
gchar *file;
+ g_type_init ();
g_thread_init (NULL);
context = g_option_context_new ("[STYLESHEET] FILE");
@@ -132,9 +147,15 @@ main (gint argc, gchar **argv)
params[5] = "2";
params[6] = NULL;
- transform = yelp_transform_new (stylesheet,
- (YelpTransformFunc) transform_func,
- NULL);
+ transform = yelp_transform_new ();
+ g_object_weak_ref ((GObject *) transform, transform_destroyed, NULL);
+ if (!yelp_transform_set_stylesheet (transform, stylesheet, NULL))
+ return 1;
+
+ g_signal_connect (transform, "chunk-ready", (GCallback) transform_chunk, NULL);
+ g_signal_connect (transform, "finished", (GCallback) transform_finished, NULL);
+ g_signal_connect (transform, "error", (GCallback) transform_error, NULL);
+
parser = xmlNewParserCtxt ();
doc = xmlCtxtReadFile (parser,
file,
@@ -145,7 +166,8 @@ main (gint argc, gchar **argv)
xmlXIncludeProcessFlags (doc,
XML_PARSE_DTDLOAD | XML_PARSE_NOCDATA |
XML_PARSE_NOENT | XML_PARSE_NONET );
- yelp_transform_start (transform, doc, params);
+ if (!yelp_transform_start (transform, doc, params, NULL))
+ return 1;
if (random_timeout) {
GRand *rand = g_rand_new ();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]