Chameleon

Chameleon Svn Source Tree

Root/branches/slice/trunkM/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 TagPtr tmpTag;
667
668 length = FixDataMatchingTag(buffer, kXMLTagString);
669 if (length == -1) return -1;
670
671 tmpTag = NewTag();
672 if (tmpTag == 0) return -1;
673
674 string = NewSymbol(buffer);
675 if (string == 0)
676 {
677 XMLFreeTag(tmpTag);
678 return -1;
679 }
680
681 tmpTag->type = kTagTypeString;
682 tmpTag->string = string;
683 tmpTag->tag = 0;
684tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
685 tmpTag->tagNext = 0;
686
687 *tag = tmpTag;
688 return length;
689}
690
691//==========================================================================
692// ParseTagInteger
693
694static long
695ParseTagInteger( char * buffer, TagPtr * tag )
696{
697 long length, integer;
698bool negative = false;
699 TagPtr tmpTag;
700char* val = buffer;
701 int size;
702
703 size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
704 if (length == -1) return -1;
705
706 tmpTag = NewTag();
707 if (tmpTag == 0) return -1;
708
709 integer = 0;
710
711if(buffer[0] == '<')
712{
713verbose("Warning integer is non existant\n");
714//getc();
715tmpTag->type = kTagTypeInteger;
716tmpTag->string = 0;
717tmpTag->tag = 0;
718tmpTag->offset = 0;
719tmpTag->tagNext = 0;
720
721*tag = tmpTag;
722
723return 0;
724}
725
726
727if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
728{
729val += 2;
730while(*val)
731{
732if ((*val >= '0' && *val <= '9'))// 0 - 9
733{
734integer = (integer * 16) + (*val++ - '0');
735}
736else if ((*val >= 'a' && *val <= 'f'))// a - f
737{
738integer = (integer * 16) + (*val++ - 'a' + 10);
739}
740else if ((*val >= 'A' && *val <= 'F'))// A - F
741{
742integer = (integer * 16) + (*val++ - 'a' + 10);
743}
744else
745{
746printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
747getchar();
748return -1;
749}
750}
751}
752else if ( size )// Decimal value
753{
754if (*val == '-')
755{
756negative = true;
757val++;
758size--;
759}
760
761for (integer = 0; size > 0; size--)
762{
763if(*val) // UGLY HACK, fix me.
764{
765if (*val < '0' || *val > '9')
766{
767printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
768getchar();
769return -1;
770}
771
772integer = (integer * 10) + (*val++ - '0');
773}
774}
775
776if (negative)
777integer = -integer;
778}
779
780 tmpTag->type = kTagTypeInteger;
781tmpTag->string = (char *)integer;
782tmpTag->tag = 0;
783tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
784 tmpTag->tagNext = 0;
785
786 *tag = tmpTag;
787
788 return length;
789}
790
791//==========================================================================
792// ParseTagData
793
794static long
795ParseTagData( char * buffer, TagPtr * tag )
796{
797 long length;
798 TagPtr tmpTag;
799
800 length = FixDataMatchingTag(buffer, kXMLTagData);
801 if (length == -1) return -1;
802
803 tmpTag = NewTag();
804 if (tmpTag == 0) return -1;
805
806//printf("ParseTagData unimplimented\n");
807//printf("Data: %s\n", buffer);
808//getchar();
809
810// TODO: base64 decode
811
812char* string = NewSymbol(buffer);
813 tmpTag->type = kTagTypeData;
814 tmpTag->string = string;
815 tmpTag->tag = 0;
816tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
817 tmpTag->tagNext = 0;
818
819 *tag = tmpTag;
820
821 return length;
822}
823
824//==========================================================================
825// ParseTagDate
826
827static long
828ParseTagDate( char * buffer, TagPtr * tag )
829{
830 long length;
831 TagPtr tmpTag;
832
833 length = FixDataMatchingTag(buffer, kXMLTagDate);
834 if (length == -1) return -1;
835
836 tmpTag = NewTag();
837 if (tmpTag == 0) return -1;
838
839printf("ParseTagDate unimplimented\n");
840getchar();
841
842 tmpTag->type = kTagTypeDate;
843 tmpTag->string = 0;
844 tmpTag->tag = 0;
845tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
846 tmpTag->tagNext = 0;
847
848 *tag = tmpTag;
849
850 return length;
851}
852
853//==========================================================================
854// ParseTagBoolean
855
856long
857ParseTagBoolean( char * buffer, TagPtr * tag, long type )
858{
859 TagPtr tmpTag;
860
861 tmpTag = NewTag();
862 if (tmpTag == 0) return -1;
863
864 tmpTag->type = type;
865 tmpTag->string = 0;
866 tmpTag->tag = 0;
867tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
868 tmpTag->tagNext = 0;
869
870 *tag = tmpTag;
871
872 return 0;
873}
874
875//==========================================================================
876// GetNextTag
877
878static long
879GetNextTag( char * buffer, char ** tag, long * start )
880{
881 long cnt, cnt2;
882
883 if (tag == 0) return -1;
884
885 // Find the start of the tag.
886 cnt = 0;
887 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
888 if (buffer[cnt] == '\0') return -1;
889
890 // Find the end of the tag.
891 cnt2 = cnt + 1;
892 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
893 if (buffer[cnt2] == '\0') return -1;
894
895 // Fix the tag data.
896 *tag = buffer + cnt + 1;
897 buffer[cnt2] = '\0';
898 if (start) *start = cnt;
899
900 return cnt2 + 1;
901}
902
903//==========================================================================
904// FixDataMatchingTag
905// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
906// Returns the length of the data found, counting the end tag,
907// or -1 if the end tag was not found.
908
909static long
910FixDataMatchingTag( char * buffer, char * tag )
911{
912 long length, start, stop;
913 char * endTag;
914
915 start = 0;
916 while (1)
917 {
918 length = GetNextTag(buffer + start, &endTag, &stop);
919 if (length == -1) return -1;
920
921 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
922 start += length;
923 }
924
925 buffer[start + stop] = '\0';
926
927 return start + length;
928}
929
930//==========================================================================
931// NewTag
932
933#define kTagsPerBlock (0x1000)
934
935static TagPtr gTagsFree;
936
937static TagPtr
938NewTag( void )
939{
940long cnt;
941TagPtr tag;
942
943 if (gTagsFree == 0)
944 {
945 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
946 if (tag == 0) return 0;
947
948 // Initalize the new tags.
949 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
950 {
951 tag[cnt].type = kTagTypeNone;
952 tag[cnt].string = 0;
953 tag[cnt].tag = 0;
954 tag[cnt].tagNext = tag + cnt + 1;
955 }
956 tag[kTagsPerBlock - 1].tagNext = 0;
957
958 gTagsFree = tag;
959 }
960
961 tag = gTagsFree;
962 gTagsFree = tag->tagNext;
963
964 return tag;
965}
966
967//==========================================================================
968// XMLFreeTag
969
970void
971XMLFreeTag( TagPtr tag )
972{
973#if DOFREE
974 if (tag == 0) return;
975
976 if (tag->string) FreeSymbol(tag->string);
977
978 XMLFreeTag(tag->tag);
979 XMLFreeTag(tag->tagNext);
980
981 // Clear and free the tag.
982 tag->type = kTagTypeNone;
983 tag->string = 0;
984 tag->tag = 0;
985tag->offset = 0;
986 tag->tagNext = gTagsFree;
987 gTagsFree = tag;
988#else
989 return;
990#endif
991}
992
993//==========================================================================
994// Symbol object.
995
996struct Symbol
997{
998 long refCount;
999 struct Symbol *next;
1000 char string[];
1001};
1002typedef struct Symbol Symbol, *SymbolPtr;
1003
1004static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
1005
1006static SymbolPtr gSymbolsHead;
1007
1008//==========================================================================
1009// NewSymbol
1010
1011static char *
1012NewSymbol( char * string )
1013{
1014static SymbolPtr lastGuy = 0;
1015SymbolPtr symbol;
1016
1017 // Look for string in the list of symbols.
1018 symbol = FindSymbol(string, 0);
1019
1020 // Add the new symbol.
1021 if (symbol == 0)
1022 {
1023 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1024 if (symbol == 0) //return 0;
1025 stop("NULL symbol!");
1026
1027 // Set the symbol's data.
1028 symbol->refCount = 0;
1029 strcpy(symbol->string, string);
1030
1031 // Add the symbol to the list.
1032 symbol->next = gSymbolsHead;
1033 gSymbolsHead = symbol;
1034 }
1035
1036 // Update the refCount and return the string.
1037 symbol->refCount++;
1038
1039 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
1040 return symbol->string;
1041}
1042
1043//==========================================================================
1044// FreeSymbol
1045
1046#if DOFREE
1047static void
1048FreeSymbol( char * string )
1049{
1050 SymbolPtr symbol, prev;
1051prev = 0;
1052
1053 // Look for string in the list of symbols.
1054 symbol = FindSymbol(string, &prev);
1055 if (symbol == 0) return;
1056
1057 // Update the refCount.
1058 symbol->refCount--;
1059
1060 if (symbol->refCount != 0) return;
1061
1062 // Remove the symbol from the list.
1063 if (prev != 0) prev->next = symbol->next;
1064 else gSymbolsHead = symbol->next;
1065
1066 // Free the symbol's memory.
1067 free(symbol);
1068}
1069#endif
1070
1071//==========================================================================
1072// FindSymbol
1073
1074static SymbolPtr
1075FindSymbol( char * string, SymbolPtr * prevSymbol )
1076{
1077 SymbolPtr symbol, prev;
1078
1079 symbol = gSymbolsHead;
1080 prev = 0;
1081
1082 while (symbol != 0) {
1083 if (!strcmp(symbol->string, string)) break;
1084
1085 prev = symbol;
1086 symbol = symbol->next;
1087 }
1088
1089 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
1090
1091 return symbol;
1092}
1093
1094bool XMLIsType(TagPtr dict, enum xmltype type)
1095{
1096if(!dict) return (type == kTagTypeNone);
1097return (dict->type == type);
1098}
1099
1100/*** Cast functions ***/
1101bool XMLIsArray(TagPtr entry)
1102{
1103 return entry && (entry->type == kTagTypeArray);
1104}
1105
1106TagPtr XMLCastArray(TagPtr dict)
1107{
1108if(!dict) return NULL;
1109if(dict->type == kTagTypeArray) return dict;
1110else return NULL;
1111}
1112
1113bool XMLIsDict(TagPtr entry)
1114{
1115 return entry && (entry->type == kTagTypeDict);
1116}
1117
1118
1119TagPtr XMLCastDict(TagPtr dict)
1120{
1121if(!dict) return NULL;
1122if(dict->type == kTagTypeDict) return dict;
1123else return NULL;
1124}
1125
1126bool XMLIsString(TagPtr entry)
1127{
1128 return entry &&
1129 ((entry->type == kTagTypeString) ||
1130 (entry->type == kTagTypeKey));
1131}
1132
1133char* XMLCastString(TagPtr dict)
1134{
1135if(!dict) return NULL;
1136
1137if((dict->type == kTagTypeString) ||
1138 (dict->type == kTagTypeKey)) return dict->string;
1139
1140return NULL;
1141}
1142
1143long XMLCastStringOffset(TagPtr dict)
1144{
1145if(dict &&
1146 ((dict->type == kTagTypeString) ||
1147 (dict->type == kTagTypeKey)))
1148{
1149return dict->offset;
1150}
1151else
1152{
1153return -1;
1154}
1155}
1156
1157bool XMLIsBoolean(TagPtr entry)
1158{
1159 return entry &&
1160 ((entry->type == kTagTypeTrue) ||
1161 (entry->type == kTagTypeFalse));
1162}
1163
1164bool XMLCastBoolean(TagPtr dict)
1165{
1166if(!dict) return false;
1167if(dict->type == kTagTypeTrue) return true;
1168return false;
1169}
1170
1171bool XMLIsInteger(TagPtr entry)
1172{
1173 return entry && (entry->type == kTagTypeInteger);
1174}
1175
1176int XMLCastInteger(TagPtr dict)
1177{
1178if(!dict)
1179{
1180//printf("XMLCastInteger: null dict\n");
1181return 0;
1182}
1183if(dict->type == kTagTypeInteger) return (int)(dict->string);
1184return 0;
1185}
1186
1187bool XMLAddTagToDictionary(TagPtr dict, char* key, TagPtr value)
1188{
1189 if (!dict || dict->type != kTagTypeDict) return false;
1190
1191 TagPtr tmpTag;
1192 char* string;
1193
1194 tmpTag = NewTag();
1195 if (tmpTag == 0)
1196 {
1197 return false;
1198 }
1199
1200 string = NewSymbol(key);
1201 if (string == 0)
1202 {
1203 XMLFreeTag(tmpTag);
1204 return false;
1205 }
1206
1207 tmpTag->type = kTagTypeKey;
1208 tmpTag->string = string;
1209 tmpTag->tag = value;
1210tmpTag->offset = 0;
1211 tmpTag->tagNext = 0;
1212
1213 TagPtr tagList = dict->tag;
1214 if(!tagList)
1215 {
1216 // First tag
1217 dict->tag = tmpTag;
1218 return true;
1219 }
1220 while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1221 if(tagList)
1222 {
1223 tagList->tagNext = tmpTag;
1224 return true;
1225 }
1226 return false;
1227}

Archive Download this file

Revision: 1207