Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/arch/i386/libsaio/xml.c

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

Archive Download this file

Revision: 1302