Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2323