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 silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
78 silc_set_errno_location(NULL,
79 XML_GetCurrentLineNumber(parser->parser),
80 XML_GetCurrentColumnNumber(parser->parser));
81 XML_StopParser(parser->parser, FALSE);
85 for (i = 0; atts[i]; i += 2)
86 silc_hash_table_add(t, (void *)atts[i], (void *)atts[i + 1]);
89 if (parser->handler.start_element)
90 parser->handler.start_element(parser, name, t, parser->context);
93 silc_hash_table_free(t);
98 static void silc_xml_expat_end_element(void *userData,
101 SilcXMLParser parser = userData;
103 if (parser->handler.end_element)
104 parser->handler.end_element(parser, name, parser->context);
109 static void silc_xml_expat_data(void *userData,
114 SilcXMLParser parser = userData;
116 if (parser->handler.data)
117 parser->handler.data(parser, (const unsigned char *)s,
118 (SilcUInt32)len, parser->context);
121 /* Processing instruction */
123 static void silc_xml_expat_pi(void *userData,
124 const XML_Char *target,
125 const XML_Char *data)
127 SilcXMLParser parser = userData;
129 if (parser->handler.pi)
130 parser->handler.pi(parser, target, data, parser->context);
135 SilcXMLParser silc_xml_parser_create(SilcXMLParams params,
136 SilcXMLParserHandler handler,
139 SilcXMLParser parser;
142 parser = silc_calloc(1, sizeof(*parser));
146 SILC_LOG_DEBUG(("Allcoated XML parser %p", parser));
149 parser->params = *params;
151 parser->handler = *handler;
152 parser->context = context;
154 /* Allocate expat parser */
155 if (parser->params.no_namespace)
156 ep = XML_ParserCreate("UTF-8");
158 ep = XML_ParserCreateNS("UTF-8", '\0');
161 silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
169 XML_SetUserData(ep, parser);
170 XML_SetElementHandler(ep, silc_xml_expat_start_element,
171 silc_xml_expat_end_element);
172 XML_SetCharacterDataHandler(ep, silc_xml_expat_data);
173 XML_SetProcessingInstructionHandler(ep, silc_xml_expat_pi);
180 void silc_xml_parser_free(SilcXMLParser parser)
185 SILC_LOG_DEBUG(("Free XML parser %p", parser));
188 XML_ParserFree(parser->parser);
194 SilcBool silc_xml_parse(SilcXMLParser parser,
195 const unsigned char *data,
200 SILC_LOG_DEBUG(("Parse XML data with parser %p", parser));
202 if (!parser || !data) {
203 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
208 ret = XML_Parse(parser->parser, (const char *)data, (int)data_len, 1);
210 silc_set_errno_reason(silc_xml_expat_error(parser->parser),
211 silc_xml_get_error(parser));
220 SilcBool silc_xml_parse_file(SilcXMLParser parser,
221 const char *filename)
228 silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
232 SILC_LOG_DEBUG(("Parse XML file '%s' with parser %p", filename, parser));
234 data = silc_file_readfile(filename, &data_len, NULL);
238 ret = silc_xml_parse(parser, data, data_len);
240 silc_set_errno_reason(silc_xml_expat_error(parser->parser),
241 silc_xml_get_error(parser));
242 silc_set_errno_location(filename,
243 XML_GetCurrentLineNumber(parser->parser),
244 XML_GetCurrentColumnNumber(parser->parser));
255 const char *silc_xml_get_attribute(SilcXMLParser parser,
256 SilcHashTable attributes,
264 if (!silc_hash_table_find(attributes, (void *)name, NULL, (void *)&val))
270 /* Return current location */
272 void silc_xml_current_location(SilcXMLParser parser,
273 SilcUInt32 *current_line,
274 SilcUInt32 *current_column)
277 *current_line = XML_GetCurrentLineNumber(parser->parser);
279 *current_column = XML_GetCurrentColumnNumber(parser->parser);
282 #endif /* HAVE_EXPAT_H */