Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2328