Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/libsaio/xml.c

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

Archive Download this file

Revision: 2045