5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2008 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 #include <silcruntime.h>
22 /* XML parser context */
23 struct SilcXMLParserStruct {
24 void *parser; /* Parser implementation */
25 SilcXMLParserHandlerStruct handler; /* Handler */
26 void *context; /* User context */
27 SilcXMLParamsStruct params; /* Parser parameters */
34 /* Map expat error to silc_errno */
36 static SilcResult silc_xml_expat_error(XML_Parser parser)
38 enum XML_Error error = XML_GetErrorCode(parser);
43 case XML_ERROR_NO_MEMORY:
44 return SILC_ERR_OUT_OF_MEMORY;
45 case XML_ERROR_UNKNOWN_ENCODING:
46 case XML_ERROR_INCORRECT_ENCODING:
47 return SILC_ERR_BAD_ENCODING;
48 case XML_ERROR_ABORTED:
49 return SILC_ERR_ABORTED;
51 return SILC_ERR_SYNTAX;
55 /* Return error string */
57 static const char *silc_xml_get_error(SilcXMLParser parser)
59 return XML_ErrorString(XML_GetErrorCode(parser->parser));
64 static void silc_xml_expat_start_element(void *userData,
66 const XML_Char **atts)
68 SilcXMLParser parser = userData;
69 SilcHashTable t = NULL;
72 if (atts && atts[0]) {
73 t = silc_hash_table_alloc(NULL, 0, silc_hash_utf8_string, NULL,
74 silc_hash_utf8_compare, NULL,
77 XML_StopParser(parser->parser, FALSE);
81 for (i = 0; atts[i]; i += 2)
82 silc_hash_table_add(t, (void *)atts[i], (void *)atts[i + 1]);
85 if (parser->handler.start_element)
86 parser->handler.start_element(parser, name, t, parser->context);
89 silc_hash_table_free(t);
94 static void silc_xml_expat_end_element(void *userData,
97 SilcXMLParser parser = userData;
99 if (parser->handler.end_element)
100 parser->handler.end_element(parser, name, parser->context);
105 static void silc_xml_expat_data(void *userData,
110 SilcXMLParser parser = userData;
112 if (parser->handler.data)
113 parser->handler.data(parser, (const unsigned char *)s,
114 (SilcUInt32)len, parser->context);
117 /* Processing instruction */
119 static void silc_xml_expat_pi(void *userData,
120 const XML_Char *target,
121 const XML_Char *data)
123 SilcXMLParser parser = userData;
125 if (parser->handler.pi)
126 parser->handler.pi(parser, target, data, parser->context);
131 SilcXMLParser silc_xml_parser_create(SilcXMLParams params,
132 SilcXMLParserHandler handler,
135 SilcXMLParser parser;
138 parser = silc_calloc(1, sizeof(*parser));
142 SILC_LOG_DEBUG(("Allcoated XML parser %p", parser));
145 parser->params = *params;
147 parser->handler = *handler;
148 parser->context = context;
150 /* Allocate expat parser */
151 if (parser->params.no_namespace)
152 ep = XML_ParserCreate("UTF-8");
154 ep = XML_ParserCreateNS("UTF-8", '\0');
157 silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
165 XML_SetUserData(ep, parser);
166 XML_SetElementHandler(ep, silc_xml_expat_start_element,
167 silc_xml_expat_end_element);
168 XML_SetCharacterDataHandler(ep, silc_xml_expat_data);
169 XML_SetProcessingInstructionHandler(ep, silc_xml_expat_pi);
176 void silc_xml_parser_free(SilcXMLParser parser)
181 SILC_LOG_DEBUG(("Free XML parser %p", parser));
184 XML_ParserFree(parser->parser);
190 SilcBool silc_xml_parse(SilcXMLParser parser,
191 const unsigned char *data,
196 SILC_LOG_DEBUG(("Parse XML data with parser %p", parser));
198 if (!parser || !data) {
199 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
204 ret = XML_Parse(parser->parser, (const char *)data, (int)data_len, 1);
206 silc_set_errno_reason(silc_xml_expat_error(parser->parser),
207 silc_xml_get_error(parser));
216 SilcBool silc_xml_parse_file(SilcXMLParser parser,
217 const char *filename)
224 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
228 SILC_LOG_DEBUG(("Parse XML file '%s' with parser %p", filename, parser));
230 data = silc_file_readfile(filename, &data_len, NULL);
234 ret = silc_xml_parse(parser, data, data_len);
237 silc_set_errno_reason(silc_xml_expat_error(parser->parser),
238 silc_xml_get_error(parser));
239 silc_set_errno_location(filename,
240 XML_GetCurrentLineNumber(parser->parser),
241 XML_GetCurrentColumnNumber(parser->parser));
252 const char *silc_xml_get_attribute(SilcXMLParser parser,
253 SilcHashTable attributes,
261 if (!silc_hash_table_find(attributes, (void *)name, NULL, (void *)&val))
267 /* Return current location */
269 void silc_xml_current_location(SilcXMLParser parser,
270 SilcUInt32 *current_line,
271 SilcUInt32 *current_column)
274 *current_line = XML_GetCurrentLineNumber(parser->parser);
276 *current_column = XML_GetCurrentColumnNumber(parser->parser);
279 #endif /* HAVE_EXPAT_H */