Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 2037