00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
#include "dbus-gparser.h"
00025
#include <expat.h>
00026
00027
static void*
00028 expat_g_malloc (size_t sz)
00029 {
00030
return g_malloc (sz);
00031 }
00032
00033
static void*
00034 expat_g_realloc (
void *mem, size_t sz)
00035 {
00036
return g_realloc (mem, sz);
00037 }
00038
00039
static XML_Memory_Handling_Suite memsuite =
00040 {
00041 expat_g_malloc,
00042 expat_g_realloc,
00043 g_free
00044 };
00045
00049 typedef struct
00050
{
00051 Parser *parser;
00052 const char *filename;
00053 GString *content;
00054 GError **error;
00055 gboolean failed;
00056 }
ExpatParseContext;
00057
00058
static dbus_bool_t
00059 process_content (
ExpatParseContext *context)
00060 {
00061
if (context->
failed)
00062
return FALSE;
00063
00064
if (context->
content->len > 0)
00065 {
00066
if (!parser_content (context->
parser,
00067 context->
content->str,
00068 context->
content->len,
00069 context->
error))
00070 {
00071 context->
failed =
TRUE;
00072
return FALSE;
00073 }
00074 g_string_set_size (context->
content, 0);
00075 }
00076
00077
return TRUE;
00078 }
00079
00080
static void
00081 expat_StartElementHandler (
void *userData,
00082
const XML_Char *name,
00083
const XML_Char **atts)
00084 {
00085
ExpatParseContext *context = userData;
00086
int i;
00087
char **names;
00088
char **values;
00089
00090
00091
00092
00093
if (context->
failed)
00094
return;
00095
00096
if (!process_content (context))
00097
return;
00098
00099
00100
for (i = 0; atts[i] !=
NULL; ++i)
00101 ;
00102
00103 g_assert (i % 2 == 0);
00104 names = g_new0 (
char *, i / 2 + 1);
00105 values = g_new0 (
char *, i / 2 + 1);
00106
00107 i = 0;
00108
while (atts[i] !=
NULL)
00109 {
00110 g_assert (i % 2 == 0);
00111 names [i / 2] = (
char*) atts[i];
00112 values[i / 2] = (
char*) atts[i+1];
00113
00114 i += 2;
00115 }
00116
00117
if (!parser_start_element (context->
parser,
00118 name,
00119 (
const char **) names,
00120 (
const char **) values,
00121 context->
error))
00122 {
00123 g_free (names);
00124 g_free (values);
00125 context->
failed =
TRUE;
00126
return;
00127 }
00128
00129 g_free (names);
00130 g_free (values);
00131 }
00132
00133
static void
00134 expat_EndElementHandler (
void *userData,
00135
const XML_Char *name)
00136 {
00137
ExpatParseContext *context = userData;
00138
00139
if (!process_content (context))
00140
return;
00141
00142
if (!parser_end_element (context->
parser,
00143 name,
00144 context->
error))
00145 {
00146 context->
failed =
TRUE;
00147
return;
00148 }
00149 }
00150
00151
00152
static void
00153 expat_CharacterDataHandler (
void *userData,
00154
const XML_Char *s,
00155
int len)
00156 {
00157
ExpatParseContext *context = userData;
00158
00159
if (context->
failed)
00160
return;
00161
00162 g_string_append_len (context->
content,
00163 s, len);
00164 }
00165
00166 NodeInfo*
00167 description_load_from_file (
const char *filename,
00168 GError **error)
00169 {
00170
char *contents;
00171 gsize len;
00172 NodeInfo *nodes;
00173
00174 contents =
NULL;
00175
if (!g_file_get_contents (filename, &contents, &len, error))
00176
return NULL;
00177
00178 nodes = description_load_from_string (contents, len, error);
00179 g_free (contents);
00180
00181
return nodes;
00182 }
00183
00184 NodeInfo*
00185 description_load_from_string (
const char *str,
00186
int len,
00187 GError **error)
00188 {
00189 XML_Parser expat;
00190
ExpatParseContext context;
00191 NodeInfo *nodes;
00192
00193 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00194
00195 expat =
NULL;
00196 context.
parser =
NULL;
00197 context.
error = error;
00198 context.
failed =
FALSE;
00199
00200 expat = XML_ParserCreate_MM (
"UTF-8", &memsuite, NULL);
00201
if (expat ==
NULL)
00202 g_error (
"No memory to create XML parser\n");
00203
00204 context.
parser = parser_new ();
00205 context.
content = g_string_new (NULL);
00206
00207 XML_SetUserData (expat, &context);
00208 XML_SetElementHandler (expat,
00209 expat_StartElementHandler,
00210 expat_EndElementHandler);
00211 XML_SetCharacterDataHandler (expat,
00212 expat_CharacterDataHandler);
00213
00214
if (!XML_Parse (expat, str, len, TRUE))
00215 {
00216
if (context.
error !=
NULL &&
00217 *context.
error ==
NULL)
00218 {
00219
enum XML_Error e;
00220
00221 e = XML_GetErrorCode (expat);
00222
if (e == XML_ERROR_NO_MEMORY)
00223 g_error (
"Not enough memory to parse XML document");
00224
else
00225 g_set_error (error,
00226 G_MARKUP_ERROR,
00227 G_MARKUP_ERROR_PARSE,
00228
"Error in D-BUS description XML, line %d, column %d: %s\n",
00229 XML_GetCurrentLineNumber (expat),
00230 XML_GetCurrentColumnNumber (expat),
00231 XML_ErrorString (e));
00232 }
00233
00234
goto failed;
00235 }
00236
00237
if (context.
failed)
00238
goto failed;
00239
00240
if (!parser_finished (context.
parser, error))
00241
goto failed;
00242
00243 XML_ParserFree (expat);
00244 g_string_free (context.
content, TRUE);
00245
00246 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
00247 nodes = parser_get_nodes (context.
parser);
00248 node_info_ref (nodes);
00249 parser_unref (context.
parser);
00250
return nodes;
00251
00252 failed:
00253 g_return_val_if_fail (error == NULL || *error != NULL, NULL);
00254
00255 g_string_free (context.
content, TRUE);
00256
if (expat)
00257 XML_ParserFree (expat);
00258
if (context.
parser)
00259 parser_unref (context.
parser);
00260
return NULL;
00261 }
00262