Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 596