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