Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2249