Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2629