Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

dbus-gloader-expat.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */ 00002 /* dbus-gloader-expat.c expat XML loader 00003 * 00004 * Copyright (C) 2003 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 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 /* Expat seems to suck and can't abort the parse if we 00091 * throw an error. Expat 2.0 is supposed to fix this. 00092 */ 00093 if (context->failed) 00094 return; 00095 00096 if (!process_content (context)) 00097 return; 00098 00099 /* "atts" is key, value, key, value, NULL */ 00100 for (i = 0; atts[i] != NULL; ++i) 00101 ; /* nothing */ 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 /* s is not 0 terminated. */ 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

Generated on Tue Oct 12 02:07:52 2004 for D-BUS by doxygen 1.3.7