1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-gloader-expat.c expat XML loader
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
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.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "dbus-gparser.h"
28 expat_g_malloc (size_t sz)
34 expat_g_realloc (void *mem, size_t sz)
36 return g_realloc (mem, sz);
39 static XML_Memory_Handling_Suite memsuite =
47 * Context for Expat parser for introspection data.
51 Parser *parser; /**< The parser for the introspection data */
52 const char *filename; /**< The filename being loaded */
53 GString *content; /**< The content of the current element */
54 GError **error; /**< Error return location */
55 gboolean failed; /**< True if parse has failed */
59 process_content (ExpatParseContext *context)
64 if (context->content->len > 0)
66 if (!parser_content (context->parser,
67 context->content->str,
68 context->content->len,
71 context->failed = TRUE;
74 g_string_set_size (context->content, 0);
81 expat_StartElementHandler (void *userData,
83 const XML_Char **atts)
85 ExpatParseContext *context = userData;
90 /* Expat seems to suck and can't abort the parse if we
91 * throw an error. Expat 2.0 is supposed to fix this.
96 if (!process_content (context))
99 /* "atts" is key, value, key, value, NULL */
100 for (i = 0; atts[i] != NULL; ++i)
103 g_assert (i % 2 == 0);
104 names = g_new0 (char *, i / 2 + 1);
105 values = g_new0 (char *, i / 2 + 1);
108 while (atts[i] != NULL)
110 g_assert (i % 2 == 0);
111 names [i / 2] = (char*) atts[i];
112 values[i / 2] = (char*) atts[i+1];
117 if (!parser_start_element (context->parser,
119 (const char **) names,
120 (const char **) values,
125 context->failed = TRUE;
134 expat_EndElementHandler (void *userData,
135 const XML_Char *name)
137 ExpatParseContext *context = userData;
139 if (!process_content (context))
142 if (!parser_end_element (context->parser,
146 context->failed = TRUE;
151 /* s is not 0 terminated. */
153 expat_CharacterDataHandler (void *userData,
157 ExpatParseContext *context = userData;
162 g_string_append_len (context->content,
167 description_load_from_file (const char *filename,
175 if (!g_file_get_contents (filename, &contents, &len, error))
178 parser = description_load_from_string (contents, len, error);
185 description_load_from_string (const char *str,
190 ExpatParseContext context;
192 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
195 context.parser = NULL;
196 context.error = error;
197 context.failed = FALSE;
199 expat = XML_ParserCreate_MM ("UTF-8", &memsuite, NULL);
201 g_error ("No memory to create XML parser\n");
203 context.parser = parser_new ();
204 context.content = g_string_new (NULL);
206 XML_SetUserData (expat, &context);
207 XML_SetElementHandler (expat,
208 expat_StartElementHandler,
209 expat_EndElementHandler);
210 XML_SetCharacterDataHandler (expat,
211 expat_CharacterDataHandler);
213 if (!XML_Parse (expat, str, len, TRUE))
215 if (context.error != NULL &&
216 *context.error == NULL)
220 e = XML_GetErrorCode (expat);
221 if (e == XML_ERROR_NO_MEMORY)
222 g_error ("Not enough memory to parse XML document");
226 G_MARKUP_ERROR_PARSE,
227 "Error in D-BUS description XML, line %d, column %d: %s\n",
228 XML_GetCurrentLineNumber (expat),
229 XML_GetCurrentColumnNumber (expat),
230 XML_ErrorString (e));
239 if (!parser_finished (context.parser, error))
242 XML_ParserFree (expat);
243 g_string_free (context.content, TRUE);
245 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
246 return context.parser;
249 g_return_val_if_fail (error == NULL || *error != NULL, NULL);
251 g_string_free (context.content, TRUE);
253 XML_ParserFree (expat);
255 parser_unref (context.parser);