Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1984