summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2010-10-08 15:24:34 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2010-10-08 15:24:34 +0100
commite214e31e95f68c7088950daaa6acc39f2eaa1173 (patch)
tree4754e1df33802085c6d0cdebbc2141f6457f6473 /lib
parent2dfe5319d5a3603a450717a271a59f8b575e0588 (diff)
downloadtelepathy-salut-e214e31e95f68c7088950daaa6acc39f2eaa1173.tar.gz
Implement GibberXmppReader in terms of WockyXmppReader
It has a different programming model (it emits signals rather than just having a stanza queue) so instead of being the same, it's a subclass.
Diffstat (limited to 'lib')
-rw-r--r--lib/gibber/gibber-xmpp-reader.c376
-rw-r--r--lib/gibber/gibber-xmpp-reader.h6
2 files changed, 59 insertions, 323 deletions
diff --git a/lib/gibber/gibber-xmpp-reader.c b/lib/gibber/gibber-xmpp-reader.c
index 096958bd..a21dd017 100644
--- a/lib/gibber/gibber-xmpp-reader.c
+++ b/lib/gibber/gibber-xmpp-reader.c
@@ -18,14 +18,8 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libxml/parser.h>
-
#include "gibber-xmpp-reader.h"
+
#include "gibber-signals-marshal.h"
#include "gibber-xmpp-stanza.h"
@@ -35,7 +29,7 @@
#define DEBUG_FLAG DEBUG_XMPP_READER
#include "gibber-debug.h"
-G_DEFINE_TYPE (GibberXmppReader, gibber_xmpp_reader, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GibberXmppReader, gibber_xmpp_reader, WOCKY_TYPE_XMPP_READER)
/* signal enum */
enum {
@@ -47,104 +41,34 @@ enum {
static guint signals[LAST_SIGNAL] = {0};
-/* Parser prototypes */
-static void _start_element_ns (void *user_data,
- const xmlChar *localname, const xmlChar *prefix, const xmlChar *uri,
- int nb_namespaces, const xmlChar **namespaces, int nb_attributes,
- int nb_defaulted, const xmlChar **attributes);
-
-static void _end_element_ns (void *user_data, const xmlChar *localname,
- const xmlChar *prefix, const xmlChar *URI);
-
-static void _characters (void *user_data, const xmlChar *ch, int len);
-
-static void _error (void *user_data, xmlErrorPtr error);
-
-static xmlSAXHandler parser_handler = {
- .initialized = XML_SAX2_MAGIC,
- .startElementNs = _start_element_ns,
- .endElementNs = _end_element_ns,
- .characters = _characters,
- .serror = _error,
-};
-
-typedef enum {
- STATE_STREAM_CLOSE,
- STATE_STREAM_OPENED,
- STATE_STREAM_OPEN,
- STATE_STREAM_CLOSED,
-} StreamState;
-
/* private structure */
typedef struct _GibberXmppReaderPrivate GibberXmppReaderPrivate;
struct _GibberXmppReaderPrivate
{
- xmlParserCtxtPtr parser;
- guint depth;
- GibberXmppStanza *stanza;
- GibberXmppNode *node;
- GQueue *nodes;
- gchar *to;
- gchar *from;
- gchar *version;
- gboolean dispose_has_run;
- gboolean error;
- gboolean stream_mode;
- GQueue *stanzas;
- StreamState state;
+ gboolean emitted_opened;
+ gboolean emitted_closed;
};
#define GIBBER_XMPP_READER_GET_PRIVATE(o) \
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GIBBER_TYPE_XMPP_READER, \
GibberXmppReaderPrivate))
-
-static void
-gibber_init_xml_parser (GibberXmppReader *obj)
-{
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (obj);
-
- if (priv->parser != NULL)
- xmlFreeParserCtxt (priv->parser);
-
- priv->parser = xmlCreatePushParserCtxt (&parser_handler, obj, NULL, 0, NULL);
- xmlCtxtUseOptions (priv->parser, XML_PARSE_NOENT);
- priv->depth = 0;
- priv->state = STATE_STREAM_CLOSE;
-}
-
static void
gibber_xmpp_reader_init (GibberXmppReader *obj)
{
GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (obj);
- /* allocate any data required by the object here */
- gibber_init_xml_parser (obj);
-
- priv->stanza = NULL;
- priv->nodes = g_queue_new ();
- priv->node = NULL;
- priv->error = FALSE;
- priv->stream_mode = TRUE;
- priv->stanzas = g_queue_new ();
- priv->state = STATE_STREAM_CLOSE;
+ priv->emitted_opened = FALSE;
+ priv->emitted_closed = FALSE;
}
-static void gibber_xmpp_reader_dispose (GObject *object);
-static void gibber_xmpp_reader_finalize (GObject *object);
-
static void
gibber_xmpp_reader_class_init (GibberXmppReaderClass *gibber_xmpp_reader_class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (gibber_xmpp_reader_class);
-
g_type_class_add_private (gibber_xmpp_reader_class,
sizeof (GibberXmppReaderPrivate));
- object_class->dispose = gibber_xmpp_reader_dispose;
- object_class->finalize = gibber_xmpp_reader_finalize;
-
signals[RECEIVED_STANZA] = g_signal_new ("received-stanza",
G_OBJECT_CLASS_TYPE(gibber_xmpp_reader_class),
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
@@ -170,282 +94,94 @@ gibber_xmpp_reader_class_init (GibberXmppReaderClass *gibber_xmpp_reader_class)
G_TYPE_NONE, 0);
}
-void
-gibber_xmpp_reader_dispose (GObject *object)
-{
- GibberXmppReader *self = GIBBER_XMPP_READER (object);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
-
- if (priv->dispose_has_run)
- return;
-
- priv->dispose_has_run = TRUE;
-
- /* release any references held by the object here */
- while (!g_queue_is_empty (priv->stanzas)) {
- gpointer stanza;
- stanza = g_queue_pop_head (priv->stanzas);
- g_object_unref (stanza);
- }
-
- if (G_OBJECT_CLASS (gibber_xmpp_reader_parent_class)->dispose)
- G_OBJECT_CLASS (gibber_xmpp_reader_parent_class)->dispose (object);
-}
-
-void
-gibber_xmpp_reader_finalize (GObject *object)
-{
- GibberXmppReader *self = GIBBER_XMPP_READER (object);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
-
- /* free any data held directly by the object here */
- if (priv->parser != NULL) {
- xmlFreeParserCtxt (priv->parser);
- priv->parser = NULL;
- }
- g_queue_free (priv->stanzas);
- g_queue_free (priv->nodes);
- g_free (priv->to);
- g_free (priv->from);
- g_free (priv->version);
-
- G_OBJECT_CLASS (gibber_xmpp_reader_parent_class)->finalize (object);
-}
-
-
GibberXmppReader *
gibber_xmpp_reader_new (void)
{
- return g_object_new (GIBBER_TYPE_XMPP_READER, NULL);
+ return g_object_new (GIBBER_TYPE_XMPP_READER,
+ NULL);
}
GibberXmppReader *
gibber_xmpp_reader_new_no_stream (void)
{
- GibberXmppReader *result = g_object_new (GIBBER_TYPE_XMPP_READER, NULL);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (result);
-
- priv->stream_mode = FALSE;
-
- return result;
+ return g_object_new (GIBBER_TYPE_XMPP_READER,
+ "streaming-mode", FALSE,
+ NULL);
}
-static void
-_start_element_ns (void *user_data, const xmlChar *localname,
- const xmlChar *prefix, const xmlChar *uri, int nb_namespaces,
- const xmlChar **namespaces, int nb_attributes, int nb_defaulted,
- const xmlChar **attributes)
+gboolean
+gibber_xmpp_reader_push (GibberXmppReader *reader, const guint8 *data,
+ gsize length, GError **error)
{
- GibberXmppReader *self = GIBBER_XMPP_READER (user_data);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
- int i;
+ WockyXmppReader *wocky = WOCKY_XMPP_READER (reader);
+ GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (reader);
+ WockyStanza *stanza;
+ GError *e = NULL;
+ gboolean streaming_mode;
- if (prefix)
- {
- DEBUG ("Element %s:%s started, depth %d", prefix, localname,
- priv->depth);
- }
- else
- {
- DEBUG ("Element %s started, depth %d", localname, priv->depth);
- }
+ g_return_val_if_fail (wocky_xmpp_reader_get_state (wocky) !=
+ WOCKY_XMPP_READER_STATE_ERROR, FALSE);
- if (priv->stream_mode && G_UNLIKELY (priv->depth == 0))
- {
- if (strcmp ("stream", (gchar *) localname)
- || strcmp (XMPP_STREAM_NAMESPACE, (gchar *) uri))
- {
- priv->error = TRUE;
- return;
- }
- priv->state = STATE_STREAM_OPENED;
-
- for (i = 0; i < nb_attributes * 5; i+=5)
- {
- if (!strcmp ((gchar *) attributes[i], "to"))
- {
- g_free (priv->to);
- priv->to = g_strndup ((gchar *) attributes[i+3],
- (gsize) (attributes[i+4] - attributes[i+3]));
- }
-
- if (!strcmp ((gchar *) attributes[i], "from"))
- {
- g_free (priv->from);
- priv->from = g_strndup ((gchar *) attributes[i+3],
- (gsize) (attributes[i+4] - attributes[i+3]));
- }
-
- if (!strcmp ((gchar *) attributes[i], "version"))
- {
- g_free (priv->version);
- priv->version = g_strndup ((gchar *) attributes[i+3],
- (gsize) (attributes[i+4] - attributes[i+3]));
- }
- }
- priv->depth++;
- return;
- }
+ g_object_get (wocky,
+ "streaming-mode", &streaming_mode,
+ NULL);
- if (priv->stanza == NULL)
- {
- if (uri != NULL)
- {
- priv->stanza = wocky_stanza_new ((gchar *) localname, (gchar *) uri);
- }
- else
- {
- /* This can only happy in non-streaming mode when the top node
- * of the document doesn't have a namespace. */
- DEBUG ("Stanza without a namespace, using dummy namespace..");
- priv->stanza = wocky_stanza_new ((gchar *) localname, (gchar *) "");
- }
-
- priv->node = wocky_stanza_get_top_node (priv->stanza);
- }
- else
- {
- g_queue_push_tail (priv->nodes, priv->node);
- priv->node = gibber_xmpp_node_add_child_ns (priv->node,
- (gchar *) localname, (gchar *) uri);
- }
+ wocky_xmpp_reader_push (wocky, data, length);
- for (i = 0; i < nb_attributes * 5; i+=5)
+ if (wocky_xmpp_reader_get_state (wocky) == WOCKY_XMPP_READER_STATE_OPENED
+ && !priv->emitted_opened)
{
- /* Node is localname, prefix, uri, valuestart, valueend */
- if (attributes[i+1] != NULL && !strcmp ((gchar *) attributes[i+1], "xml")
- && !strcmp ((gchar *) attributes[i], "lang"))
- {
- gibber_xmpp_node_set_language_n (priv->node,
- (gchar *) attributes[i+3],
- (gsize) (attributes[i+4] - attributes[i+3]));
- }
- else
- {
- gibber_xmpp_node_set_attribute_n_ns (priv->node,
- (gchar *) attributes[i], (gchar *) attributes[i+3],
- (gsize)(attributes[i+4] - attributes[i+3]),
- (gchar *) attributes[i+2]);
- }
- }
- priv->depth++;
-}
+ gchar *from = NULL, *to = NULL, *version = NULL;
-static void
-_characters (void *user_data, const xmlChar *ch, int len)
-{
- GibberXmppReader *self = GIBBER_XMPP_READER (user_data);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
+ g_object_get (wocky,
+ "from", &from,
+ "to", &to,
+ "version", &version,
+ NULL);
- if (priv->node != NULL)
- {
- gibber_xmpp_node_append_content_n (priv->node, (const gchar *)ch,
- (gsize)len);
+ priv->emitted_opened = TRUE;
+ g_signal_emit (reader, signals[STREAM_OPENED], 0, to, from, version);
+ g_free (to);
+ g_free (from);
+ g_free (version);
}
-}
-static void
-_end_element_ns (void *user_data, const xmlChar *localname,
- const xmlChar *prefix, const xmlChar *uri)
-{
- GibberXmppReader *self = GIBBER_XMPP_READER (user_data);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
-
- priv->depth--;
-
- if (prefix)
- {
- DEBUG ("Element %s:%s ended, depth %d", prefix, localname, priv->depth);
- }
- else
+ for (stanza = wocky_xmpp_reader_pop_stanza (wocky);
+ stanza != NULL;
+ stanza = wocky_xmpp_reader_pop_stanza (wocky))
{
- DEBUG ("Element %s ended, depth %d", localname, priv->depth);
+ g_signal_emit (reader, signals[RECEIVED_STANZA], 0, stanza);
+ g_object_unref (stanza);
}
- if (priv->node && priv->node->content)
+ if (wocky_xmpp_reader_get_state (wocky) == WOCKY_XMPP_READER_STATE_CLOSED
+ && !priv->emitted_closed)
{
- /* Remove content if it's purely whitespace */
- const char *c;
- for (c = priv->node->content; *c != '\0' && g_ascii_isspace (*c); c++)
- ;
- if (*c == '\0')
- gibber_xmpp_node_set_content (priv->node, NULL);
+ priv->emitted_closed = TRUE;
+ g_signal_emit (reader, signals[STREAM_CLOSED], 0);
}
- if (priv->stream_mode && priv->depth == 0)
- {
- priv->state = STATE_STREAM_CLOSED;
- }
- else if (priv->depth == (priv->stream_mode ? 1 : 0))
+ if (!streaming_mode)
{
- g_assert (g_queue_get_length (priv->nodes) == 0);
- DEBUG ("Received stanza");
- g_queue_push_tail (priv->stanzas, priv->stanza);
- priv->stanza = NULL;
- priv->node = NULL;
+ wocky_xmpp_reader_reset (wocky);
}
- else
- {
- priv->node = (GibberXmppNode *) g_queue_pop_tail (priv->nodes);
- }
-}
-
-static void
-_error (void *user_data, xmlErrorPtr error)
-{
- GibberXmppReader *self = GIBBER_XMPP_READER (user_data);
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (self);
- priv->error = TRUE;
-
- DEBUG ("Parsing failed %s", error->message);
-}
-
-gboolean
-gibber_xmpp_reader_push (GibberXmppReader *reader, const guint8 *data,
- gsize length, GError **error)
-{
- GibberXmppReaderPrivate *priv = GIBBER_XMPP_READER_GET_PRIVATE (reader);
- xmlParserCtxtPtr parser;
-
- g_assert (!priv->error);
- DEBUG ("Parsing chunk: %.*s", (int)length, data);
-
- parser = priv->parser;
- xmlParseChunk (parser, (const char*)data, length, FALSE);
- if (priv->state == STATE_STREAM_OPENED)
- {
- priv->state = STATE_STREAM_OPEN;
- g_signal_emit (reader, signals[STREAM_OPENED], 0,
- priv->to, priv->from, priv->version);
- }
+ e = wocky_xmpp_reader_get_error (wocky);
- while (!g_queue_is_empty (priv->stanzas))
+ if (e == NULL)
{
- gpointer stanza;
- stanza = g_queue_pop_head (priv->stanzas);
- g_signal_emit (reader, signals[RECEIVED_STANZA], 0, stanza);
- g_object_unref (stanza);
+ return TRUE;
}
-
- if (priv->state == STATE_STREAM_CLOSED)
+ else
{
- priv->state = STATE_STREAM_CLOSE;
- g_signal_emit (reader, signals[STREAM_CLOSED], 0);
+ g_propagate_error (error, e);
+ return FALSE;
}
-
- if (!priv->stream_mode)
- {
- gibber_init_xml_parser (reader);
- }
-
- return !priv->error;
}
void
gibber_xmpp_reader_reset (GibberXmppReader *reader)
{
- DEBUG ("Resetting xmpp reader");
- gibber_init_xml_parser (reader);
+ wocky_xmpp_reader_reset (WOCKY_XMPP_READER (reader));
}
diff --git a/lib/gibber/gibber-xmpp-reader.h b/lib/gibber/gibber-xmpp-reader.h
index 89853e6f..fc6a91d4 100644
--- a/lib/gibber/gibber-xmpp-reader.h
+++ b/lib/gibber/gibber-xmpp-reader.h
@@ -22,6 +22,7 @@
#define __GIBBER_XMPP_READER_H__
#include <glib-object.h>
+#include <wocky/wocky-xmpp-reader.h>
G_BEGIN_DECLS
@@ -29,11 +30,11 @@ typedef struct _GibberXmppReader GibberXmppReader;
typedef struct _GibberXmppReaderClass GibberXmppReaderClass;
struct _GibberXmppReaderClass {
- GObjectClass parent_class;
+ WockyXmppReaderClass parent_class;
};
struct _GibberXmppReader {
- GObject parent;
+ WockyXmppReader parent;
};
GType gibber_xmpp_reader_get_type (void);
@@ -55,7 +56,6 @@ GType gibber_xmpp_reader_get_type (void);
(G_TYPE_INSTANCE_GET_CLASS ((obj), GIBBER_TYPE_XMPP_READER, \
GibberXmppReaderClass))
-
GibberXmppReader * gibber_xmpp_reader_new (void);
GibberXmppReader * gibber_xmpp_reader_new_no_stream (void);
void gibber_xmpp_reader_reset (GibberXmppReader *reader);