Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/libsaio/xml.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
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); 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 long length;
797 TagPtr tmpTag;
798
799 length = FixDataMatchingTag(buffer, kXMLTagData);
800 if (length == -1) return -1;
801
802 tmpTag = NewTag();
803 if (tmpTag == 0) return -1;
804
805//printf("ParseTagData unimplimented\n");
806//printf("Data: %s\n", buffer);
807//getchar();
808
809// TODO: base64 decode
810
811char* string = NewSymbol(buffer);
812 tmpTag->type = kTagTypeData;
813 tmpTag->string = string;
814 tmpTag->tag = 0;
815tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
816 tmpTag->tagNext = 0;
817
818 *tag = tmpTag;
819
820 return length;
821}
822
823//==========================================================================
824// ParseTagDate
825
826static long
827ParseTagDate( char * buffer, TagPtr * tag )
828{
829 long length;
830 TagPtr tmpTag;
831
832 length = FixDataMatchingTag(buffer, kXMLTagDate);
833 if (length == -1) return -1;
834
835 tmpTag = NewTag();
836 if (tmpTag == 0) return -1;
837
838printf("ParseTagDate unimplimented\n");
839getchar();
840
841 tmpTag->type = kTagTypeDate;
842 tmpTag->string = 0;
843 tmpTag->tag = 0;
844tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
845 tmpTag->tagNext = 0;
846
847 *tag = tmpTag;
848
849 return length;
850}
851
852//==========================================================================
853// ParseTagBoolean
854
855long
856ParseTagBoolean( char * buffer, TagPtr * tag, long type )
857{
858 TagPtr tmpTag;
859
860 tmpTag = NewTag();
861 if (tmpTag == 0) return -1;
862
863 tmpTag->type = type;
864 tmpTag->string = 0;
865 tmpTag->tag = 0;
866tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
867 tmpTag->tagNext = 0;
868
869 *tag = tmpTag;
870
871 return 0;
872}
873
874//==========================================================================
875// GetNextTag
876
877static long
878GetNextTag( char * buffer, char ** tag, long * start )
879{
880 long cnt, cnt2;
881
882 if (tag == 0) return -1;
883
884 // Find the start of the tag.
885 cnt = 0;
886 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
887 if (buffer[cnt] == '\0') return -1;
888
889 // Find the end of the tag.
890 cnt2 = cnt + 1;
891 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
892 if (buffer[cnt2] == '\0') return -1;
893
894 // Fix the tag data.
895 *tag = buffer + cnt + 1;
896 buffer[cnt2] = '\0';
897 if (start) *start = cnt;
898
899 return cnt2 + 1;
900}
901
902//==========================================================================
903// FixDataMatchingTag
904// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
905// Returns the length of the data found, counting the end tag,
906// or -1 if the end tag was not found.
907
908static long
909FixDataMatchingTag( char * buffer, char * tag )
910{
911 long length, start, stop;
912 char * endTag;
913
914 start = 0;
915 while (1)
916 {
917 length = GetNextTag(buffer + start, &endTag, &stop);
918 if (length == -1) return -1;
919
920 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
921 start += length;
922 }
923
924 buffer[start + stop] = '\0';
925
926 return start + length;
927}
928
929//==========================================================================
930// NewTag
931
932#define kTagsPerBlock (0x1000)
933
934static TagPtr gTagsFree;
935
936static TagPtr
937NewTag( void )
938{
939long cnt;
940TagPtr tag;
941
942 if (gTagsFree == 0)
943 {
944 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
945 if (tag == 0) return 0;
946
947 // Initalize the new tags.
948 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
949 {
950 tag[cnt].type = kTagTypeNone;
951 tag[cnt].string = 0;
952 tag[cnt].tag = 0;
953 tag[cnt].tagNext = tag + cnt + 1;
954 }
955 tag[kTagsPerBlock - 1].tagNext = 0;
956
957 gTagsFree = tag;
958 }
959
960 tag = gTagsFree;
961 gTagsFree = tag->tagNext;
962
963 return tag;
964}
965
966//==========================================================================
967// XMLFreeTag
968
969void
970XMLFreeTag( TagPtr tag )
971{
972#if DOFREE
973 if (tag == 0) return;
974
975 if (tag->string) FreeSymbol(tag->string);
976
977 XMLFreeTag(tag->tag);
978 XMLFreeTag(tag->tagNext);
979
980 // Clear and free the tag.
981 tag->type = kTagTypeNone;
982 tag->string = 0;
983 tag->tag = 0;
984tag->offset = 0;
985 tag->tagNext = gTagsFree;
986 gTagsFree = tag;
987#else
988 return;
989#endif
990}
991
992//==========================================================================
993// Symbol object.
994
995struct Symbol
996{
997 long refCount;
998 struct Symbol *next;
999 char string[];
1000};
1001typedef struct Symbol Symbol, *SymbolPtr;
1002
1003static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
1004
1005static SymbolPtr gSymbolsHead;
1006
1007//==========================================================================
1008// NewSymbol
1009
1010static char *
1011NewSymbol( char * string )
1012{
1013static SymbolPtr lastGuy = 0;
1014SymbolPtr symbol;
1015
1016 // Look for string in the list of symbols.
1017 symbol = FindSymbol(string, 0);
1018
1019 // Add the new symbol.
1020 if (symbol == 0)
1021 {
1022 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1023 if (symbol == 0) //return 0;
1024 stop("NULL symbol!");
1025
1026 // Set the symbol's data.
1027 symbol->refCount = 0;
1028 strcpy(symbol->string, string);
1029
1030 // Add the symbol to the list.
1031 symbol->next = gSymbolsHead;
1032 gSymbolsHead = symbol;
1033 }
1034
1035 // Update the refCount and return the string.
1036 symbol->refCount++;
1037
1038 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
1039 return symbol->string;
1040}
1041
1042//==========================================================================
1043// FreeSymbol
1044
1045#if DOFREE
1046static void
1047FreeSymbol( char * string )
1048{
1049 SymbolPtr symbol, prev;
1050prev = 0;
1051
1052 // Look for string in the list of symbols.
1053 symbol = FindSymbol(string, &prev);
1054 if (symbol == 0) return;
1055
1056 // Update the refCount.
1057 symbol->refCount--;
1058
1059 if (symbol->refCount != 0) return;
1060
1061 // Remove the symbol from the list.
1062 if (prev != 0) prev->next = symbol->next;
1063 else gSymbolsHead = symbol->next;
1064
1065 // Free the symbol's memory.
1066 free(symbol);
1067}
1068#endif
1069
1070//==========================================================================
1071// FindSymbol
1072
1073static SymbolPtr
1074FindSymbol( char * string, SymbolPtr * prevSymbol )
1075{
1076 SymbolPtr symbol, prev;
1077
1078 symbol = gSymbolsHead;
1079 prev = 0;
1080
1081 while (symbol != 0) {
1082 if (!strcmp(symbol->string, string)) break;
1083
1084 prev = symbol;
1085 symbol = symbol->next;
1086 }
1087
1088 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
1089
1090 return symbol;
1091}
1092
1093bool XMLIsType(TagPtr dict, enum xmltype type)
1094{
1095if(!dict) return (type == kTagTypeNone);
1096return (dict->type == type);
1097}
1098
1099/*** Cast functions ***/
1100bool XMLIsArray(TagPtr entry)
1101{
1102 return entry && (entry->type == kTagTypeArray);
1103}
1104
1105TagPtr XMLCastArray(TagPtr dict)
1106{
1107if(!dict) return NULL;
1108if(dict->type == kTagTypeArray) return dict;
1109else return NULL;
1110}
1111
1112bool XMLIsDict(TagPtr entry)
1113{
1114 return entry && (entry->type == kTagTypeDict);
1115}
1116
1117
1118TagPtr XMLCastDict(TagPtr dict)
1119{
1120if(!dict) return NULL;
1121if(dict->type == kTagTypeDict) return dict;
1122else return NULL;
1123}
1124
1125bool XMLIsString(TagPtr entry)
1126{
1127 return entry &&
1128 ((entry->type == kTagTypeString) ||
1129 (entry->type == kTagTypeKey));
1130}
1131
1132char* XMLCastString(TagPtr dict)
1133{
1134if(!dict) return NULL;
1135
1136if((dict->type == kTagTypeString) ||
1137 (dict->type == kTagTypeKey)) return dict->string;
1138
1139return NULL;
1140}
1141
1142long XMLCastStringOffset(TagPtr dict)
1143{
1144if(dict &&
1145 ((dict->type == kTagTypeString) ||
1146 (dict->type == kTagTypeKey)))
1147{
1148return dict->offset;
1149}
1150else
1151{
1152return -1;
1153}
1154}
1155
1156bool XMLIsBoolean(TagPtr entry)
1157{
1158 return entry &&
1159 ((entry->type == kTagTypeTrue) ||
1160 (entry->type == kTagTypeFalse));
1161}
1162
1163bool XMLCastBoolean(TagPtr dict)
1164{
1165if(!dict) return false;
1166if(dict->type == kTagTypeTrue) return true;
1167return false;
1168}
1169
1170bool XMLIsInteger(TagPtr entry)
1171{
1172 return entry && (entry->type == kTagTypeInteger);
1173}
1174
1175int XMLCastInteger(TagPtr dict)
1176{
1177if(!dict)
1178{
1179//printf("XMLCastInteger: null dict\n");
1180return 0;
1181}
1182if(dict->type == kTagTypeInteger) return (int)(dict->string);
1183return 0;
1184}
1185
1186bool XMLAddTagToDictionary(TagPtr dict, char* key, TagPtr value)
1187{
1188 if (!dict || dict->type != kTagTypeDict) return false;
1189
1190 TagPtr tmpTag;
1191 char* string;
1192
1193 tmpTag = NewTag();
1194 if (tmpTag == 0)
1195 {
1196 return false;
1197 }
1198
1199 string = NewSymbol(key);
1200 if (string == 0)
1201 {
1202 XMLFreeTag(tmpTag);
1203 return false;
1204 }
1205
1206 tmpTag->type = kTagTypeKey;
1207 tmpTag->string = string;
1208 tmpTag->tag = value;
1209tmpTag->offset = 0;
1210 tmpTag->tagNext = 0;
1211
1212 TagPtr tagList = dict->tag;
1213 if(!tagList)
1214 {
1215 // First tag
1216 dict->tag = tmpTag;
1217 return true;
1218 }
1219 while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1220 if(tagList)
1221 {
1222 tagList->tagNext = tmpTag;
1223 return true;
1224 }
1225 return false;
1226}

Archive Download this file

Revision: 1808