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

Archive Download this file

Revision: 2865