Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2238