TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
xml.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : xml.cpp
4 created : Sat Mar 18 23:50:46 CET 2000
5 copyright : (C) 2000 by Eric Espie
6 email : torcs@free.fr
7 version : $Id$
8
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20/*
21 * This set of function is used to store and retrieve
22 * values in parameters files written in XML.
23 */
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <cstring>
28#include <sys/stat.h>
29#include "xmlparse.h"
30#include <xml.h>
31#include <portability.h>
32
33#define BUFMAX 256
34
35/*
36 * NAME:
37 * NewElt
38 *
39 * FUNCTION:
40 * Creates a new element
41 *
42 * PARAMETERS:
43 * name and attributes
44 *
45 * RETURNS:
46 * new element created
47 *
48 */
49static txmlElement *
50NewElt(const char *name, const char **atts)
51{
52 int nAtts;
53 const char **p;
54 const char *s1, *s2;
55 txmlElement *newElt;
56 txmlAttribute *newAttr;
57
58
59 /* Create a new element */
60 if ((newElt = (txmlElement*)malloc(sizeof(txmlElement))) == NULL) {
61 return (txmlElement*)NULL;
62 }
63 newElt->name = strdup(name);
64 newElt->pcdata = (char*)NULL;
65 newElt->attr = (txmlAttribute*)NULL;
66 newElt->sub = (txmlElement*)NULL;
67 newElt->up = (txmlElement*)NULL;
68 newElt->next = newElt;
69 newElt->level = 0;
70
71 /* attributes */
72 p = atts;
73 while (*p)
74 ++p;
75 nAtts = (p - atts) >> 1;
76 if (nAtts > 1) {
77 qsort((void *)atts, nAtts, sizeof(char *) * 2, (int (*)(const void *, const void *))strcmp);
78 }
79
80 while (*atts) {
81 s1 = *atts++;
82 s2 = *atts++;
83 if ((newAttr = (txmlAttribute*)malloc(sizeof(txmlAttribute))) == NULL) {
84 return (txmlElement*)NULL;
85 }
86 newAttr->name = strdup(s1);
87 newAttr->value = strdup(s2);
88 /* insert in attributes ring */
89 if (newElt->attr == NULL) {
90 newElt->attr = newAttr;
91 newAttr->next = newAttr;
92 } else {
93 newAttr->next = newElt->attr->next;
94 newElt->attr->next = newAttr;
95 newElt->attr = newAttr;
96 }
97 }
98
99 return newElt;
100}
101
102
103/*
104 * NAME:
105 * xmlInsertElt
106 *
107 * FUNCTION:
108 * Create and Insert a new element in the sub-list of
109 * the element given in parameter
110 *
111 * PARAMETERS:
112 * curElt element
113 * name name of the new element
114 * atts attribute list of the new element
115 *
116 * RETURNS:
117 * the new element created.
118 *
119 * NOTE:
120 * Use NULL as current element to create a new tree
121 */
123xmlInsertElt(txmlElement *curElt, const char *name, const char **atts)
124{
125 txmlElement *newElt;
126
127 newElt = NewElt(name, atts);
128
129 if (curElt) {
130 if (curElt->sub == NULL) {
131 curElt->sub = newElt;
132 newElt->next = newElt;
133 } else {
134 newElt->next = curElt->sub->next;
135 curElt->sub->next = newElt;
136 curElt->sub = newElt;
137 }
138 newElt->up = curElt;
139 newElt->level = curElt->level + 1;
140 }
141
142 return newElt;
143}
144
145/*
146 * Function
147 * startElement
148 *
149 * Description
150 *
151 *
152 * Parameters
153 *
154 *
155 * Return
156 *
157 */
158static void
159startElement(void *userData, const char *name, const char **atts)
160{
161 txmlElement **curElt = (txmlElement **)userData;
162
163 *curElt = xmlInsertElt(*curElt, name, atts);
164}
165
166/*
167 * Function
168 * endElement
169 *
170 * Description
171 *
172 *
173 * Parameters
174 *
175 *
176 * Return
177 * none
178 */
179static void
180endElement(void *userData, const char * /* name */)
181{
182 txmlElement **curElt = (txmlElement **)userData;
183
184 if ((*curElt)->up != NULL) {
185 *curElt = (*curElt)->up;
186 }
187}
188
189static void
190CharacterData(void *userData, const char *s, int len)
191{
192 char *s1,*s2,*s3;
193 txmlElement **curElt = (txmlElement **)userData;
194
195 if ((s1 = (char*)malloc(len+1)) == NULL) {
196 return;
197 }
198 strncpy(s1, s, len);
199
200 /* remove spaces in front */
201 s2 = s1;
202 while ((*s2 == ' ') || (*s2 == '\t') || (*s2 == '\n')) {
203 s2++;
204 }
205
206 /* remove spaces at the end */
207 s3 = s1+len-1;
208 while (((*s3 == ' ') || (*s3 == '\t') || (*s3 == '\n')) && (s3 > s2)) {
209 s3--;
210 }
211
212 if (s3 > s2) {
213 *(s3+1) = 0;
214 (*curElt)->pcdata = strdup(s2);
215 }
216 free(s1);
217}
218
219/*
220 * Function
221 * xmlReadFile
222 *
223 * Description
224 * Read a config file
225 *
226 * Parameters
227 * file name of the config file
228 *
229 * Return
230 * root of the tree
231 * NULL error.
232 *
233 * Remarks
234 *
235 */
237xmlReadFile(const char *file)
238{
239 FILE *in;
240 char buf[BUFSIZ];
241 XML_Parser parser;
242 int done;
243 txmlElement *retElt;
244
245 if ((in = fopen(file, "r")) == NULL) {
246 fprintf(stderr, "xmlReadFile: file %s has pb (access rights ?)\n", file);
247 return (txmlElement*)NULL;
248 }
249
250 parser = XML_ParserCreate((XML_Char*)NULL);
251 XML_SetUserData(parser, &retElt);
254 do {
255 size_t len = fread(buf, 1, sizeof(buf), in);
256 done = len < sizeof(buf);
257 if (!XML_Parse(parser, buf, len, done)) {
258 fprintf(stderr, "file: %s -> %s at line %d\n", file, XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser));
259
260 XML_ParserFree(parser);
261 fclose(in);
262 return (txmlElement*)NULL;
263 }
264 } while (!done);
265
266 XML_ParserFree(parser);
267 fclose(in);
268
269 return retElt;
270}
271
272static void
273wr(int indent, const char *buf, FILE *out)
274{
275 char blank[BUFMAX];
276 int i;
277
278 for(i = 0; i < indent*2; i++) blank[i] = ' ';
279 blank[i] = 0;
280 fprintf(out, "%s%s", blank, buf);
281}
282
283static void
284wrrec(txmlElement *startElt, FILE *out)
285{
286 txmlElement *curElt;
287 txmlAttribute *curAttr;
288 char buf[BUFMAX];
289
290 curElt = startElt;
291
292 if (curElt) {
293 wr(0, "\n", out);
294 do {
295 curElt = curElt->next;
296 snprintf(buf, BUFMAX, "<%s", curElt->name);
297 wr(curElt->level, buf, out);
298 curAttr = curElt->attr;
299 if (curAttr) {
300 do {
301 curAttr = curAttr->next;
302 snprintf(buf, BUFMAX, " %s=\"%s\"", curAttr->name, curAttr->value);
303 wr(0, buf, out);
304 } while (curAttr != curElt->attr);
305 }
306 snprintf(buf, BUFMAX, ">");
307 wr(0, buf, out);
308 if (curElt->pcdata) {
309 snprintf(buf, BUFMAX, "%s", curElt->pcdata);
310 wr(0, buf, out);
311 }
312 /* recurse the nested elements */
313 wrrec(curElt->sub, out);
314 snprintf(buf, BUFMAX, "</%s>\n", curElt->name);
315 wr(0, buf, out);
316 } while (curElt != startElt);
317 wr(curElt->level-1, "", out);
318 }
319}
320
321/*
322 * Function
323 * xmlWriteFile
324 *
325 * Description
326 * Write a parameter file
327 *
328 * Parameters
329 * file name of the config file
330 * startElt root of the tree to write
331 *
332 * Return
333 * 0 ok
334 * -1 failed
335 *
336 * Remarks
337 * the file is created if necessary
338 */
339int
340xmlWriteFile(const char *file, txmlElement *startElt, char *dtd)
341{
342 char buf[BUFMAX];
343 FILE *out;
344
345 if ((out = fopen(file, "w")) == NULL) {
346 fprintf(stderr, "xmlWriteFile: file %s has pb (access rights ?)\n", file);
347 return -1;
348 }
349
350 snprintf(buf, BUFMAX, "<?xml version=\"1.0\" ?>\n");
351 wr(0, buf, out);
352 snprintf(buf, BUFMAX, "\n<!DOCTYPE params SYSTEM \"%s\">\n\n", dtd);
353 wr(0, buf, out);
354
355 wrrec(startElt, out);
356 wr(0, "\n", out);
357
358 fclose(out);
359 return 0;
360}
361
362/*
363 * NAME:
364 * xmlGetAttr
365 *
366 * FUNCTION:
367 * Get the attribute value of an element
368 *
369 * PARAMETERS:
370 * curElt element to consider
371 * attrname name of the attribute
372 *
373 * RETURNS:
374 * the attribute value or NULL if attribute is not present
375 *
376 */
377char *
378xmlGetAttr(txmlElement *curElt, char *attrname)
379{
380 txmlAttribute *cutAttr;
381
382 cutAttr = curElt->attr;
383 if (cutAttr) {
384 do {
385 cutAttr = cutAttr->next;
386 if (strcmp(cutAttr->name, attrname) == 0) {
387 return strdup(cutAttr->value);
388 }
389 } while (cutAttr != curElt->attr);
390 }
391 return (char*)NULL;
392}
393
394/*
395 * NAME:
396 * xmlNextElt
397 *
398 * FUNCTION:
399 * Get the next element (same level)
400 *
401 * PARAMETERS:
402 * startElt element to start with
403 *
404 * RETURNS:
405 * the next element or NULL if no more element
406 * at the same level
407 *
408 */
411{
412 txmlElement *curElt;
413
414 curElt = startElt->next;
415 if (curElt->up != NULL) {
416 if (curElt->up->sub->next == curElt) {
417 return (txmlElement*)NULL;
418 }
419 return curElt;
420 }
421 return (txmlElement*)NULL;
422}
423
424
425/*
426 * NAME:
427 * xmlSubElt
428 *
429 * FUNCTION:
430 * Get the first sub-element (nested level)
431 *
432 * PARAMETERS:
433 * startElt element to start with
434 *
435 * RETURNS:
436 * the first sub-element or NULL if no sub-element
437 *
438 */
441{
442 if (startElt->sub != NULL) {
443 return startElt->sub->next;
444 }
445
446 return (txmlElement*)NULL;
447}
448
449
450/*
451 * NAME:
452 * xmlWalkElt
453 *
454 * FUNCTION:
455 * Walk all the tree
456 *
457 * PARAMETERS:
458 * startElt element to start with
459 *
460 * RETURNS:
461 * the next element in the tree or NULL if all the tree
462 * has been parsed.
463 *
464 */
467{
468 txmlElement *curElt;
469
470 curElt = startElt;
471 /* in depth first */
472 if (curElt->sub != NULL) {
473 return curElt->sub->next;
474 }
475
476 /* go to the next element */
477 if ((curElt->up != NULL) && (curElt != curElt->up->sub)) {
478 return curElt->next;
479 }
480
481 /* end of the ring should go upward */
482 while (curElt->up != NULL) {
483 curElt = curElt->up;
484 if ((curElt->up != NULL) && (curElt != curElt->up->sub)) {
485 return curElt->next;
486 }
487 }
488
489 return (txmlElement*)NULL;
490}
491
492
493/*
494 * NAME:
495 * xmlWalkSubElt
496 *
497 * FUNCTION:
498 * walk a sub-tree
499 *
500 * PARAMETERS:
501 * startElt element to start with
502 * topElt sub-tree root
503 *
504 * RETURNS:
505 * next element in in-depth search or NULL if all sub-tree has been parsed
506 *
507 */
510{
511 txmlElement *curElt;
512
513 curElt = startElt;
514 /* in depth first */
515 if (curElt->sub != NULL) {
516 return curElt->sub->next;
517 }
518
519 /* go to the next element */
520 if ((curElt->up != NULL) && (curElt != curElt->up->sub) && (curElt != topElt)) {
521 return curElt->next;
522 }
523
524 /* end of the ring should go upward */
525 while ((curElt->up != NULL) && (curElt != topElt)) {
526 curElt = curElt->up;
527 if ((curElt->up != NULL) && (curElt != curElt->up->sub)) {
528 return curElt->next;
529 }
530 }
531
532 return (txmlElement*)NULL;
533}
534
535
536/*
537 * NAME:
538 * xmlFindNextElt
539 *
540 * FUNCTION:
541 * Find the next element corresponding to name
542 *
543 * PARAMETERS:
544 * startElt element to start with
545 * name name of the element to find
546 *
547 * RETURNS:
548 * pointer on next element corresponding to name
549 * or NULL if no more.
550 *
551 */
553xmlFindNextElt(txmlElement *startElt, char *name)
554{
555 txmlElement *curElt;
556
557 curElt = startElt;
558 curElt = xmlWalkElt(curElt);
559 while (curElt) {
560 if (strcmp(curElt->name, name) == 0) {
561 return curElt;
562 }
563 curElt = xmlWalkElt(curElt);
564 }
565 return (txmlElement*)NULL;
566}
567
568
569/*
570 * NAME:
571 * xmlFindEltAttr
572 *
573 * FUNCTION:
574 * Find an element with its name an an attribute value
575 *
576 * PARAMETERS:
577 * startElt element to start with
578 * name name of the element to search
579 * attrname attribute name
580 * attrvalue attribute value of the searched element
581 *
582 * RETURNS:
583 * the corresponding element or NULL if not found
584 *
585 */
587xmlFindEltAttr(txmlElement *startElt, char *name, char *attrname, char *attrvalue)
588{
589 txmlElement *curElt;
590 txmlAttribute *cutAttr;
591
592 curElt = startElt;
593 curElt = xmlWalkElt(curElt);
594 while (curElt) {
595 if (strcmp(curElt->name, name) == 0) {
596 cutAttr = curElt->attr;
597 if (cutAttr) {
598 do {
599 cutAttr = cutAttr->next;
600 if (strcmp(cutAttr->name, attrname) == 0) {
601 if (strcmp(cutAttr->value, attrvalue) == 0) {
602 return curElt;
603 } else {
604 cutAttr = curElt->attr;
605 }
606 }
607 } while (cutAttr != curElt->attr);
608 }
609 }
610 curElt = xmlWalkElt(curElt);
611 }
612 return (txmlElement*)NULL;
613}
614
615
616
617
618
619
static Point p[4]
Definition Convex.cpp:54
char * name
Definition xml.h:11
struct xmlAttribute * next
Definition xml.h:13
char * value
Definition xml.h:12
char * name
Definition xml.h:17
struct xmlElement * up
Definition xml.h:23
int level
Definition xml.h:20
struct xmlElement * sub
Definition xml.h:22
struct xmlAttribute * attr
Definition xml.h:19
char * pcdata
Definition xml.h:18
struct xmlElement * next
Definition xml.h:21
txmlElement * xmlInsertElt(txmlElement *curElt, const char *name, const char **atts)
Definition xml.cpp:123
txmlElement * xmlFindNextElt(txmlElement *startElt, char *name)
Definition xml.cpp:553
static void wrrec(txmlElement *startElt, FILE *out)
Definition xml.cpp:284
txmlElement * xmlWalkElt(txmlElement *startElt)
Definition xml.cpp:466
static void wr(int indent, const char *buf, FILE *out)
Definition xml.cpp:273
txmlElement * xmlFindEltAttr(txmlElement *startElt, char *name, char *attrname, char *attrvalue)
Definition xml.cpp:587
static void endElement(void *userData, const char *)
Definition xml.cpp:180
txmlElement * xmlSubElt(txmlElement *startElt)
Definition xml.cpp:440
static void startElement(void *userData, const char *name, const char **atts)
Definition xml.cpp:159
static void CharacterData(void *userData, const char *s, int len)
Definition xml.cpp:190
txmlElement * xmlWalkSubElt(txmlElement *startElt, txmlElement *topElt)
Definition xml.cpp:509
#define BUFMAX
Definition xml.cpp:33
static txmlElement * NewElt(const char *name, const char **atts)
Definition xml.cpp:50
txmlElement * xmlReadFile(const char *file)
Definition xml.cpp:237
int xmlWriteFile(const char *file, txmlElement *startElt, char *dtd)
Definition xml.cpp:340
char * xmlGetAttr(txmlElement *curElt, char *attrname)
Definition xml.cpp:378
txmlElement * xmlNextElt(txmlElement *startElt)
Definition xml.cpp:410
struct xmlAttribute txmlAttribute
struct xmlElement txmlElement
enum XML_Error XMLPARSEAPI XML_GetErrorCode(XML_Parser parser)
char XML_Char
Definition xmlparse.h:60
void XMLPARSEAPI XML_SetElementHandler(XML_Parser parser, XML_StartElementHandler start, XML_EndElementHandler end)
int XMLPARSEAPI XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
void XMLPARSEAPI XML_SetUserData(XML_Parser parser, void *userData)
const XML_LChar XMLPARSEAPI * XML_ErrorString(int code)
void * XML_Parser
Definition xmlparse.h:33
void XMLPARSEAPI XML_ParserFree(XML_Parser parser)
XML_Parser XMLPARSEAPI XML_ParserCreate(const XML_Char *encoding)
void XMLPARSEAPI XML_SetCharacterDataHandler(XML_Parser parser, XML_CharacterDataHandler handler)
int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser)