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

busclass-xml.c

Go to the documentation of this file.
00001 
00010 /* $Progeny$
00011  *
00012  * AUTHOR: John R. Daily <jdaily@progeny.com>
00013  *
00014  * Copyright 2002 Progeny Linux Systems, Inc.
00015  * Copyright 2002 Hewlett-Packard Company
00016  *
00017  * Permission is hereby granted, free of charge, to any person obtaining a
00018  * copy of this software and associated documentation files (the "Software"),
00019  * to deal in the Software without restriction, including without limitation
00020  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00021  * and/or sell copies of the Software, and to permit persons to whom the
00022  * Software is furnished to do so, subject to the following conditions:
00023  *
00024  * The above copyright notice and this permission notice shall be included in
00025  * all copies or substantial portions of the Software.
00026  *
00027  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00028  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00029  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00030  * THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00031  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00032  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00033  * DEALINGS IN THE SOFTWARE.
00034  */
00035 
00036 #include "config.h"
00037 
00038 #include <sys/types.h>
00039 
00040 #include <assert.h>
00041 #include <limits.h>
00042 #include <stdio.h>
00043 #include <string.h>
00044 
00045 #include <expat.h>
00046 
00047 #include <discover/discover.h>
00048 #include <discover/discover-xml.h>
00049 
00050 #include <discover/load-url.h>
00051 #include <discover/utils.h>
00052 
00054 struct discover_xml_busclass {
00055     char *id;
00056     char *name;
00057     discover_xml_busclass_t *next;
00058 };
00059 
00060 static discover_xml_busclass_t *busclasses[BUS_COUNT];
00061 
00062 struct context {
00063     discover_xml_busclass_t **blist;
00064 
00065     int unknown_level; /* How deep are we into unknown XML tags? */
00066 };
00067 
00068 static char *known_bus_elements[] = {
00069     "busclass",
00070     "busclass_list",
00071     NULL
00072 };
00073 
00074 static bool
00075 unknown_bus_element(const XML_Char * const tag)
00076 {
00077     int i;
00078     for (i = 0; known_bus_elements[i] != NULL; i++) {
00079         if (strcmp(tag, known_bus_elements[i]) == 0)
00080             return false;
00081     }
00082     return true;
00083 }
00084 
00085 static void
00086 start_element(void *ctx, const XML_Char *name, const XML_Char *attrs[])
00087 {
00088     struct context *context = ctx;
00089     int i;
00090     char *vid, *vname;
00091     discover_xml_busclass_t *next, **blist;
00092 
00093     assert(context != NULL);
00094     assert(name != NULL);
00095     assert(attrs != NULL);
00096 
00097     if (unknown_bus_element(name)) {
00098         context->unknown_level++;
00099         return;
00100     }
00101 
00102     if (context->unknown_level > 0) {
00103         return;
00104     }
00105 
00106     if (strcmp(name, "busclass") == 0) {
00107         vid = vname = NULL;
00108         for (i = 0; attrs[i]; i += 2) {
00109             if (strcmp(attrs[i], "id") == 0) {
00110                 vid = (char *) attrs[i + 1];
00111             } else if (strcmp(attrs[i], "name") == 0) {
00112                 vname = (char *) attrs[i + 1];
00113             }
00114         }
00115 
00116         assert(vid != NULL);
00117         assert(vname != NULL);
00118 
00119         blist = context->blist;
00120         next = *blist;
00121         *blist = discover_xml_busclass_new();
00122         (*blist)->id = _discover_xstrdup(vid);
00123         (*blist)->name = _discover_xstrdup(vname);
00124         (*blist)->next = next;
00125     }
00126 }
00127 
00128 static void
00129 end_element(void *ctx, const XML_Char *name)
00130 {
00131     struct context *context = ctx;
00132 
00133     assert(context != NULL);
00134     assert(name != NULL);
00135 
00136     if (unknown_bus_element(name)) {
00137         context->unknown_level--;
00138         return;
00139     }
00140 
00141     if (context->unknown_level > 0) {
00142         return;
00143     }
00144 
00145     /*
00146      * We don't have any end tags to worry about, but if we did, they
00147      * would be handled here.
00148      */
00149 }
00150 
00151 
00164 /* Sshh!  Don't tell, but this doesn't actually do any merging at all.
00165  * Instead, it simply inserts newer entries at the front of the list,
00166  * meaning that busclass info found later supersedes info found earlier.
00167  * This gives the illusion of merging, but potentially wastes memory
00168  * with duplicates.
00169  */
00170 void
00171 discover_xml_merge_busclass_url(discover_xml_busclass_t **blist,
00172                                 char *url, discover_error_t *status)
00173 {
00174     XML_Parser parser;
00175     struct context context;
00176 
00177     assert(url != NULL);
00178     assert(status != NULL);
00179 
00180     status->code = 0;
00181 
00182     context.blist = blist;
00183     context.unknown_level = 0;
00184 
00185     parser = XML_ParserCreate(NULL);
00186     XML_SetElementHandler(parser, start_element, end_element);
00187     XML_SetUserData(parser, &context);
00188 
00189     if (!_discover_load_url(url, parser)) {
00190         XML_ParserFree(parser);
00191         status->code = DISCOVER_EIO;
00192         return;
00193     }
00194 
00195     if (!XML_Parse(parser, "", 0, 1)) {
00196         XML_ParserFree(parser);
00197         status->code = DISCOVER_EXML;
00198         return;
00199     }
00200 
00201     XML_ParserFree(parser);
00202 
00203     return;
00204 }
00205 
00212 discover_xml_busclass_t *
00213 discover_xml_get_busclasses(discover_bus_t bus, discover_error_t *status)
00214 {
00215     discover_xml_url_t *urls, *i;
00216     char *url;
00217 
00218     assert(status != NULL);
00219 
00220     status->code = 0;
00221 
00222     if (!busclasses[bus]) {
00223         urls = discover_xml_get_data_urls(bus, BUSCLASS_TYPE, status);
00224         if (status->code != 0) {
00225             return NULL;
00226         }
00227 
00228         for (i = urls;
00229              i;
00230              i = discover_xml_url_get_next(i)) {
00231             url = discover_xml_url_get_url(i);
00232             discover_xml_merge_busclass_url(&(busclasses[bus]), url, status);
00233             if (status->code != 0) {
00234                 return NULL;
00235             }
00236         }
00237     }
00238 
00239     return busclasses[bus];
00240 }
00241 
00242 
00246 void
00247 discover_xml_free_busclasses(void)
00248 {
00249     int i;
00250     for (i = 0; i < BUS_COUNT; i++) {
00251         discover_xml_busclass_free(busclasses[i]);
00252         busclasses[i] = NULL;
00253     }
00254 }
00255 
00262 char *
00263 discover_xml_busclass_to_class(char *busclass,
00264                                discover_xml_busclass_t *busclasses)
00265 {
00266     char *result;
00267 
00268     assert(busclass != NULL);
00269     assert(busclasses != NULL);
00270 
00271     result = NULL;
00272 
00273     for (;
00274          busclasses;
00275          busclasses = busclasses->next) {
00276         if (strcmp(busclass, busclasses->id) == 0) {
00277             result = busclasses->name;
00278             break;
00279         }
00280     }
00281 
00282     return result;
00283 }
00284 
00294 int
00295 discover_xml_busclass_cmp(char *busclass, char *discover_class,
00296                           discover_xml_busclass_t *busclasses)
00297 {
00298     char *found_class_name = NULL;
00299 
00300     assert(busclass != NULL);
00301     assert(discover_class != NULL);
00302     assert(busclasses != NULL);
00303 
00304     if (strcmp(discover_class, "all") == 0) {
00305         return 0;
00306     }
00307 
00308     found_class_name = discover_xml_busclass_to_class(busclass, busclasses);
00309 
00310     /*
00311      * If the busclass database doesn't know about this device class, we
00312      * can't make any valid comparison.
00313      */
00314     if (found_class_name == NULL) {
00315         return -1;
00316     }
00317 
00318     return strcmp(found_class_name, discover_class);
00319 }
00320 
00326 char *
00327 discover_xml_busclass_get_id(discover_xml_busclass_t *busclass)
00328 {
00329     assert(busclass != NULL);
00330 
00331     return busclass->id;
00332 }
00333 
00339 char *
00340 discover_xml_busclass_get_name(discover_xml_busclass_t *busclass)
00341 {
00342     assert(busclass != NULL);
00343 
00344     return busclass->name;
00345 }
00346 
00351 discover_xml_busclass_t *
00352 discover_xml_busclass_get_next(discover_xml_busclass_t *busclass)
00353 {
00354     assert(busclass != NULL);
00355 
00356     return busclass->next;
00357 }
00358 
00362 discover_xml_busclass_t *
00363 discover_xml_busclass_new(void)
00364 {
00365     discover_xml_busclass_t *new;
00366 
00367     new = _discover_xmalloc(sizeof(discover_xml_busclass_t));
00368 
00369     new->id = NULL;
00370     new->name = NULL;
00371     new->next = NULL;
00372 
00373     return new;
00374 }
00375 
00381 void
00382 discover_xml_busclass_free(discover_xml_busclass_t *busclasses)
00383 {
00384     discover_xml_busclass_t *busclass, *last;
00385 
00386     last = NULL;
00387 
00388     for (busclass = busclasses;
00389          busclass;
00390          busclass = busclass->next) {
00391         if (busclass->id) {
00392             free(busclass->id);
00393         }
00394 
00395         if (busclass->name) {
00396             free(busclass->name);
00397         }
00398 
00399         if (last) {
00400             free(last);
00401         }
00402         last = busclass;
00403     }
00404 
00405     if (last) {
00406         free(last);
00407     }
00408 }
00409 
00412 /*
00413  * Local variables:
00414  * c-file-style: "progeny"
00415  * indent-tabs-mode: nil
00416  * End:
00417  */
00418 /* 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