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

Archive Download this file

Revision: 972