Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

vendor-xml.c

Go to the documentation of this file.
00001 
00011 /* $Progeny$
00012  *
00013  * AUTHOR: John R. Daily <jdaily@progeny.com>
00014  *
00015  * Copyright 2002 Progeny Linux Systems, Inc.
00016  * Copyright 2002 Hewlett-Packard Company
00017  *
00018  * Permission is hereby granted, free of charge, to any person obtaining a
00019  * copy of this software and associated documentation files (the "Software"),
00020  * to deal in the Software without restriction, including without limitation
00021  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00022  * and/or sell copies of the Software, and to permit persons to whom the
00023  * Software is furnished to do so, subject to the following conditions:
00024  *
00025  * The above copyright notice and this permission notice shall be included in
00026  * all copies or substantial portions of the Software.
00027  *
00028  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00029  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00030  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00031  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00032  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00033  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00034  * DEALINGS IN THE SOFTWARE.
00035  */
00036 
00037 #include "config.h"
00038 
00039 #include <sys/types.h>
00040 
00041 #include <assert.h>
00042 #include <limits.h>
00043 #include <stdio.h>
00044 #include <string.h>
00045 
00046 #include <expat.h>
00047 
00048 #include <discover/discover.h>
00049 #include <discover/discover-xml.h>
00050 
00051 #include <discover/load-url.h>
00052 #include <discover/utils.h>
00053 
00055 struct discover_xml_vendor {
00056     char *id;
00057     char *name;
00058     discover_xml_vendor_t *next;
00059 };
00060 
00061 static discover_xml_vendor_t *vendors[BUS_COUNT];
00062 
00064 struct context {
00065     discover_xml_vendor_t **vlist;
00066 
00067     int unknown_level; /* How deep are we into unknown XML tags? */
00068 };
00069 
00070 static char *known_vendor_elements[] = {
00071     "vendor",
00072     "vendor_list",
00073     NULL
00074 };
00075 
00076 
00077 static bool
00078 unknown_vendor_element(const XML_Char * const tag)
00079 {
00080     int i;
00081     for (i = 0; known_vendor_elements[i] != NULL; i++) {
00082         if (strcmp(tag, known_vendor_elements[i]) == 0)
00083             return false;
00084     }
00085     return true;
00086 }
00087 
00088 static void
00089 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00090 {
00091     struct context *context = ctx;
00092     int i;
00093     char *vid, *vname;
00094     discover_xml_vendor_t *next, **vlist;
00095 
00096     assert(context != NULL);
00097     assert(name != NULL);
00098     assert(attrs != NULL);
00099 
00100     if (unknown_vendor_element(name)) {
00101         context->unknown_level++;
00102         return;
00103     }
00104 
00105     if (context->unknown_level > 0) {
00106         return;
00107     }
00108 
00109     if (strcmp(name, "vendor") == 0) {
00110         vid = vname = NULL;
00111         for (i = 0; attrs[i]; i += 2) {
00112             if (strcmp(attrs[i], "id") == 0) {
00113                 vid = (char *) attrs[i + 1];
00114             } else if (strcmp(attrs[i], "name") == 0) {
00115                 vname = (char *) attrs[i + 1];
00116             }
00117         }
00118 
00119         assert(vid != NULL);
00120         assert(vname != NULL);
00121 
00122         vlist = context->vlist;
00123         next = *vlist;
00124         *vlist = discover_xml_vendor_new();
00125         (*vlist)->id = _discover_xstrdup(vid);
00126         (*vlist)->name = _discover_xstrdup(vname);
00127         (*vlist)->next = next;
00128     }
00129 }
00130 
00131 static void
00132 end_element(void *ctx, const XML_Char *name)
00133 {
00134     struct context *context = ctx;
00135 
00136     assert(context != NULL);
00137     assert(name != NULL);
00138 
00139     if (unknown_vendor_element(name)) {
00140         context->unknown_level--;
00141         return;
00142     }
00143 
00144     if (context->unknown_level > 0) {
00145         return;
00146     }
00147 
00148     /*
00149      * We don't have any end tags to worry about, but if we did, they
00150      * would be handled here.
00151      */
00152 }
00153 
00166 /* Sshh!  Don't tell, but this doesn't actually do any merging at all.
00167  * Instead, it simply inserts newer entries at the front of the list,
00168  * meaning that vendor info found later supersedes info found earlier.
00169  * This gives the illusion of merging, but potentially wastes memory
00170  * with duplicates.
00171  */
00172 void
00173 discover_xml_merge_vendor_url(discover_xml_vendor_t **vlist,
00174                               char *url, discover_error_t *status)
00175 {
00176     XML_Parser parser;
00177     struct context context;
00178 
00179     assert(url != NULL);
00180     assert(status != NULL);
00181 
00182     status->code = 0;
00183 
00184     context.vlist = vlist;
00185     context.unknown_level = 0;
00186 
00187     parser = XML_ParserCreate(NULL);
00188     XML_SetElementHandler(parser, start_element, end_element);
00189     XML_SetUserData(parser, &context);
00190 
00191     if (!_discover_load_url(url, parser)) {
00192         XML_ParserFree(parser);
00193         status->code = DISCOVER_EIO;
00194         return;
00195     }
00196 
00197     if (!XML_Parse(parser, "", 0, 1)) {
00198         XML_ParserFree(parser);
00199         status->code = DISCOVER_EXML;
00200         return;
00201     }
00202 
00203     XML_ParserFree(parser);
00204 
00205     return;
00206 }
00207 
00214 discover_xml_vendor_t *
00215 discover_xml_get_vendors(discover_bus_t bus, discover_error_t *status)
00216 {
00217     discover_xml_url_t *urls, *i;
00218     char *url;
00219 
00220     assert(status != NULL);
00221 
00222     status->code = 0;
00223 
00224     if (!vendors[bus]) {
00225         urls = discover_xml_get_data_urls(bus, VENDOR_TYPE, status);
00226         if (status->code != 0) {
00227             return NULL;
00228         }
00229 
00230         for (i = urls;
00231              i;
00232              i = discover_xml_url_get_next(i)) {
00233             url = discover_xml_url_get_url(i);
00234             discover_xml_merge_vendor_url(&(vendors[bus]), url, status);
00235             if (status->code != 0) {
00236                 return NULL;
00237             }
00238         }
00239     }
00240 
00241     return vendors[bus];
00242 }
00243 
00247 void
00248 discover_xml_free_vendors(void)
00249 {
00250     int i;
00251     for (i = 0; i < BUS_COUNT; i++) {
00252         discover_xml_vendor_free(vendors[i]);
00253         vendors[i] = NULL;
00254     }
00255 }
00256 
00263 char *
00264 discover_xml_vendor_id2name(discover_xml_vendor_t *vendors, char *id)
00265 {
00266     discover_xml_vendor_t *vendor;
00267     char *name;
00268 
00269     assert(vendors != NULL);
00270     assert(id != NULL);
00271 
00272     name = NULL;
00273 
00274     for (vendor = vendors;
00275          vendor;
00276          vendor = vendor->next) {
00277         if (strcmp(id, vendor->id) == 0) {
00278             name = vendor->name;
00279             break;
00280         }
00281     }
00282 
00283     return name;
00284 }
00285 
00289 char *
00290 discover_xml_vendor_get_id(discover_xml_vendor_t *vendor)
00291 {
00292     assert(vendor != NULL);
00293 
00294     return vendor->id;
00295 }
00296 
00300 char *
00301 discover_xml_vendor_get_name(discover_xml_vendor_t *vendor)
00302 {
00303     assert(vendor != NULL);
00304 
00305     return vendor->name;
00306 }
00307 
00311 discover_xml_vendor_t *
00312 discover_xml_vendor_get_next(discover_xml_vendor_t *vendor)
00313 {
00314     assert(vendor != NULL);
00315 
00316     return vendor->next;
00317 }
00318 
00322 discover_xml_vendor_t *
00323 discover_xml_vendor_new(void)
00324 {
00325     discover_xml_vendor_t *new;
00326 
00327     new = _discover_xmalloc(sizeof(discover_xml_vendor_t));
00328 
00329     new->id = NULL;
00330     new->name = NULL;
00331     new->next = NULL;
00332 
00333     return new;
00334 }
00335 
00341 void
00342 discover_xml_vendor_free(discover_xml_vendor_t *vendors)
00343 {
00344     discover_xml_vendor_t *vendor, *last;
00345 
00346     last = NULL;
00347 
00348     for (vendor = vendors;
00349          vendor;
00350          vendor = vendor->next) {
00351         if (vendor->id) {
00352             free(vendor->id);
00353         }
00354 
00355         if (vendor->name) {
00356             free(vendor->name);
00357         }
00358 
00359         if (last) {
00360             free(last);
00361         }
00362         last = vendor;
00363     }
00364 
00365     if (last) {
00366         free(last);
00367     }
00368 }
00369 
00372 /*
00373  * Local variables:
00374  * c-file-style: "progeny"
00375  * indent-tabs-mode: nil
00376  * End:
00377  */
00378 /* vim: set cin fo=tcroq sw=4 et sts=4 tw=75: */

Generated on Thu Jul 28 03:38:00 2005 for discover by  doxygen 1.4.2