Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2618