Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1066