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

Archive Download this file

Revision: 2761