diff -r 000000000000 -r d0f3a028347a loudmouth/src/lm-parser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/loudmouth/src/lm-parser.c Tue Feb 02 01:10:06 2010 +0200 @@ -0,0 +1,284 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Imendio 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 +#include + +#include + +#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_verbose ("[parser_start_node_cb]: 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 (strcmp ("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);*/ + lm_verbose ("[parser_end_node_cb]:Trying to close node: %s\n", node_name); + if (!parser->cur_node) { + /* FIXME: LM-1 should look at this */ + return; + } + + if (strcmp (parser->cur_node->name, node_name) != 0) { + if (strcmp (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");*/ + lm_verbose("[parser_end_node_cb]: 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; + + lm_message_node_unref (tmp_node); + } + UNUSED_FORMAL_PARAM(context); + UNUSED_FORMAL_PARAM(error); +} + +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); + } + UNUSED_FORMAL_PARAM(context); + UNUSED_FORMAL_PARAM(error); + UNUSED_FORMAL_PARAM(text_len); +} + +static void +parser_error_cb (GMarkupParseContext *context, + GError *error, + gpointer user_data) +{ + g_return_if_fail (user_data != NULL); + g_return_if_fail (error != NULL); + + g_warning ("Parsing failed: %s\n", error->message); + UNUSED_FORMAL_PARAM(context); +} + +EXPORT_C 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; +} + +EXPORT_C 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_markup_parse_context_parse (parser->context, string, + (gssize)strlen (string), NULL)) { + } else { + g_markup_parse_context_free (parser->context); + parser->context = NULL; + } +} + +EXPORT_C void +lm_parser_free (LmParser *parser) +{ + if (parser->notify) { + (* parser->notify) (parser->user_data); + } + + if (parser->context) { + g_markup_parse_context_free (parser->context); + } + g_free (parser->m_parser); + g_free (parser); +} +