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