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/* tagStart points just past the '<' */
923/* Find the end of the tag. */
924tagEnd = tagStart;
925do {
926c = *tagEnd++;
927if (c == '>') {
928break;
929}
930} while (c);
931if (!c) {
932return -1;
933}
934
935/* tagEnd points just past the '>' */
936/* Fix up tag data by nulling out the '>' */
937--tagEnd;
938*tagEnd = '\0';
939
940*tag = tagStart; /* first char after initial '<' */
941if (start) {
942*start = (long) (tagStart - buffer) - 1; /* offset of the initial '<' itself */
943}
944
945/* Return offset to the char after '>' */
946return (long) (tagEnd - buffer) + 1;
947}
948
949//==========================================================================
950// FixDataMatchingTag
951// Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
952// Returns the length of the data found, counting the end tag,
953// or -1 if the end tag was not found.
954
955static long
956FixDataMatchingTag( char * buffer, char * tag )
957{
958 long length, start, stop;
959 char * endTag;
960
961 start = 0;
962 while (1)
963 {
964 length = GetNextTag(buffer + start, &endTag, &stop);
965 if (length == -1) return -1;
966
967 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
968 start += length;
969 }
970
971 buffer[start + stop] = '\0';
972
973 return start + length;
974}
975
976//==========================================================================
977// NewTag
978
979#define kTagsPerBlock (0x1000)
980
981static TagPtr gTagsFree;
982
983static TagPtr
984NewTag( void )
985{
986long cnt;
987TagPtr tag;
988
989 if (gTagsFree == 0)
990 {
991 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
992 if (tag == 0) return 0;
993
994 // Initalize the new tags.
995 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
996 {
997 tag[cnt].type = kTagTypeNone;
998 tag[cnt].string = 0;
999 tag[cnt].tag = 0;
1000 tag[cnt].tagNext = tag + cnt + 1;
1001 }
1002 tag[kTagsPerBlock - 1].tagNext = 0;
1003
1004 gTagsFree = tag;
1005 }
1006
1007 tag = gTagsFree;
1008 gTagsFree = tag->tagNext;
1009
1010 return tag;
1011}
1012
1013//==========================================================================
1014// XMLFreeTag
1015
1016void
1017XMLFreeTag( TagPtr tag )
1018{
1019#if DOFREE
1020if (tag == 0) {
1021return;
1022}
1023
1024if (!XMLIsInteger(tag) && tag->string) {
1025FreeSymbol(tag->string);
1026}
1027
1028XMLFreeTag(tag->tag);
1029XMLFreeTag(tag->tagNext);
1030
1031// Clear and free the tag.
1032tag->type = kTagTypeNone;
1033tag->string = 0;
1034tag->tag = 0;
1035tag->offset = 0;
1036tag->tagNext = gTagsFree;
1037gTagsFree = tag;
1038#else
1039return;
1040#endif
1041}
1042
1043//==========================================================================
1044// Symbol object.
1045
1046struct Symbol
1047{
1048long refCount;
1049struct Symbol *next;
1050char string[];
1051};
1052typedef struct Symbol Symbol, *SymbolPtr;
1053
1054static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
1055
1056static SymbolPtr gSymbolsHead;
1057
1058//==========================================================================
1059// NewSymbol
1060
1061static char *
1062NewSymbol( char * string )
1063{
1064static SymbolPtr lastGuy = 0;
1065SymbolPtr symbol;
1066
1067// Look for string in the list of symbols.
1068symbol = FindSymbol(string, 0);
1069
1070 // Add the new symbol.
1071if (symbol == 0) {
1072symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
1073if (symbol == 0) { //return 0;
1074stop("NULL symbol!");
1075}
1076
1077// Set the symbol's data.
1078symbol->refCount = 0;
1079strcpy(symbol->string, string);
1080
1081// Add the symbol to the list.
1082symbol->next = gSymbolsHead;
1083gSymbolsHead = symbol;
1084}
1085
1086// Update the refCount and return the string.
1087symbol->refCount++;
1088
1089if (lastGuy && lastGuy->next != 0) {
1090stop("last guy not last!");
1091}
1092
1093return symbol->string;
1094}
1095
1096//==========================================================================
1097// FreeSymbol
1098
1099#if DOFREE
1100static void
1101FreeSymbol( char * string )
1102{
1103SymbolPtr symbol, prev;
1104prev = 0;
1105
1106// Look for string in the list of symbols.
1107symbol = FindSymbol(string, &prev);
1108if (symbol == 0) {
1109return;
1110}
1111
1112// Update the refCount.
1113symbol->refCount--;
1114
1115if (symbol->refCount != 0) {
1116return;
1117}
1118
1119// Remove the symbol from the list.
1120if (prev != 0) {
1121prev->next = symbol->next;
1122} else {
1123gSymbolsHead = symbol->next;
1124}
1125
1126// Free the symbol's memory.
1127free(symbol);
1128}
1129#endif
1130
1131//==========================================================================
1132// FindSymbol
1133
1134static SymbolPtr
1135FindSymbol( char * string, SymbolPtr * prevSymbol )
1136{
1137SymbolPtr symbol, prev;
1138
1139symbol = gSymbolsHead;
1140prev = 0;
1141
1142while (symbol != 0) {
1143if (!strcmp(symbol->string, string)) {
1144break;
1145}
1146
1147prev = symbol;
1148symbol = symbol->next;
1149}
1150
1151if ((symbol != 0) && (prevSymbol != 0)) {
1152*prevSymbol = prev;
1153}
1154
1155return symbol;
1156}
1157
1158bool XMLIsType(TagPtr dict, enum xmltype type)
1159{
1160if(!dict) {
1161return (type == kTagTypeNone);
1162}
1163return (dict->type == type);
1164}
1165
1166/*** Cast functions ***/
1167bool XMLIsArray(TagPtr entry)
1168{
1169return entry && (entry->type == kTagTypeArray);
1170}
1171
1172TagPtr XMLCastArray(TagPtr dict)
1173{
1174if(!dict) {
1175return NULL;
1176}
1177if(dict->type == kTagTypeArray) {
1178return dict;
1179} else {
1180return NULL;
1181}
1182}
1183
1184bool XMLIsDict(TagPtr entry)
1185{
1186 return entry && (entry->type == kTagTypeDict);
1187}
1188
1189bool XMLIsData(TagPtr entry)
1190{
1191return entry && (entry->type == kTagTypeData);
1192}
1193
1194TagPtr XMLCastDict(TagPtr dict)
1195{
1196if(!dict) {
1197return NULL;
1198}
1199if(dict->type == kTagTypeDict) {
1200return dict;
1201} else {
1202return NULL;
1203}
1204}
1205
1206bool XMLIsString(TagPtr entry)
1207{
1208 return entry && ((entry->type == kTagTypeString) || (entry->type == kTagTypeKey));
1209}
1210
1211char* XMLCastString(TagPtr dict)
1212{
1213if(!dict) {
1214return NULL;
1215}
1216
1217if((dict->type == kTagTypeString) || (dict->type == kTagTypeKey)) {
1218return dict->string;
1219}
1220
1221return NULL;
1222}
1223
1224char* XMLCastData(TagPtr dict, int* length)
1225{
1226if(!dict) {
1227return NULL;
1228}
1229
1230if((dict->type == kTagTypeData) || (dict->type == kTagTypeKey)) {
1231*length = dict->offset;
1232return dict->string;
1233}
1234*length = 0;
1235return NULL;
1236}
1237
1238
1239long XMLCastStringOffset(TagPtr dict)
1240{
1241if(dict && ((dict->type == kTagTypeString) || (dict->type == kTagTypeKey))) {
1242return dict->offset;
1243} else {
1244return -1;
1245}
1246}
1247
1248bool XMLIsBoolean(TagPtr entry)
1249{
1250return entry && ((entry->type == kTagTypeTrue) || (entry->type == kTagTypeFalse));
1251}
1252
1253bool XMLCastBoolean(TagPtr dict)
1254{
1255if(!dict) {
1256return false;
1257}
1258if(dict->type == kTagTypeTrue) {
1259return true;
1260}
1261return false;
1262}
1263
1264bool XMLIsInteger(TagPtr entry)
1265{
1266 return entry && (entry->type == kTagTypeInteger);
1267}
1268
1269int XMLCastInteger(TagPtr dict)
1270{
1271if(!dict) {
1272//printf("XMLCastInteger: null dict\n");
1273return 0;
1274}
1275if(dict->type == kTagTypeInteger) {
1276return (int)(dict->string);
1277}
1278return 0;
1279}
1280
1281bool XMLAddTagToDictionary(TagPtr dict, char* key, TagPtr value)
1282{
1283if (!dict || dict->type != kTagTypeDict) {
1284return false;
1285}
1286
1287TagPtr tmpTag;
1288char* string;
1289
1290tmpTag = NewTag();
1291if (tmpTag == 0) {
1292return false;
1293}
1294
1295string = NewSymbol(key);
1296if (string == 0) {
1297XMLFreeTag(tmpTag);
1298return false;
1299}
1300
1301tmpTag->type = kTagTypeKey;
1302tmpTag->string = string;
1303tmpTag->tag = value;
1304tmpTag->offset = 0;
1305tmpTag->tagNext = 0;
1306
1307TagPtr tagList = dict->tag;
1308if(!tagList) {
1309// First tag
1310dict->tag = tmpTag;
1311return true;
1312}
1313while(tagList && tagList->tagNext) tagList = tagList->tagNext;
1314if(tagList) {
1315tagList->tagNext = tmpTag;
1316return true;
1317}
1318
1319XMLFreeTag(tmpTag);
1320return false;
1321}
1322

Archive Download this file

Revision: 2341