Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2760