Chameleon

Chameleon Svn Source Tree

Root/branches/JrCs/i386/libsaio/xml.c

1/*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2003 Apple Computer, Inc. All Rights
7 * Reserved.
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 2.0 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
13 *
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25#include "bootstruct.h"
26#include "libsaio.h"
27#include "sl.h"
28#include "xml.h"
29
30string_ref *ref_strings = NULL;
31
32/// TODO: remove below
33static char* buffer_start = NULL;
34// TODO: redo the next two functions
35void SaveRefString(char* string, int id)
36{
37//printf("Adding Ref String %d (%s)\n", id, string);
38string_ref* tmp = ref_strings;
39while(tmp)
40{
41if(tmp->id == id)
42{
43tmp->string = malloc(strlen(string)+1);
44sprintf(tmp->string, "%s", string);
45return;
46}
47tmp = tmp->next;
48}
49
50string_ref* new_ref = malloc(sizeof(string_ref));
51new_ref->string = malloc(strlen(string)+1);
52sprintf(new_ref->string, "%s", string);
53new_ref->id = id;
54new_ref->next = ref_strings;
55ref_strings = new_ref;
56}
57
58char* GetRefString(int id)
59{
60string_ref* tmp = ref_strings;
61while(tmp)
62{
63if(tmp->id == id) return tmp->string;
64tmp = tmp->next;
65}
66//verbose("Unable to locate Ref String %d\n", id);
67return "";
68}
69
70struct Module {
71 struct Module *nextModule;
72 long willLoad;
73 TagPtr dict;
74 char *plistAddr;
75 long plistLength;
76 char *driverPath;
77};
78typedef struct Module Module, *ModulePtr;
79
80struct DriverInfo {
81 char *plistAddr;
82 long plistLength;
83 void *moduleAddr;
84 long moduleLength;
85};
86typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
87
88#define kDriverPackageSignature1 'MKXT'
89#define kDriverPackageSignature2 'MOSX'
90
91struct DriversPackage {
92 unsigned long signature1;
93 unsigned long signature2;
94 unsigned long length;
95 unsigned long adler32;
96 unsigned long version;
97 unsigned long numDrivers;
98 unsigned long reserved1;
99 unsigned long reserved2;
100};
101typedef struct DriversPackage DriversPackage;
102
103enum {
104 kCFBundleType2,
105 kCFBundleType3
106};
107
108
109#define DOFREE 1
110
111static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
112static long ParseTagKey(char *buffer, TagPtr *tag);
113static long ParseTagString(char *buffer, TagPtr *tag);
114static long ParseTagInteger(char *buffer, TagPtr *tag);
115static long ParseTagData(char *buffer, TagPtr *tag);
116static long ParseTagDate(char *buffer, TagPtr *tag);
117static long GetNextTag(char *buffer, char **tag, long *start);
118static long FixDataMatchingTag(char *buffer, char *tag);
119static TagPtr NewTag(void);
120static char *NewSymbol(char *string);
121#if DOFREE
122static void FreeSymbol(char *string);
123#endif
124
125
126//==========================================================================
127// XMLGetProperty
128
129TagPtr
130XMLGetProperty( TagPtr dict, const char * key )
131{
132 TagPtr tagList, tag;
133
134 if (dict->type != kTagTypeDict) return 0;
135
136 tag = 0;
137 tagList = dict->tag;
138 while (tagList)
139 {
140 tag = tagList;
141 tagList = tag->tagNext;
142
143 if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;
144
145 if (!strcmp(tag->string, key)) return tag->tag;
146 }
147
148 return 0;
149}
150
151//==========================================================================
152// XMLGetProperty
153
154TagPtr
155XMLGetKey( TagPtr dict, int id )
156{
157 TagPtr tagList, tag;
158
159 if (dict->type != kTagTypeDict) return 0;
160
161 tag = 0;
162 int element = 0;
163 tagList = dict->tag;
164 while (tagList && element != id)
165 {
166 tag = tagList;
167 tagList = tag->tagNext;
168
169 if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;
170 element++;
171 if(id == element) return tag;
172 }
173 return 0;
174}
175
176TagPtr XMLGetValueForKey(TagPtr key)
177{
178 if (!key ||
179 key->type != kTagTypeKey) return 0;
180
181 return key->tag;
182}
183
184
185// XMLGetTag(int index)
186
187// XMLTagCount( TagPtr dict )
188int XMLTagCount( TagPtr dict )
189{
190int count = 0;
191TagPtr tagList, tag;
192
193 if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) return 0;
194tag = 0;
195 tagList = dict->tag;
196 while (tagList)
197 {
198tag = tagList;
199 tagList = tag->tagNext;
200
201if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0)))
202&& (dict->type != kTagTypeArray)// If we are an array, any element is valid
203) continue;
204
205//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string);
206
207count++;
208 }
209
210return count;
211}
212
213TagPtr XMLGetElement( TagPtr dict, int id )
214{
215if(dict->type != kTagTypeArray) return 0;
216
217int element = 0;
218TagPtr tmp = dict->tag;
219
220while(element < id)
221{
222element++;
223tmp = tmp->tagNext;
224}
225
226return tmp;
227}
228/* Function for basic XML character entities parsing */
229
230char*
231XMLDecode(const char* src)
232{
233 typedef const struct XMLEntity {
234 const char* name;
235 size_t nameLen;
236 char value;
237 } XMLEntity;
238
239 /* This is ugly, but better than specifying the lengths by hand */
240 #define _e(str,c) {str,sizeof(str)-1,c}
241 const XMLEntity ents[] = {
242 _e("quot;",'"'), _e("apos;",'\''),
243 _e("lt;", '<'), _e("gt;", '>'),
244 _e("amp;", '&')
245 };
246
247 size_t len;
248 const char *s;
249 char *out, *o;
250
251 if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) )
252 return 0;
253
254 o = out;
255 s = src;
256 while (s <= src+len) /* Make sure the terminator is also copied */
257 {
258 if ( *s == '&' )
259 {
260 bool entFound = false;
261 int i;
262
263 s++;
264 for ( i = 0; i < sizeof(ents); 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: HEAD