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

Archive Download this file

Revision: 2709