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

Archive Download this file

Revision: 2347