Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 899