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

Archive Download this file

Revision: 2182