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
151if(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();
446tmpTag->type = kTagTypeInteger;
447tmpTag->string = (char*) integer;
448tmpTag->tag = 0;
449tmpTag->tagNext = 0;
450tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
451
452*tag = tmpTag;
453
454length = 0;
455//printf("Located IDREF, id = %d, string = %s\n", id, str);
456}
457 else
458{
459length = ParseTagInteger(buffer + pos, tag);
460}
461}
462
463/***** data ****/
464 else if (!strcmp(tagName, kXMLTagData))
465 {
466 length = ParseTagData(buffer + pos, tag);
467 }
468else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))
469 {
470 length = ParseTagData(buffer + pos, tag);
471 }
472 else if (!strcmp(tagName, kXMLTagDate))
473 {
474 length = ParseTagDate(buffer + pos, tag);
475 }
476
477/***** date ****/
478else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))
479 {
480 length = ParseTagDate(buffer + pos, tag);
481 }
482
483/***** false ****/
484 else if (!strcmp(tagName, kXMLTagFalse))
485 {
486 length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
487 }
488/***** true ****/
489 else if (!strcmp(tagName, kXMLTagTrue))
490 {
491 length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
492 }
493
494/***** array ****/
495 else if (!strcmp(tagName, kXMLTagArray))
496 {
497 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
498 }
499else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))
500 {
501 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
502 }
503 else if (!strcmp(tagName, kXMLTagArray "/"))
504 {
505 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
506 }
507
508/***** unknown ****/
509 else
510 {
511 *tag = 0;
512 length = 0;
513 }
514
515
516 if (length == -1) return -1;
517
518 return pos + length;
519}
520
521//==========================================================================
522// ParseTagList
523
524static long
525ParseTagList( char * buffer, TagPtr * tag, long type, long empty )
526{
527long length, pos;
528TagPtr tagList, tmpTag;
529
530 tagList = 0;
531 pos = 0;
532
533 if (!empty)
534 {
535 while (1)
536 {
537 length = XMLParseNextTag(buffer + pos, &tmpTag);
538 if (length == -1) break;
539
540 pos += length;
541
542 if (tmpTag == 0) break;
543 tmpTag->tagNext = tagList;
544 tagList = tmpTag;
545 }
546
547 if (length == -1)
548 {
549 XMLFreeTag(tagList);
550 return -1;
551 }
552 }
553
554 tmpTag = NewTag();
555 if (tmpTag == 0)
556 {
557 XMLFreeTag(tagList);
558 return -1;
559 }
560
561 tmpTag->type = type;
562 tmpTag->string = 0;
563tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
564 tmpTag->tag = tagList;
565 tmpTag->tagNext = 0;
566
567 *tag = tmpTag;
568
569 return pos;
570}
571
572//==========================================================================
573// ParseTagKey
574
575static long
576ParseTagKey( char * buffer, TagPtr * tag )
577{
578 long length, length2;
579 char *string;
580 TagPtr tmpTag, subTag;
581
582 length = FixDataMatchingTag(buffer, kXMLTagKey);
583 if (length == -1) return -1;
584
585 length2 = XMLParseNextTag(buffer + length, &subTag);
586 if (length2 == -1) return -1;
587
588 tmpTag = NewTag();
589 if (tmpTag == 0)
590 {
591 XMLFreeTag(subTag);
592 return -1;
593 }
594
595 string = NewSymbol(buffer);
596 if (string == 0)
597 {
598 XMLFreeTag(subTag);
599 XMLFreeTag(tmpTag);
600 return -1;
601 }
602
603 tmpTag->type = kTagTypeKey;
604 tmpTag->string = string;
605 tmpTag->tag = subTag;
606tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
607 tmpTag->tagNext = 0;
608
609 *tag = tmpTag;
610
611 return length + length2;
612}
613
614//==========================================================================
615// ParseTagString
616
617static long
618ParseTagString( char * buffer, TagPtr * tag )
619{
620 long length;
621 char * string;
622 TagPtr tmpTag;
623
624 length = FixDataMatchingTag(buffer, kXMLTagString);
625 if (length == -1) return -1;
626
627 tmpTag = NewTag();
628 if (tmpTag == 0) return -1;
629
630 string = NewSymbol(buffer);
631 if (string == 0)
632 {
633 XMLFreeTag(tmpTag);
634 return -1;
635 }
636
637 tmpTag->type = kTagTypeString;
638 tmpTag->string = string;
639 tmpTag->tag = 0;
640tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
641 tmpTag->tagNext = 0;
642
643 *tag = tmpTag;
644 return length;
645}
646
647//==========================================================================
648// ParseTagInteger
649
650static long
651ParseTagInteger( char * buffer, TagPtr * tag )
652{
653 long length, integer;
654bool negative = false;
655 TagPtr tmpTag = 0;
656char* val = buffer;
657 int size;
658
659
660if(buffer[0] == '<')
661{
662printf("Warning integer is non existant\n");
663getc();
664tmpTag->type = kTagTypeInteger;
665tmpTag->string = 0;
666tmpTag->tag = 0;
667tmpTag->offset = 0;
668tmpTag->tagNext = 0;
669
670*tag = tmpTag;
671
672return 0;
673}
674
675 size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
676 if (length == -1) return -1;
677
678 tmpTag = NewTag();
679 if (tmpTag == 0) return -1;
680
681 integer = 0;
682
683if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
684{
685val += 2;
686while(*val)
687{
688if ((*val >= '0' && *val <= '9'))// 0 - 9
689{
690integer = (integer * 16) + (*val++ - '0');
691}
692else if ((*val >= 'a' && *val <= 'f'))// a - f
693{
694integer = (integer * 16) + (*val++ - 'a' + 10);
695}
696else if ((*val >= 'A' && *val <= 'F'))// A - F
697{
698integer = (integer * 16) + (*val++ - 'a' + 10);
699}
700else
701{
702printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
703getc();
704return -1;
705
706}
707
708}
709}
710else if ( size )// Decimal value
711{
712if (*val == '-')
713{
714negative = true;
715val++;
716size--;
717}
718
719for (integer = 0; size > 0; size--)
720{
721if(*val) // UGLY HACK, fix me.
722{
723if (*val < '0' || *val > '9')
724{
725printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
726getc();
727return -1;
728}
729
730integer = (integer * 10) + (*val++ - '0');
731}
732}
733
734if (negative)
735integer = -integer;
736}
737
738 tmpTag->type = kTagTypeInteger;
739tmpTag->string = (char *)integer;
740tmpTag->tag = 0;
741tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
742 tmpTag->tagNext = 0;
743
744 *tag = tmpTag;
745
746 return length;
747}
748
749//==========================================================================
750// ParseTagData
751
752static long
753ParseTagData( char * buffer, TagPtr * tag )
754{
755 long length;
756 TagPtr tmpTag;
757
758 length = FixDataMatchingTag(buffer, kXMLTagData);
759 if (length == -1) return -1;
760
761 tmpTag = NewTag();
762 if (tmpTag == 0) return -1;
763
764//printf("ParseTagData unimplimented\n");
765//printf("Data: %s\n", buffer);
766//getc();
767
768// TODO: base64 decode
769
770char* string = NewSymbol(buffer);
771 tmpTag->type = kTagTypeData;
772 tmpTag->string = string;
773 tmpTag->tag = 0;
774tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
775 tmpTag->tagNext = 0;
776
777 *tag = tmpTag;
778
779 return length;
780}
781
782//==========================================================================
783// ParseTagDate
784
785static long
786ParseTagDate( char * buffer, TagPtr * tag )
787{
788 long length;
789 TagPtr tmpTag;
790
791 length = FixDataMatchingTag(buffer, kXMLTagDate);
792 if (length == -1) return -1;
793
794 tmpTag = NewTag();
795 if (tmpTag == 0) return -1;
796
797printf("ParseTagDate unimplimented\n");
798getc();
799
800 tmpTag->type = kTagTypeDate;
801 tmpTag->string = 0;
802 tmpTag->tag = 0;
803tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
804 tmpTag->tagNext = 0;
805
806 *tag = tmpTag;
807
808 return length;
809}
810
811//==========================================================================
812// ParseTagBoolean
813
814static long
815ParseTagBoolean( char * buffer, TagPtr * tag, long type )
816{
817 TagPtr tmpTag;
818
819 tmpTag = NewTag();
820 if (tmpTag == 0) return -1;
821
822 tmpTag->type = type;
823 tmpTag->string = 0;
824 tmpTag->tag = 0;
825tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
826 tmpTag->tagNext = 0;
827
828 *tag = tmpTag;
829
830 return 0;
831}
832
833//==========================================================================
834// GetNextTag
835
836static long
837GetNextTag( char * buffer, char ** tag, long * start )
838{
839 long cnt, cnt2;
840
841 if (tag == 0) return -1;
842
843 // Find the start of the tag.
844 cnt = 0;
845 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
846 if (buffer[cnt] == '\0') return -1;
847
848 // Find the end of the tag.
849 cnt2 = cnt + 1;
850 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
851 if (buffer[cnt2] == '\0') return -1;
852
853 // Fix the tag data.
854 *tag = buffer + cnt + 1;
855 buffer[cnt2] = '\0';
856 if (start) *start = cnt;
857
858 return cnt2 + 1;
859}
860
861//==========================================================================
862// FixDataMatchingTag
863// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
864// Returns the length of the data found, counting the end tag,
865// or -1 if the end tag was not found.
866
867static long
868FixDataMatchingTag( char * buffer, char * tag )
869{
870 long length, start, stop;
871 char * endTag;
872
873 start = 0;
874 while (1)
875 {
876 length = GetNextTag(buffer + start, &endTag, &stop);
877 if (length == -1) return -1;
878
879 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
880 start += length;
881 }
882
883 buffer[start + stop] = '\0';
884
885 return start + length;
886}
887
888//==========================================================================
889// NewTag
890
891#define kTagsPerBlock (0x1000)
892
893static TagPtr gTagsFree;
894
895static TagPtr
896NewTag( void )
897{
898long cnt;
899TagPtr tag;
900
901 if (gTagsFree == 0)
902 {
903#if USEMALLOC
904 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
905#else
906 tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag));
907#endif
908 if (tag == 0) return 0;
909
910 // Initalize the new tags.
911 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
912 {
913 tag[cnt].type = kTagTypeNone;
914 tag[cnt].string = 0;
915 tag[cnt].tag = 0;
916 tag[cnt].tagNext = tag + cnt + 1;
917 }
918 tag[kTagsPerBlock - 1].tagNext = 0;
919
920 gTagsFree = tag;
921 }
922
923 tag = gTagsFree;
924 gTagsFree = tag->tagNext;
925
926 return tag;
927}
928
929//==========================================================================
930// XMLFreeTag
931
932void
933XMLFreeTag( TagPtr tag )
934{
935#if DOFREE
936 if (tag == 0) return;
937
938 if (tag->string) FreeSymbol(tag->string);
939
940 XMLFreeTag(tag->tag);
941 XMLFreeTag(tag->tagNext);
942
943 // Clear and free the tag.
944 tag->type = kTagTypeNone;
945 tag->string = 0;
946 tag->tag = 0;
947tag->offset = 0;
948 tag->tagNext = gTagsFree;
949 gTagsFree = tag;
950#else
951 return;
952#endif
953}
954
955//==========================================================================
956// Symbol object.
957
958struct Symbol
959{
960 long refCount;
961 struct Symbol *next;
962 char string[];
963};
964typedef struct Symbol Symbol, *SymbolPtr;
965
966static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
967
968static SymbolPtr gSymbolsHead;
969
970//==========================================================================
971// NewSymbol
972
973static char *
974NewSymbol( char * string )
975{
976 static SymbolPtr lastGuy = 0;
977SymbolPtr symbol;
978
979 // Look for string in the list of symbols.
980 symbol = FindSymbol(string, 0);
981
982 // Add the new symbol.
983 if (symbol == 0)
984 {
985#if USEMALLOC
986 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
987#else
988 symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol) + 1 + strlen(string));
989#endif
990 if (symbol == 0) {
991 stop("NULL symbol!");
992 return 0;
993 }
994 // Set the symbol's data.
995 symbol->refCount = 0;
996 strcpy(symbol->string, string);
997
998 // Add the symbol to the list.
999 symbol->next = gSymbolsHead;
1000 gSymbolsHead = symbol;
1001 }
1002
1003 // Update the refCount and return the string.
1004 symbol->refCount++;
1005
1006 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
1007 return symbol->string;
1008}
1009
1010//==========================================================================
1011// FreeSymbol
1012
1013#if DOFREE
1014static void
1015FreeSymbol( char * string )
1016{
1017 SymbolPtr symbol, prev;
1018prev = 0;
1019
1020 // Look for string in the list of symbols.
1021 symbol = FindSymbol(string, &prev);
1022 if (symbol == 0) return;
1023
1024 // Update the refCount.
1025 symbol->refCount--;
1026
1027 if (symbol->refCount != 0) return;
1028
1029 // Remove the symbol from the list.
1030 if (prev != 0) prev->next = symbol->next;
1031 else gSymbolsHead = symbol->next;
1032
1033 // Free the symbol's memory.
1034 free(symbol);
1035}
1036#endif
1037
1038//==========================================================================
1039// FindSymbol
1040
1041static SymbolPtr
1042FindSymbol( char * string, SymbolPtr * prevSymbol )
1043{
1044 SymbolPtr symbol, prev;
1045
1046 symbol = gSymbolsHead;
1047 prev = 0;
1048
1049 while (symbol != 0) {
1050 if (!strcmp(symbol->string, string)) break;
1051
1052 prev = symbol;
1053 symbol = symbol->next;
1054 }
1055
1056 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
1057
1058 return symbol;
1059}
1060
1061
1062
1063bool XMLIsType(TagPtr dict, enum xmltype type)
1064{
1065if(!dict) return (type == kTagTypeNone);
1066return (dict->type == (long)type);
1067}
1068
1069
1070/*** Cast functions ***/
1071TagPtr XMLCastArray(TagPtr dict)
1072{
1073if(!dict) return NULL;
1074if(dict->type == kTagTypeArray) return dict;
1075else return NULL;
1076}
1077
1078
1079TagPtr XMLCastDict(TagPtr dict)
1080{
1081if(!dict) return NULL;
1082if(dict->type == kTagTypeDict) return dict;
1083else return NULL;
1084}
1085
1086char* XMLCastString(TagPtr dict)
1087{
1088if(!dict) return NULL;
1089
1090if((dict->type == kTagTypeString) ||
1091 (dict->type == kTagTypeKey)) return dict->string;
1092
1093return NULL;
1094}
1095
1096long XMLCastStringOffset(TagPtr dict)
1097{
1098if(dict &&
1099 ((dict->type == kTagTypeString) ||
1100 (dict->type == kTagTypeKey)))
1101{
1102return dict->offset;
1103}
1104else
1105{
1106return -1;
1107}
1108}
1109
1110
1111bool XMLCastBoolean(TagPtr dict)
1112{
1113if(!dict) return false;
1114if(dict->type == kTagTypeTrue) return true;
1115return false;
1116}
1117
1118int XMLCastInteger(TagPtr dict)
1119{
1120if(!dict)
1121{
1122printf("XMLCastInteger: null dict\n");
1123return 0;
1124}
1125if(dict->type == kTagTypeInteger) return (int)(dict->string);
1126return 0;
1127}
1128

Archive Download this file

Revision: 1913