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
596/***** false ****/
597else if (!strncmp(tagName, kXMLTagFalse, sizeof(kXMLTagFalse)))
598{
599length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
600}
601
602/***** true ****/
603else if (!strncmp(tagName, kXMLTagTrue, sizeof(kXMLTagTrue)))
604{
605length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
606}
607
608/***** plist ****/
609
610
611/***** dict ****/
612
613
614/***** data ****/
615else if (!strncmp(tagName, kXMLTagData, sizeof(kXMLTagData)))
616{
617length = ParseTagData(buffer + pos, tag);
618}
619else if (!strncmp(tagName, kXMLTagData " ", strlen(kXMLTagData " ")))
620{
621length = ParseTagData(buffer + pos, tag);
622}
623
624else if (!strncmp(tagName, kXMLTagDate, sizeof(kXMLTagDate)))
625{
626length = ParseTagDate(buffer + pos, tag);
627}
628
629/***** date ****/
630else if (!strncmp(tagName, kXMLTagDate " ", strlen(kXMLTagDate " ")))
631{
632length = ParseTagDate(buffer + pos, tag);
633}
634/***** array ****/
635else if (!strncmp(tagName, kXMLTagArray, sizeof(kXMLTagArray) ))
636{
637length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
638}
639else if (!strncmp(tagName, kXMLTagArray " ", strlen(kXMLTagArray " ")))
640{
641length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
642}
643else if (!strncmp(tagName, kXMLTagArray "/", strlen(kXMLTagArray "/")))
644{
645length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
646}
647
648/***** unknown ****/
649else
650{
651// it wasn't parsed so we consumed no additional characters
652*tag = NULL;
653length = 0;
654}
655
656if (length == -1)
657{
658return -1;
659}
660
661return pos + length;
662}
663
664//==========================================================================
665// ParseTagList
666static long ParseTagList( char *buffer, TagPtr *tag, long type, long empty )
667{
668longpos = 0;
669longlength = 0;
670TagPtrtagList = NULL;
671TagPtrtmpTag;
672
673
674if (!empty)
675{
676while (1)
677{
678length = XMLParseNextTag(buffer + pos, &tmpTag);
679if (length == -1)
680{
681break;
682}
683
684pos += length;
685
686// detect end of list
687if (tmpTag == NULL)
688{
689break;
690}
691tmpTag->tagNext = tagList;
692tagList = tmpTag;
693}
694
695if (length == -1)
696{
697XMLFreeTag(tagList);
698return -1;
699}
700}
701
702tmpTag = NewTag();
703if (tmpTag == NULL)
704{
705XMLFreeTag(tagList);
706return -1;
707}
708
709tmpTag->type = type;
710tmpTag->string = 0;
711tmpTag->offset = buffer_start ? buffer - buffer_start : 0;
712tmpTag->tag = tagList;
713tmpTag->tagNext = 0;
714
715*tag = tmpTag;
716
717return pos;
718}
719
720//==========================================================================
721// ParseTagKey
722static long ParseTagKey( char *buffer, TagPtr *tag )
723{
724longlength = 0;
725longlength2 = 0;
726char*string;
727TagPtrtmpTag;
728TagPtrsubTag;
729
730length = FixDataMatchingTag(buffer, kXMLTagKey);
731if (length == -1)
732{
733return -1;
734}
735
736length2 = XMLParseNextTag(buffer + length, &subTag);
737if (length2 == -1)
738{
739return -1;
740}
741
742tmpTag = NewTag();
743if (tmpTag == NULL)
744{
745XMLFreeTag(subTag);
746return -1;
747}
748
749string = NewSymbol(buffer);
750if (string == NULL)
751{
752XMLFreeTag(subTag);
753XMLFreeTag(tmpTag);
754return -1;
755}
756
757tmpTag->type = kTagTypeKey;
758tmpTag->string = string;
759tmpTag->tag = subTag;
760tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
761tmpTag->tagNext = 0;
762
763*tag = tmpTag;
764
765return length + length2;
766}
767
768//==========================================================================
769// ParseTagString
770static long ParseTagString( char *buffer, TagPtr *tag )
771{
772longlength = 0;
773char*string;
774
775length = FixDataMatchingTag(buffer, kXMLTagString);
776if (length == -1)
777{
778return -1;
779}
780
781TagPtr tmpTag = NewTag();
782if (tmpTag == NULL)
783{
784return -1;
785}
786
787string = NewSymbol(buffer);
788if (string == NULL)
789{
790XMLFreeTag(tmpTag);
791return -1;
792}
793
794tmpTag->type = kTagTypeString;
795tmpTag->string = string;
796tmpTag->tag = NULL;
797tmpTag->tagNext = NULL;
798tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
799
800*tag = tmpTag;
801return length;
802}
803
804//==========================================================================
805// ParseTagInteger
806static long ParseTagInteger( char *buffer, TagPtr *tag )
807{
808long length, integer;
809bool negative = false;
810TagPtr tmpTag;
811char* val = buffer;
812int size;
813
814if(buffer[0] == '<')
815{
816printf("Warning integer is non existant\n");
817getchar();
818tmpTag = NewTag();
819tmpTag->type = kTagTypeInteger;
820tmpTag->string = 0;
821tmpTag->tag = 0;
822tmpTag->offset = 0;
823tmpTag->tagNext = 0;
824
825*tag = tmpTag;
826
827return 0;
828}
829
830size = length = FixDataMatchingTag(buffer, kXMLTagInteger);
831if (length == -1)
832{
833return -1;
834}
835
836tmpTag = NewTag();
837
838if (tmpTag == 0)
839{
840return -1;
841}
842integer = 0;
843
844if(size > 1 && (val[1] == 'x' || val[1] == 'X'))// Hex value
845{
846val += 2;
847while(*val)
848{
849if ((*val >= '0' && *val <= '9'))// 0 - 9
850{
851integer = (integer * 16) + (*val++ - '0');
852}
853else if ((*val >= 'a' && *val <= 'f'))// a - f
854{
855integer = (integer * 16) + (*val++ - 'a' + 10);
856}
857else if ((*val >= 'A' && *val <= 'F'))// A - F
858{
859integer = (integer * 16) + (*val++ - 'A' + 10);
860}
861else
862{
863printf("ParseTagInteger hex error (0x%x) in buffer %s\n", *val, buffer);
864getchar();
865XMLFreeTag(tmpTag);
866return -1;
867}
868}
869}
870else if ( size )// Decimal value
871{
872if (*val == '-')
873{
874negative = true;
875val++;
876size--;
877}
878
879for (integer = 0; size > 0; size--)
880{
881if(*val) // UGLY HACK, fix me.
882{
883if (*val < '0' || *val > '9')
884{
885printf("ParseTagInteger decimal error (0x%x) in buffer %s\n", *val, buffer);
886getchar();
887return -1;
888}
889
890integer = (integer * 10) + (*val++ - '0');
891}
892}
893
894if (negative) {
895integer = -integer;
896}
897}
898
899tmpTag->type = kTagTypeInteger;
900tmpTag->string = (char *)integer;
901tmpTag->tag = NULL;
902tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
903tmpTag->tagNext = NULL;
904
905*tag = tmpTag;
906
907return length;
908}
909
910//==========================================================================
911// ParseTagData
912static long ParseTagData( char *buffer, TagPtr *tag)
913{
914intactuallen = 0;
915longlength = 0;
916TagPtrtmpTag;
917char*string;
918
919length = FixDataMatchingTag(buffer, kXMLTagData);
920if (length == -1)
921{
922return -1;
923}
924
925tmpTag = NewTag();
926if (tmpTag == NULL)
927{
928return -1;
929}
930
931//printf("ParseTagData unimplimented\n");
932//printf("Data: %s\n", buffer);
933//getchar();
934
935string = BASE64Decode(buffer, strlen(buffer), &actuallen);
936tmpTag->type = kTagTypeData;
937tmpTag->string = string;
938
939tmpTag->tag = NULL;
940tmpTag->offset = actuallen; // buffer_start ? buffer - buffer_start: 0;
941
942tmpTag->tagNext = NULL;
943
944*tag = tmpTag;
945
946return length;
947}
948
949//==========================================================================
950// ParseTagDate
951static long ParseTagDate( char *buffer, TagPtr *tag )
952{
953longlength = 0;
954TagPtrtmpTag;
955
956length = FixDataMatchingTag(buffer, kXMLTagDate);
957if (length == -1)
958{
959return -1;
960}
961
962tmpTag = NewTag();
963if (tmpTag == NULL)
964{
965return -1;
966}
967
968printf("ParseTagDate unimplimented\n");
969getchar();
970
971tmpTag->type = kTagTypeDate;
972tmpTag->string = NULL;
973tmpTag->tag = NULL;
974tmpTag->tagNext = NULL;
975tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
976
977*tag = tmpTag;
978
979return length;
980}
981
982//==========================================================================
983// ParseTagBoolean
984long ParseTagBoolean( char *buffer, TagPtr *tag, long type )
985{
986TagPtr tmpTag;
987
988tmpTag = NewTag();
989if (tmpTag == NULL)
990{
991return -1;
992}
993
994tmpTag->type = type;
995tmpTag->string = NULL;
996tmpTag->tag = NULL;
997tmpTag->tagNext = NULL;
998tmpTag->offset = buffer_start ? buffer - buffer_start: 0;
999
1000
1001*tag = tmpTag;
1002
1003return 0;
1004}
1005
1006//==========================================================================
1007// GetNextTag
1008static long GetNextTag( char *buffer, char **tag, long *start )
1009{
1010longcnt;
1011longcnt2;
1012
1013if (tag == NULL)
1014{
1015return -1;
1016}
1017
1018// Find the start of the tag.
1019cnt = 0;
1020while ((buffer[cnt] != '\0') && (buffer[cnt] != '<'))
1021{
1022cnt++;
1023}
1024
1025if (buffer[cnt] == '\0')
1026{
1027return -1;
1028}
1029// Find the end of the tag.
1030cnt2 = cnt + 1;
1031while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>'))
1032{
1033cnt2++;
1034}
1035
1036if (buffer[cnt2] == '\0')
1037{
1038return -1;
1039}
1040
1041// Fix the tag data.
1042*tag = buffer + cnt + 1;
1043buffer[cnt2] = '\0';
1044if (start)
1045{
1046*start = cnt;
1047}
1048
1049return cnt2 + 1;
1050}
1051
1052//==========================================================================
1053// FixDataMatchingTag
1054// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
1055// Returns the length of the data found, counting the end tag,
1056// or -1 if the end tag was not found.
1057static long FixDataMatchingTag( char *buffer, char *tag )
1058{
1059longlength;
1060longstart;
1061longstop;
1062char*endTag;
1063
1064start = 0;
1065while (1)
1066{
1067length = GetNextTag(buffer + start, &endTag, &stop);
1068if (length == -1)
1069{
1070return -1;
1071}
1072
1073if ((*endTag == '/') && !strcmp(endTag + 1, tag))
1074{
1075break;
1076}
1077
1078start += length;
1079}
1080
1081buffer[start + stop] = '\0';
1082
1083return start + length;
1084}
1085
1086//==========================================================================
1087// NewTag
1088#define kTagsPerBlock (0x1000)
1089
1090static TagPtr gTagsFree= NULL;
1091static TagPtr NewTag( void )
1092{
1093longcnt;
1094TagPtrtag;
1095
1096if (gTagsFree == NULL)
1097{
1098tag = (TagPtr)malloc(kTagsPerBlock *sizeof(Tag));
1099if (tag == NULL)
1100{
1101return NULL;
1102}
1103
1104// Initalize the new tags.
1105for (cnt = 0; cnt < kTagsPerBlock; cnt++)
1106{
1107tag[cnt].type = kTagTypeNone;
1108tag[cnt].string = 0;
1109tag[cnt].tag = 0;
1110tag[cnt].tagNext = tag + cnt + 1;
1111}
1112tag[kTagsPerBlock - 1].tagNext = 0;
1113
1114gTagsFree = tag;
1115}
1116
1117tag = gTagsFree;
1118gTagsFree = tag->tagNext;
1119
1120return tag;
1121}
1122
1123//==========================================================================
1124// XMLFreeTag
1125void XMLFreeTag( TagPtr tag )
1126{
1127#if DOFREE
1128if (tag == NULL)
1129{
1130return;
1131}
1132
1133if (!XMLIsInteger(tag) && tag->string)
1134{
1135FreeSymbol(tag->string);
1136}
1137
1138XMLFreeTag(tag->tag);
1139XMLFreeTag(tag->tagNext);
1140
1141// Clear and free the tag.
1142tag->type = kTagTypeNone;
1143tag->string = NULL;
1144tag->tag = NULL;
1145tag->offset = 0;
1146tag->tagNext = gTagsFree;
1147gTagsFree = tag;
1148#else
1149return;
1150#endif
1151}
1152
1153//==========================================================================
1154// Symbol object.
1155struct Symbol
1156{
1157long refCount;
1158struct Symbol *next;
1159char string[];
1160};
1161typedef struct Symbol Symbol, *SymbolPtr;
1162
1163static SymbolPtr FindSymbol(char *string, SymbolPtr *prevSymbol);
1164
1165static SymbolPtr gSymbolsHead= NULL;
1166
1167//==========================================================================
1168// NewSymbol
1169static char *NewSymbol( char *string )
1170{
1171static SymbolPtr lastGuy = 0;
1172
1173SymbolPtrsymbol;
1174
1175// Look for string in the list of symbols.
1176symbol = FindSymbol(string, 0);
1177
1178// Add the new symbol.
1179if (symbol == NULL)
1180{
1181symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1182if (symbol == NULL)
1183{
1184stop("NULL symbol!");
1185}
1186
1187// Set the symbol's data.
1188symbol->refCount = 0;
1189strcpy(symbol->string, string);
1190
1191// Add the symbol to the list.
1192symbol->next = gSymbolsHead;
1193gSymbolsHead = symbol;
1194}
1195
1196// Update the refCount and return the string.
1197symbol->refCount++;
1198
1199if (lastGuy && lastGuy->next != 0)
1200{
1201stop("last guy not last!");
1202}
1203
1204return symbol->string;
1205}
1206
1207//==========================================================================
1208// FreeSymbol
1209#if DOFREE
1210static void FreeSymbol( char *string )
1211{
1212SymbolPtr symbol, prev;
1213prev = NULL;
1214
1215// Look for string in the list of symbols.
1216symbol = FindSymbol(string, &prev);
1217if (symbol == NULL)
1218{
1219return;
1220}
1221
1222// Update the refCount.
1223symbol->refCount--;
1224
1225if (symbol->refCount != 0)
1226{
1227return;
1228}
1229
1230// Remove the symbol from the list.
1231if (prev != NULL)
1232{
1233prev->next = symbol->next;
1234}
1235else
1236{
1237gSymbolsHead = symbol->next;
1238}
1239
1240// Free the symbol's memory.
1241free(symbol);
1242}
1243#endif
1244
1245//==========================================================================
1246// FindSymbol
1247static SymbolPtr FindSymbol( char *string, SymbolPtr *prevSymbol )
1248{
1249SymbolPtr symbol, prev;
1250
1251if (string == NULL)
1252{
1253return NULL;
1254}
1255
1256symbol = gSymbolsHead;
1257prev = NULL;
1258
1259while (symbol != NULL)
1260{
1261if (!strcmp(symbol->string, string))
1262{
1263break;
1264}
1265
1266prev = symbol;
1267symbol = symbol->next;
1268}
1269
1270if ((symbol != NULL) && (prevSymbol != NULL))
1271{
1272*prevSymbol = prev;
1273}
1274
1275return symbol;
1276}
1277
1278bool XMLIsType(TagPtr dict, enum xmltype type)
1279{
1280if(!dict)
1281{
1282return (type == kTagTypeNone);
1283}
1284return (dict->type == type);
1285}
1286
1287/*** Cast functions ***/
1288bool XMLIsArray(TagPtr entry)
1289{
1290return entry && (entry->type == kTagTypeArray);
1291}
1292
1293TagPtr XMLCastArray(TagPtr dict)
1294{
1295if(!dict)
1296{
1297return NULL;
1298}
1299
1300if(dict->type == kTagTypeArray)
1301{
1302return dict;
1303} else {
1304return NULL;
1305}
1306}
1307
1308bool XMLIsDict(TagPtr entry)
1309{
1310 return entry && (entry->type == kTagTypeDict);
1311}
1312
1313bool XMLIsData(TagPtr entry)
1314{
1315return entry && (entry->type == kTagTypeData);
1316}
1317
1318TagPtr XMLCastDict(TagPtr dict)
1319{
1320if(!dict)
1321{
1322return NULL;
1323}
1324
1325if(dict->type == kTagTypeDict)
1326{
1327return dict;
1328}
1329else
1330{
1331return NULL;
1332}
1333}
1334
1335bool XMLIsString(TagPtr entry)
1336{
1337 return entry && ((entry->type == kTagTypeString) || (entry->type == kTagTypeKey));
1338}
1339
1340char *XMLCastString(TagPtr dict)
1341{
1342if(!dict)
1343{
1344return NULL;
1345}
1346
1347if((dict->type == kTagTypeString) || (dict->type == kTagTypeKey))
1348{
1349return dict->string;
1350}
1351
1352return NULL;
1353}
1354
1355char *XMLCastData(TagPtr dict, int* length)
1356{
1357if(!dict)
1358{
1359return NULL;
1360}
1361
1362if((dict->type == kTagTypeData) || (dict->type == kTagTypeKey))
1363{
1364*length = dict->offset;
1365return dict->string;
1366}
1367*length = 0;
1368return NULL;
1369}
1370
1371
1372long XMLCastStringOffset(TagPtr dict)
1373{
1374if(dict && ((dict->type == kTagTypeString) || (dict->type == kTagTypeKey)))
1375{
1376return dict->offset;
1377}
1378else
1379{
1380return -1;
1381}
1382}
1383
1384bool XMLIsBoolean(TagPtr entry)
1385{
1386return entry && ((entry->type == kTagTypeTrue) || (entry->type == kTagTypeFalse));
1387}
1388
1389bool XMLCastBoolean(TagPtr dict)
1390{
1391if(!dict)
1392{
1393return false;
1394}
1395
1396if(dict->type == kTagTypeTrue)
1397{
1398return true;
1399}
1400return false;
1401}
1402
1403bool XMLIsInteger(TagPtr entry)
1404{
1405 return entry && (entry->type == kTagTypeInteger);
1406}
1407
1408int XMLCastInteger(TagPtr dict)
1409{
1410if(!dict)
1411{
1412//printf("XMLCastInteger: null dict\n");
1413return 0;
1414}
1415
1416if(dict->type == kTagTypeInteger)
1417{
1418return (int)(dict->string);
1419}
1420return 0;
1421}
1422
1423bool XMLAddTagToDictionary(TagPtr dict, char *key, TagPtr value)
1424{
1425if (!dict || dict->type != kTagTypeDict)
1426{
1427return false;
1428}
1429
1430TagPtr tmpTag;
1431char* string;
1432
1433tmpTag = NewTag();
1434if (tmpTag == 0)
1435{
1436return false;
1437}
1438
1439string = NewSymbol(key);
1440if (string == 0)
1441{
1442XMLFreeTag(tmpTag);
1443return false;
1444}
1445
1446tmpTag->type = kTagTypeKey;
1447tmpTag->string = string;
1448tmpTag->tag = value;
1449tmpTag->offset = 0;
1450tmpTag->tagNext = 0;
1451
1452TagPtr tagList = dict->tag;
1453if(!tagList)
1454{
1455// First tag
1456dict->tag = tmpTag;
1457return true;
1458}
1459while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1460if(tagList)
1461{
1462tagList->tagNext = tmpTag;
1463return true;
1464}
1465
1466XMLFreeTag(tmpTag);
1467return false;
1468}
1469

Archive Download this file

Revision: 2853