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 }
59snprintf(tmp->string, strlen(string)+1,"%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 }
74snprintf(new_ref->string, strlen(string)+1,"%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
189typedef const struct XMLEntity {
190const char* name;
191size_t nameLen;
192char value;
193} XMLEntity;
194
195/* This is ugly, but better than specifying the lengths by hand */
196#define _e(str,c) {str,sizeof(str)-1,c}
197const XMLEntity ents[] = {
198_e("quot;",'"'), _e("apos;",'\''),
199_e("lt;", '<'), _e("gt;", '>'),
200_e("amp;", '&')
201};
202
203char*
204XMLDecode(const char* src)
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)/sizeof(ents[0])); 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 = 0;
257 pos = 0;
258char *configBuffer;
259
260
261length = strlen(buffer) + 1;
262 configBuffer = malloc(length);
263 if (!configBuffer) {
264 return -1;
265 }
266 strlcpy(configBuffer, buffer, length);
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 (!strncmp(tagName, kXMLTagDict, sizeof(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 (!strncmp(tagName, kXMLTagKey, sizeof(kXMLTagKey)))
322 {
323 length = ParseTagKey(buffer + pos, tag);
324 }
325
326/***** string ****/
327 else if (!strncmp(tagName, kXMLTagString, sizeof(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 (!strncmp(tagName, kXMLTagInteger, sizeof(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 (!strncmp(tagName, kXMLTagData, sizeof(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 (!strncmp(tagName, kXMLTagDate, sizeof(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 (!strncmp(tagName, kXMLTagFalse, sizeof(kXMLTagFalse)))
501 {
502 length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
503 }
504/***** true ****/
505 else if (!strncmp(tagName, kXMLTagTrue, sizeof(kXMLTagTrue)))
506 {
507 length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
508 }
509
510/***** array ****/
511 else if (!strncmp(tagName, kXMLTagArray, sizeof(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 (!strncmp(tagName, kXMLTagArray "/", strlen(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 tmpTag = 0;
548 pos = 0;
549
550 if (!empty)
551 {
552 while (1)
553 {
554 length = XMLParseNextTag(buffer + pos, &tmpTag);
555 if (length == -1) break;
556
557 pos += length;
558
559 if (tmpTag == 0) break;
560 tmpTag->tagNext = tagList;
561 tagList = tmpTag;
562 }
563
564 if (length == -1)
565 {
566 XMLFreeTag(tagList);
567 return -1;
568 }
569 }
570
571 tmpTag = NewTag();
572 if (tmpTag == 0)
573 {
574 XMLFreeTag(tagList);
575 return -1;
576 }
577
578 tmpTag->type = type;
579 tmpTag->string = 0;
580tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
581 tmpTag->tag = tagList;
582 tmpTag->tagNext = 0;
583
584 *tag = tmpTag;
585
586 return pos;
587}
588
589//==========================================================================
590// ParseTagKey
591
592static long
593ParseTagKey( char * buffer, TagPtr * tag )
594{
595 long length, length2;
596 char *string;
597 TagPtr tmpTag, subTag;
598
599 length = FixDataMatchingTag(buffer, kXMLTagKey);
600 if (length == -1) return -1;
601
602 length2 = XMLParseNextTag(buffer + length, &subTag);
603 if (length2 == -1) return -1;
604
605 tmpTag = NewTag();
606 if (tmpTag == 0)
607 {
608 XMLFreeTag(subTag);
609 return -1;
610 }
611
612 string = NewSymbol(buffer);
613 if (string == 0)
614 {
615 XMLFreeTag(subTag);
616 XMLFreeTag(tmpTag);
617 return -1;
618 }
619
620 tmpTag->type = kTagTypeKey;
621 tmpTag->string = string;
622 tmpTag->tag = subTag;
623tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
624 tmpTag->tagNext = 0;
625
626 *tag = tmpTag;
627
628 return length + length2;
629}
630
631//==========================================================================
632// ParseTagString
633
634static long
635ParseTagString( char * buffer, TagPtr * tag )
636{
637 long length;
638 char * string;
639 TagPtr tmpTag;
640
641 length = FixDataMatchingTag(buffer, kXMLTagString);
642 if (length == -1) return -1;
643
644 tmpTag = NewTag();
645 if (tmpTag == 0) return -1;
646
647 string = NewSymbol(buffer);
648 if (string == 0)
649 {
650 XMLFreeTag(tmpTag);
651 return -1;
652 }
653
654 tmpTag->type = kTagTypeString;
655 tmpTag->string = string;
656 tmpTag->tag = 0;
657tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
658 tmpTag->tagNext = 0;
659
660 *tag = tmpTag;
661 return length;
662}
663
664//==========================================================================
665// ParseTagInteger
666
667static long
668ParseTagInteger( char * buffer, TagPtr * tag )
669{
670 long length, integer;
671bool negative = false;
672 TagPtr tmpTag;
673char* val = buffer;
674 int size;
675
676 tmpTag = NewTag();
677 if (tmpTag == 0) return -1;
678
679if(buffer[0] == '<')
680{
681printf("Warning integer is non existant\n");
682getc();
683tmpTag->type = kTagTypeInteger;
684tmpTag->string = 0;
685tmpTag->tag = 0;
686tmpTag->offset = 0;
687tmpTag->tagNext = 0;
688
689*tag = tmpTag;
690
691return 0;
692}
693
694 size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
695 if (length == -1) return -1;
696
697 integer = 0;
698
699if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
700{
701val += 2;
702while(*val)
703{
704if ((*val >= '0' && *val <= '9'))// 0 - 9
705{
706integer = (integer * 16) + (*val++ - '0');
707}
708else if ((*val >= 'a' && *val <= 'f'))// a - f
709{
710integer = (integer * 16) + (*val++ - 'a' + 10);
711}
712else if ((*val >= 'A' && *val <= 'F'))// A - F
713{
714integer = (integer * 16) + (*val++ - 'a' + 10);
715}
716else
717{
718printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
719getc();
720return -1;
721
722}
723
724}
725}
726else if ( size )// Decimal value
727{
728if (*val == '-')
729{
730negative = true;
731val++;
732size--;
733}
734
735for (integer = 0; size > 0; size--)
736{
737if(*val) // UGLY HACK, fix me.
738{
739if (*val < '0' || *val > '9')
740{
741printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
742getc();
743return -1;
744}
745
746integer = (integer * 10) + (*val++ - '0');
747}
748}
749
750if (negative)
751integer = -integer;
752}
753
754 tmpTag->type = kTagTypeInteger;
755tmpTag->string = (char *)integer;
756tmpTag->tag = 0;
757tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
758 tmpTag->tagNext = 0;
759
760 *tag = tmpTag;
761
762 return length;
763}
764
765//==========================================================================
766// ParseTagData
767
768static long
769ParseTagData( char * buffer, TagPtr * tag )
770{
771 long length;
772 TagPtr tmpTag;
773
774 length = FixDataMatchingTag(buffer, kXMLTagData);
775 if (length == -1) return -1;
776
777 tmpTag = NewTag();
778 if (tmpTag == 0) return -1;
779
780//printf("ParseTagData unimplimented\n");
781//printf("Data: %s\n", buffer);
782//getc();
783
784// TODO: base64 decode
785
786char* string = NewSymbol(buffer);
787 tmpTag->type = kTagTypeData;
788 tmpTag->string = string;
789 tmpTag->tag = 0;
790tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
791 tmpTag->tagNext = 0;
792
793 *tag = tmpTag;
794
795 return length;
796}
797
798//==========================================================================
799// ParseTagDate
800
801static long
802ParseTagDate( char * buffer, TagPtr * tag )
803{
804 long length;
805 TagPtr tmpTag;
806
807 length = FixDataMatchingTag(buffer, kXMLTagDate);
808 if (length == -1) return -1;
809
810 tmpTag = NewTag();
811 if (tmpTag == 0) return -1;
812
813printf("ParseTagDate unimplimented\n");
814getc();
815
816 tmpTag->type = kTagTypeDate;
817 tmpTag->string = 0;
818 tmpTag->tag = 0;
819tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
820 tmpTag->tagNext = 0;
821
822 *tag = tmpTag;
823
824 return length;
825}
826
827//==========================================================================
828// ParseTagBoolean
829
830static long
831ParseTagBoolean( char * buffer, TagPtr * tag, long type )
832{
833 TagPtr tmpTag;
834
835 tmpTag = NewTag();
836 if (tmpTag == 0) return -1;
837
838 tmpTag->type = type;
839 tmpTag->string = 0;
840 tmpTag->tag = 0;
841tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
842 tmpTag->tagNext = 0;
843
844 *tag = tmpTag;
845
846 return 0;
847}
848
849//==========================================================================
850// GetNextTag
851
852static long
853GetNextTag( char * buffer, char ** tag, long * start )
854{
855 long cnt, cnt2;
856
857 if (tag == 0) return -1;
858
859 // Find the start of the tag.
860 cnt = 0;
861 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
862 if (buffer[cnt] == '\0') return -1;
863
864 // Find the end of the tag.
865 cnt2 = cnt + 1;
866 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
867 if (buffer[cnt2] == '\0') return -1;
868
869 // Fix the tag data.
870 *tag = buffer + cnt + 1;
871 buffer[cnt2] = '\0';
872 if (start) *start = cnt;
873
874 return cnt2 + 1;
875}
876
877//==========================================================================
878// FixDataMatchingTag
879// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
880// Returns the length of the data found, counting the end tag,
881// or -1 if the end tag was not found.
882
883static long
884FixDataMatchingTag( char * buffer, char * tag )
885{
886 long length, start, stop;
887 char * endTag;
888
889 start = 0;
890 while (1)
891 {
892 length = GetNextTag(buffer + start, &endTag, &stop);
893 if (length == -1) return -1;
894
895 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
896 start += length;
897 }
898
899 buffer[start + stop] = '\0';
900
901 return start + length;
902}
903
904//==========================================================================
905// NewTag
906
907#define kTagsPerBlock (0x1000)
908
909static TagPtr gTagsFree;
910
911static TagPtr
912NewTag( void )
913{
914long cnt;
915TagPtr tag = 0;
916
917 if (gTagsFree == 0)
918 {
919#if USEMALLOC
920 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
921#else
922 tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag));
923#endif
924 if (tag == 0) return 0;
925
926 // Initalize the new tags.
927 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
928 {
929 tag[cnt].type = kTagTypeNone;
930 tag[cnt].string = 0;
931 tag[cnt].tag = 0;
932 tag[cnt].tagNext = tag + cnt + 1;
933 }
934 tag[kTagsPerBlock - 1].tagNext = 0;
935
936 gTagsFree = tag;
937 }
938
939 tag = gTagsFree;
940 gTagsFree = tag->tagNext;
941
942 return tag;
943}
944
945//==========================================================================
946// XMLFreeTag
947
948void
949XMLFreeTag( TagPtr tag )
950{
951#if DOFREE
952 if (tag == 0) return;
953
954 if (tag->string) FreeSymbol(tag->string);
955
956 XMLFreeTag(tag->tag);
957 XMLFreeTag(tag->tagNext);
958
959 // Clear and free the tag.
960 tag->type = kTagTypeNone;
961 tag->string = 0;
962 tag->tag = 0;
963tag->offset = 0;
964 tag->tagNext = gTagsFree;
965 gTagsFree = tag;
966#else
967 return;
968#endif
969}
970
971//==========================================================================
972// Symbol object.
973
974struct Symbol
975{
976 long refCount;
977 struct Symbol *next;
978 char *string;
979};
980typedef struct Symbol Symbol, *SymbolPtr;
981
982static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
983
984static SymbolPtr gSymbolsHead;
985
986//==========================================================================
987// NewSymbol
988
989static char *
990NewSymbol( char * string )
991{
992 static SymbolPtr lastGuy = 0;
993SymbolPtr symbol;
994
995 // Look for string in the list of symbols.
996 symbol = FindSymbol(string, 0);
997
998 // Add the new symbol.
999 if (symbol == 0)
1000 {
1001 int len;
1002#if USEMALLOC
1003 symbol = (SymbolPtr)malloc(sizeof(Symbol) );
1004#else
1005 symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol));
1006#endif
1007 if (symbol == 0) {
1008 stop("NULL symbol!");
1009 return 0;
1010 }
1011 len = strlen(string) + 1;
1012 symbol->string = (char*)malloc(len);
1013 if (symbol->string == 0) {
1014 free(symbol);
1015 stop("NULL symbol->string!");
1016 return 0;
1017 }
1018 // Set the symbol's data.
1019 symbol->refCount = 0;
1020 strlcpy(symbol->string, string, len);
1021
1022 // Add the symbol to the list.
1023 symbol->next = gSymbolsHead;
1024 gSymbolsHead = symbol;
1025 }
1026
1027 // Update the refCount and return the string.
1028 symbol->refCount++;
1029
1030 if (lastGuy && lastGuy->next != 0)
1031 {
1032 free(symbol);
1033 stop("last guy not last!");
1034 return 0;
1035 }
1036 return symbol->string;
1037}
1038
1039//==========================================================================
1040// FreeSymbol
1041
1042#if DOFREE
1043static void
1044FreeSymbol( char * string )
1045{
1046 SymbolPtr symbol, prev;
1047prev = 0;
1048
1049 // Look for string in the list of symbols.
1050 symbol = FindSymbol(string, &prev);
1051 if (symbol == 0) return;
1052
1053 // Update the refCount.
1054 symbol->refCount--;
1055
1056 if (symbol->refCount != 0) return;
1057
1058 // Remove the symbol from the list.
1059 if (prev != 0) prev->next = symbol->next;
1060 else gSymbolsHead = symbol->next;
1061
1062 // Free the symbol's memory.
1063 if (symbol->string) free(symbol->string);
1064 free(symbol);
1065}
1066#endif
1067
1068//==========================================================================
1069// FindSymbol
1070
1071static SymbolPtr
1072FindSymbol( char * string, SymbolPtr * prevSymbol )
1073{
1074 SymbolPtr symbol, prev;
1075
1076 symbol = gSymbolsHead;
1077 prev = 0;
1078
1079 while (symbol != 0) {
1080 if (!strcmp(symbol->string, string)) break;
1081
1082 prev = symbol;
1083 symbol = symbol->next;
1084 }
1085
1086 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
1087
1088 return symbol;
1089}
1090
1091
1092
1093bool XMLIsType(TagPtr dict, enum xmltype type)
1094{
1095if(!dict) return (type == kTagTypeNone);
1096return (dict->type == (long)type);
1097}
1098
1099
1100/*** Cast functions ***/
1101TagPtr XMLCastArray(TagPtr dict)
1102{
1103if(!dict) return NULL;
1104if(dict->type == kTagTypeArray) return dict;
1105else return NULL;
1106}
1107
1108
1109TagPtr XMLCastDict(TagPtr dict)
1110{
1111if(!dict) return NULL;
1112if(dict->type == kTagTypeDict) return dict;
1113else return NULL;
1114}
1115
1116char* XMLCastString(TagPtr dict)
1117{
1118if(!dict) return NULL;
1119
1120if((dict->type == kTagTypeString) ||
1121 (dict->type == kTagTypeKey)) return dict->string;
1122
1123return NULL;
1124}
1125
1126long XMLCastStringOffset(TagPtr dict)
1127{
1128if(dict &&
1129 ((dict->type == kTagTypeString) ||
1130 (dict->type == kTagTypeKey)))
1131{
1132return dict->offset;
1133}
1134else
1135{
1136return -1;
1137}
1138}
1139
1140
1141bool XMLCastBoolean(TagPtr dict)
1142{
1143if(!dict) return false;
1144if(dict->type == kTagTypeTrue) return true;
1145return false;
1146}
1147
1148int XMLCastInteger(TagPtr dict)
1149{
1150if(!dict)
1151{
1152printf("XMLCastInteger: null dict\n");
1153return 0;
1154}
1155if(dict->type == kTagTypeInteger) return (int)(dict->string);
1156return 0;
1157}
1158

Archive Download this file

Revision: 2118