loudmouth/lm-parser.c
changeset 1 50e230cf7818
child 3 5c632650c603
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loudmouth/lm-parser.c	Mon May 19 18:27:00 2003 +0000
@@ -0,0 +1,288 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2003 Mikael Hallendal <micke@codefactory.se>
+ * Copyright (C) 2003 CodeFactory AB. 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include <config.h>
+#include <string.h>
+
+#include "lm-debug.h"
+#include "lm-internals.h"
+#include "lm-message-node.h"
+#include "lm-parser.h"
+
+#define SHORT_END_TAG "/>"
+#define XML_MAX_DEPTH 5
+
+#define LM_PARSER(o) ((LmParser *) o)
+
+struct LmParser {
+	LmParserMessageFunction  function;
+	gpointer                 user_data;
+	GDestroyNotify           notify;
+	
+	LmMessageNode           *cur_root;
+	LmMessageNode           *cur_node;
+		
+	GMarkupParser           *m_parser;
+	GMarkupParseContext     *context;
+};
+
+
+/* Used while parsing */
+static void    parser_start_node_cb (GMarkupParseContext  *context,
+				     const gchar          *node_name,
+				     const gchar         **attribute_names,
+				     const gchar         **attribute_values,
+				     gpointer              user_data,
+				     GError              **error);
+static void    parser_end_node_cb   (GMarkupParseContext  *context,
+				     const gchar          *node_name,
+				     gpointer              user_data,
+				     GError              **error);
+static void    parser_text_cb       (GMarkupParseContext  *context,
+				     const gchar          *text,
+				     gsize                 text_len,  
+				     gpointer              user_data,
+				     GError              **error);
+static void    parser_error_cb      (GMarkupParseContext  *context,
+				     GError               *error,
+				     gpointer              user_data);
+
+static void
+parser_start_node_cb (GMarkupParseContext  *context,
+		      const gchar          *node_name,
+		      const gchar         **attribute_names,
+		      const gchar         **attribute_values,
+		      gpointer              user_data,
+		      GError              **error)
+{	
+	LmParser     *parser;
+	gint          i;
+	
+	parser = LM_PARSER (user_data);;
+	
+
+/* 	parser->cur_depth++; */
+
+	if (!parser->cur_root) {
+		/* New toplevel element */
+		parser->cur_root = _lm_message_node_new (node_name);
+		parser->cur_node = parser->cur_root;
+	} else {
+		LmMessageNode *parent_node;
+		
+		parent_node = parser->cur_node;
+		
+		parser->cur_node = _lm_message_node_new (node_name);
+		_lm_message_node_add_child_node (parent_node,
+						 parser->cur_node);
+	}
+
+	for (i = 0; attribute_names[i]; ++i) {
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER, 
+		       "ATTRIBUTE: %s = %s\n", 
+		       attribute_names[i],
+		       attribute_values[i]);
+		
+		lm_message_node_set_attributes (parser->cur_node,
+						attribute_names[i],
+						attribute_values[i], 
+						NULL);
+	}
+	
+	if (g_ascii_strcasecmp ("stream:stream", node_name) == 0) {
+		parser_end_node_cb (context,
+				    "stream:stream",
+				    user_data, 
+				    error);
+	}
+}
+
+static void
+parser_end_node_cb (GMarkupParseContext  *context,
+		    const gchar          *node_name,
+		    gpointer              user_data,
+		    GError              **error)
+{
+	LmParser     *parser;
+	
+	parser = LM_PARSER (user_data);
+	
+	g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER,
+	       "Trying to close node: %s\n", node_name);
+
+	if (g_ascii_strcasecmp (parser->cur_node->name, node_name) != 0) {
+		if (g_ascii_strcasecmp (node_name, "stream:stream")) {
+			g_print ("Got an stream:stream end\n");
+		}
+		g_warning ("Trying to close node that isn't open: %s",
+			   node_name);
+		return;
+	}
+
+	if (parser->cur_node == parser->cur_root) {
+		LmMessage *m;
+		
+		m = _lm_message_new_from_node (parser->cur_root);
+
+		if (!m) {
+			g_warning ("Couldn't create message: %s\n",
+				   parser->cur_root->name);
+			return;
+		}
+
+		g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER,
+		       "Have a new message\n");
+		if (parser->function) {
+			(* parser->function) (parser, m, parser->user_data);
+		}
+
+		lm_message_unref (m);
+ 		lm_message_node_unref (parser->cur_root);
+		
+		parser->cur_node = parser->cur_root = NULL;
+	} else {
+		LmMessageNode *tmp_node;
+		tmp_node = parser->cur_node;
+		parser->cur_node = parser->cur_node->parent;
+	}
+}
+
+static void
+parser_text_cb (GMarkupParseContext   *context,
+		const gchar           *text,
+		gsize                  text_len,  
+		gpointer               user_data,
+		GError               **error)
+{
+	LmParser *parser;
+	
+	g_return_if_fail (user_data != NULL);
+	
+	parser = LM_PARSER (user_data);
+	
+	if (parser->cur_node && strcmp (text, "") != 0) {
+		lm_message_node_set_value (parser->cur_node, text);
+	} 
+}
+
+static void
+parser_error_cb (GMarkupParseContext *context,
+		 GError              *error,
+		 gpointer             user_data)
+{
+	LmParser     *parser;
+	
+	g_return_if_fail (user_data != NULL);
+	
+	parser = LM_PARSER (user_data);
+
+	g_markup_parse_context_free (parser->context);
+	parser->context = NULL;
+}
+
+LmParser *
+lm_parser_new (LmParserMessageFunction function, 
+	       gpointer                user_data, 
+	       GDestroyNotify          notify)
+{
+	LmParser *parser;
+	
+	parser = g_new0 (LmParser, 1);
+	if (!parser) {
+		return NULL;
+	}
+	
+	parser->m_parser                = g_new0 (GMarkupParser, 1);
+	if (!parser->m_parser) {
+		g_free (parser);
+		return NULL;
+	}
+
+	parser->function  = function;
+	parser->user_data = user_data;
+	parser->notify    = notify;
+	
+	parser->m_parser->start_element = parser_start_node_cb;
+	parser->m_parser->end_element   = parser_end_node_cb;
+	parser->m_parser->text          = parser_text_cb;
+	parser->m_parser->error         = parser_error_cb;
+
+	parser->context = g_markup_parse_context_new (parser->m_parser, 0,
+						    parser, NULL);
+
+	parser->cur_root = NULL;
+	parser->cur_node = NULL;
+
+	return parser;
+}
+
+void
+lm_parser_parse (LmParser *parser, const gchar *string)
+{
+	g_return_if_fail (parser != NULL);
+	
+	if (!parser->context) {
+		parser->context = g_markup_parse_context_new (parser->m_parser, 0,
+							      parser, NULL);
+	}
+
+	if (!g_utf8_validate (string, -1, NULL)) {
+		gchar *tmp;
+		
+		/* We can't do much better than guess what charset the string is
+		 * encoded in... Try ISO-8859-1.
+		 */
+		tmp = g_convert (string, -1,
+				 "UTF-8", "ISO-8859-1",
+				 NULL, NULL,
+				 NULL);
+		
+		if (tmp) {
+			if (g_markup_parse_context_parse (parser->context, tmp, 
+							  strlen (tmp), NULL)) {
+			} else {
+				g_warning ("Parsing failed\n");
+			}
+			
+			g_free (tmp);
+		} else {
+			g_warning ("Trying to parse a string that is not UTF-8 and not ISO-8859-1.");
+		}
+	} else {
+		if (g_markup_parse_context_parse (parser->context, string, 
+						  strlen (string), NULL)) {
+		} else {
+			g_warning ("Parsing failed\n");
+		}
+	}
+}
+
+void
+lm_parser_free (LmParser *parser)
+{
+	if (parser->notify) {
+		(* parser->notify) (parser->user_data);
+	}
+	
+	g_free (parser);
+	g_print ("Free parser\n");
+}
+