Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/i386/libsaio/xml.c

1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights
7 * Reserved.
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 2.0 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
13 *
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include "bootstruct.h"
26#include "libsaio.h"
27#include "sl.h"
28#include "xml.h"
29
30#define ASSERT_DICT \
31if (dict == DEFAULT_BOOT_CONFIG_DICT) \
32dict = bootInfo->bootConfig.dictionary ; \
33else if (dict == DEFAULT_SYSTEM_CONFIG_DICT) \
34dict = bootInfo->SystemConfig.dictionary ; \
35else if (dict == DEFAULT_OVERRIDE_CONFIG_DICT) \
36dict = bootInfo->overrideConfig.dictionary ; \
37else if (dict == DEFAULT_SMBIOS_CONFIG_DICT) \
38dict = bootInfo->smbiosConfig.dictionary ; \
39else if (dict == DEFAULT_HELPER_CONFIG_DICT) \
40dict = bootInfo->helperConfig.dictionary ;
41
42string_ref *ref_strings = NULL;
43
44/// TODO: remove below
45static char* buffer_start = NULL;
46// TODO: redo the next two functions
47static void SaveRefString(char* string, int id)
48{
49//printf("Adding Ref String %d (%s)\n", id, string);
50string_ref* tmp = ref_strings;
51while(tmp)
52{
53if(tmp->id == id)
54{
55tmp->string = malloc(strlen(string+1));
56sprintf(tmp->string, "%s", string);
57return;
58}
59tmp = tmp->next;
60}
61
62string_ref* new_ref = malloc(sizeof(string_ref));
63new_ref->string = malloc(strlen(string)+1);
64sprintf(new_ref->string, "%s", string);
65new_ref->id = id;
66new_ref->next = ref_strings;
67ref_strings = new_ref;
68}
69
70static char* GetRefString(int id)
71{
72string_ref* tmp = ref_strings;
73while(tmp)
74{
75if(tmp->id == id) return tmp->string;
76tmp = tmp->next;
77}
78//verbose("Unable to locate Ref String %d\n", id);
79return "Unknown";
80}
81
82#define USEMALLOC 1
83#define DOFREE 1
84
85static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
86static long ParseTagKey(char *buffer, TagPtr *tag);
87static long ParseTagString(char *buffer, TagPtr *tag);
88static long ParseTagInteger(char *buffer, TagPtr *tag);
89static long ParseTagData(char *buffer, TagPtr *tag);
90static long ParseTagDate(char *buffer, TagPtr *tag);
91static long ParseTagBoolean(char *buffer, TagPtr *tag, long type);
92static long GetNextTag(char *buffer, char **tag, long *start);
93static long FixDataMatchingTag(char *buffer, char *tag);
94static TagPtr NewTag(void);
95static char *NewSymbol(char *string);
96#if DOFREE
97static void FreeSymbol(char *string);
98#endif
99
100
101//==========================================================================
102// XMLGetProperty
103
104TagPtr
105XMLGetProperty( TagPtr dict, const char * key )
106{
107 TagPtr tagList, tag;
108
109 ASSERT_DICT
110
111 if (dict->type != kTagTypeDict) return 0;
112
113 tag = 0;
114 tagList = dict->tag;
115 while (tagList)
116 {
117 tag = tagList;
118 tagList = tag->tagNext;
119
120 if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;
121
122 if (!strcmp(tag->string, key)) return tag->tag;
123 }
124
125 return 0;
126}
127
128
129// XMLGetTag(int index)
130
131// XMLTagCount( TagPtr dict )
132int XMLTagCount( TagPtr dict )
133{
134int count = 0;
135TagPtr tagList, tag;
136
137 ASSERT_DICT
138
139 if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) return 0;
140tag = 0;
141 tagList = dict->tag;
142 while (tagList)
143 {
144tag = tagList;
145 tagList = tag->tagNext;
146
147if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0)))
148&& (dict->type != kTagTypeArray)// If we are an array, any element is valid
149) continue;
150
151//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string);
152
153count++;
154 }
155
156return count;
157}
158
159TagPtr XMLGetElement( TagPtr dict, int id )
160{
161 ASSERT_DICT
162
163if(dict->type != kTagTypeArray) return 0;
164
165int element = 0;
166TagPtr tmp = dict->tag;
167
168while(element < id)
169{
170element++;
171tmp = tmp->tagNext;
172}
173
174return tmp;
175}
176/* Function for basic XML character entities parsing */
177
178char*
179XMLDecode(const char* src)
180{
181 typedef const struct XMLEntity {
182 const char* name;
183 size_t nameLen;
184 char value;
185 } XMLEntity;
186
187 /* This is ugly, but better than specifying the lengths by hand */
188#define _e(str,c) {str,sizeof(str)-1,c}
189 const XMLEntity ents[] = {
190 _e("quot;",'"'), _e("apos;",'\''),
191 _e("lt;", '<'), _e("gt;", '>'),
192 _e("amp;", '&')
193 };
194
195 size_t len;
196 const char *s;
197 char *out, *o;
198
199 if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) )
200 return 0;
201
202 o = out;
203 s = src;
204 while (s <= src+len) /* Make sure the terminator is also copied */
205 {
206 if ( *s == '&' )
207 {
208 bool entFound = false;
209 int i;
210
211 s++;
212 for ( i = 0; (unsigned)i < sizeof(ents); i++)
213 {
214 if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 )
215 {
216 entFound = true;
217 break;
218 }
219 }
220 if ( entFound )
221 {
222 *o++ = ents[i].value;
223 s += ents[i].nameLen;
224 continue;
225 }
226 }
227
228 *o++ = *s++;
229 }
230
231 return out;
232}
233
234//==========================================================================
235// XMLParseFile
236// Expects to see one dictionary in the XML file, the final pos will be returned
237// If the pos is not equal to the strlen, then there are multiple dicts
238// Puts the first dictionary it finds in the
239// tag pointer and returns the end of the dic, or returns -1 if not found.
240//
241long
242XMLParseFile( char * buffer, TagPtr * dict )
243{
244 long length, pos;
245 TagPtr tag;
246 pos = 0;
247char *configBuffer;
248
249
250
251 configBuffer = malloc(strlen(buffer)+1);
252 strcpy(configBuffer, buffer);
253
254buffer_start = configBuffer;
255
256 while (1)
257 {
258 length = XMLParseNextTag(configBuffer + pos, &tag);
259 if (length == -1) break;
260
261 pos += length;
262
263 if (tag == 0) continue;
264 if (tag->type == kTagTypeDict) break;
265
266 XMLFreeTag(tag);
267 }
268free(configBuffer);
269if (length < 0) {
270 return -1;
271 }
272 *dict = tag;
273 return pos;
274}
275
276//==========================================================================
277// ParseNextTag
278// TODO: cleanup
279long
280XMLParseNextTag( char * buffer, TagPtr * tag )
281{
282long length, pos;
283char * tagName;
284
285 length = GetNextTag(buffer, &tagName, 0);
286 if (length == -1) return -1;
287
288pos = length;
289 if (!strncmp(tagName, kXMLTagPList, 6))
290 {
291 length = 0;
292 }
293/***** dict ****/
294 else if (!strcmp(tagName, kXMLTagDict))
295 {
296 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
297 }
298 else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/')
299 {
300 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);
301 }
302 else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " ")))
303 {
304 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
305 }
306/***** key ****/
307 else if (!strcmp(tagName, kXMLTagKey))
308 {
309 length = ParseTagKey(buffer + pos, tag);
310 }
311
312/***** string ****/
313 else if (!strcmp(tagName, kXMLTagString))
314 {
315 length = ParseTagString(buffer + pos, tag);
316 }
317 else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " ")))
318 {
319// TODO: save tag if if found
320if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID)))
321{
322// ID=
323int id = 0;
324int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1;
325while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
326tagName[cnt] = 0;
327char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\"");
328while(*val)
329{
330if ((*val >= '0' && *val <= '9'))// 0 - 9
331{
332id = (id * 10) + (*val++ - '0');
333}
334else
335{
336printf("ParseStringID error (0x%x)\n", *val);
337getc();
338return -1;
339
340}
341
342}
343length = ParseTagString(buffer + pos, tag);
344
345SaveRefString(buffer + pos, id);
346}
347else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
348{
349// IDREF=
350int id = 0;
351int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1;
352while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
353tagName[cnt] = 0;
354char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\"");
355while(*val)
356{
357if ((*val >= '0' && *val <= '9'))// 0 - 9
358{
359id = (id * 10) + (*val++ - '0');
360}
361else
362{
363printf("ParseStringIDREF error (0x%x)\n", *val);
364getc();
365return -1;
366
367}
368
369}
370char* str = GetRefString(id);
371
372TagPtr tmpTag = NewTag();
373tmpTag->type = kTagTypeString;
374tmpTag->string = str;
375tmpTag->tag = 0;
376tmpTag->tagNext = 0;
377tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
378*tag = tmpTag;
379
380length = 0;
381//printf("Located IDREF, id = %d, string = %s\n", id, str);
382}
383
384 }
385
386/***** integer ****/
387 else if (!strcmp(tagName, kXMLTagInteger))
388 {
389 length = ParseTagInteger(buffer + pos, tag);
390 }
391 else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " ")))
392 {
393if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID)))
394{
395// ID=
396int id = 0;
397int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1;
398while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
399tagName[cnt] = 0;
400char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\"");
401while(*val)
402{
403if ((*val >= '0' && *val <= '9'))// 0 - 9
404{
405id = (id * 10) + (*val++ - '0');
406}
407else
408{
409printf("ParseIntegerID error (0x%x)\n", *val);
410getc();
411return -1;
412
413}
414
415}
416length = ParseTagInteger(buffer + pos, tag);
417
418SaveRefString((*tag)->string, id);
419}
420else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
421{
422// IDREF=
423int id = 0;
424int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1;
425while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
426tagName[cnt] = 0;
427char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\"");
428while(*val)
429{
430if ((*val >= '0' && *val <= '9'))// 0 - 9
431{
432id = (id * 10) + (*val++ - '0');
433}
434else
435{
436printf("ParseStringIDREF error (0x%x)\n", *val);
437getc();
438return -1;
439
440}
441
442}
443int integer = (int)GetRefString(id);
444
445TagPtr tmpTag = NewTag();
446 if (tmpTag == 0) return -1;
447
448tmpTag->type = kTagTypeInteger;
449tmpTag->string = (char*) integer;
450tmpTag->tag = 0;
451tmpTag->tagNext = 0;
452tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
453
454*tag = tmpTag;
455
456length = 0;
457//printf("Located IDREF, id = %d, string = %s\n", id, str);
458}
459 else
460{
461length = ParseTagInteger(buffer + pos, tag);
462}
463}
464
465/***** data ****/
466 else if (!strcmp(tagName, kXMLTagData))
467 {
468 length = ParseTagData(buffer + pos, tag);
469 }
470else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))
471 {
472 length = ParseTagData(buffer + pos, tag);
473 }
474 else if (!strcmp(tagName, kXMLTagDate))
475 {
476 length = ParseTagDate(buffer + pos, tag);
477 }
478
479/***** date ****/
480else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))
481 {
482 length = ParseTagDate(buffer + pos, tag);
483 }
484
485/***** false ****/
486 else if (!strcmp(tagName, kXMLTagFalse))
487 {
488 length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
489 }
490/***** true ****/
491 else if (!strcmp(tagName, kXMLTagTrue))
492 {
493 length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
494 }
495
496/***** array ****/
497 else if (!strcmp(tagName, kXMLTagArray))
498 {
499 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
500 }
501else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))
502 {
503 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
504 }
505 else if (!strcmp(tagName, kXMLTagArray "/"))
506 {
507 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
508 }
509
510/***** unknown ****/
511 else
512 {
513 *tag = 0;
514 length = 0;
515 }
516
517
518 if (length == -1) return -1;
519
520 return pos + length;
521}
522
523//==========================================================================
524// ParseTagList
525
526static long
527ParseTagList( char * buffer, TagPtr * tag, long type, long empty )
528{
529long length, pos;
530TagPtr tagList, tmpTag;
531
532 tagList = 0;
533 pos = 0;
534
535 if (!empty)
536 {
537 while (1)
538 {
539 length = XMLParseNextTag(buffer + pos, &tmpTag);
540 if (length == -1) break;
541
542 pos += length;
543
544 if (tmpTag == 0) break;
545 tmpTag->tagNext = tagList;
546 tagList = tmpTag;
547 }
548
549 if (length == -1)
550 {
551 XMLFreeTag(tagList);
552 return -1;
553 }
554 }
555
556 tmpTag = NewTag();
557 if (tmpTag == 0)
558 {
559 XMLFreeTag(tagList);
560 return -1;
561 }
562
563 tmpTag->type = type;
564 tmpTag->string = 0;
565tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
566 tmpTag->tag = tagList;
567 tmpTag->tagNext = 0;
568
569 *tag = tmpTag;
570
571 return pos;
572}
573
574//==========================================================================
575// ParseTagKey
576
577static long
578ParseTagKey( char * buffer, TagPtr * tag )
579{
580 long length, length2;
581 char *string;
582 TagPtr tmpTag, subTag;
583
584 length = FixDataMatchingTag(buffer, kXMLTagKey);
585 if (length == -1) return -1;
586
587 length2 = XMLParseNextTag(buffer + length, &subTag);
588 if (length2 == -1) return -1;
589
590 tmpTag = NewTag();
591 if (tmpTag == 0)
592 {
593 XMLFreeTag(subTag);
594 return -1;
595 }
596
597 string = NewSymbol(buffer);
598 if (string == 0)
599 {
600 XMLFreeTag(subTag);
601 XMLFreeTag(tmpTag);
602 return -1;
603 }
604
605 tmpTag->type = kTagTypeKey;
606 tmpTag->string = string;
607 tmpTag->tag = subTag;
608tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
609 tmpTag->tagNext = 0;
610
611 *tag = tmpTag;
612
613 return length + length2;
614}
615
616//==========================================================================
617// ParseTagString
618
619static long
620ParseTagString( char * buffer, TagPtr * tag )
621{
622 long length;
623 char * string;
624 TagPtr tmpTag;
625
626 length = FixDataMatchingTag(buffer, kXMLTagString);
627 if (length == -1) return -1;
628
629 tmpTag = NewTag();
630 if (tmpTag == 0) return -1;
631
632 string = NewSymbol(buffer);
633 if (string == 0)
634 {
635 XMLFreeTag(tmpTag);
636 return -1;
637 }
638
639 tmpTag->type = kTagTypeString;
640 tmpTag->string = string;
641 tmpTag->tag = 0;
642tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
643 tmpTag->tagNext = 0;
644
645 *tag = tmpTag;
646 return length;
647}
648
649//==========================================================================
650// ParseTagInteger
651
652static long
653ParseTagInteger( char * buffer, TagPtr * tag )
654{
655 long length, integer;
656bool negative = false;
657 TagPtr tmpTag;
658char* val = buffer;
659 int size;
660
661 tmpTag = NewTag();
662 if (tmpTag == 0) return -1;
663
664if(buffer[0] == '<')
665{
666printf("Warning integer is non existant\n");
667getc();
668tmpTag->type = kTagTypeInteger;
669tmpTag->string = 0;
670tmpTag->tag = 0;
671tmpTag->offset = 0;
672tmpTag->tagNext = 0;
673
674*tag = tmpTag;
675
676return 0;
677}
678
679 size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
680 if (length == -1) return -1;
681
682 integer = 0;
683
684if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
685{
686val += 2;
687while(*val)
688{
689if ((*val >= '0' && *val <= '9'))// 0 - 9
690{
691integer = (integer * 16) + (*val++ - '0');
692}
693else if ((*val >= 'a' && *val <= 'f'))// a - f
694{
695integer = (integer * 16) + (*val++ - 'a' + 10);
696}
697else if ((*val >= 'A' && *val <= 'F'))// A - F
698{
699integer = (integer * 16) + (*val++ - 'a' + 10);
700}
701else
702{
703printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
704getc();
705return -1;
706
707}
708
709}
710}
711else if ( size )// Decimal value
712{
713if (*val == '-')
714{
715negative = true;
716val++;
717size--;
718}
719
720for (integer = 0; size > 0; size--)
721{
722if(*val) // UGLY HACK, fix me.
723{
724if (*val < '0' || *val > '9')
725{
726printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
727getc();
728return -1;
729}
730
731integer = (integer * 10) + (*val++ - '0');
732}
733}
734
735if (negative)
736integer = -integer;
737}
738
739 tmpTag->type = kTagTypeInteger;
740tmpTag->string = (char *)integer;
741tmpTag->tag = 0;
742tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
743 tmpTag->tagNext = 0;
744
745 *tag = tmpTag;
746
747 return length;
748}
749
750//==========================================================================
751// ParseTagData
752
753static long
754ParseTagData( char * buffer, TagPtr * tag )
755{
756 long length;
757 TagPtr tmpTag;
758
759 length = FixDataMatchingTag(buffer, kXMLTagData);
760 if (length == -1) return -1;
761
762 tmpTag = NewTag();
763 if (tmpTag == 0) return -1;
764
765//printf("ParseTagData unimplimented\n");
766//printf("Data: %s\n", buffer);
767//getc();
768
769// TODO: base64 decode
770
771char* string = NewSymbol(buffer);
772 tmpTag->type = kTagTypeData;
773 tmpTag->string = string;
774 tmpTag->tag = 0;
775tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
776 tmpTag->tagNext = 0;
777
778 *tag = tmpTag;
779
780 return length;
781}
782
783//==========================================================================
784// ParseTagDate
785
786static long
787ParseTagDate( char * buffer, TagPtr * tag )
788{
789 long length;
790 TagPtr tmpTag;
791
792 length = FixDataMatchingTag(buffer, kXMLTagDate);
793 if (length == -1) return -1;
794
795 tmpTag = NewTag();
796 if (tmpTag == 0) return -1;
797
798printf("ParseTagDate unimplimented\n");
799getc();
800
801 tmpTag->type = kTagTypeDate;
802 tmpTag->string = 0;
803 tmpTag->tag = 0;
804tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
805 tmpTag->tagNext = 0;
806
807 *tag = tmpTag;
808
809 return length;
810}
811
812//==========================================================================
813// ParseTagBoolean
814
815static long
816ParseTagBoolean( char * buffer, TagPtr * tag, long type )
817{
818 TagPtr tmpTag;
819
820 tmpTag = NewTag();
821 if (tmpTag == 0) return -1;
822
823 tmpTag->type = type;
824 tmpTag->string = 0;
825 tmpTag->tag = 0;
826tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
827 tmpTag->tagNext = 0;
828
829 *tag = tmpTag;
830
831 return 0;
832}
833
834//==========================================================================
835// GetNextTag
836
837static long
838GetNextTag( char * buffer, char ** tag, long * start )
839{
840 long cnt, cnt2;
841
842 if (tag == 0) return -1;
843
844 // Find the start of the tag.
845 cnt = 0;
846 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
847 if (buffer[cnt] == '\0') return -1;
848
849 // Find the end of the tag.
850 cnt2 = cnt + 1;
851 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
852 if (buffer[cnt2] == '\0') return -1;
853
854 // Fix the tag data.
855 *tag = buffer + cnt + 1;
856 buffer[cnt2] = '\0';
857 if (start) *start = cnt;
858
859 return cnt2 + 1;
860}
861
862//==========================================================================
863// FixDataMatchingTag
864// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
865// Returns the length of the data found, counting the end tag,
866// or -1 if the end tag was not found.
867
868static long
869FixDataMatchingTag( char * buffer, char * tag )
870{
871 long length, start, stop;
872 char * endTag;
873
874 start = 0;
875 while (1)
876 {
877 length = GetNextTag(buffer + start, &endTag, &stop);
878 if (length == -1) return -1;
879
880 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
881 start += length;
882 }
883
884 buffer[start + stop] = '\0';
885
886 return start + length;
887}
888
889//==========================================================================
890// NewTag
891
892#define kTagsPerBlock (0x1000)
893
894static TagPtr gTagsFree;
895
896static TagPtr
897NewTag( void )
898{
899long cnt;
900TagPtr tag;
901
902 if (gTagsFree == 0)
903 {
904#if USEMALLOC
905 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
906#else
907 tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag));
908#endif
909 if (tag == 0) return 0;
910
911 // Initalize the new tags.
912 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
913 {
914 tag[cnt].type = kTagTypeNone;
915 tag[cnt].string = 0;
916 tag[cnt].tag = 0;
917 tag[cnt].tagNext = tag + cnt + 1;
918 }
919 tag[kTagsPerBlock - 1].tagNext = 0;
920
921 gTagsFree = tag;
922 }
923
924 tag = gTagsFree;
925 gTagsFree = tag->tagNext;
926
927 return tag;
928}
929
930//==========================================================================
931// XMLFreeTag
932
933void
934XMLFreeTag( TagPtr tag )
935{
936#if DOFREE
937 if (tag == 0) return;
938
939 if (tag->string) FreeSymbol(tag->string);
940
941 XMLFreeTag(tag->tag);
942 XMLFreeTag(tag->tagNext);
943
944 // Clear and free the tag.
945 tag->type = kTagTypeNone;
946 tag->string = 0;
947 tag->tag = 0;
948tag->offset = 0;
949 tag->tagNext = gTagsFree;
950 gTagsFree = tag;
951#else
952 return;
953#endif
954}
955
956//==========================================================================
957// Symbol object.
958
959struct Symbol
960{
961 long refCount;
962 struct Symbol *next;
963 char string[];
964};
965typedef struct Symbol Symbol, *SymbolPtr;
966
967static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
968
969static SymbolPtr gSymbolsHead;
970
971//==========================================================================
972// NewSymbol
973
974static char *
975NewSymbol( char * string )
976{
977 static SymbolPtr lastGuy = 0;
978SymbolPtr symbol;
979
980 // Look for string in the list of symbols.
981 symbol = FindSymbol(string, 0);
982
983 // Add the new symbol.
984 if (symbol == 0)
985 {
986#if USEMALLOC
987 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
988#else
989 symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol) + 1 + strlen(string));
990#endif
991 if (symbol == 0) {
992 stop("NULL symbol!");
993 return 0;
994 }
995 // Set the symbol's data.
996 symbol->refCount = 0;
997 strcpy(symbol->string, string);
998
999 // Add the symbol to the list.
1000 symbol->next = gSymbolsHead;
1001 gSymbolsHead = symbol;
1002 }
1003
1004 // Update the refCount and return the string.
1005 symbol->refCount++;
1006
1007 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
1008 return symbol->string;
1009}
1010
1011//==========================================================================
1012// FreeSymbol
1013
1014#if DOFREE
1015static void
1016FreeSymbol( char * string )
1017{
1018 SymbolPtr symbol, prev;
1019prev = 0;
1020
1021 // Look for string in the list of symbols.
1022 symbol = FindSymbol(string, &prev);
1023 if (symbol == 0) return;
1024
1025 // Update the refCount.
1026 symbol->refCount--;
1027
1028 if (symbol->refCount != 0) return;
1029
1030 // Remove the symbol from the list.
1031 if (prev != 0) prev->next = symbol->next;
1032 else gSymbolsHead = symbol->next;
1033
1034 // Free the symbol's memory.
1035 free(symbol);
1036}
1037#endif
1038
1039//==========================================================================
1040// FindSymbol
1041
1042static SymbolPtr
1043FindSymbol( char * string, SymbolPtr * prevSymbol )
1044{
1045 SymbolPtr symbol, prev;
1046
1047 symbol = gSymbolsHead;
1048 prev = 0;
1049
1050 while (symbol != 0) {
1051 if (!strcmp(symbol->string, string)) break;
1052
1053 prev = symbol;
1054 symbol = symbol->next;
1055 }
1056
1057 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
1058
1059 return symbol;
1060}
1061
1062
1063
1064bool XMLIsType(TagPtr dict, enum xmltype type)
1065{
1066if(!dict) return (type == kTagTypeNone);
1067return (dict->type == (long)type);
1068}
1069
1070
1071/*** Cast functions ***/
1072TagPtr XMLCastArray(TagPtr dict)
1073{
1074if(!dict) return NULL;
1075if(dict->type == kTagTypeArray) return dict;
1076else return NULL;
1077}
1078
1079
1080TagPtr XMLCastDict(TagPtr dict)
1081{
1082if(!dict) return NULL;
1083if(dict->type == kTagTypeDict) return dict;
1084else return NULL;
1085}
1086
1087char* XMLCastString(TagPtr dict)
1088{
1089if(!dict) return NULL;
1090
1091if((dict->type == kTagTypeString) ||
1092 (dict->type == kTagTypeKey)) return dict->string;
1093
1094return NULL;
1095}
1096
1097long XMLCastStringOffset(TagPtr dict)
1098{
1099if(dict &&
1100 ((dict->type == kTagTypeString) ||
1101 (dict->type == kTagTypeKey)))
1102{
1103return dict->offset;
1104}
1105else
1106{
1107return -1;
1108}
1109}
1110
1111
1112bool XMLCastBoolean(TagPtr dict)
1113{
1114if(!dict) return false;
1115if(dict->type == kTagTypeTrue) return true;
1116return false;
1117}
1118
1119int XMLCastInteger(TagPtr dict)
1120{
1121if(!dict)
1122{
1123printf("XMLCastInteger: null dict\n");
1124return 0;
1125}
1126if(dict->type == kTagTypeInteger) return (int)(dict->string);
1127return 0;
1128}
1129

Archive Download this file

Revision: 1929