Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2839