Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2769