Chameleon

Chameleon Svn Source Tree

Root/branches/Bungo/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{
72struct Module *nextModule;
73longwillLoad;
74TagPtrdict;
75char*plistAddr;
76longplistLength;
77char*driverPath;
78};
79typedef struct Module Module, *ModulePtr;
80
81struct DriverInfo
82{
83char*plistAddr;
84longplistLength;
85void*moduleAddr;
86longmoduleLength;
87};
88typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
89
90#define kDriverPackageSignature1 'MKXT'
91#define kDriverPackageSignature2 'MOSX'
92
93struct DriversPackage
94{
95unsigned long signature1;
96unsigned long signature2;
97unsigned long length;
98unsigned long adler32;
99unsigned long version;
100unsigned long numDrivers;
101unsigned long reserved1;
102unsigned long reserved2;
103};
104typedef struct DriversPackage DriversPackage;
105
106enum
107{
108kCFBundleType2,
109kCFBundleType3
110};
111
112
113#define DOFREE 1
114
115static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
116static long ParseTagKey(char *buffer, TagPtr *tag);
117static long ParseTagString(char *buffer, TagPtr *tag);
118static long ParseTagInteger(char *buffer, TagPtr *tag);
119static long ParseTagData(char *buffer, TagPtr *tag);
120static long ParseTagDate(char *buffer, TagPtr *tag);
121//static long ParseTagBoolean(char *buffer, TagPtr *tag, long type);
122static long GetNextTag(char *buffer, char **tag, long *start);
123static long FixDataMatchingTag(char *buffer, char *tag);
124static TagPtr NewTag(void);
125static char *NewSymbol(char *string);
126#if DOFREE
127static void FreeSymbol(char *string);
128#endif
129
130
131//==========================================================================
132// XMLGetProperty
133
134TagPtr
135XMLGetProperty(TagPtr dict, const char * key)
136{
137 TagPtr tagList, tag;
138
139 if (dict->type != kTagTypeDict) return 0;
140
141 tag = 0;
142 tagList = dict->tag;
143 while (tagList)
144 {
145 tag = tagList;
146 tagList = tag->tagNext;
147
148if ((tag->type != kTagTypeKey) || (tag->string == 0)) {
149continue;
150}
151
152if (!strcmp(tag->string, key)) {
153return tag->tag;
154}
155}
156
157return 0;
158}
159
160//==========================================================================
161// XMLGetProperty
162
163TagPtr
164XMLGetKey( TagPtr dict, int id )
165{
166TagPtr tagList, tag;
167
168if (dict->type != kTagTypeDict) {
169return 0;
170}
171
172tag = 0;
173int element = 0;
174tagList = dict->tag;
175while (tagList && element != id)
176{
177tag = tagList;
178tagList = tag->tagNext;
179
180if ((tag->type != kTagTypeKey) || (tag->string == 0)) {
181continue;
182}
183
184 element++;
185if(id == element) {
186return tag;
187}
188
189}
190return 0;
191}
192
193TagPtr XMLGetValueForKey(TagPtr key)
194{
195if (!key || key->type != kTagTypeKey) {
196return 0;
197}
198
199return key->tag;
200}
201
202
203// XMLGetTag(int index)
204
205// XMLTagCount( TagPtr dict )
206int XMLTagCount( TagPtr dict )
207{
208int count = 0;
209TagPtr tagList, tag;
210
211if (dict->type != kTagTypeDict && dict->type != kTagTypeArray) {
212return 0;
213}
214
215tag = 0;
216tagList = dict->tag;
217while (tagList)
218{
219tag = tagList;
220tagList = tag->tagNext;
221
222if (((tag->type != kTagTypeKey) && ((tag->string == 0) || (tag->string[0] == 0)))
223&& (dict->type != kTagTypeArray)// If we are an array, any element is valid
224) {
225continue;
226}
227
228//if(tag->type == kTagTypeKey) printf("Located key %s\n", tag->string);
229
230count++;
231}
232
233return count;
234}
235
236TagPtr XMLGetElement( TagPtr dict, int id )
237{
238if(dict->type != kTagTypeArray) {
239return 0;
240}
241
242int element = 0;
243TagPtr tmp = dict->tag;
244
245while(element < id)
246{
247element++;
248tmp = tmp->tagNext;
249}
250
251return tmp;
252}
253/* Function for basic XML character entities parsing */
254
255char*
256XMLDecode(const char* src)
257{
258typedef const struct XMLEntity {
259const char* name;
260size_t nameLen;
261char value;
262} XMLEntity;
263
264/* This is ugly, but better than specifying the lengths by hand */
265#define _e(str,c) {str,sizeof(str)-1,c}
266const XMLEntity ents[] = {
267_e("quot;",'"'), _e("apos;",'\''),
268_e("lt;", '<'), _e("gt;", '>'),
269_e("amp;", '&')
270};
271
272size_t len;
273const char *s;
274char *out, *o;
275
276if ( !src || !(len = strlen(src)) || !(out = malloc(len+1)) ) {
277return 0;
278}
279
280o = out;
281s = src;
282while (s <= src+len) /* Make sure the terminator is also copied */
283{
284if ( *s == '&' ) {
285bool entFound = false;
286int i;
287
288s++;
289for ( i = 0; i < sizeof(ents)/sizeof(ents[0]); i++)
290{
291if ( strncmp(s, ents[i].name, ents[i].nameLen) == 0 ) {
292entFound = true;
293break;
294}
295}
296if ( entFound ) {
297*o++ = ents[i].value;
298s += ents[i].nameLen;
299
300continue;
301}
302}
303
304*o++ = *s++;
305}
306
307return out;
308}
309
310//#if UNUSED
311//==========================================================================
312// XMLParseFile
313// Expects to see one dictionary in the XML file, the final pos will be returned
314// If the pos is not equal to the strlen, then there are multiple dicts
315// Puts the first dictionary it finds in the
316// tag pointer and returns the end of the dic, or returns -1 if not found.
317//
318long
319XMLParseFile( char * buffer, TagPtr * dict )
320{
321long length, pos;
322TagPtr tag;
323pos = 0;
324char *configBuffer;
325
326int strlength = strlen(buffer);
327configBuffer = malloc(strlength+1);
328bcopy(buffer, configBuffer, strlength);
329configBuffer[strlength] = 0;
330
331buffer_start = configBuffer;
332
333 while (1)
334 {
335 length = XMLParseNextTag(configBuffer + pos, &tag);
336 if (length == -1) break;
337
338 pos += length;
339
340 if (tag == 0) continue;
341 if (tag->type == kTagTypeDict) break;
342
343 XMLFreeTag(tag);
344 }
345free(configBuffer);
346if (length < 0) {
347 return -1;
348 }
349 *dict = tag;
350 return pos;
351}
352//#endif /* UNUSED */
353
354//==========================================================================
355// ParseNextTag
356// TODO: cleanup
357long XMLParseNextTag( char * buffer, TagPtr * tag )
358{
359long length, pos;
360char * tagName;
361
362length = GetNextTag(buffer, &tagName, 0);
363if (length == -1) {
364return -1;
365}
366
367pos = length;
368if (!strncmp(tagName, kXMLTagPList, 6))
369{
370length = 0;
371 // just a header; nothing to parse
372 // return-via-reference tag should be left alone
373}
374/***** dict ****/
375else if (!strcmp(tagName, kXMLTagDict))
376{
377length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
378}
379else if (!strncmp(tagName, kXMLTagDict, strlen(kXMLTagDict)) && tagName[strlen(tagName)-1] == '/')
380{
381length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);
382}
383else if (!strncmp(tagName, kXMLTagDict " ", strlen(kXMLTagDict " ")))
384{
385length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
386}
387/***** key ****/
388else if (!strcmp(tagName, kXMLTagKey))
389{
390length = ParseTagKey(buffer + pos, tag);
391}
392
393/***** string ****/
394else if (!strcmp(tagName, kXMLTagString))
395{
396length = ParseTagString(buffer + pos, tag);
397}
398else if (!strncmp(tagName, kXMLTagString " ", strlen(kXMLTagString " ")))
399{
400// TODO: save tag if if found
401if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringID, strlen(kXMLStringID)))
402{
403// ID=
404int id = 0;
405int cnt = strlen(kXMLTagString " " kXMLStringID "\"") + 1;
406while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
407tagName[cnt] = 0;
408char* val = tagName + strlen(kXMLTagString " " kXMLStringID "\"");
409while(*val)
410{
411if ((*val >= '0' && *val <= '9'))// 0 - 9
412{
413id = (id * 10) + (*val++ - '0');
414}
415else
416{
417printf("ParseStringID error (0x%x)\n", *val);
418getchar();
419return -1;
420}
421}
422length = ParseTagString(buffer + pos, tag);
423
424SaveRefString(buffer + pos, id);
425}
426else if(!strncmp(tagName + strlen(kXMLTagString " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
427{
428// IDREF=
429int id = 0;
430int cnt = strlen(kXMLTagString " " kXMLStringIDRef "\"") + 1;
431while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
432tagName[cnt] = 0;
433char* val = tagName + strlen(kXMLTagString " " kXMLStringIDRef "\"");
434while(*val)
435{
436if ((*val >= '0' && *val <= '9'))// 0 - 9
437{
438id = (id * 10) + (*val++ - '0');
439}
440else
441{
442printf("ParseStringIDREF error (0x%x)\n", *val);
443getchar();
444return -1;
445}
446}
447char* str = GetRefString(id);
448
449TagPtr tmpTag = NewTag();
450tmpTag->type = kTagTypeString;
451tmpTag->string = str;
452tmpTag->tag = 0;
453tmpTag->tagNext = 0;
454tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
455*tag = tmpTag;
456
457length = 0;
458//printf("Located IDREF, id = %d, string = %s\n", id, str);
459}
460}
461
462/***** integer ****/
463else if (!strcmp(tagName, kXMLTagInteger))
464{
465length = ParseTagInteger(buffer + pos, tag);
466}
467else if (!strncmp(tagName, kXMLTagInteger " ", strlen(kXMLTagInteger " ")))
468{
469if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringID, strlen(kXMLStringID)))
470{
471// ID=
472int id = 0;
473int cnt = strlen(kXMLTagInteger " " kXMLStringID "\"") + 1;
474while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
475tagName[cnt] = 0;
476char* val = tagName + strlen(kXMLTagInteger " " kXMLStringID "\"");
477while(*val)
478{
479if ((*val >= '0' && *val <= '9'))// 0 - 9
480{
481id = (id * 10) + (*val++ - '0');
482}
483else
484{
485printf("ParseIntegerID error (0x%x)\n", *val);
486getchar();
487return -1;
488}
489}
490length = ParseTagInteger(buffer + pos, tag);
491
492SaveRefString((*tag)->string, id);
493}
494else if(!strncmp(tagName + strlen(kXMLTagInteger " "), kXMLStringIDRef, strlen(kXMLStringIDRef)))
495{
496// IDREF=
497int id = 0;
498int cnt = strlen(kXMLTagInteger " " kXMLStringIDRef "\"") + 1;
499while ((tagName[cnt] != '\0') && (tagName[cnt] != '"')) cnt++;
500tagName[cnt] = 0;
501char* val = tagName + strlen(kXMLTagInteger " " kXMLStringIDRef "\"");
502while(*val)
503{
504if ((*val >= '0' && *val <= '9'))// 0 - 9
505{
506id = (id * 10) + (*val++ - '0');
507}
508else
509{
510printf("ParseStringIDREF error (0x%x)\n", *val);
511getchar();
512return -1;
513}
514}
515int integer = (int)GetRefString(id);
516
517TagPtr tmpTag = NewTag();
518tmpTag->type = kTagTypeInteger;
519tmpTag->string = (char*) integer;
520tmpTag->tag = 0;
521tmpTag->tagNext = 0;
522tmpTag->offset = buffer_start ? buffer - buffer_start + pos : 0;
523
524*tag = tmpTag;
525
526length = 0;
527//printf("Located IDREF, id = %d, string = %s\n", id, str);
528}
529else
530{
531length = ParseTagInteger(buffer + pos, tag);
532}
533}
534
535/***** data ****/
536else if (!strcmp(tagName, kXMLTagData))
537{
538length = ParseTagData(buffer + pos, tag);
539}
540else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))
541{
542length = ParseTagData(buffer + pos, tag);
543}
544else if (!strcmp(tagName, kXMLTagDate))
545{
546length = ParseTagDate(buffer + pos, tag);
547}
548
549/***** date ****/
550else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))
551{
552length = ParseTagDate(buffer + pos, tag);
553}
554
555/***** false ****/
556else if (!strcmp(tagName, kXMLTagFalse))
557{
558length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
559}
560/***** true ****/
561else if (!strcmp(tagName, kXMLTagTrue))
562{
563length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
564}
565
566/***** array ****/
567else if (!strcmp(tagName, kXMLTagArray))
568{
569length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
570}
571else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))
572{
573length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
574}
575else if (!strcmp(tagName, kXMLTagArray "/"))
576{
577length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
578}
579
580/***** unknown ****/
581else
582{
583 // it wasn't parsed so we consumed no additional characters
584*tag = 0;
585length = 0;
586}
587
588if (length == -1) {
589return -1;
590}
591
592return pos + length;
593}
594
595//==========================================================================
596// ParseTagList
597
598static long ParseTagList( char * buffer, TagPtr * tag, long type, long empty )
599{
600long length, pos;
601TagPtr tagList, tmpTag;
602
603tagList = 0;
604pos = 0;
605
606if (!empty)
607{
608while (1)
609{
610length = XMLParseNextTag(buffer + pos, &tmpTag);
611if (length == -1) {
612break;
613}
614
615pos += length;
616
617// detect end of list
618if (tmpTag == 0) {
619break;
620}
621tmpTag->tagNext = tagList;
622tagList = tmpTag;
623}
624
625if (length == -1)
626{
627XMLFreeTag(tagList);
628return -1;
629}
630}
631
632tmpTag = NewTag();
633if (tmpTag == 0)
634{
635XMLFreeTag(tagList);
636return -1;
637}
638
639tmpTag->type = type;
640tmpTag->string = 0;
641tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
642tmpTag->tag = tagList;
643tmpTag->tagNext = 0;
644
645*tag = tmpTag;
646
647return pos;
648}
649
650//==========================================================================
651// ParseTagKey
652
653static long ParseTagKey( char * buffer, TagPtr * tag )
654{
655long length, length2;
656char *string;
657TagPtr tmpTag, subTag;
658
659length = FixDataMatchingTag(buffer, kXMLTagKey);
660if (length == -1) {
661return -1;
662}
663
664length2 = XMLParseNextTag(buffer + length, &subTag);
665if (length2 == -1) {
666return -1;
667}
668
669tmpTag = NewTag();
670if (tmpTag == 0) {
671XMLFreeTag(subTag);
672return -1;
673}
674
675string = NewSymbol(buffer);
676if (string == 0) {
677XMLFreeTag(subTag);
678XMLFreeTag(tmpTag);
679return -1;
680}
681
682tmpTag->type = kTagTypeKey;
683tmpTag->string = string;
684tmpTag->tag = subTag;
685tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
686tmpTag->tagNext = 0;
687
688*tag = tmpTag;
689
690return length + length2;
691}
692
693//==========================================================================
694// ParseTagString
695
696static long ParseTagString( char * buffer, TagPtr * tag )
697{
698long length;
699char * string;
700
701length = FixDataMatchingTag(buffer, kXMLTagString);
702if (length == -1) {
703return -1;
704}
705
706TagPtr tmpTag = NewTag();
707if (tmpTag == 0) {
708return -1;
709}
710
711string = NewSymbol(buffer);
712if (string == 0) {
713XMLFreeTag(tmpTag);
714return -1;
715}
716
717tmpTag->type = kTagTypeString;
718tmpTag->string = string;
719tmpTag->tag = 0;
720tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
721tmpTag->tagNext = 0;
722
723*tag = tmpTag;
724return length;
725}
726
727//==========================================================================
728// ParseTagInteger
729
730static long ParseTagInteger( char * buffer, TagPtr * tag )
731{
732long length, integer;
733bool negative = false;
734TagPtr tmpTag;
735char* val = buffer;
736int size;
737
738if(buffer[0] == '<')
739{
740printf("Warning integer is non existant\n");
741getchar();
742tmpTag = NewTag();
743tmpTag->type = kTagTypeInteger;
744tmpTag->string = 0;
745tmpTag->tag = 0;
746tmpTag->offset = 0;
747tmpTag->tagNext = 0;
748
749*tag = tmpTag;
750
751return 0;
752}
753
754size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
755if (length == -1) return -1;
756
757tmpTag = NewTag();
758if (tmpTag == 0) return -1;
759
760integer = 0;
761
762if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
763{
764val += 2;
765while(*val)
766{
767if ((*val >= '0' && *val <= '9'))// 0 - 9
768{
769integer = (integer * 16) + (*val++ - '0');
770}
771else if ((*val >= 'a' && *val <= 'f'))// a - f
772{
773integer = (integer * 16) + (*val++ - 'a' + 10);
774}
775else if ((*val >= 'A' && *val <= 'F'))// A - F
776{
777integer = (integer * 16) + (*val++ - 'a' + 10);
778}
779else
780{
781printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
782getchar();
783XMLFreeTag(tmpTag);
784return -1;
785}
786}
787}
788else if ( size )// Decimal value
789{
790if (*val == '-')
791{
792negative = true;
793val++;
794size--;
795}
796
797for (integer = 0; size > 0; size--)
798{
799if(*val) // UGLY HACK, fix me.
800{
801if (*val < '0' || *val > '9')
802{
803printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
804getchar();
805return -1;
806}
807
808integer = (integer * 10) + (*val++ - '0');
809}
810}
811
812if (negative)
813integer = -integer;
814}
815
816tmpTag->type = kTagTypeInteger;
817tmpTag->string = (char *)integer;
818tmpTag->tag = 0;
819tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
820tmpTag->tagNext = 0;
821
822*tag = tmpTag;
823
824return length;
825}
826
827//==========================================================================
828// ParseTagData
829
830static long ParseTagData( char * buffer, TagPtr * tag )
831{
832int actuallen = 0;
833long length;
834TagPtr tmpTag;
835
836length = FixDataMatchingTag(buffer, kXMLTagData);
837if (length == -1) return -1;
838
839tmpTag = NewTag();
840if (tmpTag == 0) return -1;
841
842//printf("ParseTagData unimplimented\n");
843//printf("Data: %s\n", buffer);
844//getchar();
845
846char* string = BASE64Decode(buffer, strlen(buffer), &actuallen);
847tmpTag->type = kTagTypeData;
848tmpTag->string = string;
849tmpTag->tag = 0;
850tmpTag->offset = actuallen; // buffer_start ? buffer - buffer_start: 0;
851tmpTag->tagNext = 0;
852
853*tag = tmpTag;
854
855return length;
856}
857
858//==========================================================================
859// ParseTagDate
860
861static long ParseTagDate( char * buffer, TagPtr * tag )
862{
863long length;
864TagPtr tmpTag;
865
866length = FixDataMatchingTag(buffer, kXMLTagDate);
867if (length == -1) return -1;
868
869tmpTag = NewTag();
870if (tmpTag == 0) return -1;
871
872printf("ParseTagDate unimplimented\n");
873getchar();
874
875tmpTag->type = kTagTypeDate;
876tmpTag->string = 0;
877tmpTag->tag = 0;
878tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
879tmpTag->tagNext = 0;
880
881*tag = tmpTag;
882
883return length;
884}
885
886//==========================================================================
887// ParseTagBoolean
888
889long ParseTagBoolean( char * buffer, TagPtr * tag, long type )
890{
891TagPtr tmpTag;
892
893tmpTag = NewTag();
894if (tmpTag == 0) return -1;
895
896tmpTag->type = type;
897tmpTag->string = 0;
898tmpTag->tag = 0;
899tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
900tmpTag->tagNext = 0;
901
902*tag = tmpTag;
903
904return 0;
905}
906
907//==========================================================================
908// GetNextTag
909
910static long GetNextTag( char * buffer, char ** tag, long * start )
911{
912long cnt, cnt2;
913
914if (tag == 0) return -1;
915
916// Find the start of the tag.
917cnt = 0;
918while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
919if (buffer[cnt] == '\0') return -1;
920// Find the end of the tag.
921cnt2 = cnt + 1;
922while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
923if (buffer[cnt2] == '\0') return -1;
924
925// Fix the tag data.
926*tag = buffer + cnt + 1;
927buffer[cnt2] = '\0';
928if (start) *start = cnt;
929
930return cnt2 + 1;
931}
932
933//==========================================================================
934// FixDataMatchingTag
935// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
936// Returns the length of the data found, counting the end tag,
937// or -1 if the end tag was not found.
938
939static long
940FixDataMatchingTag( char * buffer, char * tag )
941{
942 long length, start, stop;
943 char * endTag;
944
945 start = 0;
946 while (1)
947 {
948 length = GetNextTag(buffer + start, &endTag, &stop);
949 if (length == -1) return -1;
950
951 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
952 start += length;
953 }
954
955 buffer[start + stop] = '\0';
956
957 return start + length;
958}
959
960//==========================================================================
961// NewTag
962
963#define kTagsPerBlock (0x1000)
964
965static TagPtr gTagsFree;
966
967static TagPtr
968NewTag( void )
969{
970long cnt;
971TagPtr tag;
972
973 if (gTagsFree == 0)
974 {
975 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
976 if (tag == 0) return 0;
977
978 // Initalize the new tags.
979 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
980 {
981 tag[cnt].type = kTagTypeNone;
982 tag[cnt].string = 0;
983 tag[cnt].tag = 0;
984 tag[cnt].tagNext = tag + cnt + 1;
985 }
986 tag[kTagsPerBlock - 1].tagNext = 0;
987
988 gTagsFree = tag;
989 }
990
991 tag = gTagsFree;
992 gTagsFree = tag->tagNext;
993
994 return tag;
995}
996
997//==========================================================================
998// XMLFreeTag
999
1000void
1001XMLFreeTag( TagPtr tag )
1002{
1003#if DOFREE
1004if (tag == 0)
1005{
1006return;
1007}
1008
1009if (!XMLIsInteger(tag) && tag->string)
1010{
1011FreeSymbol(tag->string);
1012}
1013
1014XMLFreeTag(tag->tag);
1015XMLFreeTag(tag->tagNext);
1016
1017// Clear and free the tag.
1018tag->type = kTagTypeNone;
1019tag->string = 0;
1020tag->tag = 0;
1021tag->offset = 0;
1022tag->tagNext = gTagsFree;
1023gTagsFree = tag;
1024#else
1025return;
1026#endif
1027}
1028
1029//==========================================================================
1030// Symbol object.
1031
1032struct Symbol
1033{
1034long refCount;
1035struct Symbol *next;
1036char string[];
1037};
1038typedef struct Symbol Symbol, *SymbolPtr;
1039
1040static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
1041
1042static SymbolPtr gSymbolsHead;
1043
1044//==========================================================================
1045// NewSymbol
1046
1047static char *NewSymbol( char * string )
1048{
1049static SymbolPtr lastGuy = 0;
1050SymbolPtr symbol;
1051
1052// Look for string in the list of symbols.
1053symbol = FindSymbol(string, 0);
1054
1055 // Add the new symbol.
1056if (symbol == 0)
1057{
1058symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1059if (symbol == 0) //return 0;
1060{
1061stop("NULL symbol!");
1062}
1063
1064// Set the symbol's data.
1065symbol->refCount = 0;
1066strcpy(symbol->string, string);
1067
1068// Add the symbol to the list.
1069symbol->next = gSymbolsHead;
1070gSymbolsHead = symbol;
1071}
1072
1073// Update the refCount and return the string.
1074symbol->refCount++;
1075
1076if (lastGuy && lastGuy->next != 0)
1077{
1078stop("last guy not last!");
1079}
1080
1081return symbol->string;
1082}
1083
1084//==========================================================================
1085// FreeSymbol
1086
1087#if DOFREE
1088static void FreeSymbol( char * string )
1089{
1090SymbolPtr symbol, prev;
1091prev = 0;
1092
1093// Look for string in the list of symbols.
1094symbol = FindSymbol(string, &prev);
1095if (symbol == 0)
1096{
1097return;
1098}
1099
1100// Update the refCount.
1101symbol->refCount--;
1102
1103if (symbol->refCount != 0)
1104{
1105return;
1106}
1107
1108// Remove the symbol from the list.
1109if (prev != 0)
1110{
1111prev->next = symbol->next;
1112}
1113else
1114{
1115gSymbolsHead = symbol->next;
1116}
1117
1118// Free the symbol's memory.
1119free(symbol);
1120}
1121#endif
1122
1123//==========================================================================
1124// FindSymbol
1125
1126static SymbolPtr FindSymbol( char * string, SymbolPtr * prevSymbol )
1127{
1128SymbolPtr symbol, prev;
1129
1130symbol = gSymbolsHead;
1131prev = 0;
1132
1133while (symbol != 0)
1134{
1135if (!strcmp(symbol->string, string))
1136{
1137break;
1138}
1139
1140prev = symbol;
1141symbol = symbol->next;
1142}
1143
1144if ((symbol != 0) && (prevSymbol != 0))
1145{
1146*prevSymbol = prev;
1147}
1148
1149return symbol;
1150}
1151
1152bool XMLIsType(TagPtr dict, enum xmltype type)
1153{
1154if(!dict)
1155{
1156return (type == kTagTypeNone);
1157}
1158return (dict->type == type);
1159}
1160
1161/*** Cast functions ***/
1162bool XMLIsArray(TagPtr entry)
1163{
1164return entry && (entry->type == kTagTypeArray);
1165}
1166
1167TagPtr XMLCastArray(TagPtr dict)
1168{
1169if(!dict)
1170{
1171return NULL;
1172}
1173
1174if(dict->type == kTagTypeArray)
1175{
1176return dict;
1177}
1178else
1179{
1180return NULL;
1181}
1182}
1183
1184bool XMLIsDict(TagPtr entry)
1185{
1186 return entry && (entry->type == kTagTypeDict);
1187}
1188
1189bool XMLIsData(TagPtr entry)
1190{
1191return entry && (entry->type == kTagTypeData);
1192}
1193
1194TagPtr XMLCastDict(TagPtr dict)
1195{
1196if(!dict)
1197{
1198return NULL;
1199}
1200
1201if(dict->type == kTagTypeDict)
1202{
1203return dict;
1204}
1205else
1206{
1207return NULL;
1208}
1209}
1210
1211bool XMLIsString(TagPtr entry)
1212{
1213 return entry && ((entry->type == kTagTypeString) || (entry->type == kTagTypeKey));
1214}
1215
1216char* XMLCastString(TagPtr dict)
1217{
1218if(!dict)
1219{
1220return NULL;
1221}
1222
1223if((dict->type == kTagTypeString) || (dict->type == kTagTypeKey))
1224{
1225return dict->string;
1226}
1227
1228return NULL;
1229}
1230
1231char* XMLCastData(TagPtr dict, int* length)
1232{
1233if(!dict)
1234{
1235return NULL;
1236}
1237
1238if((dict->type == kTagTypeData) || (dict->type == kTagTypeKey))
1239{
1240*length = dict->offset;
1241return dict->string;
1242}
1243*length = 0;
1244return NULL;
1245}
1246
1247
1248long XMLCastStringOffset(TagPtr dict)
1249{
1250if(dict && ((dict->type == kTagTypeString) || (dict->type == kTagTypeKey)))
1251{
1252return dict->offset;
1253}
1254else
1255{
1256return -1;
1257}
1258}
1259
1260bool XMLIsBoolean(TagPtr entry)
1261{
1262return entry && ((entry->type == kTagTypeTrue) || (entry->type == kTagTypeFalse));
1263}
1264
1265bool XMLCastBoolean(TagPtr dict)
1266{
1267if(!dict)
1268{
1269return false;
1270}
1271
1272if(dict->type == kTagTypeTrue)
1273{
1274return true;
1275}
1276
1277return false;
1278}
1279
1280bool XMLIsInteger(TagPtr entry)
1281{
1282 return entry && (entry->type == kTagTypeInteger);
1283}
1284
1285int XMLCastInteger(TagPtr dict)
1286{
1287if(!dict)
1288{
1289//printf("XMLCastInteger: null dict\n");
1290return 0;
1291}
1292if(dict->type == kTagTypeInteger)
1293{
1294return (int)(dict->string);
1295}
1296
1297return 0;
1298}
1299
1300bool XMLAddTagToDictionary(TagPtr dict, char* key, TagPtr value)
1301{
1302if (!dict || dict->type != kTagTypeDict)
1303{
1304return false;
1305}
1306
1307TagPtr tmpTag;
1308char* string;
1309
1310tmpTag = NewTag();
1311if (tmpTag == 0)
1312{
1313return false;
1314}
1315
1316string = NewSymbol(key);
1317if (string == 0)
1318{
1319XMLFreeTag(tmpTag);
1320return false;
1321}
1322
1323tmpTag->type = kTagTypeKey;
1324tmpTag->string = string;
1325tmpTag->tag = value;
1326tmpTag->offset = 0;
1327tmpTag->tagNext = 0;
1328
1329TagPtr tagList = dict->tag;
1330if(!tagList)
1331{
1332// First tag
1333dict->tag = tmpTag;
1334return true;
1335}
1336while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1337if(tagList)
1338{
1339tagList->tagNext = tmpTag;
1340return true;
1341}
1342
1343XMLFreeTag(tmpTag);
1344return false;
1345}
1346

Archive Download this file

Revision: 2324