loudmouth/src/lm-parser.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
       
     2 /*
       
     3  * Copyright (C) 2003 Imendio AB
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public License as
       
     7  * published by the Free Software Foundation; either version 2 of the
       
     8  * License, or (at your option) any later version.
       
     9  *
       
    10  * This program is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  *
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this program; if not, write to the
       
    17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    18  * Boston, MA 02111-1307, USA.
       
    19  */
       
    20 
       
    21 #include <config.h>
       
    22 #include <string.h>
       
    23 
       
    24 #include <glib.h>
       
    25 
       
    26 #include "lm-debug.h"
       
    27 #include "lm-internals.h"
       
    28 #include "lm-message-node.h"
       
    29 #include "lm-parser.h"
       
    30 
       
    31 #define SHORT_END_TAG "/>"
       
    32 #define XML_MAX_DEPTH 5
       
    33 
       
    34 #define LM_PARSER(o) ((LmParser *) o)
       
    35 
       
    36 struct LmParser {
       
    37 	LmParserMessageFunction  function;
       
    38 	gpointer                 user_data;
       
    39 	GDestroyNotify           notify;
       
    40 	
       
    41 	LmMessageNode           *cur_root;
       
    42 	LmMessageNode           *cur_node;
       
    43 		
       
    44 	GMarkupParser           *m_parser;
       
    45 	GMarkupParseContext     *context;
       
    46 };
       
    47 
       
    48 
       
    49 /* Used while parsing */
       
    50 static void    parser_start_node_cb (GMarkupParseContext  *context,
       
    51 				     const gchar          *node_name,
       
    52 				     const gchar         **attribute_names,
       
    53 				     const gchar         **attribute_values,
       
    54 				     gpointer              user_data,
       
    55 				     GError              **error);
       
    56 static void    parser_end_node_cb   (GMarkupParseContext  *context,
       
    57 				     const gchar          *node_name,
       
    58 				     gpointer              user_data,
       
    59 				     GError              **error);
       
    60 static void    parser_text_cb       (GMarkupParseContext  *context,
       
    61 				     const gchar          *text,
       
    62 				     gsize                 text_len,  
       
    63 				     gpointer              user_data,
       
    64 				     GError              **error);
       
    65 static void    parser_error_cb      (GMarkupParseContext  *context,
       
    66 				     GError               *error,
       
    67 				     gpointer              user_data);
       
    68 
       
    69 static void
       
    70 parser_start_node_cb (GMarkupParseContext  *context,
       
    71 		      const gchar          *node_name,
       
    72 		      const gchar         **attribute_names,
       
    73 		      const gchar         **attribute_values,
       
    74 		      gpointer              user_data,
       
    75 		      GError              **error)
       
    76 {	
       
    77 	LmParser     *parser;
       
    78 	gint          i;
       
    79 	
       
    80 	parser = LM_PARSER (user_data);;
       
    81 	
       
    82 
       
    83 /* 	parser->cur_depth++; */
       
    84 
       
    85 	if (!parser->cur_root) {
       
    86 		/* New toplevel element */
       
    87 		parser->cur_root = _lm_message_node_new (node_name);
       
    88 		parser->cur_node = parser->cur_root;
       
    89 	} else {
       
    90 		LmMessageNode *parent_node;
       
    91 		
       
    92 		parent_node = parser->cur_node;
       
    93 		
       
    94 		parser->cur_node = _lm_message_node_new (node_name);
       
    95 		_lm_message_node_add_child_node (parent_node,
       
    96 						 parser->cur_node);
       
    97 	}
       
    98 
       
    99 	for (i = 0; attribute_names[i]; ++i) {
       
   100 		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER, 
       
   101 		       "ATTRIBUTE: %s = %s\n", 
       
   102 		       attribute_names[i],
       
   103 		       attribute_values[i]);*/
       
   104 		
       
   105 		lm_verbose ("[parser_start_node_cb]: ATTRIBUTE: %s = %s\n", 
       
   106 		       attribute_names[i],
       
   107 		       attribute_values[i]);
       
   108 		
       
   109 		lm_message_node_set_attributes (parser->cur_node,
       
   110 						attribute_names[i],
       
   111 						attribute_values[i], 
       
   112 						NULL);
       
   113 	}
       
   114 	
       
   115 	if (strcmp ("stream:stream", node_name) == 0) {
       
   116 		parser_end_node_cb (context,
       
   117 				    "stream:stream",
       
   118 				    user_data, 
       
   119 				    error);
       
   120 	}
       
   121 }
       
   122 
       
   123 static void
       
   124 parser_end_node_cb (GMarkupParseContext  *context,
       
   125 		    const gchar          *node_name,
       
   126 		    gpointer              user_data,
       
   127 		    GError              **error)
       
   128 {
       
   129 	LmParser     *parser;
       
   130 	
       
   131 	parser = LM_PARSER (user_data);
       
   132 	
       
   133 	/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER,
       
   134 	       "Trying to close node: %s\n", node_name);*/
       
   135     lm_verbose ("[parser_end_node_cb]:Trying to close node: %s\n", node_name);
       
   136     if (!parser->cur_node) {
       
   137                 /* FIXME: LM-1 should look at this */
       
   138                 return;
       
   139         }
       
   140         
       
   141 	if (strcmp (parser->cur_node->name, node_name) != 0) {
       
   142 		if (strcmp (node_name, "stream:stream")) {
       
   143 			g_print ("Got an stream:stream end\n");
       
   144 		}
       
   145 		g_warning ("Trying to close node that isn't open: %s",
       
   146 			   node_name);
       
   147 		return;
       
   148 	}
       
   149 
       
   150 	if (parser->cur_node == parser->cur_root) {
       
   151 		LmMessage *m;
       
   152 		
       
   153 		m = _lm_message_new_from_node (parser->cur_root);
       
   154 
       
   155 		if (!m) {
       
   156 			g_warning ("Couldn't create message: %s\n",
       
   157 				   parser->cur_root->name);
       
   158 			return;
       
   159 		}
       
   160 
       
   161 		/*g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_PARSER,
       
   162 		       "Have a new message\n");*/
       
   163 		lm_verbose("[parser_end_node_cb]: Have a new message\n");
       
   164 		if (parser->function) {
       
   165 			(* parser->function) (parser, m, parser->user_data);
       
   166 		}
       
   167 
       
   168 		lm_message_unref (m);
       
   169 		lm_message_node_unref (parser->cur_root);
       
   170 		
       
   171 			
       
   172 		parser->cur_node = parser->cur_root = NULL;
       
   173 	} else {
       
   174 		LmMessageNode *tmp_node;
       
   175 		tmp_node = parser->cur_node;
       
   176 		parser->cur_node = parser->cur_node->parent;
       
   177 
       
   178 		lm_message_node_unref (tmp_node);
       
   179 	}
       
   180 	UNUSED_FORMAL_PARAM(context);
       
   181 	UNUSED_FORMAL_PARAM(error);
       
   182 }
       
   183 
       
   184 static void
       
   185 parser_text_cb (GMarkupParseContext   *context,
       
   186 		const gchar           *text,
       
   187 		gsize                  text_len,  
       
   188 		gpointer               user_data,
       
   189 		GError               **error)
       
   190 {
       
   191 	LmParser *parser;
       
   192 	
       
   193 	g_return_if_fail (user_data != NULL);
       
   194 	
       
   195 	parser = LM_PARSER (user_data);
       
   196 	
       
   197 	if (parser->cur_node && strcmp (text, "") != 0) {
       
   198 		lm_message_node_set_value (parser->cur_node, text);
       
   199 	} 
       
   200 	UNUSED_FORMAL_PARAM(context);
       
   201 	UNUSED_FORMAL_PARAM(error);
       
   202 	UNUSED_FORMAL_PARAM(text_len);
       
   203 }
       
   204 
       
   205 static void
       
   206 parser_error_cb (GMarkupParseContext *context,
       
   207 		 GError              *error,
       
   208 		 gpointer             user_data)
       
   209 {
       
   210 	g_return_if_fail (user_data != NULL);
       
   211 	g_return_if_fail (error != NULL);
       
   212 	
       
   213 	g_warning ("Parsing failed: %s\n", error->message);
       
   214 	UNUSED_FORMAL_PARAM(context);
       
   215 }
       
   216 
       
   217 EXPORT_C LmParser *
       
   218 lm_parser_new (LmParserMessageFunction function, 
       
   219 	       gpointer                user_data, 
       
   220 	       GDestroyNotify          notify)
       
   221 {
       
   222 	LmParser *parser;
       
   223 	
       
   224 	parser = g_new0 (LmParser, 1);
       
   225 	if (!parser) {
       
   226 		return NULL;
       
   227 	}
       
   228 	
       
   229 	parser->m_parser = g_new0 (GMarkupParser, 1);
       
   230 	if (!parser->m_parser) {
       
   231 		g_free (parser);
       
   232 		return NULL;
       
   233 	}
       
   234 
       
   235 	parser->function  = function;
       
   236 	parser->user_data = user_data;
       
   237 	parser->notify    = notify;
       
   238 	
       
   239 	parser->m_parser->start_element = parser_start_node_cb;
       
   240 	parser->m_parser->end_element   = parser_end_node_cb;
       
   241 	parser->m_parser->text          = parser_text_cb;
       
   242 	parser->m_parser->error         = parser_error_cb;
       
   243 
       
   244 	parser->context = g_markup_parse_context_new (parser->m_parser, 0,
       
   245 						      parser, NULL);
       
   246 
       
   247 	parser->cur_root = NULL;
       
   248 	parser->cur_node = NULL;
       
   249 
       
   250 	return parser;
       
   251 }
       
   252 
       
   253 EXPORT_C void
       
   254 lm_parser_parse (LmParser *parser, const gchar *string)
       
   255 {
       
   256 	g_return_if_fail (parser != NULL);
       
   257 	
       
   258         if (!parser->context) {
       
   259                 parser->context = g_markup_parse_context_new (parser->m_parser, 0,
       
   260                                                               parser, NULL);
       
   261         }
       
   262         
       
   263         if (g_markup_parse_context_parse (parser->context, string, 
       
   264                                           (gssize)strlen (string), NULL)) {
       
   265         } else {
       
   266 		g_markup_parse_context_free (parser->context);
       
   267 		parser->context = NULL;
       
   268         }
       
   269 }
       
   270 
       
   271 EXPORT_C void
       
   272 lm_parser_free (LmParser *parser)
       
   273 {
       
   274 	if (parser->notify) {
       
   275 		(* parser->notify) (parser->user_data);
       
   276 	}
       
   277 
       
   278 	if (parser->context) {
       
   279 		g_markup_parse_context_free (parser->context);
       
   280 	}
       
   281 	g_free (parser->m_parser);
       
   282 	g_free (parser);
       
   283 }
       
   284