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

Archive Download this file

Revision: 2338