xmlParser.cc (10152:52c552138ba1) xmlParser.cc (10234:5cb711fa6176)
1/**
2 ****************************************************************************
3 * <P> XML.c - implementation file for basic XML parser written in ANSI C++
4 * for portability. It works by using recursion and a node tree for breaking
5 * down the elements of an XML document. </P>
6 *
7 * @version V2.41
8 * @author Frank Vanden Berghen

--- 61 unchanged lines hidden (view full) ---

70 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
71 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
72 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
73 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
74 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 *
77 * Copyright (c) 2002, Business-Insight
1/**
2 ****************************************************************************
3 * <P> XML.c - implementation file for basic XML parser written in ANSI C++
4 * for portability. It works by using recursion and a node tree for breaking
5 * down the elements of an XML document. </P>
6 *
7 * @version V2.41
8 * @author Frank Vanden Berghen

--- 61 unchanged lines hidden (view full) ---

70 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
71 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
72 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
73 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
74 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
75 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
76 *
77 * Copyright (c) 2002, Business-Insight
78 * Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
78 * <a href="http://www.Business-Insight.com">Business-Insight</a>
79 * All rights reserved.
80 *
81 ****************************************************************************
82 */
83#ifndef _CRT_SECURE_NO_DEPRECATE
84#define _CRT_SECURE_NO_DEPRECATE
85#endif
86#include "xmlParser.h"
87#ifdef _XMLWINDOWS
88//#ifdef _DEBUG
89//#define _CRTDBG_MAP_ALLOC
90//#include <crtdbg.h>
91//#endif
92#define WIN32_LEAN_AND_MEAN
93#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
79 * <a href="http://www.Business-Insight.com">Business-Insight</a>
80 * All rights reserved.
81 *
82 ****************************************************************************
83 */
84#ifndef _CRT_SECURE_NO_DEPRECATE
85#define _CRT_SECURE_NO_DEPRECATE
86#endif
87#include "xmlParser.h"
88#ifdef _XMLWINDOWS
89//#ifdef _DEBUG
90//#define _CRTDBG_MAP_ALLOC
91//#include <crtdbg.h>
92//#endif
93#define WIN32_LEAN_AND_MEAN
94#include <Windows.h> // to have IsTextUnicode, MultiByteToWideChar, WideCharToMultiByte to handle unicode files
94 // to have "MessageBoxA" to display error messages for openFilHelper
95// to have "MessageBoxA" to display error messages for openFilHelper
95#endif
96
97#include <memory.h>
98
99#include <cassert>
100#include <cstdio>
101#include <cstdlib>
102#include <cstring>
103
96#endif
97
98#include <memory.h>
99
100#include <cassert>
101#include <cstdio>
102#include <cstdlib>
103#include <cstring>
104
104XMLCSTR XMLNode::getVersion() { return _CXML("v2.39"); }
105void freeXMLString(XMLSTR t){if(t)free(t);}
105XMLCSTR XMLNode::getVersion() {
106 return _CXML("v2.39");
107}
108void freeXMLString(XMLSTR t) {
109 if (t)free(t);
110}
106
107static XMLNode::XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8;
108static char guessWideCharChars=1, dropWhiteSpace=1, removeCommentsInMiddleOfText=1;
109
111
112static XMLNode::XMLCharEncoding characterEncoding=XMLNode::char_encoding_UTF8;
113static char guessWideCharChars=1, dropWhiteSpace=1, removeCommentsInMiddleOfText=1;
114
110inline int mmin( const int t1, const int t2 ) { return t1 < t2 ? t1 : t2; }
115inline int mmin( const int t1, const int t2 ) {
116 return t1 < t2 ? t1 : t2;
117}
111
112// You can modify the initialization of the variable "XMLClearTags" below
113// to change the clearTags that are currently recognized by the library.
114// The number on the second columns is the length of the string inside the
115// first column. The "<!DOCTYPE" declaration must be the second in the list.
116// The "<!--" declaration must be the third in the list.
118
119// You can modify the initialization of the variable "XMLClearTags" below
120// to change the clearTags that are currently recognized by the library.
121// The number on the second columns is the length of the string inside the
122// first column. The "<!DOCTYPE" declaration must be the second in the list.
123// The "<!--" declaration must be the third in the list.
117typedef struct { XMLCSTR lpszOpen; int openTagLen; XMLCSTR lpszClose;} ALLXMLClearTag;
118static ALLXMLClearTag XMLClearTags[] =
119{
120 { _CXML("<![CDATA["),9, _CXML("]]>") },
121 { _CXML("<!DOCTYPE"),9, _CXML(">") },
122 { _CXML("<!--") ,4, _CXML("-->") },
123 { _CXML("<PRE>") ,5, _CXML("</PRE>") },
124typedef struct {
125 XMLCSTR lpszOpen;
126 int openTagLen;
127 XMLCSTR lpszClose;
128} ALLXMLClearTag;
129static ALLXMLClearTag XMLClearTags[] = {
130 { _CXML("<![CDATA["), 9, _CXML("]]>") },
131 { _CXML("<!DOCTYPE"), 9, _CXML(">") },
132 { _CXML("<!--") , 4, _CXML("-->") },
133 { _CXML("<PRE>") , 5, _CXML("</PRE>") },
124// { _CXML("<Script>") ,8, _CXML("</Script>")},
134// { _CXML("<Script>") ,8, _CXML("</Script>")},
125 { NULL ,0, NULL }
135 { NULL , 0, NULL }
126};
127
128// You can modify the initialization of the variable "XMLEntities" below
129// to change the character entities that are currently recognized by the library.
130// The number on the second columns is the length of the string inside the
131// first column. Additionally, the syntaxes "&#xA0;" and "&#160;" are recognized.
136};
137
138// You can modify the initialization of the variable "XMLEntities" below
139// to change the character entities that are currently recognized by the library.
140// The number on the second columns is the length of the string inside the
141// first column. Additionally, the syntaxes "&#xA0;" and "&#160;" are recognized.
132typedef struct { XMLCSTR s; int l; XMLCHAR c;} XMLCharacterEntity;
133static XMLCharacterEntity XMLEntities[] =
134{
142typedef struct {
143 XMLCSTR s;
144 int l;
145 XMLCHAR c;
146} XMLCharacterEntity;
147static XMLCharacterEntity XMLEntities[] = {
135 { _CXML("&amp;" ), 5, _CXML('&' )},
136 { _CXML("&lt;" ), 4, _CXML('<' )},
137 { _CXML("&gt;" ), 4, _CXML('>' )},
138 { _CXML("&quot;"), 6, _CXML('\"')},
139 { _CXML("&apos;"), 6, _CXML('\'')},
140 { NULL , 0, '\0' }
141};
142
143// When rendering the XMLNode to a string (using the "createXMLString" function),
144// you can ask for a beautiful formatting. This formatting is using the
145// following indentation character:
146#define INDENTCHAR _CXML('\t')
147
148// The following function parses the XML errors into a user friendly string.
149// You can edit this to change the output language of the library to something else.
148 { _CXML("&amp;" ), 5, _CXML('&' )},
149 { _CXML("&lt;" ), 4, _CXML('<' )},
150 { _CXML("&gt;" ), 4, _CXML('>' )},
151 { _CXML("&quot;"), 6, _CXML('\"')},
152 { _CXML("&apos;"), 6, _CXML('\'')},
153 { NULL , 0, '\0' }
154};
155
156// When rendering the XMLNode to a string (using the "createXMLString" function),
157// you can ask for a beautiful formatting. This formatting is using the
158// following indentation character:
159#define INDENTCHAR _CXML('\t')
160
161// The following function parses the XML errors into a user friendly string.
162// You can edit this to change the output language of the library to something else.
150XMLCSTR XMLNode::getError(XMLError xerror)
151{
152 switch (xerror)
153 {
154 case eXMLErrorNone: return _CXML("No error");
155 case eXMLErrorMissingEndTag: return _CXML("Warning: Unmatched end tag");
156 case eXMLErrorNoXMLTagFound: return _CXML("Warning: No XML tag found");
157 case eXMLErrorEmpty: return _CXML("Error: No XML data");
158 case eXMLErrorMissingTagName: return _CXML("Error: Missing start tag name");
159 case eXMLErrorMissingEndTagName: return _CXML("Error: Missing end tag name");
160 case eXMLErrorUnmatchedEndTag: return _CXML("Error: Unmatched end tag");
161 case eXMLErrorUnmatchedEndClearTag: return _CXML("Error: Unmatched clear tag end");
162 case eXMLErrorUnexpectedToken: return _CXML("Error: Unexpected token found");
163 case eXMLErrorNoElements: return _CXML("Error: No elements found");
164 case eXMLErrorFileNotFound: return _CXML("Error: File not found");
165 case eXMLErrorFirstTagNotFound: return _CXML("Error: First Tag not found");
166 case eXMLErrorUnknownCharacterEntity:return _CXML("Error: Unknown character entity");
167 case eXMLErrorCharacterCodeAbove255: return _CXML("Error: Character code above 255 is forbidden in MultiByte char mode.");
168 case eXMLErrorCharConversionError: return _CXML("Error: unable to convert between WideChar and MultiByte chars");
169 case eXMLErrorCannotOpenWriteFile: return _CXML("Error: unable to open file for writing");
170 case eXMLErrorCannotWriteFile: return _CXML("Error: cannot write into file");
163XMLCSTR XMLNode::getError(XMLError xerror) {
164 switch (xerror) {
165 case eXMLErrorNone:
166 return _CXML("No error");
167 case eXMLErrorMissingEndTag:
168 return _CXML("Warning: Unmatched end tag");
169 case eXMLErrorNoXMLTagFound:
170 return _CXML("Warning: No XML tag found");
171 case eXMLErrorEmpty:
172 return _CXML("Error: No XML data");
173 case eXMLErrorMissingTagName:
174 return _CXML("Error: Missing start tag name");
175 case eXMLErrorMissingEndTagName:
176 return _CXML("Error: Missing end tag name");
177 case eXMLErrorUnmatchedEndTag:
178 return _CXML("Error: Unmatched end tag");
179 case eXMLErrorUnmatchedEndClearTag:
180 return _CXML("Error: Unmatched clear tag end");
181 case eXMLErrorUnexpectedToken:
182 return _CXML("Error: Unexpected token found");
183 case eXMLErrorNoElements:
184 return _CXML("Error: No elements found");
185 case eXMLErrorFileNotFound:
186 return _CXML("Error: File not found");
187 case eXMLErrorFirstTagNotFound:
188 return _CXML("Error: First Tag not found");
189 case eXMLErrorUnknownCharacterEntity:
190 return _CXML("Error: Unknown character entity");
191 case eXMLErrorCharacterCodeAbove255:
192 return _CXML("Error: Character code above 255 is forbidden in MultiByte char mode.");
193 case eXMLErrorCharConversionError:
194 return _CXML("Error: unable to convert between WideChar and MultiByte chars");
195 case eXMLErrorCannotOpenWriteFile:
196 return _CXML("Error: unable to open file for writing");
197 case eXMLErrorCannotWriteFile:
198 return _CXML("Error: cannot write into file");
171
199
172 case eXMLErrorBase64DataSizeIsNotMultipleOf4: return _CXML("Warning: Base64-string length is not a multiple of 4");
173 case eXMLErrorBase64DecodeTruncatedData: return _CXML("Warning: Base64-string is truncated");
174 case eXMLErrorBase64DecodeIllegalCharacter: return _CXML("Error: Base64-string contains an illegal character");
175 case eXMLErrorBase64DecodeBufferTooSmall: return _CXML("Error: Base64 decode output buffer is too small");
200 case eXMLErrorBase64DataSizeIsNotMultipleOf4:
201 return _CXML("Warning: Base64-string length is not a multiple of 4");
202 case eXMLErrorBase64DecodeTruncatedData:
203 return _CXML("Warning: Base64-string is truncated");
204 case eXMLErrorBase64DecodeIllegalCharacter:
205 return _CXML("Error: Base64-string contains an illegal character");
206 case eXMLErrorBase64DecodeBufferTooSmall:
207 return _CXML("Error: Base64 decode output buffer is too small");
176 };
177 return _CXML("Unknown");
178}
179
180/////////////////////////////////////////////////////////////////////////
181// Here start the abstraction layer to be OS-independent //
182/////////////////////////////////////////////////////////////////////////
183
184// Here is an abstraction layer to access some common string manipulation functions.
185// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
186// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
187// If you plan to "port" the library to a new system/compiler, all you have to do is
188// to edit the following lines.
189#ifdef XML_NO_WIDE_CHAR
208 };
209 return _CXML("Unknown");
210}
211
212/////////////////////////////////////////////////////////////////////////
213// Here start the abstraction layer to be OS-independent //
214/////////////////////////////////////////////////////////////////////////
215
216// Here is an abstraction layer to access some common string manipulation functions.
217// The abstraction layer is currently working for gcc, Microsoft Visual Studio 6.0,
218// Microsoft Visual Studio .NET, CC (sun compiler) and Borland C++.
219// If you plan to "port" the library to a new system/compiler, all you have to do is
220// to edit the following lines.
221#ifdef XML_NO_WIDE_CHAR
190char myIsTextWideChar(const void *b, int len) { return FALSE; }
222char myIsTextWideChar(const void *b, int len) {
223 return FALSE;
224}
191#else
225#else
192 #if defined (UNDER_CE) || !defined(_XMLWINDOWS)
193 char myIsTextWideChar(const void *b, int len) // inspired by the Wine API: RtlIsTextUnicode
194 {
226#if defined (UNDER_CE) || !defined(_XMLWINDOWS)
227// inspired by the Wine API: RtlIsTextUnicode
228char myIsTextWideChar(const void *b, int len) {
195#ifdef sun
229#ifdef sun
196 // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
197 if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
230 // for SPARC processors: wchar_t* buffers must always be alligned, otherwise it's a char* buffer.
231 if ((((unsigned long)b)%sizeof(wchar_t))!=0) return FALSE;
198#endif
232#endif
199 const wchar_t *s=(const wchar_t*)b;
233 const wchar_t *s = (const wchar_t*)b;
200
234
201 // buffer too small:
202 if (len<(int)sizeof(wchar_t)) return FALSE;
235 // buffer too small:
236 if (len < (int)sizeof(wchar_t)) return FALSE;
203
237
204 // odd length test
205 if (len&1) return FALSE;
238 // odd length test
239 if (len&1) return FALSE;
206
240
207 /* only checks the first 256 characters */
208 len=mmin(256,len/sizeof(wchar_t));
241 /* only checks the first 256 characters */
242 len = mmin(256, len / sizeof(wchar_t));
209
243
210 // Check for the special byte order:
211 if (*((unsigned short*)s) == 0xFFFE) return TRUE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
212 if (*((unsigned short*)s) == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE
244 // Check for the special byte order:
245 if (*((unsigned short*)s) == 0xFFFE) return TRUE; // IS_TEXT_UNICODE_REVERSE_SIGNATURE;
246 if (*((unsigned short*)s) == 0xFEFF) return TRUE; // IS_TEXT_UNICODE_SIGNATURE
213
247
214 // checks for ASCII characters in the UNICODE stream
215 int i,stats=0;
216 for (i=0; i<len; i++) if (s[i]<=(unsigned short)255) stats++;
217 if (stats>len/2) return TRUE;
248 // checks for ASCII characters in the UNICODE stream
249 int i, stats=0;
250 for (i=0; i251 if (stats>len/2) return TRUE;
218
252
219 // Check for UNICODE NULL chars
220 for (i=0; i<len; i++) if (!s[i]) return TRUE;
253 // Check for UNICODE NULL chars
254 for (i=0; i
221
255
222 return FALSE;
223 }
224 #else
225 char myIsTextWideChar(const void *b,int l) { return (char)IsTextUnicode((CONST LPVOID)b,l,NULL); };
226 #endif
256 return FALSE;
257}
258#else
259char myIsTextWideChar(const void *b, int l) {
260 return (char)IsTextUnicode((CONST LPVOID)b, l, NULL);
261};
227#endif
262#endif
263#endif
228
229#ifdef _XMLWINDOWS
230// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
264
265#ifdef _XMLWINDOWS
266// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
231 #ifdef _XMLWIDECHAR
232 wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce)
233 {
234 int i;
235 if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,NULL,0);
236 else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,NULL,0);
237 if (i<0) return NULL;
238 wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(XMLCHAR));
239 if (ce==XMLNode::char_encoding_UTF8) i=(int)MultiByteToWideChar(CP_UTF8,0 ,s,-1,d,i);
240 else i=(int)MultiByteToWideChar(CP_ACP ,MB_PRECOMPOSED,s,-1,d,i);
241 d[i]=0;
242 return d;
243 }
244 static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return _wfopen(filename,mode); }
245 static inline int xstrlen(XMLCSTR c) { return (int)wcslen(c); }
246 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _wcsnicmp(c1,c2,l);}
247 static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);}
248 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _wcsicmp(c1,c2); }
249 static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
250 static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); }
251 #else
252 char *myWideCharToMultiByte(const wchar_t *s)
253 {
254 UINT codePage=CP_ACP; if (characterEncoding==XMLNode::char_encoding_UTF8) codePage=CP_UTF8;
255 int i=(int)WideCharToMultiByte(codePage, // code page
256 0, // performance and mapping flags
257 s, // wide-character string
258 -1, // number of chars in string
259 NULL, // buffer for new string
260 0, // size of buffer
261 NULL, // default for unmappable chars
262 NULL // set when default char used
263 );
264 if (i<0) return NULL;
265 char *d=(char*)malloc(i+1);
266 WideCharToMultiByte(codePage, // code page
267 0, // performance and mapping flags
268 s, // wide-character string
269 -1, // number of chars in string
270 d, // buffer for new string
271 i, // size of buffer
272 NULL, // default for unmappable chars
273 NULL // set when default char used
274 );
275 d[i]=0;
276 return d;
277 }
278 static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
279 static inline int xstrlen(XMLCSTR c) { return (int)strlen(c); }
280 #ifdef __BORLANDC__
281 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strnicmp(c1,c2,l);}
282 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return stricmp(c1,c2); }
283 #else
284 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return _strnicmp(c1,c2,l);}
285 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return _stricmp(c1,c2); }
286 #endif
287 static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);}
288 static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
289 static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); }
290 #endif
267#ifdef _XMLWIDECHAR
268wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) {
269 int i;
270 if (ce == XMLNode::char_encoding_UTF8) {
271 i = (int)MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
272 } else {
273 i = (int)MultiByteToWideChar(CP_ACP , MB_PRECOMPOSED, s, -1, NULL, 0);
274 }
275 if (i < 0) {
276 return NULL;
277 }
278 wchar_t *d = (wchar_t *)malloc((i + 1) * sizeof(XMLCHAR));
279 if (ce == XMLNode::char_encoding_UTF8) {
280 i = (int)MultiByteToWideChar(CP_UTF8, 0, s, -1, d, i);
281 } else {
282 i = (int)MultiByteToWideChar(CP_ACP , MB_PRECOMPOSED, s, -1, d, i);
283 }
284 d[i] = 0;
285 return d;
286}
287static inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
288 return _wfopen(filename, mode);
289}
290static inline int xstrlen(XMLCSTR c) {
291 return (int)wcslen(c);
292}
293static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
294 return _wcsnicmp(c1, c2, l);
295}
296static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
297 return wcsncmp(c1, c2, l);
298}
299static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
300 return _wcsicmp(c1, c2);
301}
302static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
303 return (XMLSTR)wcsstr(c1, c2);
304}
305static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
306 return (XMLSTR)wcscpy(c1, c2);
307}
291#else
308#else
309char *myWideCharToMultiByte(const wchar_t *s) {
310 UINT codePage = CP_ACP;
311 if (characterEncoding == XMLNode::char_encoding_UTF8) codePage = CP_UTF8;
312 int i = (int)WideCharToMultiByte(codePage, // code page
313 0, // performance and mapping flags
314 s, // wide-character string
315 -1, // number of chars in string
316 NULL, // buffer for new string
317 0, // size of buffer
318 NULL, // default for unmappable chars
319 NULL // set when default char used
320 );
321 if (i<0) return NULL;
322 char *d=(char*)malloc(i+1);
323 WideCharToMultiByte(codePage, // code page
324 0, // performance and mapping flags
325 s, // wide-character string
326 -1, // number of chars in string
327 d, // buffer for new string
328 i, // size of buffer
329 NULL, // default for unmappable chars
330 NULL // set when default char used
331 );
332 d[i] = 0;
333 return d;
334}
335static inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
336 return fopen(filename, mode);
337}
338static inline int xstrlen(XMLCSTR c) {
339 return (int)strlen(c);
340}
341#ifdef __BORLANDC__
342static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
343 return strnicmp(c1, c2, l);
344}
345static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
346 return stricmp(c1, c2);
347}
348#else
349static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
350 return _strnicmp(c1, c2, l);
351}
352static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
353 return _stricmp(c1, c2);
354}
355#endif
356static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
357 return strncmp(c1, c2, l);
358}
359static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
360 return (XMLSTR)strstr(c1, c2);
361}
362static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
363 return (XMLSTR)strcpy(c1, c2);
364}
365#endif
366#else
292// for gcc and CC
367// for gcc and CC
293 #ifdef XML_NO_WIDE_CHAR
294 char *myWideCharToMultiByte(const wchar_t *s) { return NULL; }
295 #else
296 char *myWideCharToMultiByte(const wchar_t *s)
297 {
298 const wchar_t *ss=s;
299 int i=(int)wcsrtombs(NULL,&ss,0,NULL);
300 if (i<0) return NULL;
301 char *d=(char *)malloc(i+1);
302 wcsrtombs(d,&s,i,NULL);
303 d[i]=0;
304 return d;
305 }
306 #endif
307 #ifdef _XMLWIDECHAR
308 wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce)
309 {
310 const char *ss=s;
311 int i=(int)mbsrtowcs(NULL,&ss,0,NULL);
312 if (i<0) return NULL;
313 wchar_t *d=(wchar_t *)malloc((i+1)*sizeof(wchar_t));
314 mbsrtowcs(d,&s,i,NULL);
315 d[i]=0;
316 return d;
317 }
318 int xstrlen(XMLCSTR c) { return wcslen(c); }
319 #ifdef sun
320 // for CC
321 #include <widec.h>
322 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncasecmp(c1,c2,l);}
323 static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wsncmp(c1,c2,l);}
324 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wscasecmp(c1,c2); }
325 #else
326 // for gcc
327 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncasecmp(c1,c2,l);}
328 static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return wcsncmp(c1,c2,l);}
329 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return wcscasecmp(c1,c2); }
330 #endif
331 static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)wcsstr(c1,c2); }
332 static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)wcscpy(c1,c2); }
333 static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode)
334 {
335 char *filenameAscii=myWideCharToMultiByte(filename);
336 FILE *f;
337 if (mode[0]==_CXML('r')) f=fopen(filenameAscii,"rb");
338 else f=fopen(filenameAscii,"wb");
339 free(filenameAscii);
340 return f;
341 }
342 #else
343 static inline FILE *xfopen(XMLCSTR filename,XMLCSTR mode) { return fopen(filename,mode); }
344 static inline int xstrlen(XMLCSTR c) { return strlen(c); }
345 static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncasecmp(c1,c2,l);}
346 static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) { return strncmp(c1,c2,l);}
347 static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) { return strcasecmp(c1,c2); }
348 static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) { return (XMLSTR)strstr(c1,c2); }
349 static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) { return (XMLSTR)strcpy(c1,c2); }
350 #endif
351 static inline int _strnicmp(const char *c1,const char *c2, int l) { return strncasecmp(c1,c2,l);}
368#ifdef XML_NO_WIDE_CHAR
369char *myWideCharToMultiByte(const wchar_t *s) {
370 return NULL;
371}
372#else
373char *myWideCharToMultiByte(const wchar_t *s) {
374 const wchar_t *ss = s;
375 int i = (int)wcsrtombs(NULL, &ss, 0, NULL);
376 if (i < 0) return NULL;
377 char *d = (char *)malloc(i + 1);
378 wcsrtombs(d, &s, i, NULL);
379 d[i] = 0;
380 return d;
381}
352#endif
382#endif
383#ifdef _XMLWIDECHAR
384wchar_t *myMultiByteToWideChar(const char *s, XMLNode::XMLCharEncoding ce) {
385 const char *ss = s;
386 int i = (int)mbsrtowcs(NULL, &ss, 0, NULL);
387 if (i < 0) return NULL;
388 wchar_t *d = (wchar_t *)malloc((i + 1) * sizeof(wchar_t));
389 mbsrtowcs(d, &s, i, NULL);
390 d[i] = 0;
391 return d;
392}
393int xstrlen(XMLCSTR c) {
394 return wcslen(c);
395}
396#ifdef sun
397// for CC
398#include <widec.h>
399static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
400 return wsncasecmp(c1, c2, l);
401}
402static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
403 return wsncmp(c1, c2, l);
404}
405static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
406 return wscasecmp(c1, c2);
407}
408#else
409// for gcc
410static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
411 return wcsncasecmp(c1, c2, l);
412}
413static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
414 return wcsncmp(c1, c2, l);
415}
416static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
417 return wcscasecmp(c1, c2);
418}
419#endif
420static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
421 return (XMLSTR)wcsstr(c1, c2);
422}
423static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
424 return (XMLSTR)wcscpy(c1, c2);
425}
426static inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
427 char *filenameAscii = myWideCharToMultiByte(filename);
428 FILE *f;
429 if (mode[0] == _CXML('r')) f = fopen(filenameAscii, "rb");
430 else f = fopen(filenameAscii, "wb");
431 free(filenameAscii);
432 return f;
433}
434#else
435static inline FILE *xfopen(XMLCSTR filename, XMLCSTR mode) {
436 return fopen(filename, mode);
437}
438static inline int xstrlen(XMLCSTR c) {
439 return strlen(c);
440}
441static inline int xstrnicmp(XMLCSTR c1, XMLCSTR c2, int l) {
442 return strncasecmp(c1, c2, l);
443}
444static inline int xstrncmp(XMLCSTR c1, XMLCSTR c2, int l) {
445 return strncmp(c1, c2, l);
446}
447static inline int xstricmp(XMLCSTR c1, XMLCSTR c2) {
448 return strcasecmp(c1, c2);
449}
450static inline XMLSTR xstrstr(XMLCSTR c1, XMLCSTR c2) {
451 return (XMLSTR)strstr(c1, c2);
452}
453static inline XMLSTR xstrcpy(XMLSTR c1, XMLCSTR c2) {
454 return (XMLSTR)strcpy(c1, c2);
455}
456#endif
457static inline int _strnicmp(const char *c1, const char *c2, int l) {
458 return strncasecmp(c1, c2, l);
459}
460#endif
353
354
355///////////////////////////////////////////////////////////////////////////////
356// the "xmltoc,xmltob,xmltoi,xmltol,xmltof,xmltoa" functions //
357///////////////////////////////////////////////////////////////////////////////
358// These 6 functions are not used inside the XMLparser.
359// There are only here as "convenience" functions for the user.
360// If you don't need them, you can delete them without any trouble.
361#ifdef _XMLWIDECHAR
461
462
463///////////////////////////////////////////////////////////////////////////////
464// the "xmltoc,xmltob,xmltoi,xmltol,xmltof,xmltoa" functions //
465///////////////////////////////////////////////////////////////////////////////
466// These 6 functions are not used inside the XMLparser.
467// There are only here as "convenience" functions for the user.
468// If you don't need them, you can delete them without any trouble.
469#ifdef _XMLWIDECHAR
362 #ifdef _XMLWINDOWS
363 // for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
364 char xmltob(XMLCSTR t,int v){ if (t&&(*t)) return (char)_wtoi(t); return v; }
365 int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return _wtoi(t); return v; }
366 long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return _wtol(t); return v; }
367 double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; }
368 #else
369 #ifdef sun
370 // for CC
371 #include <widec.h>
372 char xmltob(XMLCSTR t,int v){ if (t) return (char)wstol(t,NULL,10); return v; }
373 int xmltoi(XMLCSTR t,int v){ if (t) return (int)wstol(t,NULL,10); return v; }
374 long xmltol(XMLCSTR t,long v){ if (t) return wstol(t,NULL,10); return v; }
375 #else
376 // for gcc
377 char xmltob(XMLCSTR t,int v){ if (t) return (char)wcstol(t,NULL,10); return v; }
378 int xmltoi(XMLCSTR t,int v){ if (t) return (int)wcstol(t,NULL,10); return v; }
379 long xmltol(XMLCSTR t,long v){ if (t) return wcstol(t,NULL,10); return v; }
380 #endif
381 double xmltof(XMLCSTR t,double v){ if (t&&(*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/ return v; }
382 #endif
470#ifdef _XMLWINDOWS
471// for Microsoft Visual Studio 6.0 and Microsoft Visual Studio .NET and Borland C++ Builder 6.0
472char xmltob(XMLCSTR t, int v) {
473 if (t && (*t)) return (char)_wtoi(t);
474 return v;
475}
476int xmltoi(XMLCSTR t, int v) {
477 if (t && (*t)) return _wtoi(t);
478 return v;
479}
480long xmltol(XMLCSTR t, long v) {
481 if (t && (*t)) return _wtol(t);
482 return v;
483}
484double xmltof(XMLCSTR t, double v) {
485 if (t && (*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/
486 return v;
487}
383#else
488#else
384 char xmltob(XMLCSTR t,char v){ if (t&&(*t)) return (char)atoi(t); return v; }
385 int xmltoi(XMLCSTR t,int v){ if (t&&(*t)) return atoi(t); return v; }
386 long xmltol(XMLCSTR t,long v){ if (t&&(*t)) return atol(t); return v; }
387 double xmltof(XMLCSTR t,double v){ if (t&&(*t)) return atof(t); return v; }
489#ifdef sun
490// for CC
491#include <widec.h>
492char xmltob(XMLCSTR t, int v) {
493 if (t) return (char)wstol(t, NULL, 10);
494 return v;
495}
496int xmltoi(XMLCSTR t, int v) {
497 if (t) return (int)wstol(t, NULL, 10);
498 return v;
499}
500long xmltol(XMLCSTR t, long v) {
501 if (t) return wstol(t, NULL, 10);
502 return v;
503}
504#else
505// for gcc
506char xmltob(XMLCSTR t, int v) {
507 if (t) return (char)wcstol(t, NULL, 10);
508 return v;
509}
510int xmltoi(XMLCSTR t, int v) {
511 if (t) return (int)wcstol(t, NULL, 10);
512 return v;
513}
514long xmltol(XMLCSTR t, long v) {
515 if (t) return wcstol(t, NULL, 10);
516 return v;
517}
388#endif
518#endif
389XMLCSTR xmltoa(XMLCSTR t,XMLCSTR v){ if (t) return t; return v; }
390XMLCHAR xmltoc(XMLCSTR t,XMLCHAR v){ if (t&&(*t)) return *t; return v; }
519double xmltof(XMLCSTR t, double v) {
520 if (t && (*t)) wscanf(t, "%f", &v); /*v=_wtof(t);*/
521 return v;
522}
523#endif
524#else
525char xmltob(XMLCSTR t, char v) {
526 if (t && (*t)) return (char)atoi(t);
527 return v;
528}
529int xmltoi(XMLCSTR t, int v) {
530 if (t && (*t)) return atoi(t);
531 return v;
532}
533long xmltol(XMLCSTR t, long v) {
534 if (t && (*t)) return atol(t);
535 return v;
536}
537double xmltof(XMLCSTR t, double v) {
538 if (t && (*t)) return atof(t);
539 return v;
540}
541#endif
542XMLCSTR xmltoa(XMLCSTR t, XMLCSTR v) {
543 if (t) return t;
544 return v;
545}
546XMLCHAR xmltoc(XMLCSTR t, XMLCHAR v) {
547 if (t && (*t)) return *t;
548 return v;
549}
391
392/////////////////////////////////////////////////////////////////////////
393// the "openFileHelper" function //
394/////////////////////////////////////////////////////////////////////////
395
396// Since each application has its own way to report and deal with errors, you should modify & rewrite
397// the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs.
550
551/////////////////////////////////////////////////////////////////////////
552// the "openFileHelper" function //
553/////////////////////////////////////////////////////////////////////////
554
555// Since each application has its own way to report and deal with errors, you should modify & rewrite
556// the following "openFileHelper" function to get an "error reporting mechanism" tailored to your needs.
398XMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag)
399{
557XMLNode XMLNode::openFileHelper(XMLCSTR filename, XMLCSTR tag) {
400 // guess the value of the global parameter "characterEncoding"
401 // (the guess is based on the first 200 bytes of the file).
558 // guess the value of the global parameter "characterEncoding"
559 // (the guess is based on the first 200 bytes of the file).
402 FILE *f=xfopen(filename,_CXML("rb"));
403 if (f)
404 {
560 FILE *f = xfopen(filename, _CXML("rb"));
561 if (f) {
405 char bb[205];
562 char bb[205];
406 int l=(int)fread(bb,1,200,f);
407 setGlobalOptions(guessCharEncoding(bb,l),guessWideCharChars,dropWhiteSpace,removeCommentsInMiddleOfText);
563 int l = (int)fread(bb, 1, 200, f);
564 setGlobalOptions(guessCharEncoding(bb, l), guessWideCharChars,
565 dropWhiteSpace, removeCommentsInMiddleOfText);
408 fclose(f);
409 }
410
411 // parse the file
412 XMLResults pResults;
566 fclose(f);
567 }
568
569 // parse the file
570 XMLResults pResults;
413 XMLNode xnode=XMLNode::parseFile(filename,tag,&pResults);
571 XMLNode xnode = XMLNode::parseFile(filename, tag, &pResults);
414
415 // display error message (if any)
572
573 // display error message (if any)
416 if (pResults.error != eXMLErrorNone)
417 {
574 if (pResults.error != eXMLErrorNone) {
418 // create message
575 // create message
419 char message[2000],*s1=(char*)"",*s3=(char*)""; XMLCSTR s2=_CXML("");
420 if (pResults.error==eXMLErrorFirstTagNotFound) { s1=(char*)"First Tag should be '"; s2=tag; s3=(char*)"'.\n"; }
576 char message[2000], *s1 = (char*)"", *s3 = (char*)"";
577 XMLCSTR s2 = _CXML("");
578 if (pResults.error == eXMLErrorFirstTagNotFound) {
579 s1 = (char*)"First Tag should be '";
580 s2 = tag;
581 s3 = (char*)"'.\n";
582 }
421 sprintf(message,
422#ifdef _XMLWIDECHAR
583 sprintf(message,
584#ifdef _XMLWIDECHAR
423 "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
585 "XML Parsing error inside file '%S'.\n%S\nAt line %i, column %i.\n%s%S%s"
424#else
586#else
425 "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
587 "XML Parsing error inside file '%s'.\n%s\nAt line %i, column %i.\n%s%s%s"
426#endif
588#endif
427 ,filename,XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn,s1,s2,s3);
589 , filename, XMLNode::getError(pResults.error), pResults.nLine,
590 pResults.nColumn, s1, s2, s3);
428
429 // display message
430#if defined(_XMLWINDOWS) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
591
592 // display message
593#if defined(_XMLWINDOWS) && !defined(UNDER_CE) && !defined(_XMLPARSER_NO_MESSAGEBOX_)
431 MessageBoxA(NULL,message,"XML Parsing error",MB_OK|MB_ICONERROR|MB_TOPMOST);
594 MessageBoxA(NULL, message, "XML Parsing error", MB_OK | MB_ICONERROR |
595 MB_TOPMOST);
432#else
596#else
433 printf("%s",message);
597 printf("%s", message);
434#endif
435 exit(255);
436 }
437 return xnode;
438}
439
440/////////////////////////////////////////////////////////////////////////
441// Here start the core implementation of the XMLParser library //
442/////////////////////////////////////////////////////////////////////////
443
444// You should normally not change anything below this point.
445
446#ifndef _XMLWIDECHAR
447// If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte.
448// If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes).
449// If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes).
450// This table is used as lookup-table to know the length of a character (in byte) based on the
451// content of the first byte of the character.
452// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
598#endif
599 exit(255);
600 }
601 return xnode;
602}
603
604/////////////////////////////////////////////////////////////////////////
605// Here start the core implementation of the XMLParser library //
606/////////////////////////////////////////////////////////////////////////
607
608// You should normally not change anything below this point.
609
610#ifndef _XMLWIDECHAR
611// If "characterEncoding=ascii" then we assume that all characters have the same length of 1 byte.
612// If "characterEncoding=UTF8" then the characters have different lengths (from 1 byte to 4 bytes).
613// If "characterEncoding=ShiftJIS" then the characters have different lengths (from 1 byte to 2 bytes).
614// This table is used as lookup-table to know the length of a character (in byte) based on the
615// content of the first byte of the character.
616// (note: if you modify this, you must always have XML_utf8ByteTable[0]=0 ).
453static const char XML_utf8ByteTable[256] =
454{
617static const char XML_utf8ByteTable[256] = {
455 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
618 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
456 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
457 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
458 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
459 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
460 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
461 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
462 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
463 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70 End of ASCII range
464 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80 0x80 to 0xc1 invalid
465 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
466 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
467 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
468 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0 0xc2 to 0xdf 2 byte
469 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
470 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,// 0xe0 0xe0 to 0xef 3 byte
471 4,4,4,4,4,1,1,1,1,1,1,1,1,1,1,1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
619 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
620 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
621 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
622 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
623 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
624 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
625 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
626 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70 End of ASCII range
627 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x80 0x80 to 0xc1 invalid
628 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x90
629 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xa0
630 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xb0
631 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0 0xc2 to 0xdf 2 byte
632 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
633 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,// 0xe0 0xe0 to 0xef 3 byte
634 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid
472};
635};
473static const char XML_legacyByteTable[256] =
474{
475 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
476 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
477 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
478 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
479 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
480 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
636static const char XML_legacyByteTable[256] = {
637 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
638 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
639 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
640 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
641 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
642 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
481};
643};
482static const char XML_sjisByteTable[256] =
483{
644static const char XML_sjisByteTable[256] = {
484 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
645 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
485 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
486 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
487 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
488 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
489 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
490 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
491 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
492 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
493 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0x9F 2 bytes
494 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90
495 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xa0
496 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xb0
497 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xc0
498 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0xd0
499 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0 0xe0 to 0xef 2 bytes
500 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 // 0xf0
646 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
647 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
648 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
649 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
650 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
651 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
652 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
653 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
654 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x80 0x81 to 0x9F 2 bytes
655 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x90
656 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xa0
657 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xb0
658 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xc0
659 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0xd0
660 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0 0xe0 to 0xef 2 bytes
661 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0
501};
662};
502static const char XML_gb2312ByteTable[256] =
503{
663static const char XML_gb2312ByteTable[256] = {
504// 0 1 2 3 4 5 6 7 8 9 a b c d e f
664// 0 1 2 3 4 5 6 7 8 9 a b c d e f
505 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
506 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
507 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
508 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
509 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
510 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
511 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
512 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
513 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x80
514 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x90
515 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0 0xa1 to 0xf7 2 bytes
516 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0
517 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0
518 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
519 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0
520 2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1 // 0xf0
665 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
666 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
667 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
668 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
669 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
670 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
671 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
672 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
673 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x80
674 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x90
675 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xa0 0xa1 to 0xf7 2 bytes
676 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xb0
677 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0
678 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
679 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0
680 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0
521};
681};
522static const char XML_gbk_big5_ByteTable[256] =
523{
682static const char XML_gbk_big5_ByteTable[256] = {
524 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
683 // 0 1 2 3 4 5 6 7 8 9 a b c d e f
525 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x00
526 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x10
527 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x20
528 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x30
529 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x40
530 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x50
531 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x60
532 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,// 0x70
533 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x80 0x81 to 0xfe 2 bytes
534 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0x90
535 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xa0
536 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xb0
537 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xc0
538 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xd0
539 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,// 0xe0
540 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1 // 0xf0
684 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x00
685 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x10
686 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x20
687 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x30
688 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x40
689 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x50
690 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x60
691 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,// 0x70
692 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x80 0x81 to 0xfe 2 bytes
693 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0x90
694 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xa0
695 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xb0
696 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xc0
697 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xd0
698 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,// 0xe0
699 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1 // 0xf0
541};
700};
542static const char *XML_ByteTable=(const char *)XML_utf8ByteTable; // the default is "characterEncoding=XMLNode::encoding_UTF8"
701// the default is "characterEncoding=XMLNode::encoding_UTF8"
702static const char *XML_ByteTable = (const char *)XML_utf8ByteTable;
543#endif
544
545
546XMLNode XMLNode::emptyXMLNode;
703#endif
704
705
706XMLNode XMLNode::emptyXMLNode;
547XMLClear XMLNode::emptyXMLClear={ NULL, NULL, NULL};
548XMLAttribute XMLNode::emptyXMLAttribute={ NULL, NULL};
707XMLClear XMLNode::emptyXMLClear = { NULL, NULL, NULL};
708XMLAttribute XMLNode::emptyXMLAttribute = { NULL, NULL};
549
550// Enumeration used to decipher what type a token is
709
710// Enumeration used to decipher what type a token is
551typedef enum XMLTokenTypeTag
552{
711typedef enum XMLTokenTypeTag {
553 eTokenText = 0,
554 eTokenQuotedText,
555 eTokenTagStart, /* "<" */
556 eTokenTagEnd, /* "</" */
557 eTokenCloseTag, /* ">" */
558 eTokenEquals, /* "=" */
559 eTokenDeclaration, /* "<?" */
560 eTokenShortHandClose, /* "/>" */
561 eTokenClear,
562 eTokenError
563} XMLTokenType;
564
565// Main structure used for parsing XML
712 eTokenText = 0,
713 eTokenQuotedText,
714 eTokenTagStart, /* "<" */
715 eTokenTagEnd, /* "</" */
716 eTokenCloseTag, /* ">" */
717 eTokenEquals, /* "=" */
718 eTokenDeclaration, /* "<?" */
719 eTokenShortHandClose, /* "/>" */
720 eTokenClear,
721 eTokenError
722} XMLTokenType;
723
724// Main structure used for parsing XML
566typedef struct XML
567{
725typedef struct XML {
568 XMLCSTR lpXML;
569 XMLCSTR lpszText;
570 int nIndex,nIndexMissigEndTag;
571 enum XMLError error;
572 XMLCSTR lpEndTag;
573 int cbEndTag;
574 XMLCSTR lpNewElement;
575 int cbNewElement;
576 int nFirst;
577} XML;
578
726 XMLCSTR lpXML;
727 XMLCSTR lpszText;
728 int nIndex,nIndexMissigEndTag;
729 enum XMLError error;
730 XMLCSTR lpEndTag;
731 int cbEndTag;
732 XMLCSTR lpNewElement;
733 int cbNewElement;
734 int nFirst;
735} XML;
736
579typedef struct
580{
737typedef struct {
581 ALLXMLClearTag *pClr;
582 XMLCSTR pStr;
583} NextToken;
584
585// Enumeration used when parsing attributes
738 ALLXMLClearTag *pClr;
739 XMLCSTR pStr;
740} NextToken;
741
742// Enumeration used when parsing attributes
586typedef enum Attrib
587{
743typedef enum Attrib {
588 eAttribName = 0,
589 eAttribEquals,
590 eAttribValue
591} Attrib;
592
593// Enumeration used when parsing elements to dictate whether we are currently
594// inside a tag
744 eAttribName = 0,
745 eAttribEquals,
746 eAttribValue
747} Attrib;
748
749// Enumeration used when parsing elements to dictate whether we are currently
750// inside a tag
595typedef enum Status
596{
751typedef enum Status {
597 eInsideTag = 0,
598 eOutsideTag
599} Status;
600
752 eInsideTag = 0,
753 eOutsideTag
754} Status;
755
601XMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const
602{
756XMLError XMLNode::writeToFile(XMLCSTR filename, const char *encoding, char nFormat) const {
603 if (!d) return eXMLErrorNone;
757 if (!d) return eXMLErrorNone;
604 FILE *f=xfopen(filename,_CXML("wb"));
758 FILE *f = xfopen(filename, _CXML("wb"));
605 if (!f) return eXMLErrorCannotOpenWriteFile;
606#ifdef _XMLWIDECHAR
759 if (!f) return eXMLErrorCannotOpenWriteFile;
760#ifdef _XMLWIDECHAR
607 unsigned char h[2]={ 0xFF, 0xFE };
608 if (!fwrite(h,2,1,f)) return eXMLErrorCannotWriteFile;
609 if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
610 {
611 if (!fwrite(L"<?xml version=\"1.0\" encoding=\"utf-16\"?>\n",sizeof(wchar_t)*40,1,f))
761 unsigned char h[2] = { 0xFF, 0xFE };
762 if (!fwrite(h, 2, 1, f)) return eXMLErrorCannotWriteFile;
763 if ((!isDeclaration()) && ((d->lpszName) ||
764 (!getChildNode().isDeclaration()))) {
765 if (!fwrite(L"\n",
766 sizeof(wchar_t)*40, 1, f))
612 return eXMLErrorCannotWriteFile;
613 }
614#else
767 return eXMLErrorCannotWriteFile;
768 }
769#else
615 if ((!isDeclaration())&&((d->lpszName)||(!getChildNode().isDeclaration())))
616 {
617 if (characterEncoding==char_encoding_UTF8)
618 {
770 if ((!isDeclaration()) && ((d->lpszName) ||
771 (!getChildNode().isDeclaration()))) {
772 if (characterEncoding == char_encoding_UTF8) {
619 // header so that windows recognize the file as UTF-8:
773 // header so that windows recognize the file as UTF-8:
620 unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
621 encoding="utf-8";
622 } else if (characterEncoding==char_encoding_ShiftJIS) encoding="SHIFT-JIS";
774 unsigned char h[3] = {0xEF, 0xBB, 0xBF};
775 if (!fwrite(h, 3, 1, f)) return eXMLErrorCannotWriteFile;
776 encoding = "utf-8";
777 } else if (characterEncoding == char_encoding_ShiftJIS)
778 encoding = "SHIFT-JIS";
623
779
624 if (!encoding) encoding="ISO-8859-1";
625 if (fprintf(f,"<?xml version=\"1.0\" encoding=\"%s\"?>\n",encoding)<0) return eXMLErrorCannotWriteFile;
626 } else
627 {
628 if (characterEncoding==char_encoding_UTF8)
629 {
630 unsigned char h[3]={0xEF,0xBB,0xBF}; if (!fwrite(h,3,1,f)) return eXMLErrorCannotWriteFile;
780 if (!encoding) encoding = "ISO-8859-1";
781 if (fprintf(f, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", encoding)
782 < 0)
783 return eXMLErrorCannotWriteFile;
784 } else {
785 if (characterEncoding == char_encoding_UTF8) {
786 unsigned char h[3] = {0xEF, 0xBB, 0xBF};
787 if (!fwrite(h, 3, 1, f)) return eXMLErrorCannotWriteFile;
631 }
632 }
633#endif
634 int i;
788 }
789 }
790#endif
791 int i;
635 XMLSTR t=createXMLString(nFormat,&i);
636 if (!fwrite(t,sizeof(XMLCHAR)*i,1,f)) return eXMLErrorCannotWriteFile;
637 if (fclose(f)!=0) return eXMLErrorCannotWriteFile;
792 XMLSTR t = createXMLString(nFormat, &i);
793 if (!fwrite(t, sizeof(XMLCHAR)*i, 1, f)) return eXMLErrorCannotWriteFile;
794 if (fclose(f) != 0) return eXMLErrorCannotWriteFile;
638 free(t);
639 return eXMLErrorNone;
640}
641
642// Duplicate a given string.
795 free(t);
796 return eXMLErrorNone;
797}
798
799// Duplicate a given string.
643XMLSTR stringDup(XMLCSTR lpszData, int cbData)
644{
645 if (lpszData==NULL) return NULL;
800XMLSTR stringDup(XMLCSTR lpszData, int cbData) {
801 if (lpszData == NULL) return NULL;
646
647 XMLSTR lpszNew;
802
803 XMLSTR lpszNew;
648 if (cbData==-1) cbData=(int)xstrlen(lpszData);
649 lpszNew = (XMLSTR)malloc((cbData+1) * sizeof(XMLCHAR));
650 if (lpszNew)
651 {
804 if (cbData == -1) cbData = (int)xstrlen(lpszData);
805 lpszNew = (XMLSTR)malloc((cbData + 1) * sizeof(XMLCHAR));
806 if (lpszNew) {
652 memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
653 lpszNew[cbData] = (XMLCHAR)NULL;
654 }
655 return lpszNew;
656}
657
807 memcpy(lpszNew, lpszData, (cbData) * sizeof(XMLCHAR));
808 lpszNew[cbData] = (XMLCHAR)NULL;
809 }
810 return lpszNew;
811}
812
658XMLSTR ToXMLStringTool::toXMLUnSafe(XMLSTR dest,XMLCSTR source)
659{
660 XMLSTR dd=dest;
813XMLSTR ToXMLStringTool::toXMLUnSafe(XMLSTR dest, XMLCSTR source) {
814 XMLSTR dd = dest;
661 XMLCHAR ch;
662 XMLCharacterEntity *entity;
815 XMLCHAR ch;
816 XMLCharacterEntity *entity;
663 while ((ch=*source))
664 {
665 entity=XMLEntities;
666 do
667 {
668 if (ch==entity->c) {xstrcpy(dest,entity->s); dest+=entity->l; source++; goto out_of_loop1; }
817 while ((ch = *source)) {
818 entity = XMLEntities;
819 do {
820 if (ch == entity->c) {
821 xstrcpy(dest, entity->s);
822 dest += entity->l;
823 source++;
824 goto out_of_loop1;
825 }
669 entity++;
826 entity++;
670 } while(entity->s);
827 } while (entity->s);
671#ifdef _XMLWIDECHAR
828#ifdef _XMLWIDECHAR
672 *(dest++)=*(source++);
829 *(dest++) = *(source++);
673#else
830#else
674 switch(XML_ByteTable[(unsigned char)ch])
675 {
676 case 4: *(dest++)=*(source++);
677 case 3: *(dest++)=*(source++);
678 case 2: *(dest++)=*(source++);
679 case 1: *(dest++)=*(source++);
831 switch (XML_ByteTable[(unsigned char)ch]) {
832 case 4:
833 *(dest++) = *(source++);
834 case 3:
835 *(dest++) = *(source++);
836 case 2:
837 *(dest++) = *(source++);
838 case 1:
839 *(dest++) = *(source++);
680 }
681#endif
682out_of_loop1:
683 ;
684 }
840 }
841#endif
842out_of_loop1:
843 ;
844 }
685 *dest=0;
845 *dest = 0;
686 return dd;
687}
688
689// private (used while rendering):
846 return dd;
847}
848
849// private (used while rendering):
690int ToXMLStringTool::lengthXMLString(XMLCSTR source)
691{
692 int r=0;
850int ToXMLStringTool::lengthXMLString(XMLCSTR source) {
851 int r = 0;
693 XMLCharacterEntity *entity;
694 XMLCHAR ch;
852 XMLCharacterEntity *entity;
853 XMLCHAR ch;
695 while ((ch=*source))
696 {
697 entity=XMLEntities;
698 do
699 {
700 if (ch==entity->c) { r+=entity->l; source++; goto out_of_loop1; }
854 while ((ch = *source)) {
855 entity = XMLEntities;
856 do {
857 if (ch == entity->c) {
858 r += entity->l;
859 source++;
860 goto out_of_loop1;
861 }
701 entity++;
862 entity++;
702 } while(entity->s);
863 } while (entity->s);
703#ifdef _XMLWIDECHAR
864#ifdef _XMLWIDECHAR
704 r++; source++;
865 r++;
866 source++;
705#else
867#else
706 ch=XML_ByteTable[(unsigned char)ch]; r+=ch; source+=ch;
868 ch = XML_ByteTable[(unsigned char)ch];
869 r += ch;
870 source += ch;
707#endif
708out_of_loop1:
709 ;
710 }
711 return r;
712}
713
871#endif
872out_of_loop1:
873 ;
874 }
875 return r;
876}
877
714ToXMLStringTool::~ToXMLStringTool(){ freeBuffer(); }
715void ToXMLStringTool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
716XMLSTR ToXMLStringTool::toXML(XMLCSTR source)
717{
718 int l=lengthXMLString(source)+1;
719 if (l>buflen) { buflen=l; buf=(XMLSTR)realloc(buf,l*sizeof(XMLCHAR)); }
720 return toXMLUnSafe(buf,source);
878ToXMLStringTool::~ToXMLStringTool() {
879 freeBuffer();
721}
880}
881void ToXMLStringTool::freeBuffer() {
882 if (buf) free(buf);
883 buf = NULL;
884 buflen = 0;
885}
886XMLSTR ToXMLStringTool::toXML(XMLCSTR source) {
887 int l = lengthXMLString(source) + 1;
888 if (l > buflen) {
889 buflen = l;
890 buf = (XMLSTR)realloc(buf, l * sizeof(XMLCHAR));
891 }
892 return toXMLUnSafe(buf, source);
893}
722
723// private:
894
895// private:
724XMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML)
725{
896XMLSTR fromXMLString(XMLCSTR s, int lo, XML *pXML) {
726 // This function is the opposite of the function "toXMLString". It decodes the escape
727 // sequences &amp;, &quot;, &apos;, &lt;, &gt; and replace them by the characters
728 // &,",',<,>. This function is used internally by the XML Parser. All the calls to
729 // the XML library will always gives you back "decoded" strings.
730 //
731 // in: string (s) and length (lo) of string
732 // out: new allocated string converted from xml
733 if (!s) return NULL;
734
897 // This function is the opposite of the function "toXMLString". It decodes the escape
898 // sequences &amp;, &quot;, &apos;, &lt;, &gt; and replace them by the characters
899 // &,",',<,>. This function is used internally by the XML Parser. All the calls to
900 // the XML library will always gives you back "decoded" strings.
901 //
902 // in: string (s) and length (lo) of string
903 // out: new allocated string converted from xml
904 if (!s) return NULL;
905
735 int ll=0,j;
906 int ll = 0, j;
736 XMLSTR d;
907 XMLSTR d;
737 XMLCSTR ss=s;
908 XMLCSTR ss = s;
738 XMLCharacterEntity *entity;
909 XMLCharacterEntity *entity;
739 while ((lo>0)&&(*s))
740 {
741 if (*s==_CXML('&'))
742 {
743 if ((lo>2)&&(s[1]==_CXML('#')))
744 {
745 s+=2; lo-=2;
746 if ((*s==_CXML('X'))||(*s==_CXML('x'))) { s++; lo--; }
747 while ((*s)&&(*s!=_CXML(';'))&&((lo--)>0)) s++;
748 if (*s!=_CXML(';'))
749 {
750 pXML->error=eXMLErrorUnknownCharacterEntity;
910 while ((lo > 0) && (*s)) {
911 if (*s == _CXML('&')) {
912 if ((lo > 2) && (s[1] == _CXML('#'))) {
913 s += 2;
914 lo -= 2;
915 if ((*s == _CXML('X')) || (*s == _CXML('x'))) {
916 s++;
917 lo--;
918 }
919 while ((*s) && (*s != _CXML(';')) && ((lo--) > 0)) {
920 s++;
921 }
922 if (*s != _CXML(';')) {
923 pXML->error = eXMLErrorUnknownCharacterEntity;
751 return NULL;
752 }
924 return NULL;
925 }
753 s++; lo--;
754 } else
755 {
756 entity=XMLEntities;
757 do
758 {
759 if ((lo>=entity->l)&&(xstrnicmp(s,entity->s,entity->l)==0)) { s+=entity->l; lo-=entity->l; break; }
926 s++;
927 lo--;
928 } else {
929 entity = XMLEntities;
930 do {
931 if ((lo >= entity->l) &&
932 (xstrnicmp(s, entity->s, entity->l) == 0)) {
933 s += entity->l;
934 lo -= entity->l;
935 break;
936 }
760 entity++;
937 entity++;
761 } while(entity->s);
762 if (!entity->s)
763 {
764 pXML->error=eXMLErrorUnknownCharacterEntity;
938 } while (entity->s);
939 if (!entity->s) {
940 pXML->error = eXMLErrorUnknownCharacterEntity;
765 return NULL;
766 }
767 }
941 return NULL;
942 }
943 }
768 } else
769 {
944 } else {
770#ifdef _XMLWIDECHAR
945#ifdef _XMLWIDECHAR
771 s++; lo--;
946 s++;
947 lo--;
772#else
948#else
773 j=XML_ByteTable[(unsigned char)*s]; s+=j; lo-=j; ll+=j-1;
949 j = XML_ByteTable[(unsigned char)*s];
950 s += j;
951 lo -= j;
952 ll += j - 1;
774#endif
775 }
776 ll++;
777 }
778
953#endif
954 }
955 ll++;
956 }
957
779 d=(XMLSTR)malloc((ll+1)*sizeof(XMLCHAR));
780 s=d;
781 while (ll-->0)
782 {
783 if (*ss==_CXML('&'))
784 {
785 if (ss[1]==_CXML('#'))
786 {
787 ss+=2; j=0;
788 if ((*ss==_CXML('X'))||(*ss==_CXML('x')))
789 {
958 d = (XMLSTR)malloc((ll + 1) * sizeof(XMLCHAR));
959 s = d;
960 while (ll-- > 0) {
961 if (*ss == _CXML('&')) {
962 if (ss[1] == _CXML('#')) {
963 ss += 2;
964 j = 0;
965 if ((*ss == _CXML('X')) || (*ss == _CXML('x'))) {
790 ss++;
966 ss++;
791 while (*ss!=_CXML(';'))
792 {
793 if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j<<4)+*ss-_CXML('0');
794 else if ((*ss>=_CXML('A'))&&(*ss<=_CXML('F'))) j=(j<<4)+*ss-_CXML('A')+10;
795 else if ((*ss>=_CXML('a'))&&(*ss<=_CXML('f'))) j=(j<<4)+*ss-_CXML('a')+10;
796 else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
967 while (*ss != _CXML(';')) {
968 if ((*ss >= _CXML('0')) && (*ss <= _CXML('9'))) {
969 j = (j << 4) + *ss - _CXML('0');
970 } else if ((*ss >= _CXML('A')) && (*ss <= _CXML('F'))) {
971 j = (j << 4) + *ss - _CXML('A') + 10;
972 } else if ((*ss >= _CXML('a')) && (*ss <= _CXML('f'))) {
973 j = (j << 4) + *ss - _CXML('a') + 10;
974 } else {
975 free((void*)s);
976 pXML->error = eXMLErrorUnknownCharacterEntity;
977 return NULL;
978 }
797 ss++;
798 }
979 ss++;
980 }
799 } else
800 {
801 while (*ss!=_CXML(';'))
802 {
803 if ((*ss>=_CXML('0'))&&(*ss<=_CXML('9'))) j=(j*10)+*ss-_CXML('0');
804 else { free((void*)s); pXML->error=eXMLErrorUnknownCharacterEntity;return NULL;}
981 } else {
982 while (*ss != _CXML(';')) {
983 if ((*ss >= _CXML('0')) && (*ss <= _CXML('9'))) {
984 j = (j * 10) + *ss - _CXML('0');
985 } else {
986 free((void*)s);
987 pXML->error = eXMLErrorUnknownCharacterEntity;
988 return NULL;
989 }
805 ss++;
806 }
807 }
808#ifndef _XMLWIDECHAR
990 ss++;
991 }
992 }
993#ifndef _XMLWIDECHAR
809 if (j>255) { free((void*)s); pXML->error=eXMLErrorCharacterCodeAbove255;return NULL;}
994 if (j > 255) {
995 free((void*)s);
996 pXML->error = eXMLErrorCharacterCodeAbove255;
997 return NULL;
998 }
810#endif
999#endif
811 (*d++)=(XMLCHAR)j; ss++;
812 } else
813 {
814 entity=XMLEntities;
815 do
816 {
817 if (xstrnicmp(ss,entity->s,entity->l)==0) { *(d++)=entity->c; ss+=entity->l; break; }
1000 (*d++) = (XMLCHAR)j;
1001 ss++;
1002 } else {
1003 entity = XMLEntities;
1004 do {
1005 if (xstrnicmp(ss, entity->s, entity->l) == 0) {
1006 *(d++) = entity->c;
1007 ss += entity->l;
1008 break;
1009 }
818 entity++;
1010 entity++;
819 } while(entity->s);
1011 } while (entity->s);
820 }
1012 }
821 } else
822 {
1013 } else {
823#ifdef _XMLWIDECHAR
1014#ifdef _XMLWIDECHAR
824 *(d++)=*(ss++);
1015 *(d++) = *(ss++);
825#else
1016#else
826 switch(XML_ByteTable[(unsigned char)*ss])
827 {
828 case 4: *(d++)=*(ss++); ll--;
829 case 3: *(d++)=*(ss++); ll--;
830 case 2: *(d++)=*(ss++); ll--;
831 case 1: *(d++)=*(ss++);
1017 switch (XML_ByteTable[(unsigned char)*ss]) {
1018 case 4:
1019 *(d++) = *(ss++);
1020 ll--;
1021 case 3:
1022 *(d++) = *(ss++);
1023 ll--;
1024 case 2:
1025 *(d++) = *(ss++);
1026 ll--;
1027 case 1:
1028 *(d++) = *(ss++);
832 }
833#endif
834 }
835 }
1029 }
1030#endif
1031 }
1032 }
836 *d=0;
1033 *d = 0;
837 return (XMLSTR)s;
838}
839
840#define XML_isSPACECHAR(ch) ((ch==_CXML('\n'))||(ch==_CXML(' '))||(ch== _CXML('\t'))||(ch==_CXML('\r')))
841
842// private:
843char myTagCompare(XMLCSTR cclose, XMLCSTR copen)
844// !!!! WARNING strange convention&:
845// return 0 if equals
846// return 1 if different
847{
848 if (!cclose) return 1;
1034 return (XMLSTR)s;
1035}
1036
1037#define XML_isSPACECHAR(ch) ((ch==_CXML('\n'))||(ch==_CXML(' '))||(ch== _CXML('\t'))||(ch==_CXML('\r')))
1038
1039// private:
1040char myTagCompare(XMLCSTR cclose, XMLCSTR copen)
1041// !!!! WARNING strange convention&:
1042// return 0 if equals
1043// return 1 if different
1044{
1045 if (!cclose) return 1;
849 int l=(int)xstrlen(cclose);
850 if (xstrnicmp(cclose, copen, l)!=0) return 1;
851 const XMLCHAR c=copen[l];
852 if (XML_isSPACECHAR(c)||
853 (c==_CXML('/' ))||
854 (c==_CXML('<' ))||
855 (c==_CXML('>' ))||
856 (c==_CXML('=' ))) return 0;
1046 int l = (int)xstrlen(cclose);
1047 if (xstrnicmp(cclose, copen, l) != 0) return 1;
1048 const XMLCHAR c = copen[l];
1049 if (XML_isSPACECHAR(c) ||
1050 (c == _CXML('/' )) ||
1051 (c == _CXML('<' )) ||
1052 (c == _CXML('>' )) ||
1053 (c == _CXML('=' ))) return 0;
857 return 1;
858}
859
860// Obtain the next character from the string.
1054 return 1;
1055}
1056
1057// Obtain the next character from the string.
861static inline XMLCHAR getNextChar(XML *pXML)
862{
1058static inline XMLCHAR getNextChar(XML *pXML) {
863 XMLCHAR ch = pXML->lpXML[pXML->nIndex];
864#ifdef _XMLWIDECHAR
1059 XMLCHAR ch = pXML->lpXML[pXML->nIndex];
1060#ifdef _XMLWIDECHAR
865 if (ch!=0) pXML->nIndex++;
1061 if (ch != 0) pXML->nIndex++;
866#else
1062#else
867 pXML->nIndex+=XML_ByteTable[(unsigned char)ch];
1063 pXML->nIndex += XML_ByteTable[(unsigned char)ch];
868#endif
869 return ch;
870}
871
872// Find the next token in a string.
873// pcbToken contains the number of characters that have been read.
1064#endif
1065 return ch;
1066}
1067
1068// Find the next token in a string.
1069// pcbToken contains the number of characters that have been read.
874static NextToken GetNextToken(XML *pXML, int *pcbToken, enum XMLTokenTypeTag *pType)
875{
1070static NextToken GetNextToken(XML *pXML, int *pcbToken,
1071 enum XMLTokenTypeTag *pType) {
876 NextToken result;
877 XMLCHAR ch;
878 XMLCHAR chTemp;
1072 NextToken result;
1073 XMLCHAR ch;
1074 XMLCHAR chTemp;
879 int indexStart,nFoundMatch,nIsText=FALSE;
880 result.pClr=NULL; // prevent warning
1075 int indexStart, nFoundMatch, nIsText = FALSE;
1076 result.pClr = NULL; // prevent warning
881
882 // Find next non-white space character
1077
1078 // Find next non-white space character
883 do { indexStart=pXML->nIndex; ch=getNextChar(pXML); } while XML_isSPACECHAR(ch);
1079 do {
1080 indexStart = pXML->nIndex;
1081 ch = getNextChar(pXML);
1082 } while XML_isSPACECHAR(ch);
884
1083
885 if (ch)
886 {
1084 if (ch) {
887 // Cache the current string pointer
888 result.pStr = &pXML->lpXML[indexStart];
889
890 // First check whether the token is in the clear tag list (meaning it
891 // does not need formatting).
1085 // Cache the current string pointer
1086 result.pStr = &pXML->lpXML[indexStart];
1087
1088 // First check whether the token is in the clear tag list (meaning it
1089 // does not need formatting).
892 ALLXMLClearTag *ctag=XMLClearTags;
893 do
894 {
895 if (xstrncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen)==0)
896 {
897 result.pClr=ctag;
898 pXML->nIndex+=ctag->openTagLen-1;
899 *pType=eTokenClear;
1090 ALLXMLClearTag *ctag = XMLClearTags;
1091 do {
1092 if (xstrncmp(ctag->lpszOpen, result.pStr, ctag->openTagLen) == 0) {
1093 result.pClr = ctag;
1094 pXML->nIndex += ctag->openTagLen - 1;
1095 *pType = eTokenClear;
900 return result;
901 }
902 ctag++;
1096 return result;
1097 }
1098 ctag++;
903 } while(ctag->lpszOpen);
1099 } while (ctag->lpszOpen);
904
905 // If we didn't find a clear tag then check for standard tokens
1100
1101 // If we didn't find a clear tag then check for standard tokens
906 switch(ch)
907 {
908 // Check for quotes
1102 switch (ch) {
1103 // Check for quotes
909 case _CXML('\''):
910 case _CXML('\"'):
911 // Type of token
912 *pType = eTokenQuotedText;
913 chTemp = ch;
914
915 // Set the size
916 nFoundMatch = FALSE;
917
918 // Search through the string to find a matching quote
1104 case _CXML('\''):
1105 case _CXML('\"'):
1106 // Type of token
1107 *pType = eTokenQuotedText;
1108 chTemp = ch;
1109
1110 // Set the size
1111 nFoundMatch = FALSE;
1112
1113 // Search through the string to find a matching quote
919 while((ch = getNextChar(pXML)))
920 {
921 if (ch==chTemp) { nFoundMatch = TRUE; break; }
922 if (ch==_CXML('<')) break;
1114 while ((ch = getNextChar(pXML))) {
1115 if (ch == chTemp) {
1116 nFoundMatch = TRUE;
1117 break;
1118 }
1119 if (ch == _CXML('<')) {
1120 break;
1121 }
923 }
924
925 // If we failed to find a matching quote
1122 }
1123
1124 // If we failed to find a matching quote
926 if (nFoundMatch == FALSE)
927 {
928 pXML->nIndex=indexStart+1;
929 nIsText=TRUE;
1125 if (nFoundMatch == FALSE) {
1126 pXML->nIndex = indexStart + 1;
1127 nIsText = TRUE;
930 break;
931 }
932
933// 4.02.2002
934// if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
935
936 break;
937
1128 break;
1129 }
1130
1131// 4.02.2002
1132// if (FindNonWhiteSpace(pXML)) pXML->nIndex--;
1133
1134 break;
1135
938 // Equals (used with attribute values)
1136 // Equals (used with attribute values)
939 case _CXML('='):
940 *pType = eTokenEquals;
941 break;
942
1137 case _CXML('='):
1138 *pType = eTokenEquals;
1139 break;
1140
943 // Close tag
1141 // Close tag
944 case _CXML('>'):
945 *pType = eTokenCloseTag;
946 break;
947
1142 case _CXML('>'):
1143 *pType = eTokenCloseTag;
1144 break;
1145
948 // Check for tag start and tag end
1146 // Check for tag start and tag end
949 case _CXML('<'):
950
951 // Peek at the next character to see if we have an end tag '</',
952 // or an xml declaration '<?'
953 chTemp = pXML->lpXML[pXML->nIndex];
954
955 // If we have a tag end...
1147 case _CXML('<'):
1148
1149 // Peek at the next character to see if we have an end tag '</',
1150 // or an xml declaration '<?'
1151 chTemp = pXML->lpXML[pXML->nIndex];
1152
1153 // If we have a tag end...
956 if (chTemp == _CXML('/'))
957 {
1154 if (chTemp == _CXML('/')) {
958 // Set the type and ensure we point at the next character
959 getNextChar(pXML);
960 *pType = eTokenTagEnd;
961 }
962
963 // If we have an XML declaration tag
1155 // Set the type and ensure we point at the next character
1156 getNextChar(pXML);
1157 *pType = eTokenTagEnd;
1158 }
1159
1160 // If we have an XML declaration tag
964 else if (chTemp == _CXML('?'))
965 {
1161 else if (chTemp == _CXML('?')) {
966
967 // Set the type and ensure we point at the next character
968 getNextChar(pXML);
969 *pType = eTokenDeclaration;
970 }
971
972 // Otherwise we must have a start tag
1162
1163 // Set the type and ensure we point at the next character
1164 getNextChar(pXML);
1165 *pType = eTokenDeclaration;
1166 }
1167
1168 // Otherwise we must have a start tag
973 else
974 {
1169 else {
975 *pType = eTokenTagStart;
976 }
977 break;
978
1170 *pType = eTokenTagStart;
1171 }
1172 break;
1173
979 // Check to see if we have a short hand type end tag ('/>').
1174 // Check to see if we have a short hand type end tag ('/>').
980 case _CXML('/'):
981
982 // Peek at the next character to see if we have a short end tag '/>'
983 chTemp = pXML->lpXML[pXML->nIndex];
984
985 // If we have a short hand end tag...
1175 case _CXML('/'):
1176
1177 // Peek at the next character to see if we have a short end tag '/>'
1178 chTemp = pXML->lpXML[pXML->nIndex];
1179
1180 // If we have a short hand end tag...
986 if (chTemp == _CXML('>'))
987 {
1181 if (chTemp == _CXML('>')) {
988 // Set the type and ensure we point at the next character
989 getNextChar(pXML);
990 *pType = eTokenShortHandClose;
991 break;
992 }
993
994 // If we haven't found a short hand closing tag then drop into the
995 // text process
996
1182 // Set the type and ensure we point at the next character
1183 getNextChar(pXML);
1184 *pType = eTokenShortHandClose;
1185 break;
1186 }
1187
1188 // If we haven't found a short hand closing tag then drop into the
1189 // text process
1190
997 // Other characters
1191 // Other characters
998 default:
999 nIsText = TRUE;
1000 }
1001
1002 // If this is a TEXT node
1192 default:
1193 nIsText = TRUE;
1194 }
1195
1196 // If this is a TEXT node
1003 if (nIsText)
1004 {
1197 if (nIsText) {
1005 // Indicate we are dealing with text
1006 *pType = eTokenText;
1198 // Indicate we are dealing with text
1199 *pType = eTokenText;
1007 while((ch = getNextChar(pXML)))
1008 {
1009 if XML_isSPACECHAR(ch)
1010 {
1011 indexStart++; break;
1200 while ((ch = getNextChar(pXML))) {
1201 if XML_isSPACECHAR(ch) {
1202 indexStart++;
1203 break;
1012
1204
1013 } else if (ch==_CXML('/'))
1014 {
1205 } else if (ch == _CXML('/')) {
1015 // If we find a slash then this maybe text or a short hand end tag
1016 // Peek at the next character to see it we have short hand end tag
1206 // If we find a slash then this maybe text or a short hand end tag
1207 // Peek at the next character to see it we have short hand end tag
1017 ch=pXML->lpXML[pXML->nIndex];
1208 ch = pXML->lpXML[pXML->nIndex];
1018 // If we found a short hand end tag then we need to exit the loop
1209 // If we found a short hand end tag then we need to exit the loop
1019 if (ch==_CXML('>')) { pXML->nIndex--; break; }
1210 if (ch == _CXML('>')) {
1211 pXML->nIndex--;
1212 break;
1213 }
1020
1214
1021 } else if ((ch==_CXML('<'))||(ch==_CXML('>'))||(ch==_CXML('=')))
1022 {
1023 pXML->nIndex--; break;
1215 } else if ((ch == _CXML('<')) || (ch == _CXML('>')) ||
1216 (ch == _CXML('='))) {
1217 pXML->nIndex--;
1218 break;
1024 }
1025 }
1026 }
1219 }
1220 }
1221 }
1027 *pcbToken = pXML->nIndex-indexStart;
1028 } else
1029 {
1222 *pcbToken = pXML->nIndex - indexStart;
1223 } else {
1030 // If we failed to obtain a valid character
1031 *pcbToken = 0;
1032 *pType = eTokenError;
1224 // If we failed to obtain a valid character
1225 *pcbToken = 0;
1226 *pType = eTokenError;
1033 result.pStr=NULL;
1227 result.pStr = NULL;
1034 }
1035
1036 return result;
1037}
1038
1228 }
1229
1230 return result;
1231}
1232
1039XMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName)
1040{
1041 if (!d) { free(lpszName); return NULL; }
1042 if (d->lpszName&&(lpszName!=d->lpszName)) free((void*)d->lpszName);
1043 d->lpszName=lpszName;
1233XMLCSTR XMLNode::updateName_WOSD(XMLSTR lpszName) {
1234 if (!d) {
1235 free(lpszName);
1236 return NULL;
1237 }
1238 if (d->lpszName && (lpszName != d->lpszName)) free((void*)d->lpszName);
1239 d->lpszName = lpszName;
1044 return lpszName;
1045}
1046
1047// private:
1240 return lpszName;
1241}
1242
1243// private:
1048XMLNode::XMLNode(struct XMLNodeDataTag *p){ d=p; (p->ref_count)++; }
1049XMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration)
1050{
1051 d=(XMLNodeData*)malloc(sizeof(XMLNodeData));
1052 d->ref_count=1;
1244XMLNode::XMLNode(struct XMLNodeDataTag *p) {
1245 d = p;
1246 (p->ref_count)++;
1247}
1248XMLNode::XMLNode(XMLNodeData *pParent, XMLSTR lpszName, char isDeclaration) {
1249 d = (XMLNodeData*)malloc(sizeof(XMLNodeData));
1250 d->ref_count = 1;
1053
1251
1054 d->lpszName=NULL;
1055 d->nChild= 0;
1252 d->lpszName = NULL;
1253 d->nChild = 0;
1056 d->nText = 0;
1057 d->nClear = 0;
1058 d->nAttribute = 0;
1059
1060 d->isDeclaration = isDeclaration;
1061
1062 d->pParent = pParent;
1254 d->nText = 0;
1255 d->nClear = 0;
1256 d->nAttribute = 0;
1257
1258 d->isDeclaration = isDeclaration;
1259
1260 d->pParent = pParent;
1063 d->pChild= NULL;
1064 d->pText= NULL;
1065 d->pClear= NULL;
1066 d->pAttribute= NULL;
1067 d->pOrder= NULL;
1261 d->pChild = NULL;
1262 d->pText = NULL;
1263 d->pClear = NULL;
1264 d->pAttribute = NULL;
1265 d->pOrder = NULL;
1068
1069 updateName_WOSD(lpszName);
1070}
1071
1266
1267 updateName_WOSD(lpszName);
1268}
1269
1072XMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) { return XMLNode(NULL,lpszName,isDeclaration); }
1073XMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) { return XMLNode(NULL,stringDup(lpszName),isDeclaration); }
1270XMLNode XMLNode::createXMLTopNode_WOSD(XMLSTR lpszName, char isDeclaration) {
1271 return XMLNode(NULL, lpszName, isDeclaration);
1272}
1273XMLNode XMLNode::createXMLTopNode(XMLCSTR lpszName, char isDeclaration) {
1274 return XMLNode(NULL, stringDup(lpszName), isDeclaration);
1275}
1074
1075#define MEMORYINCREASE 50
1076
1276
1277#define MEMORYINCREASE 50
1278
1077static inline void myFree(void *p) { if (p) free(p); }
1078static inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem)
1079{
1080 if (p==NULL) { if (memInc) return malloc(memInc*sizeofElem); return malloc(sizeofElem); }
1081 if ((memInc==0)||((newsize%memInc)==0)) p=realloc(p,(newsize+memInc)*sizeofElem);
1279static inline void myFree(void *p) {
1280 if (p) free(p);
1281}
1282static inline void *myRealloc(void *p, int newsize, int memInc, int sizeofElem) {
1283 if (p == NULL) {
1284 if (memInc) return malloc(memInc*sizeofElem);
1285 return malloc(sizeofElem);
1286 }
1287 if ((memInc == 0) || ((newsize % memInc) == 0)) {
1288 p = realloc(p, (newsize + memInc) * sizeofElem);
1289 }
1082// if (!p)
1083// {
1084// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
1085// }
1086 return p;
1087}
1088
1089// private:
1290// if (!p)
1291// {
1292// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
1293// }
1294 return p;
1295}
1296
1297// private:
1090XMLElementPosition XMLNode::findPosition(XMLNodeData *d, int index, XMLElementType xxtype)
1091{
1092 if (index<0) return -1;
1093 int i=0,j=(int)((index<<2)+xxtype),*o=d->pOrder; while (o[i]!=j) i++; return i;
1298XMLElementPosition XMLNode::findPosition(XMLNodeData *d, int index,
1299 XMLElementType xxtype) {
1300 if (index < 0) return -1;
1301 int i = 0, j = (int)((index << 2) + xxtype), *o = d->pOrder;
1302 while (o[i] != j) i++;
1303 return i;
1094}
1095
1096// private:
1097// update "order" information when deleting a content of a XMLNode
1304}
1305
1306// private:
1307// update "order" information when deleting a content of a XMLNode
1098int XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index)
1099{
1100 int n=d->nChild+d->nText+d->nClear, *o=d->pOrder,i=findPosition(d,index,t);
1101 memmove(o+i, o+i+1, (n-i)*sizeof(int));
1102 for (;i<n;i++)
1103 if ((o[i]&3)==(int)t) o[i]-=4;
1308int XMLNode::removeOrderElement(XMLNodeData *d, XMLElementType t, int index) {
1309 int n = d->nChild + d->nText + d->nClear;
1310 int *o = d->pOrder;
1311 int i = findPosition(d, index, t);
1312 memmove(o + i, o + i + 1, (n - i)*sizeof(int));
1313 for (; i < n; i++)
1314 if ((o[i]&3) == (int)t) o[i] -= 4;
1104 // We should normally do:
1105 // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
1106 // but we skip reallocation because it's too time consuming.
1107 // Anyway, at the end, it will be free'd completely at once.
1108 return i;
1109}
1110
1315 // We should normally do:
1316 // d->pOrder=(int)realloc(d->pOrder,n*sizeof(int));
1317 // but we skip reallocation because it's too time consuming.
1318 // Anyway, at the end, it will be free'd completely at once.
1319 return i;
1320}
1321
1111void *XMLNode::addToOrder(int memoryIncrease,int *_pos, int nc, void *p, int size, XMLElementType xtype)
1112{
1322void *XMLNode::addToOrder(int memoryIncrease, int *_pos, int nc, void *p,
1323 int size, XMLElementType xtype) {
1113 // in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
1114 // out: *_pos is the index inside p
1324 // in: *_pos is the position inside d->pOrder ("-1" means "EndOf")
1325 // out: *_pos is the index inside p
1115 p=myRealloc(p,(nc+1),memoryIncrease,size);
1116 int n=d->nChild+d->nText+d->nClear;
1117 d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int));
1118 int pos=*_pos,*o=d->pOrder;
1326 p = myRealloc(p, (nc + 1), memoryIncrease, size);
1327 int n = d->nChild + d->nText + d->nClear;
1328 d->pOrder = (int*)myRealloc(d->pOrder, n + 1, memoryIncrease * 3,
1329 sizeof(int));
1330 int pos = *_pos, *o = d->pOrder;
1119
1331
1120 if ((pos<0)||(pos>=n)) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
1332 if ((pos < 0) || (pos >= n)) {
1333 *_pos = nc;
1334 o[n] = (int)((nc << 2) + xtype);
1335 return p;
1336 }
1121
1337
1122 int i=pos;
1123 memmove(o+i+1, o+i, (n-i)*sizeof(int));
1338 int i = pos;
1339 memmove(o + i + 1, o + i, (n - i)*sizeof(int));
1124
1340
1125 while ((pos<n)&&((o[pos]&3)!=(int)xtype)) pos++;
1126 if (pos==n) { *_pos=nc; o[n]=(int)((nc<<2)+xtype); return p; }
1341 while ((pos < n) && ((o[pos]&3) != (int)xtype)) pos++;
1342 if (pos == n) {
1343 *_pos = nc;
1344 o[n] = (int)((nc << 2) + xtype);
1345 return p;
1346 }
1127
1347
1128 o[i]=o[pos];
1129 for (i=pos+1;i<=n;i++) if ((o[i]&3)==(int)xtype) o[i]+=4;
1348 o[i] = o[pos];
1349 for (i = pos + 1; i <= n; i++) if ((o[i]&3) == (int)xtype) o[i] += 4;
1130
1350
1131 *_pos=pos=o[pos]>>2;
1132 memmove(((char*)p)+(pos+1)*size,((char*)p)+pos*size,(nc-pos)*size);
1351 *_pos = pos = o[pos] >> 2;
1352 memmove(((char*)p) + (pos + 1)*size, ((char*)p) + pos*size, (nc - pos)*size);
1133
1134 return p;
1135}
1136
1137// Add a child node to the given element.
1353
1354 return p;
1355}
1356
1357// Add a child node to the given element.
1138XMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName, char isDeclaration, int pos)
1139{
1358XMLNode XMLNode::addChild_priv(int memoryIncrease, XMLSTR lpszName,
1359 char isDeclaration, int pos) {
1140 if (!lpszName) return emptyXMLNode;
1360 if (!lpszName) return emptyXMLNode;
1141 d->pChild=(XMLNode*)addToOrder(memoryIncrease,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
1142 d->pChild[pos].d=NULL;
1143 d->pChild[pos]=XMLNode(d,lpszName,isDeclaration);
1361 d->pChild = (XMLNode*)addToOrder(memoryIncrease, &pos, d->nChild,
1362 d->pChild, sizeof(XMLNode), eNodeChild);
1363 d->pChild[pos].d = NULL;
1364 d->pChild[pos] = XMLNode(d, lpszName, isDeclaration);
1144 d->nChild++;
1145 return d->pChild[pos];
1146}
1147
1148// Add an attribute to an element.
1365 d->nChild++;
1366 return d->pChild[pos];
1367}
1368
1369// Add an attribute to an element.
1149XMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease,XMLSTR lpszName, XMLSTR lpszValuev)
1150{
1370XMLAttribute *XMLNode::addAttribute_priv(int memoryIncrease, XMLSTR lpszName,
1371 XMLSTR lpszValuev) {
1151 if (!lpszName) return &emptyXMLAttribute;
1372 if (!lpszName) return &emptyXMLAttribute;
1152 if (!d) { myFree(lpszName); myFree(lpszValuev); return &emptyXMLAttribute; }
1153 int nc=d->nAttribute;
1154 d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(nc+1),memoryIncrease,sizeof(XMLAttribute));
1155 XMLAttribute *pAttr=d->pAttribute+nc;
1373 if (!d) {
1374 myFree(lpszName);
1375 myFree(lpszValuev);
1376 return &emptyXMLAttribute;
1377 }
1378 int nc = d->nAttribute;
1379 d->pAttribute = (XMLAttribute*)myRealloc(d->pAttribute, (nc + 1),
1380 memoryIncrease,
1381 sizeof(XMLAttribute));
1382 XMLAttribute *pAttr = d->pAttribute + nc;
1156 pAttr->lpszName = lpszName;
1157 pAttr->lpszValue = lpszValuev;
1158 d->nAttribute++;
1159 return pAttr;
1160}
1161
1162// Add text to the element.
1383 pAttr->lpszName = lpszName;
1384 pAttr->lpszValue = lpszValuev;
1385 d->nAttribute++;
1386 return pAttr;
1387}
1388
1389// Add text to the element.
1163XMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos)
1164{
1390XMLCSTR XMLNode::addText_priv(int memoryIncrease, XMLSTR lpszValue, int pos) {
1165 if (!lpszValue) return NULL;
1391 if (!lpszValue) return NULL;
1166 if (!d) { myFree(lpszValue); return NULL; }
1167 d->pText=(XMLCSTR*)addToOrder(memoryIncrease,&pos,d->nText,d->pText,sizeof(XMLSTR),eNodeText);
1168 d->pText[pos]=lpszValue;
1392 if (!d) {
1393 myFree(lpszValue);
1394 return NULL;
1395 }
1396 d->pText = (XMLCSTR*)addToOrder(memoryIncrease, &pos, d->nText, d->pText,
1397 sizeof(XMLSTR), eNodeText);
1398 d->pText[pos] = lpszValue;
1169 d->nText++;
1170 return lpszValue;
1171}
1172
1173// Add clear (unformatted) text to the element.
1399 d->nText++;
1400 return lpszValue;
1401}
1402
1403// Add clear (unformatted) text to the element.
1174XMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, int pos)
1175{
1404XMLClear *XMLNode::addClear_priv(int memoryIncrease, XMLSTR lpszValue,
1405 XMLCSTR lpszOpen, XMLCSTR lpszClose,
1406 int pos) {
1176 if (!lpszValue) return &emptyXMLClear;
1407 if (!lpszValue) return &emptyXMLClear;
1177 if (!d) { myFree(lpszValue); return &emptyXMLClear; }
1178 d->pClear=(XMLClear *)addToOrder(memoryIncrease,&pos,d->nClear,d->pClear,sizeof(XMLClear),eNodeClear);
1179 XMLClear *pNewClear=d->pClear+pos;
1408 if (!d) {
1409 myFree(lpszValue);
1410 return &emptyXMLClear;
1411 }
1412 d->pClear = (XMLClear *)addToOrder(memoryIncrease, &pos, d->nClear,
1413 d->pClear, sizeof(XMLClear),
1414 eNodeClear);
1415 XMLClear *pNewClear = d->pClear + pos;
1180 pNewClear->lpszValue = lpszValue;
1416 pNewClear->lpszValue = lpszValue;
1181 if (!lpszOpen) lpszOpen=XMLClearTags->lpszOpen;
1182 if (!lpszClose) lpszClose=XMLClearTags->lpszClose;
1417 if (!lpszOpen) lpszOpen = XMLClearTags->lpszOpen;
1418 if (!lpszClose) lpszClose = XMLClearTags->lpszClose;
1183 pNewClear->lpszOpenTag = lpszOpen;
1184 pNewClear->lpszCloseTag = lpszClose;
1185 d->nClear++;
1186 return pNewClear;
1187}
1188
1189// private:
1190// Parse a clear (unformatted) type node.
1419 pNewClear->lpszOpenTag = lpszOpen;
1420 pNewClear->lpszCloseTag = lpszClose;
1421 d->nClear++;
1422 return pNewClear;
1423}
1424
1425// private:
1426// Parse a clear (unformatted) type node.
1191char XMLNode::parseClearTag(void *px, void *_pClear)
1192{
1193 XML *pXML=(XML *)px;
1194 ALLXMLClearTag pClear=*((ALLXMLClearTag*)_pClear);
1195 int cbTemp=0;
1196 XMLCSTR lpszTemp=NULL;
1197 XMLCSTR lpXML=&pXML->lpXML[pXML->nIndex];
1198 static XMLCSTR docTypeEnd=_CXML("]>");
1427char XMLNode::parseClearTag(void *px, void *_pClear) {
1428 XML *pXML = (XML *)px;
1429 ALLXMLClearTag pClear = *((ALLXMLClearTag*)_pClear);
1430 int cbTemp = 0;
1431 XMLCSTR lpszTemp = NULL;
1432 XMLCSTR lpXML = &pXML->lpXML[pXML->nIndex];
1433 static XMLCSTR docTypeEnd = _CXML("]>");
1199
1200 // Find the closing tag
1201 // Seems the <!DOCTYPE need a better treatment so lets handle it
1434
1435 // Find the closing tag
1436 // Seems the <!DOCTYPE need a better treatment so lets handle it
1202 if (pClear.lpszOpen==XMLClearTags[1].lpszOpen)
1203 {
1204 XMLCSTR pCh=lpXML;
1205 while (*pCh)
1206 {
1207 if (*pCh==_CXML('<')) { pClear.lpszClose=docTypeEnd; lpszTemp=xstrstr(lpXML,docTypeEnd); break; }
1208 else if (*pCh==_CXML('>')) { lpszTemp=pCh; break; }
1437 if (pClear.lpszOpen == XMLClearTags[1].lpszOpen) {
1438 XMLCSTR pCh = lpXML;
1439 while (*pCh) {
1440 if (*pCh == _CXML('<')) {
1441 pClear.lpszClose = docTypeEnd;
1442 lpszTemp = xstrstr(lpXML, docTypeEnd);
1443 break;
1444 } else if (*pCh == _CXML('>')) {
1445 lpszTemp = pCh;
1446 break;
1447 }
1209#ifdef _XMLWIDECHAR
1210 pCh++;
1211#else
1448#ifdef _XMLWIDECHAR
1449 pCh++;
1450#else
1212 pCh+=XML_ByteTable[(unsigned char)(*pCh)];
1451 pCh += XML_ByteTable[(unsigned char)(*pCh)];
1213#endif
1214 }
1452#endif
1453 }
1215 } else lpszTemp=xstrstr(lpXML, pClear.lpszClose);
1454 } else lpszTemp = xstrstr(lpXML, pClear.lpszClose);
1216
1455
1217 if (lpszTemp)
1218 {
1456 if (lpszTemp) {
1219 // Cache the size and increment the index
1220 cbTemp = (int)(lpszTemp - lpXML);
1221
1457 // Cache the size and increment the index
1458 cbTemp = (int)(lpszTemp - lpXML);
1459
1222 pXML->nIndex += cbTemp+(int)xstrlen(pClear.lpszClose);
1460 pXML->nIndex += cbTemp + (int)xstrlen(pClear.lpszClose);
1223
1224 // Add the clear node to the current element
1461
1462 // Add the clear node to the current element
1225 addClear_priv(MEMORYINCREASE,stringDup(lpXML,cbTemp), pClear.lpszOpen, pClear.lpszClose,-1);
1463 addClear_priv(MEMORYINCREASE, stringDup(lpXML, cbTemp),
1464 pClear.lpszOpen, pClear.lpszClose, -1);
1226 return 0;
1227 }
1228
1229 // If we failed to find the end tag
1230 pXML->error = eXMLErrorUnmatchedEndClearTag;
1231 return 1;
1232}
1233
1465 return 0;
1466 }
1467
1468 // If we failed to find the end tag
1469 pXML->error = eXMLErrorUnmatchedEndClearTag;
1470 return 1;
1471}
1472
1234void XMLNode::exactMemory(XMLNodeData *d)
1235{
1236 if (d->pOrder) d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nText+d->nClear)*sizeof(int));
1237 if (d->pChild) d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode));
1238 if (d->pAttribute) d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute));
1239 if (d->pText) d->pText=(XMLCSTR*)realloc(d->pText,d->nText*sizeof(XMLSTR));
1240 if (d->pClear) d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear));
1473void XMLNode::exactMemory(XMLNodeData *d) {
1474 if (d->pOrder) {
1475 d->pOrder = (int*)realloc(d->pOrder, (d->nChild + d->nText + d->nClear)
1476 * sizeof(int));
1477 }
1478 if (d->pChild) {
1479 d->pChild = (XMLNode*)realloc(d->pChild, d->nChild * sizeof(XMLNode));
1480 }
1481 if (d->pAttribute) {
1482 d->pAttribute = (XMLAttribute*)realloc(d->pAttribute, d->nAttribute *
1483 sizeof(XMLAttribute));
1484 }
1485 if (d->pText) {
1486 d->pText = (XMLCSTR*)realloc(d->pText, d->nText * sizeof(XMLSTR));
1487 }
1488 if (d->pClear) {
1489 d->pClear = (XMLClear *)realloc(d->pClear, d->nClear * sizeof(XMLClear));
1490 }
1241}
1242
1491}
1492
1243char XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr)
1244{
1245 XML *pXML=(XML *)pa;
1246 XMLCSTR lpszText=pXML->lpszText;
1493char XMLNode::maybeAddTxT(void *pa, XMLCSTR tokenPStr) {
1494 XML *pXML = (XML *)pa;
1495 XMLCSTR lpszText = pXML->lpszText;
1247 if (!lpszText) return 0;
1496 if (!lpszText) return 0;
1248 if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText)&&(lpszText!=tokenPStr)) lpszText++;
1497 if (dropWhiteSpace) while (XML_isSPACECHAR(*lpszText) &&
1498 (lpszText != tokenPStr)) lpszText++;
1249 int cbText = (int)(tokenPStr - lpszText);
1499 int cbText = (int)(tokenPStr - lpszText);
1250 if (!cbText) { pXML->lpszText=NULL; return 0; }
1251 if (dropWhiteSpace) { cbText--; while ((cbText)&&XML_isSPACECHAR(lpszText[cbText])) cbText--; cbText++; }
1252 if (!cbText) { pXML->lpszText=NULL; return 0; }
1253 XMLSTR lpt=fromXMLString(lpszText,cbText,pXML);
1500 if (!cbText) {
1501 pXML->lpszText = NULL;
1502 return 0;
1503 }
1504 if (dropWhiteSpace) {
1505 cbText--;
1506 while ((cbText) && XML_isSPACECHAR(lpszText[cbText])) cbText--;
1507 cbText++;
1508 }
1509 if (!cbText) {
1510 pXML->lpszText = NULL;
1511 return 0;
1512 }
1513 XMLSTR lpt = fromXMLString(lpszText, cbText, pXML);
1254 if (!lpt) return 1;
1514 if (!lpt) return 1;
1255 pXML->lpszText=NULL;
1256 if (removeCommentsInMiddleOfText && d->nText && d->nClear)
1257 {
1515 pXML->lpszText = NULL;
1516 if (removeCommentsInMiddleOfText && d->nText && d->nClear) {
1258 // if the previous insertion was a comment (<!-- -->) AND
1259 // if the previous previous insertion was a text then, delete the comment and append the text
1517 // if the previous insertion was a comment (<!-- -->) AND
1518 // if the previous previous insertion was a text then, delete the comment and append the text
1260 int n=d->nChild+d->nText+d->nClear-1,*o=d->pOrder;
1261 if (((o[n]&3)==eNodeClear)&&((o[n-1]&3)==eNodeText))
1262 {
1263 int i=o[n]>>2;
1264 if (d->pClear[i].lpszOpenTag==XMLClearTags[2].lpszOpen)
1265 {
1519 int n = d->nChild + d->nText + d->nClear - 1, *o = d->pOrder;
1520 if (((o[n]&3) == eNodeClear) && ((o[n-1]&3) == eNodeText)) {
1521 int i = o[n] >> 2;
1522 if (d->pClear[i].lpszOpenTag == XMLClearTags[2].lpszOpen) {
1266 deleteClear(i);
1523 deleteClear(i);
1267 i=o[n-1]>>2;
1268 n=xstrlen(d->pText[i]);
1269 int n2=xstrlen(lpt)+1;
1270 d->pText[i]=(XMLSTR)realloc((void*)d->pText[i],(n+n2)*sizeof(XMLCHAR));
1524 i = o[n-1] >> 2;
1525 n = xstrlen(d->pText[i]);
1526 int n2 = xstrlen(lpt) + 1;
1527 d->pText[i] = (XMLSTR)realloc((void*)d->pText[i], (n + n2) *
1528 sizeof(XMLCHAR));
1271 if (!d->pText[i]) return 1;
1529 if (!d->pText[i]) return 1;
1272 memcpy((void*)(d->pText[i]+n),lpt,n2*sizeof(XMLCHAR));
1530 memcpy((void*)(d->pText[i] + n), lpt, n2*sizeof(XMLCHAR));
1273 free(lpt);
1274 return 0;
1275 }
1276 }
1277 }
1531 free(lpt);
1532 return 0;
1533 }
1534 }
1535 }
1278 addText_priv(MEMORYINCREASE,lpt,-1);
1536 addText_priv(MEMORYINCREASE, lpt, -1);
1279 return 0;
1280}
1281// private:
1282// Recursively parse an XML element.
1537 return 0;
1538}
1539// private:
1540// Recursively parse an XML element.
1283int XMLNode::ParseXMLElement(void *pa)
1284{
1285 XML *pXML=(XML *)pa;
1541int XMLNode::ParseXMLElement(void *pa) {
1542 XML *pXML = (XML *)pa;
1286 int cbToken;
1287 enum XMLTokenTypeTag xtype;
1288 NextToken token;
1543 int cbToken;
1544 enum XMLTokenTypeTag xtype;
1545 NextToken token;
1289 XMLCSTR lpszTemp=NULL;
1290 int cbTemp=0;
1546 XMLCSTR lpszTemp = NULL;
1547 int cbTemp = 0;
1291 char nDeclaration;
1292 XMLNode pNew;
1293 enum Status status; // inside or outside a tag
1294 enum Attrib attrib = eAttribName;
1295
1296 assert(pXML);
1297
1298 // If this is the first call to the function
1548 char nDeclaration;
1549 XMLNode pNew;
1550 enum Status status; // inside or outside a tag
1551 enum Attrib attrib = eAttribName;
1552
1553 assert(pXML);
1554
1555 // If this is the first call to the function
1299 if (pXML->nFirst)
1300 {
1556 if (pXML->nFirst) {
1301 // Assume we are outside of a tag definition
1302 pXML->nFirst = FALSE;
1303 status = eOutsideTag;
1557 // Assume we are outside of a tag definition
1558 pXML->nFirst = FALSE;
1559 status = eOutsideTag;
1304 } else
1305 {
1560 } else {
1306 // If this is not the first call then we should only be called when inside a tag.
1307 status = eInsideTag;
1308 }
1309
1310 // Iterate through the tokens in the document
1561 // If this is not the first call then we should only be called when inside a tag.
1562 status = eInsideTag;
1563 }
1564
1565 // Iterate through the tokens in the document
1311 for(;;)
1312 {
1566 for (;;) {
1313 // Obtain the next token
1314 token = GetNextToken(pXML, &cbToken, &xtype);
1315
1567 // Obtain the next token
1568 token = GetNextToken(pXML, &cbToken, &xtype);
1569
1316 if (xtype != eTokenError)
1317 {
1570 if (xtype != eTokenError) {
1318 // Check the current status
1571 // Check the current status
1319 switch(status)
1320 {
1572 switch (status) {
1321
1573
1322 // If we are outside of a tag definition
1574 // If we are outside of a tag definition
1323 case eOutsideTag:
1324
1325 // Check what type of token we obtained
1575 case eOutsideTag:
1576
1577 // Check what type of token we obtained
1326 switch(xtype)
1327 {
1328 // If we have found text or quoted text
1578 switch (xtype) {
1579 // If we have found text or quoted text
1329 case eTokenText:
1330 case eTokenCloseTag: /* '>' */
1331 case eTokenShortHandClose: /* '/>' */
1332 case eTokenQuotedText:
1333 case eTokenEquals:
1334 break;
1335
1580 case eTokenText:
1581 case eTokenCloseTag: /* '>' */
1582 case eTokenShortHandClose: /* '/>' */
1583 case eTokenQuotedText:
1584 case eTokenEquals:
1585 break;
1586
1336 // If we found a start tag '<' and declarations '1587 // If we found a start tag '<' and declarations '<?'
1337 case eTokenTagStart:
1338 case eTokenDeclaration:
1339
1340 // Cache whether this new element is a declaration or not
1341 nDeclaration = (xtype == eTokenDeclaration);
1342
1343 // If we have node text then add this to the element
1588 case eTokenTagStart:
1589 case eTokenDeclaration:
1590
1591 // Cache whether this new element is a declaration or not
1592 nDeclaration = (xtype == eTokenDeclaration);
1593
1594 // If we have node text then add this to the element
1344 if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1595 if (maybeAddTxT(pXML, token.pStr)) return FALSE;
1345
1346 // Find the name of the tag
1347 token = GetNextToken(pXML, &cbToken, &xtype);
1348
1349 // Return an error if we couldn't obtain the next token or
1350 // it wasnt text
1596
1597 // Find the name of the tag
1598 token = GetNextToken(pXML, &cbToken, &xtype);
1599
1600 // Return an error if we couldn't obtain the next token or
1601 // it wasnt text
1351 if (xtype != eTokenText)
1352 {
1602 if (xtype != eTokenText) {
1353 pXML->error = eXMLErrorMissingTagName;
1354 return FALSE;
1355 }
1356
1357 // If we found a new element which is the same as this
1358 // element then we need to pass this back to the caller..
1359
1360#ifdef APPROXIMATE_PARSING
1361 if (d->lpszName &&
1603 pXML->error = eXMLErrorMissingTagName;
1604 return FALSE;
1605 }
1606
1607 // If we found a new element which is the same as this
1608 // element then we need to pass this back to the caller..
1609
1610#ifdef APPROXIMATE_PARSING
1611 if (d->lpszName &&
1362 myTagCompare(d->lpszName, token.pStr) == 0)
1363 {
1612 myTagCompare(d->lpszName, token.pStr) == 0) {
1364 // Indicate to the caller that it needs to create a
1365 // new element.
1366 pXML->lpNewElement = token.pStr;
1367 pXML->cbNewElement = cbToken;
1368 return TRUE;
1369 } else
1370#endif
1371 {
1372 // If the name of the new element differs from the name of
1373 // the current element we need to add the new element to
1374 // the current one and recurse
1613 // Indicate to the caller that it needs to create a
1614 // new element.
1615 pXML->lpNewElement = token.pStr;
1616 pXML->cbNewElement = cbToken;
1617 return TRUE;
1618 } else
1619#endif
1620 {
1621 // If the name of the new element differs from the name of
1622 // the current element we need to add the new element to
1623 // the current one and recurse
1375 pNew = addChild_priv(MEMORYINCREASE,stringDup(token.pStr,cbToken), nDeclaration,-1);
1624 pNew = addChild_priv(MEMORYINCREASE,
1625 stringDup(token.pStr, cbToken),
1626 nDeclaration, -1);
1376
1627
1377 while (!pNew.isEmpty())
1378 {
1628 while (!pNew.isEmpty()) {
1379 // Callself to process the new node. If we return
1380 // FALSE this means we dont have any more
1381 // processing to do...
1382
1383 if (!pNew.ParseXMLElement(pXML)) return FALSE;
1629 // Callself to process the new node. If we return
1630 // FALSE this means we dont have any more
1631 // processing to do...
1632
1633 if (!pNew.ParseXMLElement(pXML)) return FALSE;
1384 else
1385 {
1634 else {
1386 // If the call to recurse this function
1387 // evented in a end tag specified in XML then
1388 // we need to unwind the calls to this
1389 // function until we find the appropriate node
1390 // (the element name and end tag name must
1391 // match)
1635 // If the call to recurse this function
1636 // evented in a end tag specified in XML then
1637 // we need to unwind the calls to this
1638 // function until we find the appropriate node
1639 // (the element name and end tag name must
1640 // match)
1392 if (pXML->cbEndTag)
1393 {
1641 if (pXML->cbEndTag) {
1394 // If we are back at the root node then we
1395 // have an unmatched end tag
1642 // If we are back at the root node then we
1643 // have an unmatched end tag
1396 if (!d->lpszName)
1397 {
1398 pXML->error=eXMLErrorUnmatchedEndTag;
1644 if (!d->lpszName) {
1645 pXML->error = eXMLErrorUnmatchedEndTag;
1399 return FALSE;
1400 }
1401
1402 // If the end tag matches the name of this
1403 // element then we only need to unwind
1404 // once more...
1405
1646 return FALSE;
1647 }
1648
1649 // If the end tag matches the name of this
1650 // element then we only need to unwind
1651 // once more...
1652
1406 if (myTagCompare(d->lpszName, pXML->lpEndTag)==0)
1407 {
1653 if (myTagCompare(d->lpszName,
1654 pXML->lpEndTag) == 0) {
1408 pXML->cbEndTag = 0;
1409 }
1410
1411 return TRUE;
1655 pXML->cbEndTag = 0;
1656 }
1657
1658 return TRUE;
1412 } else
1413 if (pXML->cbNewElement)
1414 {
1415 // If the call indicated a new element is to
1416 // be created on THIS element.
1659 } else if (pXML->cbNewElement) {
1660 // If the call indicated a new element is to
1661 // be created on THIS element.
1417
1662
1418 // If the name of this element matches the
1419 // name of the element we need to create
1420 // then we need to return to the caller
1421 // and let it process the element.
1663 // If the name of this element matches the
1664 // name of the element we need to create
1665 // then we need to return to the caller
1666 // and let it process the element.
1422
1667
1423 if (myTagCompare(d->lpszName, pXML->lpNewElement)==0)
1424 {
1425 return TRUE;
1426 }
1427
1428 // Add the new element and recurse
1429 pNew = addChild_priv(MEMORYINCREASE,stringDup(pXML->lpNewElement,pXML->cbNewElement),0,-1);
1430 pXML->cbNewElement = 0;
1668 if (myTagCompare(d->lpszName,
1669 pXML->lpNewElement) == 0) {
1670 return TRUE;
1431 }
1671 }
1432 else
1433 {
1434 // If we didn't have a new element to create
1435 pNew = emptyXMLNode;
1436
1672
1437 }
1673 // Add the new element and recurse
1674 pNew =
1675 addChild_priv(MEMORYINCREASE,
1676 stringDup(pXML->
1677 lpNewElement,
1678 pXML->
1679 cbNewElement),
1680 0, -1);
1681 pXML->cbNewElement = 0;
1682 } else {
1683 // If we didn't have a new element to create
1684 pNew = emptyXMLNode;
1685
1686 }
1438 }
1439 }
1440 }
1441 break;
1442
1687 }
1688 }
1689 }
1690 break;
1691
1443 // If we found an end tag
1692 // If we found an end tag
1444 case eTokenTagEnd:
1445
1446 // If we have node text then add this to the element
1693 case eTokenTagEnd:
1694
1695 // If we have node text then add this to the element
1447 if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1696 if (maybeAddTxT(pXML, token.pStr)) return FALSE;
1448
1449 // Find the name of the end tag
1450 token = GetNextToken(pXML, &cbTemp, &xtype);
1451
1452 // The end tag should be text
1697
1698 // Find the name of the end tag
1699 token = GetNextToken(pXML, &cbTemp, &xtype);
1700
1701 // The end tag should be text
1453 if (xtype != eTokenText)
1454 {
1702 if (xtype != eTokenText) {
1455 pXML->error = eXMLErrorMissingEndTagName;
1456 return FALSE;
1457 }
1458 lpszTemp = token.pStr;
1459
1460 // After the end tag we should find a closing tag
1461 token = GetNextToken(pXML, &cbToken, &xtype);
1703 pXML->error = eXMLErrorMissingEndTagName;
1704 return FALSE;
1705 }
1706 lpszTemp = token.pStr;
1707
1708 // After the end tag we should find a closing tag
1709 token = GetNextToken(pXML, &cbToken, &xtype);
1462 if (xtype != eTokenCloseTag)
1463 {
1710 if (xtype != eTokenCloseTag) {
1464 pXML->error = eXMLErrorMissingEndTagName;
1465 return FALSE;
1466 }
1711 pXML->error = eXMLErrorMissingEndTagName;
1712 return FALSE;
1713 }
1467 pXML->lpszText=pXML->lpXML+pXML->nIndex;
1714 pXML->lpszText = pXML->lpXML + pXML->nIndex;
1468
1469 // We need to return to the previous caller. If the name
1470 // of the tag cannot be found we need to keep returning to
1471 // caller until we find a match
1472 if (myTagCompare(d->lpszName, lpszTemp) != 0)
1473#ifdef STRICT_PARSING
1474 {
1715
1716 // We need to return to the previous caller. If the name
1717 // of the tag cannot be found we need to keep returning to
1718 // caller until we find a match
1719 if (myTagCompare(d->lpszName, lpszTemp) != 0)
1720#ifdef STRICT_PARSING
1721 {
1475 pXML->error=eXMLErrorUnmatchedEndTag;
1476 pXML->nIndexMissigEndTag=pXML->nIndex;
1722 pXML->error = eXMLErrorUnmatchedEndTag;
1723 pXML->nIndexMissigEndTag = pXML->nIndex;
1477 return FALSE;
1478 }
1479#else
1480 {
1724 return FALSE;
1725 }
1726#else
1727 {
1481 pXML->error=eXMLErrorMissingEndTag;
1482 pXML->nIndexMissigEndTag=pXML->nIndex;
1728 pXML->error = eXMLErrorMissingEndTag;
1729 pXML->nIndexMissigEndTag = pXML->nIndex;
1483 pXML->lpEndTag = lpszTemp;
1484 pXML->cbEndTag = cbTemp;
1485 }
1486#endif
1487
1488 // Return to the caller
1489 exactMemory(d);
1490 return TRUE;
1491
1730 pXML->lpEndTag = lpszTemp;
1731 pXML->cbEndTag = cbTemp;
1732 }
1733#endif
1734
1735 // Return to the caller
1736 exactMemory(d);
1737 return TRUE;
1738
1492 // If we found a clear (unformatted) token
1739 // If we found a clear (unformatted) token
1493 case eTokenClear:
1494 // If we have node text then add this to the element
1740 case eTokenClear:
1741 // If we have node text then add this to the element
1495 if (maybeAddTxT(pXML,token.pStr)) return FALSE;
1742 if (maybeAddTxT(pXML, token.pStr)) return FALSE;
1496 if (parseClearTag(pXML, token.pClr)) return FALSE;
1743 if (parseClearTag(pXML, token.pClr)) return FALSE;
1497 pXML->lpszText=pXML->lpXML+pXML->nIndex;
1744 pXML->lpszText = pXML->lpXML + pXML->nIndex;
1498 break;
1499
1500 default:
1501 break;
1502 }
1503 break;
1504
1745 break;
1746
1747 default:
1748 break;
1749 }
1750 break;
1751
1505 // If we are inside a tag definition we need to search for attributes
1752 // If we are inside a tag definition we need to search for attributes
1506 case eInsideTag:
1507
1508 // Check what part of the attribute (name, equals, value) we
1509 // are looking for.
1753 case eInsideTag:
1754
1755 // Check what part of the attribute (name, equals, value) we
1756 // are looking for.
1510 switch(attrib)
1511 {
1512 // If we are looking for a new attribute
1757 switch (attrib) {
1758 // If we are looking for a new attribute
1513 case eAttribName:
1514
1515 // Check what the current token type is
1759 case eAttribName:
1760
1761 // Check what the current token type is
1516 switch(xtype)
1517 {
1518 // If the current type is text...
1519 // Eg. 'attribute'
1762 switch (xtype) {
1763 // If the current type is text...
1764 // Eg. 'attribute'
1520 case eTokenText:
1521 // Cache the token then indicate that we are next to
1522 // look for the equals
1523 lpszTemp = token.pStr;
1524 cbTemp = cbToken;
1525 attrib = eAttribEquals;
1526 break;
1527
1765 case eTokenText:
1766 // Cache the token then indicate that we are next to
1767 // look for the equals
1768 lpszTemp = token.pStr;
1769 cbTemp = cbToken;
1770 attrib = eAttribEquals;
1771 break;
1772
1528 // If we found a closing tag...
1529 // Eg. '>'
1773 // If we found a closing tag...
1774 // Eg. '>'
1530 case eTokenCloseTag:
1531 // We are now outside the tag
1532 status = eOutsideTag;
1775 case eTokenCloseTag:
1776 // We are now outside the tag
1777 status = eOutsideTag;
1533 pXML->lpszText=pXML->lpXML+pXML->nIndex;
1778 pXML->lpszText = pXML->lpXML + pXML->nIndex;
1534 break;
1535
1779 break;
1780
1536 // If we found a short hand '/>' closing tag then we can
1537 // return to the caller
1781 // If we found a short hand '/>' closing tag then we can
1782 // return to the caller
1538 case eTokenShortHandClose:
1539 exactMemory(d);
1783 case eTokenShortHandClose:
1784 exactMemory(d);
1540 pXML->lpszText=pXML->lpXML+pXML->nIndex;
1785 pXML->lpszText = pXML->lpXML + pXML->nIndex;
1541 return TRUE;
1542
1786 return TRUE;
1787
1543 // Errors...
1788 // Errors...
1544 case eTokenQuotedText: /* '"SomeText"' */
1545 case eTokenTagStart: /* '<' */
1546 case eTokenTagEnd: /* '</' */
1547 case eTokenEquals: /* '=' */
1548 case eTokenDeclaration: /* '<?' */
1549 case eTokenClear:
1550 pXML->error = eXMLErrorUnexpectedToken;
1551 return FALSE;
1789 case eTokenQuotedText: /* '"SomeText"' */
1790 case eTokenTagStart: /* '<' */
1791 case eTokenTagEnd: /* '</' */
1792 case eTokenEquals: /* '=' */
1793 case eTokenDeclaration: /* '<?' */
1794 case eTokenClear:
1795 pXML->error = eXMLErrorUnexpectedToken;
1796 return FALSE;
1552 default: break;
1797 default:
1798 break;
1553 }
1554 break;
1555
1799 }
1800 break;
1801
1556 // If we are looking for an equals
1802 // If we are looking for an equals
1557 case eAttribEquals:
1558 // Check what the current token type is
1803 case eAttribEquals:
1804 // Check what the current token type is
1559 switch(xtype)
1560 {
1561 // If the current type is text...
1562 // Eg. 'Attribute AnotherAttribute'
1805 switch (xtype) {
1806 // If the current type is text...
1807 // Eg. 'Attribute AnotherAttribute'
1563 case eTokenText:
1564 // Add the unvalued attribute to the list
1808 case eTokenText:
1809 // Add the unvalued attribute to the list
1565 addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
1810 addAttribute_priv(MEMORYINCREASE,
1811 stringDup(lpszTemp, cbTemp), NULL);
1566 // Cache the token then indicate. We are next to
1567 // look for the equals attribute
1568 lpszTemp = token.pStr;
1569 cbTemp = cbToken;
1570 break;
1571
1812 // Cache the token then indicate. We are next to
1813 // look for the equals attribute
1814 lpszTemp = token.pStr;
1815 cbTemp = cbToken;
1816 break;
1817
1572 // If we found a closing tag 'Attribute >' or a short hand
1573 // closing tag 'Attribute />'
1818 // If we found a closing tag 'Attribute >' or a short hand
1819 // closing tag 'Attribute />'
1574 case eTokenShortHandClose:
1575 case eTokenCloseTag:
1576 // If we are a declaration element '<?' then we need
1577 // to remove extra closing '?' if it exists
1820 case eTokenShortHandClose:
1821 case eTokenCloseTag:
1822 // If we are a declaration element '<?' then we need
1823 // to remove extra closing '?' if it exists
1578 pXML->lpszText=pXML->lpXML+pXML->nIndex;
1824 pXML->lpszText = pXML->lpXML + pXML->nIndex;
1579
1580 if (d->isDeclaration &&
1825
1826 if (d->isDeclaration &&
1581 (lpszTemp[cbTemp-1]) == _CXML('?'))
1582 {
1827 (lpszTemp[cbTemp-1]) == _CXML('?')) {
1583 cbTemp--;
1828 cbTemp--;
1584 if (d->pParent && d->pParent->pParent) xtype = eTokenShortHandClose;
1829 if (d->pParent && d->pParent->pParent) {
1830 xtype = eTokenShortHandClose;
1831 }
1585 }
1586
1832 }
1833
1587 if (cbTemp)
1588 {
1834 if (cbTemp) {
1589 // Add the unvalued attribute to the list
1835 // Add the unvalued attribute to the list
1590 addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL);
1836 addAttribute_priv(MEMORYINCREASE,
1837 stringDup(lpszTemp, cbTemp), NULL);
1591 }
1592
1593 // If this is the end of the tag then return to the caller
1838 }
1839
1840 // If this is the end of the tag then return to the caller
1594 if (xtype == eTokenShortHandClose)
1595 {
1841 if (xtype == eTokenShortHandClose) {
1596 exactMemory(d);
1597 return TRUE;
1598 }
1599
1600 // We are now outside the tag
1601 status = eOutsideTag;
1602 break;
1603
1842 exactMemory(d);
1843 return TRUE;
1844 }
1845
1846 // We are now outside the tag
1847 status = eOutsideTag;
1848 break;
1849
1604 // If we found the equals token...
1605 // Eg. 'Attribute ='
1850 // If we found the equals token...
1851 // Eg. 'Attribute ='
1606 case eTokenEquals:
1607 // Indicate that we next need to search for the value
1608 // for the attribute
1609 attrib = eAttribValue;
1610 break;
1611
1852 case eTokenEquals:
1853 // Indicate that we next need to search for the value
1854 // for the attribute
1855 attrib = eAttribValue;
1856 break;
1857
1612 // Errors...
1858 // Errors...
1613 case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
1614 case eTokenTagStart: /* 'Attribute <' */
1615 case eTokenTagEnd: /* 'Attribute </' */
1616 case eTokenDeclaration: /* 'Attribute <?' */
1617 case eTokenClear:
1618 pXML->error = eXMLErrorUnexpectedToken;
1619 return FALSE;
1859 case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/
1860 case eTokenTagStart: /* 'Attribute <' */
1861 case eTokenTagEnd: /* 'Attribute </' */
1862 case eTokenDeclaration: /* 'Attribute <?' */
1863 case eTokenClear:
1864 pXML->error = eXMLErrorUnexpectedToken;
1865 return FALSE;
1620 default: break;
1866 default:
1867 break;
1621 }
1622 break;
1623
1868 }
1869 break;
1870
1624 // If we are looking for an attribute value
1871 // If we are looking for an attribute value
1625 case eAttribValue:
1626 // Check what the current token type is
1872 case eAttribValue:
1873 // Check what the current token type is
1627 switch(xtype)
1628 {
1629 // If the current type is text or quoted text...
1630 // Eg. 'Attribute = "Value"' or 'Attribute = Value' or
1631 // 'Attribute = 'Value''.
1874 switch (xtype) {
1875 // If the current type is text or quoted text...
1876 // Eg. 'Attribute = "Value"' or 'Attribute = Value' or
1877 // 'Attribute = 'Value''.
1632 case eTokenText:
1633 case eTokenQuotedText:
1634 // If we are a declaration element '<?' then we need
1635 // to remove extra closing '?' if it exists
1636 if (d->isDeclaration &&
1878 case eTokenText:
1879 case eTokenQuotedText:
1880 // If we are a declaration element '<?' then we need
1881 // to remove extra closing '?' if it exists
1882 if (d->isDeclaration &&
1637 (token.pStr[cbToken-1]) == _CXML('?'))
1638 {
1883 (token.pStr[cbToken-1]) == _CXML('?')) {
1639 cbToken--;
1640 }
1641
1884 cbToken--;
1885 }
1886
1642 if (cbTemp)
1643 {
1887 if (cbTemp) {
1644 // Add the valued attribute to the list
1888 // Add the valued attribute to the list
1645 if (xtype==eTokenQuotedText) { token.pStr++; cbToken-=2; }
1646 XMLSTR attrVal=(XMLSTR)token.pStr;
1647 if (attrVal)
1648 {
1649 attrVal=fromXMLString(attrVal,cbToken,pXML);
1889 if (xtype == eTokenQuotedText) {
1890 token.pStr++;
1891 cbToken -= 2;
1892 }
1893 XMLSTR attrVal = (XMLSTR)token.pStr;
1894 if (attrVal) {
1895 attrVal = fromXMLString(attrVal, cbToken, pXML);
1650 if (!attrVal) return FALSE;
1651 }
1896 if (!attrVal) return FALSE;
1897 }
1652 addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal);
1898 addAttribute_priv(MEMORYINCREASE,
1899 stringDup(lpszTemp, cbTemp),
1900 attrVal);
1653 }
1654
1655 // Indicate we are searching for a new attribute
1656 attrib = eAttribName;
1657 break;
1658
1901 }
1902
1903 // Indicate we are searching for a new attribute
1904 attrib = eAttribName;
1905 break;
1906
1659 // Errors...
1907 // Errors...
1660 case eTokenTagStart: /* 'Attr = <' */
1661 case eTokenTagEnd: /* 'Attr = </' */
1662 case eTokenCloseTag: /* 'Attr = >' */
1663 case eTokenShortHandClose: /* "Attr = />" */
1664 case eTokenEquals: /* 'Attr = =' */
1665 case eTokenDeclaration: /* 'Attr = <?' */
1666 case eTokenClear:
1667 pXML->error = eXMLErrorUnexpectedToken;
1668 return FALSE;
1669 break;
1908 case eTokenTagStart: /* 'Attr = <' */
1909 case eTokenTagEnd: /* 'Attr = </' */
1910 case eTokenCloseTag: /* 'Attr = >' */
1911 case eTokenShortHandClose: /* "Attr = />" */
1912 case eTokenEquals: /* 'Attr = =' */
1913 case eTokenDeclaration: /* 'Attr = <?' */
1914 case eTokenClear:
1915 pXML->error = eXMLErrorUnexpectedToken;
1916 return FALSE;
1917 break;
1670 default: break;
1918 default:
1919 break;
1671 }
1672 }
1673 }
1674 }
1675 // If we failed to obtain the next token
1920 }
1921 }
1922 }
1923 }
1924 // If we failed to obtain the next token
1676 else
1677 {
1678 if ((!d->isDeclaration)&&(d->pParent))
1679 {
1925 else {
1926 if ((!d->isDeclaration) && (d->pParent)) {
1680#ifdef STRICT_PARSING
1927#ifdef STRICT_PARSING
1681 pXML->error=eXMLErrorUnmatchedEndTag;
1928 pXML->error = eXMLErrorUnmatchedEndTag;
1682#else
1929#else
1683 pXML->error=eXMLErrorMissingEndTag;
1930 pXML->error = eXMLErrorMissingEndTag;
1684#endif
1931#endif
1685 pXML->nIndexMissigEndTag=pXML->nIndex;
1932 pXML->nIndexMissigEndTag = pXML->nIndex;
1686 }
1933 }
1687 maybeAddTxT(pXML,pXML->lpXML+pXML->nIndex);
1934 maybeAddTxT(pXML, pXML->lpXML + pXML->nIndex);
1688 return FALSE;
1689 }
1690 }
1691}
1692
1693// Count the number of lines and columns in an XML string.
1935 return FALSE;
1936 }
1937 }
1938}
1939
1940// Count the number of lines and columns in an XML string.
1694static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults)
1695{
1941static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto,
1942 XMLResults *pResults) {
1696 XMLCHAR ch;
1697 assert(lpXML);
1698 assert(pResults);
1699
1943 XMLCHAR ch;
1944 assert(lpXML);
1945 assert(pResults);
1946
1700 struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
1947 struct XML xml = { lpXML, lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0,
1948 TRUE };
1701
1702 pResults->nLine = 1;
1703 pResults->nColumn = 1;
1949
1950 pResults->nLine = 1;
1951 pResults->nColumn = 1;
1704 while (xml.nIndex<nUpto)
1705 {
1952 while (xml.nIndex < nUpto) {
1706 ch = getNextChar(&xml);
1707 if (ch != _CXML('\n')) pResults->nColumn++;
1953 ch = getNextChar(&xml);
1954 if (ch != _CXML('\n')) pResults->nColumn++;
1708 else
1709 {
1955 else {
1710 pResults->nLine++;
1956 pResults->nLine++;
1711 pResults->nColumn=1;
1957 pResults->nColumn = 1;
1712 }
1713 }
1714}
1715
1716// Parse XML and return the root element.
1958 }
1959 }
1960}
1961
1962// Parse XML and return the root element.
1717XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults)
1718{
1719 if (!lpszXML)
1720 {
1721 if (pResults)
1722 {
1723 pResults->error=eXMLErrorNoElements;
1724 pResults->nLine=0;
1725 pResults->nColumn=0;
1963XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag,
1964 XMLResults *pResults) {
1965 if (!lpszXML) {
1966 if (pResults) {
1967 pResults->error = eXMLErrorNoElements;
1968 pResults->nLine = 0;
1969 pResults->nColumn = 0;
1726 }
1727 return emptyXMLNode;
1728 }
1729
1970 }
1971 return emptyXMLNode;
1972 }
1973
1730 XMLNode xnode(NULL,NULL,FALSE);
1731 struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE };
1974 XMLNode xnode(NULL, NULL, FALSE);
1975 struct XML xml = { lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0,
1976 TRUE };
1732
1733 // Create header element
1734 xnode.ParseXMLElement(&xml);
1735 enum XMLError error = xml.error;
1977
1978 // Create header element
1979 xnode.ParseXMLElement(&xml);
1980 enum XMLError error = xml.error;
1736 if (!xnode.nChildNode()) error=eXMLErrorNoXMLTagFound;
1737 if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node
1981 if (!xnode.nChildNode()) error = eXMLErrorNoXMLTagFound;
1982 if ((xnode.nChildNode() == 1) && (xnode.nElement() == 1)) {
1983 xnode = xnode.getChildNode(); // skip the empty node
1984 }
1738
1739 // If no error occurred
1985
1986 // If no error occurred
1740 if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag)||(error==eXMLErrorNoXMLTagFound))
1741 {
1742 XMLCSTR name=xnode.getName();
1743 if (tag&&(*tag)&&((!name)||(xstricmp(name,tag))))
1744 {
1745 xnode=xnode.getChildNode(tag);
1746 if (xnode.isEmpty())
1747 {
1748 if (pResults)
1749 {
1750 pResults->error=eXMLErrorFirstTagNotFound;
1751 pResults->nLine=0;
1752 pResults->nColumn=0;
1987 if ((error == eXMLErrorNone) || (error == eXMLErrorMissingEndTag) ||
1988 (error == eXMLErrorNoXMLTagFound)) {
1989 XMLCSTR name = xnode.getName();
1990 if (tag && (*tag) && ((!name) || (xstricmp(name, tag)))) {
1991 xnode = xnode.getChildNode(tag);
1992 if (xnode.isEmpty()) {
1993 if (pResults) {
1994 pResults->error = eXMLErrorFirstTagNotFound;
1995 pResults->nLine = 0;
1996 pResults->nColumn = 0;
1753 }
1754 return emptyXMLNode;
1755 }
1756 }
1997 }
1998 return emptyXMLNode;
1999 }
2000 }
1757 } else
1758 {
2001 } else {
1759 // Cleanup: this will destroy all the nodes
1760 xnode = emptyXMLNode;
1761 }
1762
1763
1764 // If we have been given somewhere to place results
2002 // Cleanup: this will destroy all the nodes
2003 xnode = emptyXMLNode;
2004 }
2005
2006
2007 // If we have been given somewhere to place results
1765 if (pResults)
1766 {
2008 if (pResults) {
1767 pResults->error = error;
1768
1769 // If we have an error
2009 pResults->error = error;
2010
2011 // If we have an error
1770 if (error!=eXMLErrorNone)
1771 {
1772 if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag;
2012 if (error != eXMLErrorNone) {
2013 if (error == eXMLErrorMissingEndTag) {
2014 xml.nIndex = xml.nIndexMissigEndTag;
2015 }
1773 // Find which line and column it starts on.
1774 CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
1775 }
1776 }
1777 return xnode;
1778}
1779
2016 // Find which line and column it starts on.
2017 CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults);
2018 }
2019 }
2020 return xnode;
2021}
2022
1780XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults)
1781{
1782 if (pResults) { pResults->nLine=0; pResults->nColumn=0; }
1783 FILE *f=xfopen(filename,_CXML("rb"));
1784 if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; }
1785 fseek(f,0,SEEK_END);
1786 int l=ftell(f),headerSz=0;
1787 if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); return emptyXMLNode; }
1788 fseek(f,0,SEEK_SET);
1789 unsigned char *buf=(unsigned char*)malloc(l+4);
1790 l=fread(buf,1,l,f);
2023XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults) {
2024 if (pResults) {
2025 pResults->nLine = 0;
2026 pResults->nColumn = 0;
2027 }
2028 FILE *f = xfopen(filename, _CXML("rb"));
2029 if (f == NULL) {
2030 if (pResults) pResults->error = eXMLErrorFileNotFound;
2031 return emptyXMLNode;
2032 }
2033 fseek(f, 0, SEEK_END);
2034 int l = ftell(f), headerSz = 0;
2035 if (!l) {
2036 if (pResults) pResults->error = eXMLErrorEmpty;
2037 fclose(f);
2038 return emptyXMLNode;
2039 }
2040 fseek(f, 0, SEEK_SET);
2041 unsigned char *buf = (unsigned char*)malloc(l + 4);
2042 l = fread(buf, 1, l, f);
1791 fclose(f);
2043 fclose(f);
1792 buf[l]=0;buf[l+1]=0;buf[l+2]=0;buf[l+3]=0;
2044 buf[l] = 0;
2045 buf[l+1] = 0;
2046 buf[l+2] = 0;
2047 buf[l+3] = 0;
1793#ifdef _XMLWIDECHAR
2048#ifdef _XMLWIDECHAR
1794 if (guessWideCharChars)
1795 {
1796 if (!myIsTextWideChar(buf,l))
1797 {
1798 XMLNode::XMLCharEncoding ce=XMLNode::char_encoding_legacy;
1799 if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) { headerSz=3; ce=XMLNode::char_encoding_UTF8; }
1800 XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz),ce);
1801 free(buf); buf=(unsigned char*)b2; headerSz=0;
1802 } else
1803 {
1804 if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
1805 if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
2049 if (guessWideCharChars) {
2050 if (!myIsTextWideChar(buf, l)) {
2051 XMLNode::XMLCharEncoding ce = XMLNode::char_encoding_legacy;
2052 if ((buf[0] == 0xef) && (buf[1] == 0xbb) && (buf[2] == 0xbf)) {
2053 headerSz = 3;
2054 ce = XMLNode::char_encoding_UTF8;
2055 }
2056 XMLSTR b2 = myMultiByteToWideChar((const char*)(buf + headerSz), ce);
2057 free(buf);
2058 buf = (unsigned char*)b2;
2059 headerSz = 0;
2060 } else {
2061 if ((buf[0] == 0xef) && (buf[1] == 0xff)) headerSz = 2;
2062 if ((buf[0] == 0xff) && (buf[1] == 0xfe)) headerSz = 2;
1806 }
1807 }
1808#else
2063 }
2064 }
2065#else
1809 if (guessWideCharChars)
1810 {
1811 if (myIsTextWideChar(buf,l))
1812 {
1813 if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2;
1814 if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2;
1815 char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz));
1816 free(buf); buf=(unsigned char*)b2; headerSz=0;
1817 } else
1818 {
1819 if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3;
2066 if (guessWideCharChars) {
2067 if (myIsTextWideChar(buf, l)) {
2068 if ((buf[0] == 0xef) && (buf[1] == 0xff)) headerSz = 2;
2069 if ((buf[0] == 0xff) && (buf[1] == 0xfe)) headerSz = 2;
2070 char *b2 = myWideCharToMultiByte((const wchar_t*)(buf + headerSz));
2071 free(buf);
2072 buf = (unsigned char*)b2;
2073 headerSz = 0;
2074 } else {
2075 if ((buf[0] == 0xef) && (buf[1] == 0xbb) && (buf[2] == 0xbf)) {
2076 headerSz = 3;
2077 }
1820 }
1821 }
1822#endif
1823
2078 }
2079 }
2080#endif
2081
1824 if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; }
1825 XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults);
2082 if (!buf) {
2083 if (pResults) pResults->error = eXMLErrorCharConversionError;
2084 return emptyXMLNode;
2085 }
2086 XMLNode x = parseString((XMLSTR)(buf + headerSz), tag, pResults);
1826 free(buf);
1827 return x;
1828}
1829
2087 free(buf);
2088 return x;
2089}
2090
1830static inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; }
2091static inline void charmemset(XMLSTR dest, XMLCHAR c, int l) {
2092 while (l--) *(dest++) = c;
2093}
1831// private:
1832// Creates an user friendly XML string from a given element with
1833// appropriate white space and carriage returns.
1834//
1835// This recurses through all subnodes then adds contents of the nodes to the
1836// string.
2094// private:
2095// Creates an user friendly XML string from a given element with
2096// appropriate white space and carriage returns.
2097//
2098// This recurses through all subnodes then adds contents of the nodes to the
2099// string.
1837int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat)
1838{
2100int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker,
2101 int nFormat) {
1839 int nResult = 0;
2102 int nResult = 0;
1840 int cb=nFormat<0?0:nFormat;
2103 int cb = nFormat < 0 ? 0 : nFormat;
1841 int cbElement;
2104 int cbElement;
1842 int nChildFormat=-1;
1843 int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear;
1844 int i,j;
1845 if ((nFormat>=0)&&(nElementI==1)&&(pEntry->nText==1)&&(!pEntry->isDeclaration)) nFormat=-2;
2105 int nChildFormat = -1;
2106 int nElementI = pEntry->nChild + pEntry->nText + pEntry->nClear;
2107 int i, j;
2108 if ((nFormat >= 0) && (nElementI == 1) && (pEntry->nText == 1) &&
2109 (!pEntry->isDeclaration)) {
2110 nFormat = -2;
2111 }
1846
1847 assert(pEntry);
1848
1849#define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0)
1850
1851 // If the element has no name then assume this is the head node.
1852 cbElement = (int)LENSTR(pEntry->lpszName);
1853
2112
2113 assert(pEntry);
2114
2115#define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0)
2116
2117 // If the element has no name then assume this is the head node.
2118 cbElement = (int)LENSTR(pEntry->lpszName);
2119
1854 if (cbElement)
1855 {
2120 if (cbElement) {
1856 // "<elementname "
2121 // "<elementname "
1857 if (lpszMarker)
1858 {
2122 if (lpszMarker) {
1859 if (cb) charmemset(lpszMarker, INDENTCHAR, cb);
1860 nResult = cb;
2123 if (cb) charmemset(lpszMarker, INDENTCHAR, cb);
2124 nResult = cb;
1861 lpszMarker[nResult++]=_CXML('<');
1862 if (pEntry->isDeclaration) lpszMarker[nResult++]=_CXML('?');
2125 lpszMarker[nResult++] = _CXML('<');
2126 if (pEntry->isDeclaration) lpszMarker[nResult++] = _CXML('?');
1863 xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
2127 xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
1864 nResult+=cbElement;
1865 lpszMarker[nResult++]=_CXML(' ');
2128 nResult += cbElement;
2129 lpszMarker[nResult++] = _CXML(' ');
1866
2130
1867 } else
1868 {
1869 nResult+=cbElement+2+cb;
2131 } else {
2132 nResult += cbElement + 2 + cb;
1870 if (pEntry->isDeclaration) nResult++;
1871 }
1872
1873 // Enumerate attributes and add them to the string
2133 if (pEntry->isDeclaration) nResult++;
2134 }
2135
2136 // Enumerate attributes and add them to the string
1874 XMLAttribute *pAttr=pEntry->pAttribute;
1875 for (i=0; i<pEntry->nAttribute; i++)
1876 {
2137 XMLAttribute *pAttr = pEntry->pAttribute;
2138 for (i = 0; i < pEntry->nAttribute; i++) {
1877 // "Attrib
1878 cb = (int)LENSTR(pAttr->lpszName);
2139 // "Attrib
2140 cb = (int)LENSTR(pAttr->lpszName);
1879 if (cb)
1880 {
2141 if (cb) {
1881 if (lpszMarker) xstrcpy(&lpszMarker[nResult], pAttr->lpszName);
1882 nResult += cb;
1883 // "Attrib=Value "
2142 if (lpszMarker) xstrcpy(&lpszMarker[nResult], pAttr->lpszName);
2143 nResult += cb;
2144 // "Attrib=Value "
1884 if (pAttr->lpszValue)
1885 {
1886 cb=(int)ToXMLStringTool::lengthXMLString(pAttr->lpszValue);
1887 if (lpszMarker)
1888 {
1889 lpszMarker[nResult]=_CXML('=');
1890 lpszMarker[nResult+1]=_CXML('"');
1891 if (cb) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+2],pAttr->lpszValue);
1892 lpszMarker[nResult+cb+2]=_CXML('"');
2145 if (pAttr->lpszValue) {
2146 cb = (int)ToXMLStringTool::lengthXMLString(pAttr->lpszValue);
2147 if (lpszMarker) {
2148 lpszMarker[nResult] = _CXML('=');
2149 lpszMarker[nResult+1] = _CXML('"');
2150 if (cb) {
2151 ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+2],
2152 pAttr->lpszValue);
2153 }
2154 lpszMarker[nResult+cb+2] = _CXML('"');
1893 }
2155 }
1894 nResult+=cb+3;
2156 nResult += cb + 3;
1895 }
1896 if (lpszMarker) lpszMarker[nResult] = _CXML(' ');
1897 nResult++;
1898 }
1899 pAttr++;
1900 }
1901
2157 }
2158 if (lpszMarker) lpszMarker[nResult] = _CXML(' ');
2159 nResult++;
2160 }
2161 pAttr++;
2162 }
2163
1902 if (pEntry->isDeclaration)
1903 {
1904 if (lpszMarker)
1905 {
1906 lpszMarker[nResult-1]=_CXML('?');
1907 lpszMarker[nResult]=_CXML('>');
2164 if (pEntry->isDeclaration) {
2165 if (lpszMarker) {
2166 lpszMarker[nResult-1] = _CXML('?');
2167 lpszMarker[nResult] = _CXML('>');
1908 }
1909 nResult++;
2168 }
2169 nResult++;
1910 if (nFormat!=-1)
1911 {
1912 if (lpszMarker) lpszMarker[nResult]=_CXML('\n');
2170 if (nFormat != -1) {
2171 if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
1913 nResult++;
1914 }
1915 } else
1916 // If there are child nodes we need to terminate the start tag
2172 nResult++;
2173 }
2174 } else
2175 // If there are child nodes we need to terminate the start tag
1917 if (nElementI)
1918 {
1919 if (lpszMarker) lpszMarker[nResult-1]=_CXML('>');
1920 if (nFormat>=0)
1921 {
1922 if (lpszMarker) lpszMarker[nResult]=_CXML('\n');
2176 if (nElementI) {
2177 if (lpszMarker) lpszMarker[nResult-1] = _CXML('>');
2178 if (nFormat >= 0) {
2179 if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
1923 nResult++;
1924 }
1925 } else nResult--;
1926 }
1927
1928 // Calculate the child format for when we recurse. This is used to
1929 // determine the number of spaces used for prefixes.
2180 nResult++;
2181 }
2182 } else nResult--;
2183 }
2184
2185 // Calculate the child format for when we recurse. This is used to
2186 // determine the number of spaces used for prefixes.
1930 if (nFormat!=-1)
1931 {
1932 if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1;
1933 else nChildFormat=nFormat;
2187 if (nFormat != -1) {
2188 if (cbElement && (!pEntry->isDeclaration)) nChildFormat = nFormat + 1;
2189 else nChildFormat = nFormat;
1934 }
1935
1936 // Enumerate through remaining children
2190 }
2191
2192 // Enumerate through remaining children
1937 for (i=0; i<nElementI; i++)
1938 {
1939 j=pEntry->pOrder[i];
1940 switch((XMLElementType)(j&3))
1941 {
1942 // Text nodes
1943 case eNodeText:
1944 {
1945 // "Text"
1946 XMLCSTR pChild=pEntry->pText[j>>2];
1947 cb = (int)ToXMLStringTool::lengthXMLString(pChild);
1948 if (cb)
1949 {
1950 if (nFormat>=0)
1951 {
1952 if (lpszMarker)
1953 {
1954 charmemset(&lpszMarker[nResult],INDENTCHAR,nFormat+1);
1955 ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult+nFormat+1],pChild);
1956 lpszMarker[nResult+nFormat+1+cb]=_CXML('\n');
1957 }
1958 nResult+=cb+nFormat+2;
1959 } else
1960 {
1961 if (lpszMarker) ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult], pChild);
1962 nResult += cb;
2193 for (i = 0; i < nElementI; i++) {
2194 j = pEntry->pOrder[i];
2195 switch ((XMLElementType)(j&3)) {
2196 // Text nodes
2197 case eNodeText: {
2198 // "Text"
2199 XMLCSTR pChild = pEntry->pText[j>>2];
2200 cb = (int)ToXMLStringTool::lengthXMLString(pChild);
2201 if (cb) {
2202 if (nFormat >= 0) {
2203 if (lpszMarker) {
2204 charmemset(&lpszMarker[nResult], INDENTCHAR,
2205 nFormat + 1);
2206 ToXMLStringTool::toXMLUnSafe(
2207 &lpszMarker[nResult+nFormat+1], pChild);
2208 lpszMarker[nResult+nFormat+1+cb] = _CXML('\n');
1963 }
2209 }
2210 nResult += cb + nFormat + 2;
2211 } else {
2212 if (lpszMarker) {
2213 ToXMLStringTool::toXMLUnSafe(&lpszMarker[nResult],
2214 pChild);
2215 }
2216 nResult += cb;
1964 }
2217 }
1965 break;
1966 }
2218 }
2219 break;
2220 }
1967
1968 // Clear type nodes
2221
2222 // Clear type nodes
1969 case eNodeClear:
1970 {
1971 XMLClear *pChild=pEntry->pClear+(j>>2);
1972 // "OpenTag"
1973 cb = (int)LENSTR(pChild->lpszOpenTag);
1974 if (cb)
1975 {
1976 if (nFormat!=-1)
1977 {
1978 if (lpszMarker)
1979 {
1980 charmemset(&lpszMarker[nResult], INDENTCHAR, nFormat+1);
1981 xstrcpy(&lpszMarker[nResult+nFormat+1], pChild->lpszOpenTag);
1982 }
1983 nResult+=cb+nFormat+1;
2223 case eNodeClear: {
2224 XMLClear *pChild = pEntry->pClear + (j >> 2);
2225 // "OpenTag"
2226 cb = (int)LENSTR(pChild->lpszOpenTag);
2227 if (cb) {
2228 if (nFormat != -1) {
2229 if (lpszMarker) {
2230 charmemset(&lpszMarker[nResult], INDENTCHAR,
2231 nFormat + 1);
2232 xstrcpy(&lpszMarker[nResult+nFormat+1],
2233 pChild->lpszOpenTag);
1984 }
2234 }
1985 else
1986 {
1987 if (lpszMarker)xstrcpy(&lpszMarker[nResult], pChild->lpszOpenTag);
1988 nResult += cb;
2235 nResult += cb + nFormat + 1;
2236 } else {
2237 if (lpszMarker) {
2238 xstrcpy(&lpszMarker[nResult], pChild->lpszOpenTag);
1989 }
2239 }
1990 }
1991
1992 // "OpenTag Value"
1993 cb = (int)LENSTR(pChild->lpszValue);
1994 if (cb)
1995 {
1996 if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszValue);
1997 nResult += cb;
1998 }
2240 nResult += cb;
2241 }
2242 }
1999
2243
2000 // "OpenTag Value CloseTag"
2001 cb = (int)LENSTR(pChild->lpszCloseTag);
2002 if (cb)
2003 {
2004 if (lpszMarker) xstrcpy(&lpszMarker[nResult], pChild->lpszCloseTag);
2005 nResult += cb;
2244 // "OpenTag Value"
2245 cb = (int)LENSTR(pChild->lpszValue);
2246 if (cb) {
2247 if (lpszMarker) {
2248 xstrcpy(&lpszMarker[nResult], pChild->lpszValue);
2006 }
2249 }
2250 nResult += cb;
2251 }
2007
2252
2008 if (nFormat!=-1)
2009 {
2010 if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
2011 nResult++;
2253 // "OpenTag Value CloseTag"
2254 cb = (int)LENSTR(pChild->lpszCloseTag);
2255 if (cb) {
2256 if (lpszMarker) {
2257 xstrcpy(&lpszMarker[nResult], pChild->lpszCloseTag);
2012 }
2258 }
2013 break;
2259 nResult += cb;
2014 }
2015
2260 }
2261
2016 // Element nodes
2017 case eNodeChild:
2018 {
2019 // Recursively add child nodes
2020 nResult += CreateXMLStringR(pEntry->pChild[j>>2].d, lpszMarker ? lpszMarker + nResult : 0, nChildFormat);
2021 break;
2262 if (nFormat != -1) {
2263 if (lpszMarker) lpszMarker[nResult] = _CXML('\n');
2264 nResult++;
2022 }
2265 }
2023 default: break;
2266 break;
2024 }
2267 }
2268
2269 // Element nodes
2270 case eNodeChild: {
2271 // Recursively add child nodes
2272 nResult += CreateXMLStringR(pEntry->pChild[j>>2].d,
2273 lpszMarker ? lpszMarker + nResult : 0,
2274 nChildFormat);
2275 break;
2276 }
2277 default:
2278 break;
2279 }
2025 }
2026
2280 }
2281
2027 if ((cbElement)&&(!pEntry->isDeclaration))
2028 {
2282 if ((cbElement) && (!pEntry->isDeclaration)) {
2029 // If we have child entries we need to use long XML notation for
2030 // closing the element - "<elementname>blah blah blah</elementname>"
2283 // If we have child entries we need to use long XML notation for
2284 // closing the element - "<elementname>blah blah blah</elementname>"
2031 if (nElementI)
2032 {
2285 if (nElementI) {
2033 // "</elementname>\0"
2286 // "</elementname>\0"
2034 if (lpszMarker)
2035 {
2036 if (nFormat >=0)
2037 {
2038 charmemset(&lpszMarker[nResult], INDENTCHAR,nFormat);
2039 nResult+=nFormat;
2287 if (lpszMarker) {
2288 if (nFormat >= 0) {
2289 charmemset(&lpszMarker[nResult], INDENTCHAR, nFormat);
2290 nResult += nFormat;
2040 }
2041
2291 }
2292
2042 lpszMarker[nResult]=_CXML('<'); lpszMarker[nResult+1]=_CXML('/');
2293 lpszMarker[nResult] = _CXML('<');
2294 lpszMarker[nResult+1] = _CXML('/');
2043 nResult += 2;
2044 xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
2045 nResult += cbElement;
2046
2295 nResult += 2;
2296 xstrcpy(&lpszMarker[nResult], pEntry->lpszName);
2297 nResult += cbElement;
2298
2047 lpszMarker[nResult]=_CXML('>');
2299 lpszMarker[nResult] = _CXML('>');
2048 if (nFormat == -1) nResult++;
2300 if (nFormat == -1) nResult++;
2049 else
2050 {
2051 lpszMarker[nResult+1]=_CXML('\n');
2052 nResult+=2;
2301 else {
2302 lpszMarker[nResult+1] = _CXML('\n');
2303 nResult += 2;
2053 }
2304 }
2054 } else
2055 {
2056 if (nFormat>=0) nResult+=cbElement+4+nFormat;
2057 else if (nFormat==-1) nResult+=cbElement+3;
2058 else nResult+=cbElement+4;
2305 } else {
2306 if (nFormat >= 0) nResult += cbElement + 4 + nFormat;
2307 else if (nFormat == -1) nResult += cbElement + 3;
2308 else nResult += cbElement + 4;
2059 }
2309 }
2060 } else
2061 {
2310 } else {
2062 // If there are no children we can use shorthand XML notation -
2063 // "<elementname/>"
2064 // "/>\0"
2311 // If there are no children we can use shorthand XML notation -
2312 // "<elementname/>"
2313 // "/>\0"
2065 if (lpszMarker)
2066 {
2067 lpszMarker[nResult]=_CXML('/'); lpszMarker[nResult+1]=_CXML('>');
2068 if (nFormat != -1) lpszMarker[nResult+2]=_CXML('\n');
2314 if (lpszMarker) {
2315 lpszMarker[nResult] = _CXML('/');
2316 lpszMarker[nResult+1] = _CXML('>');
2317 if (nFormat != -1) lpszMarker[nResult+2] = _CXML('\n');
2069 }
2070 nResult += nFormat == -1 ? 2 : 3;
2071 }
2072 }
2073
2074 return nResult;
2075}
2076
2077#undef LENSTR
2078
2079// Create an XML string
2080// @param int nFormat - 0 if no formatting is required
2081// otherwise nonzero for formatted text
2082// with carriage returns and indentation.
2083// @param int *pnSize - [out] pointer to the size of the
2084// returned string not including the
2085// NULL terminator.
2086// @return XMLSTR - Allocated XML string, you must free
2087// this with free().
2318 }
2319 nResult += nFormat == -1 ? 2 : 3;
2320 }
2321 }
2322
2323 return nResult;
2324}
2325
2326#undef LENSTR
2327
2328// Create an XML string
2329// @param int nFormat - 0 if no formatting is required
2330// otherwise nonzero for formatted text
2331// with carriage returns and indentation.
2332// @param int *pnSize - [out] pointer to the size of the
2333// returned string not including the
2334// NULL terminator.
2335// @return XMLSTR - Allocated XML string, you must free
2336// this with free().
2088XMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const
2089{
2090 if (!d) { if (pnSize) *pnSize=0; return NULL; }
2337XMLSTR XMLNode::createXMLString(int nFormat, int *pnSize) const {
2338 if (!d) {
2339 if (pnSize) *pnSize = 0;
2340 return NULL;
2341 }
2091
2092 XMLSTR lpszResult = NULL;
2093 int cbStr;
2094
2095 // Recursively Calculate the size of the XML string
2342
2343 XMLSTR lpszResult = NULL;
2344 int cbStr;
2345
2346 // Recursively Calculate the size of the XML string
2096 if (!dropWhiteSpace) nFormat=0;
2347 if (!dropWhiteSpace) nFormat = 0;
2097 nFormat = nFormat ? 0 : -1;
2098 cbStr = CreateXMLStringR(d, 0, nFormat);
2099 // Alllocate memory for the XML string + the NULL terminator and
2100 // create the recursively XML string.
2348 nFormat = nFormat ? 0 : -1;
2349 cbStr = CreateXMLStringR(d, 0, nFormat);
2350 // Alllocate memory for the XML string + the NULL terminator and
2351 // create the recursively XML string.
2101 lpszResult=(XMLSTR)malloc((cbStr+1)*sizeof(XMLCHAR));
2352 lpszResult = (XMLSTR)malloc((cbStr + 1) * sizeof(XMLCHAR));
2102 CreateXMLStringR(d, lpszResult, nFormat);
2353 CreateXMLStringR(d, lpszResult, nFormat);
2103 lpszResult[cbStr]=_CXML('\0');
2354 lpszResult[cbStr] = _CXML('\0');
2104 if (pnSize) *pnSize = cbStr;
2105 return lpszResult;
2106}
2107
2355 if (pnSize) *pnSize = cbStr;
2356 return lpszResult;
2357}
2358
2108int XMLNode::detachFromParent(XMLNodeData *d)
2109{
2110 XMLNode *pa=d->pParent->pChild;
2111 int i=0;
2112 while (((void*)(pa[i].d))!=((void*)d)) i++;
2359int XMLNode::detachFromParent(XMLNodeData *d) {
2360 XMLNode *pa = d->pParent->pChild;
2361 int i = 0;
2362 while (((void*)(pa[i].d)) != ((void*)d)) i++;
2113 d->pParent->nChild--;
2363 d->pParent->nChild--;
2114 if (d->pParent->nChild) memmove(pa+i,pa+i+1,(d->pParent->nChild-i)*sizeof(XMLNode));
2115 else { free(pa); d->pParent->pChild=NULL; }
2116 return removeOrderElement(d->pParent,eNodeChild,i);
2364 if (d->pParent->nChild) {
2365 memmove(pa + i, pa + i + 1, (d->pParent->nChild - i)*sizeof(XMLNode));
2366 } else {
2367 free(pa);
2368 d->pParent->pChild = NULL;
2369 }
2370 return removeOrderElement(d->pParent, eNodeChild, i);
2117}
2118
2371}
2372
2119XMLNode::~XMLNode()
2120{
2373XMLNode::~XMLNode() {
2121 if (!d) return;
2122 d->ref_count--;
2123 emptyTheNode(0);
2124}
2374 if (!d) return;
2375 d->ref_count--;
2376 emptyTheNode(0);
2377}
2125void XMLNode::deleteNodeContent()
2126{
2378void XMLNode::deleteNodeContent() {
2127 if (!d) return;
2379 if (!d) return;
2128 if (d->pParent) { detachFromParent(d); d->pParent=NULL; d->ref_count--; }
2380 if (d->pParent) {
2381 detachFromParent(d);
2382 d->pParent = NULL;
2383 d->ref_count--;
2384 }
2129 emptyTheNode(1);
2130}
2385 emptyTheNode(1);
2386}
2131void XMLNode::emptyTheNode(char force)
2132{
2133 XMLNodeData *dd=d; // warning: must stay this way!
2134 if ((dd->ref_count==0)||force)
2135 {
2387void XMLNode::emptyTheNode(char force) {
2388 XMLNodeData *dd = d; // warning: must stay this way!
2389 if ((dd->ref_count == 0) || force) {
2136 if (d->pParent) detachFromParent(d);
2137 int i;
2138 XMLNode *pc;
2390 if (d->pParent) detachFromParent(d);
2391 int i;
2392 XMLNode *pc;
2139 for(i=0; i<dd->nChild; i++)
2140 {
2141 pc=dd->pChild+i;
2142 pc->d->pParent=NULL;
2393 for (i = 0; i < dd->nChild; i++) {
2394 pc = dd->pChild + i;
2395 pc->d->pParent = NULL;
2143 pc->d->ref_count--;
2144 pc->emptyTheNode(force);
2145 }
2146 myFree(dd->pChild);
2396 pc->d->ref_count--;
2397 pc->emptyTheNode(force);
2398 }
2399 myFree(dd->pChild);
2147 for(i=0; i<dd->nText; i++) free((void*)dd->pText[i]);
2400 for (i = 0; i < dd->nText; i++) free((void*)dd->pText[i]);
2148 myFree(dd->pText);
2401 myFree(dd->pText);
2149 for(i=0; i<dd->nClear; i++) free((void*)dd->pClear[i].lpszValue);
2402 for (i = 0; i < dd->nClear; i++) free((void*)dd->pClear[i].lpszValue);
2150 myFree(dd->pClear);
2403 myFree(dd->pClear);
2151 for(i=0; i<dd->nAttribute; i++)
2152 {
2404 for (i = 0; i < dd->nAttribute; i++) {
2153 free((void*)dd->pAttribute[i].lpszName);
2405 free((void*)dd->pAttribute[i].lpszName);
2154 if (dd->pAttribute[i].lpszValue) free((void*)dd->pAttribute[i].lpszValue);
2406 if (dd->pAttribute[i].lpszValue) {
2407 free((void*)dd->pAttribute[i].lpszValue);
2408 }
2155 }
2156 myFree(dd->pAttribute);
2157 myFree(dd->pOrder);
2158 myFree((void*)dd->lpszName);
2409 }
2410 myFree(dd->pAttribute);
2411 myFree(dd->pOrder);
2412 myFree((void*)dd->lpszName);
2159 dd->nChild=0; dd->nText=0; dd->nClear=0; dd->nAttribute=0;
2160 dd->pChild=NULL; dd->pText=NULL; dd->pClear=NULL; dd->pAttribute=NULL;
2161 dd->pOrder=NULL; dd->lpszName=NULL; dd->pParent=NULL;
2413 dd->nChild = 0;
2414 dd->nText = 0;
2415 dd->nClear = 0;
2416 dd->nAttribute = 0;
2417 dd->pChild = NULL;
2418 dd->pText = NULL;
2419 dd->pClear = NULL;
2420 dd->pAttribute = NULL;
2421 dd->pOrder = NULL;
2422 dd->lpszName = NULL;
2423 dd->pParent = NULL;
2162 }
2424 }
2163 if (dd->ref_count==0)
2164 {
2425 if (dd->ref_count == 0) {
2165 free(dd);
2426 free(dd);
2166 d=NULL;
2427 d = NULL;
2167 }
2168}
2169
2428 }
2429}
2430
2170XMLNode& XMLNode::operator=( const XMLNode& A )
2171{
2431XMLNode& XMLNode::operator=( const XMLNode & A ) {
2172 // shallow copy
2432 // shallow copy
2173 if (this != &A)
2174 {
2175 if (d) { d->ref_count--; emptyTheNode(0); }
2176 d=A.d;
2433 if (this != &A) {
2434 if (d) {
2435 d->ref_count--;
2436 emptyTheNode(0);
2437 }
2438 d = A.d;
2177 if (d) (d->ref_count) ++ ;
2178 }
2179 return *this;
2180}
2181
2439 if (d) (d->ref_count) ++ ;
2440 }
2441 return *this;
2442}
2443
2182XMLNode::XMLNode(const XMLNode &A)
2183{
2444XMLNode::XMLNode(const XMLNode &A) {
2184 // shallow copy
2445 // shallow copy
2185 d=A.d;
2446 d = A.d;
2186 if (d) (d->ref_count)++ ;
2187}
2188
2447 if (d) (d->ref_count)++ ;
2448}
2449
2189XMLNode XMLNode::deepCopy() const
2190{
2450XMLNode XMLNode::deepCopy() const {
2191 if (!d) return XMLNode::emptyXMLNode;
2451 if (!d) return XMLNode::emptyXMLNode;
2192 XMLNode x(NULL,stringDup(d->lpszName),d->isDeclaration);
2193 XMLNodeData *p=x.d;
2194 int n=d->nAttribute;
2195 if (n)
2196 {
2197 p->nAttribute=n; p->pAttribute=(XMLAttribute*)malloc(n*sizeof(XMLAttribute));
2198 while (n--)
2199 {
2200 p->pAttribute[n].lpszName=stringDup(d->pAttribute[n].lpszName);
2201 p->pAttribute[n].lpszValue=stringDup(d->pAttribute[n].lpszValue);
2452 XMLNode x(NULL, stringDup(d->lpszName), d->isDeclaration);
2453 XMLNodeData *p = x.d;
2454 int n = d->nAttribute;
2455 if (n) {
2456 p->nAttribute = n;
2457 p->pAttribute = (XMLAttribute*)malloc(n * sizeof(XMLAttribute));
2458 while (n--) {
2459 p->pAttribute[n].lpszName = stringDup(d->pAttribute[n].lpszName);
2460 p->pAttribute[n].lpszValue = stringDup(d->pAttribute[n].lpszValue);
2202 }
2203 }
2461 }
2462 }
2204 if (d->pOrder)
2205 {
2206 n=(d->nChild+d->nText+d->nClear)*sizeof(int); p->pOrder=(int*)malloc(n); memcpy(p->pOrder,d->pOrder,n);
2463 if (d->pOrder) {
2464 n = (d->nChild + d->nText + d->nClear) * sizeof(int);
2465 p->pOrder = (int*)malloc(n);
2466 memcpy(p->pOrder, d->pOrder, n);
2207 }
2467 }
2208 n=d->nText;
2209 if (n)
2210 {
2211 p->nText=n; p->pText=(XMLCSTR*)malloc(n*sizeof(XMLCSTR));
2212 while(n--) p->pText[n]=stringDup(d->pText[n]);
2468 n = d->nText;
2469 if (n) {
2470 p->nText = n;
2471 p->pText = (XMLCSTR*)malloc(n * sizeof(XMLCSTR));
2472 while (n--) p->pText[n] = stringDup(d->pText[n]);
2213 }
2473 }
2214 n=d->nClear;
2215 if (n)
2216 {
2217 p->nClear=n; p->pClear=(XMLClear*)malloc(n*sizeof(XMLClear));
2218 while (n--)
2219 {
2220 p->pClear[n].lpszCloseTag=d->pClear[n].lpszCloseTag;
2221 p->pClear[n].lpszOpenTag=d->pClear[n].lpszOpenTag;
2222 p->pClear[n].lpszValue=stringDup(d->pClear[n].lpszValue);
2474 n = d->nClear;
2475 if (n) {
2476 p->nClear = n;
2477 p->pClear = (XMLClear*)malloc(n * sizeof(XMLClear));
2478 while (n--) {
2479 p->pClear[n].lpszCloseTag = d->pClear[n].lpszCloseTag;
2480 p->pClear[n].lpszOpenTag = d->pClear[n].lpszOpenTag;
2481 p->pClear[n].lpszValue = stringDup(d->pClear[n].lpszValue);
2223 }
2224 }
2482 }
2483 }
2225 n=d->nChild;
2226 if (n)
2227 {
2228 p->nChild=n; p->pChild=(XMLNode*)malloc(n*sizeof(XMLNode));
2229 while (n--)
2230 {
2231 p->pChild[n].d=NULL;
2232 p->pChild[n]=d->pChild[n].deepCopy();
2233 p->pChild[n].d->pParent=p;
2484 n = d->nChild;
2485 if (n) {
2486 p->nChild = n;
2487 p->pChild = (XMLNode*)malloc(n * sizeof(XMLNode));
2488 while (n--) {
2489 p->pChild[n].d = NULL;
2490 p->pChild[n] = d->pChild[n].deepCopy();
2491 p->pChild[n].d->pParent = p;
2234 }
2235 }
2236 return x;
2237}
2238
2492 }
2493 }
2494 return x;
2495}
2496
2239XMLNode XMLNode::addChild(XMLNode childNode, int pos)
2240{
2241 XMLNodeData *dc=childNode.d;
2242 if ((!dc)||(!d)) return childNode;
2243 if (!dc->lpszName)
2244 {
2497XMLNode XMLNode::addChild(XMLNode childNode, int pos) {
2498 XMLNodeData *dc = childNode.d;
2499 if ((!dc) || (!d)) return childNode;
2500 if (!dc->lpszName) {
2245 // this is a root node: todo: correct fix
2501 // this is a root node: todo: correct fix
2246 int j=pos;
2247 while (dc->nChild)
2248 {
2249 addChild(dc->pChild[0],j);
2250 if (pos>=0) j++;
2502 int j = pos;
2503 while (dc->nChild) {
2504 addChild(dc->pChild[0], j);
2505 if (pos >= 0) j++;
2251 }
2252 return childNode;
2253 }
2506 }
2507 return childNode;
2508 }
2254 if (dc->pParent) { if ((detachFromParent(dc)<=pos)&&(dc->pParent==d)) pos--; } else dc->ref_count++;
2255 dc->pParent=d;
2509 if (dc->pParent) {
2510 if ((detachFromParent(dc) <= pos) && (dc->pParent == d)) pos--;
2511 } else dc->ref_count++;
2512 dc->pParent = d;
2256// int nc=d->nChild;
2257// d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
2513// int nc=d->nChild;
2514// d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode));
2258 d->pChild=(XMLNode*)addToOrder(0,&pos,d->nChild,d->pChild,sizeof(XMLNode),eNodeChild);
2259 d->pChild[pos].d=dc;
2515 d->pChild = (XMLNode*)addToOrder(0, &pos, d->nChild, d->pChild,
2516 sizeof(XMLNode), eNodeChild);
2517 d->pChild[pos].d = dc;
2260 d->nChild++;
2261 return childNode;
2262}
2263
2518 d->nChild++;
2519 return childNode;
2520}
2521
2264void XMLNode::deleteAttribute(int i)
2265{
2266 if ((!d)||(i<0)||(i>=d->nAttribute)) return;
2522void XMLNode::deleteAttribute(int i) {
2523 if ((!d) || (i < 0) || (i >= d->nAttribute)) return;
2267 d->nAttribute--;
2524 d->nAttribute--;
2268 XMLAttribute *p=d->pAttribute+i;
2525 XMLAttribute *p = d->pAttribute + i;
2269 free((void*)p->lpszName);
2270 if (p->lpszValue) free((void*)p->lpszValue);
2526 free((void*)p->lpszName);
2527 if (p->lpszValue) free((void*)p->lpszValue);
2271 if (d->nAttribute) memmove(p,p+1,(d->nAttribute-i)*sizeof(XMLAttribute)); else { free(p); d->pAttribute=NULL; }
2528 if (d->nAttribute) {
2529 memmove(p, p + 1, (d->nAttribute - i)*sizeof(XMLAttribute));
2530 }
2531 else {
2532 free(p);
2533 d->pAttribute = NULL;
2534 }
2272}
2273
2535}
2536
2274void XMLNode::deleteAttribute(XMLAttribute *a){ if (a) deleteAttribute(a->lpszName); }
2275void XMLNode::deleteAttribute(XMLCSTR lpszName)
2276{
2277 int j=0;
2278 getAttribute(lpszName,&j);
2279 if (j) deleteAttribute(j-1);
2537void XMLNode::deleteAttribute(XMLAttribute *a) {
2538 if (a) deleteAttribute(a->lpszName);
2280}
2539}
2540void XMLNode::deleteAttribute(XMLCSTR lpszName) {
2541 int j = 0;
2542 getAttribute(lpszName, &j);
2543 if (j) deleteAttribute(j - 1);
2544}
2281
2545
2282XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,int i)
2283{
2284 if (!d) { if (lpszNewValue) free(lpszNewValue); if (lpszNewName) free(lpszNewName); return NULL; }
2285 if (i>=d->nAttribute)
2286 {
2287 if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
2546XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue,
2547 XMLSTR lpszNewName, int i) {
2548 if (!d) {
2549 if (lpszNewValue) free(lpszNewValue);
2550 if (lpszNewName) free(lpszNewName);
2288 return NULL;
2289 }
2551 return NULL;
2552 }
2290 XMLAttribute *p=d->pAttribute+i;
2291 if (p->lpszValue&&p->lpszValue!=lpszNewValue) free((void*)p->lpszValue);
2292 p->lpszValue=lpszNewValue;
2293 if (lpszNewName&&p->lpszName!=lpszNewName) { free((void*)p->lpszName); p->lpszName=lpszNewName; };
2553 if (i >= d->nAttribute) {
2554 if (lpszNewName) return addAttribute_WOSD(lpszNewName, lpszNewValue);
2555 return NULL;
2556 }
2557 XMLAttribute *p = d->pAttribute + i;
2558 if (p->lpszValue && p->lpszValue != lpszNewValue) {
2559 free((void*)p->lpszValue);
2560 }
2561 p->lpszValue = lpszNewValue;
2562 if (lpszNewName && p->lpszName != lpszNewName) {
2563 free((void*)p->lpszName);
2564 p->lpszName = lpszNewName;
2565 };
2294 return p;
2295}
2296
2566 return p;
2567}
2568
2297XMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
2298{
2299 if (oldAttribute) return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,(XMLSTR)newAttribute->lpszName,oldAttribute->lpszName);
2300 return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,(XMLSTR)newAttribute->lpszValue);
2569XMLAttribute *XMLNode::updateAttribute_WOSD(XMLAttribute *newAttribute,
2570 XMLAttribute *oldAttribute) {
2571 if (oldAttribute) {
2572 return updateAttribute_WOSD((XMLSTR)newAttribute->lpszValue,
2573 (XMLSTR)newAttribute->lpszName,
2574 oldAttribute->lpszName);
2575 }
2576 return addAttribute_WOSD((XMLSTR)newAttribute->lpszName,
2577 (XMLSTR)newAttribute->lpszValue);
2301}
2302
2578}
2579
2303XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue, XMLSTR lpszNewName,XMLCSTR lpszOldName)
2304{
2305 int j=0;
2306 getAttribute(lpszOldName,&j);
2307 if (j) return updateAttribute_WOSD(lpszNewValue,lpszNewName,j-1);
2308 else
2309 {
2310 if (lpszNewName) return addAttribute_WOSD(lpszNewName,lpszNewValue);
2311 else return addAttribute_WOSD(stringDup(lpszOldName),lpszNewValue);
2580XMLAttribute *XMLNode::updateAttribute_WOSD(XMLSTR lpszNewValue,
2581 XMLSTR lpszNewName,
2582 XMLCSTR lpszOldName) {
2583 int j = 0;
2584 getAttribute(lpszOldName, &j);
2585 if (j) return updateAttribute_WOSD(lpszNewValue, lpszNewName, j - 1);
2586 else {
2587 if (lpszNewName) {
2588 return addAttribute_WOSD(lpszNewName, lpszNewValue);
2589 } else {
2590 return addAttribute_WOSD(stringDup(lpszOldName), lpszNewValue);
2591 }
2312 }
2313}
2314
2592 }
2593}
2594
2315int XMLNode::indexText(XMLCSTR lpszValue) const
2316{
2595int XMLNode::indexText(XMLCSTR lpszValue) const {
2317 if (!d) return -1;
2596 if (!d) return -1;
2318 int i,l=d->nText;
2319 if (!lpszValue) { if (l) return 0; return -1; }
2320 XMLCSTR *p=d->pText;
2321 for (i=0; i<l; i++) if (lpszValue==p[i]) return i;
2597 int i, l = d->nText;
2598 if (!lpszValue) {
2599 if (l) return 0;
2600 return -1;
2601 }
2602 XMLCSTR *p = d->pText;
2603 for (i = 0; i < l; i++) if (lpszValue == p[i]) return i;
2322 return -1;
2323}
2324
2604 return -1;
2605}
2606
2325void XMLNode::deleteText(int i)
2326{
2327 if ((!d)||(i<0)||(i>=d->nText)) return;
2607void XMLNode::deleteText(int i) {
2608 if ((!d) || (i < 0) || (i >= d->nText)) return;
2328 d->nText--;
2609 d->nText--;
2329 XMLCSTR *p=d->pText+i;
2610 XMLCSTR *p = d->pText + i;
2330 free((void*)*p);
2611 free((void*)*p);
2331 if (d->nText) memmove(p,p+1,(d->nText-i)*sizeof(XMLCSTR)); else { free(p); d->pText=NULL; }
2332 removeOrderElement(d,eNodeText,i);
2612 if (d->nText) memmove(p, p + 1, (d->nText - i)*sizeof(XMLCSTR));
2613 else {
2614 free(p);
2615 d->pText = NULL;
2616 }
2617 removeOrderElement(d, eNodeText, i);
2333}
2334
2618}
2619
2335void XMLNode::deleteText(XMLCSTR lpszValue) { deleteText(indexText(lpszValue)); }
2620void XMLNode::deleteText(XMLCSTR lpszValue) {
2621 deleteText(indexText(lpszValue));
2622}
2336
2623
2337XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i)
2338{
2339 if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
2340 if (i>=d->nText) return addText_WOSD(lpszNewValue);
2341 XMLCSTR *p=d->pText+i;
2342 if (*p!=lpszNewValue) { free((void*)*p); *p=lpszNewValue; }
2624XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, int i) {
2625 if (!d) {
2626 if (lpszNewValue) free(lpszNewValue);
2627 return NULL;
2628 }
2629 if (i >= d->nText) return addText_WOSD(lpszNewValue);
2630 XMLCSTR *p = d->pText + i;
2631 if (*p != lpszNewValue) {
2632 free((void*)*p);
2633 *p = lpszNewValue;
2634 }
2343 return lpszNewValue;
2344}
2345
2635 return lpszNewValue;
2636}
2637
2346XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue)
2347{
2348 if (!d) { if (lpszNewValue) free(lpszNewValue); return NULL; }
2349 int i=indexText(lpszOldValue);
2350 if (i>=0) return updateText_WOSD(lpszNewValue,i);
2638XMLCSTR XMLNode::updateText_WOSD(XMLSTR lpszNewValue, XMLCSTR lpszOldValue) {
2639 if (!d) {
2640 if (lpszNewValue) free(lpszNewValue);
2641 return NULL;
2642 }
2643 int i = indexText(lpszOldValue);
2644 if (i >= 0) return updateText_WOSD(lpszNewValue, i);
2351 return addText_WOSD(lpszNewValue);
2352}
2353
2645 return addText_WOSD(lpszNewValue);
2646}
2647
2354void XMLNode::deleteClear(int i)
2355{
2356 if ((!d)||(i<0)||(i>=d->nClear)) return;
2648void XMLNode::deleteClear(int i) {
2649 if ((!d) || (i < 0) || (i >= d->nClear)) return;
2357 d->nClear--;
2650 d->nClear--;
2358 XMLClear *p=d->pClear+i;
2651 XMLClear *p = d->pClear + i;
2359 free((void*)p->lpszValue);
2652 free((void*)p->lpszValue);
2360 if (d->nClear) memmove(p,p+1,(d->nClear-i)*sizeof(XMLClear)); else { free(p); d->pClear=NULL; }
2361 removeOrderElement(d,eNodeClear,i);
2653 if (d->nClear) memmove(p, p + 1, (d->nClear - i)*sizeof(XMLClear));
2654 else {
2655 free(p);
2656 d->pClear = NULL;
2657 }
2658 removeOrderElement(d, eNodeClear, i);
2362}
2363
2659}
2660
2364int XMLNode::indexClear(XMLCSTR lpszValue) const
2365{
2661int XMLNode::indexClear(XMLCSTR lpszValue) const {
2366 if (!d) return -1;
2662 if (!d) return -1;
2367 int i,l=d->nClear;
2368 if (!lpszValue) { if (l) return 0; return -1; }
2369 XMLClear *p=d->pClear;
2370 for (i=0; i<l; i++) if (lpszValue==p[i].lpszValue) return i;
2663 int i, l = d->nClear;
2664 if (!lpszValue) {
2665 if (l) return 0;
2666 return -1;
2667 }
2668 XMLClear *p = d->pClear;
2669 for (i = 0; i < l; i++) if (lpszValue == p[i].lpszValue) return i;
2371 return -1;
2372}
2373
2670 return -1;
2671}
2672
2374void XMLNode::deleteClear(XMLCSTR lpszValue) { deleteClear(indexClear(lpszValue)); }
2375void XMLNode::deleteClear(XMLClear *a) { if (a) deleteClear(a->lpszValue); }
2673void XMLNode::deleteClear(XMLCSTR lpszValue) {
2674 deleteClear(indexClear(lpszValue));
2675}
2676void XMLNode::deleteClear(XMLClear *a) {
2677 if (a) deleteClear(a->lpszValue);
2678}
2376
2679
2377XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i)
2378{
2379 if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
2380 if (i>=d->nClear) return addClear_WOSD(lpszNewContent);
2381 XMLClear *p=d->pClear+i;
2382 if (lpszNewContent!=p->lpszValue) { free((void*)p->lpszValue); p->lpszValue=lpszNewContent; }
2680XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, int i) {
2681 if (!d) {
2682 if (lpszNewContent) free(lpszNewContent);
2683 return NULL;
2684 }
2685 if (i >= d->nClear) return addClear_WOSD(lpszNewContent);
2686 XMLClear *p = d->pClear + i;
2687 if (lpszNewContent != p->lpszValue) {
2688 free((void*)p->lpszValue);
2689 p->lpszValue = lpszNewContent;
2690 }
2383 return p;
2384}
2385
2691 return p;
2692}
2693
2386XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent, XMLCSTR lpszOldValue)
2387{
2388 if (!d) { if (lpszNewContent) free(lpszNewContent); return NULL; }
2389 int i=indexClear(lpszOldValue);
2390 if (i>=0) return updateClear_WOSD(lpszNewContent,i);
2694XMLClear *XMLNode::updateClear_WOSD(XMLSTR lpszNewContent,
2695 XMLCSTR lpszOldValue) {
2696 if (!d) {
2697 if (lpszNewContent) free(lpszNewContent);
2698 return NULL;
2699 }
2700 int i = indexClear(lpszOldValue);
2701 if (i >= 0) return updateClear_WOSD(lpszNewContent, i);
2391 return addClear_WOSD(lpszNewContent);
2392}
2393
2702 return addClear_WOSD(lpszNewContent);
2703}
2704
2394XMLClear *XMLNode::updateClear_WOSD(XMLClear *newP,XMLClear *oldP)
2395{
2396 if (oldP) return updateClear_WOSD((XMLSTR)newP->lpszValue,(XMLSTR)oldP->lpszValue);
2705XMLClear *XMLNode::updateClear_WOSD(XMLClear *newP, XMLClear *oldP) {
2706 if (oldP) {
2707 return updateClear_WOSD((XMLSTR)newP->lpszValue,
2708 (XMLSTR)oldP->lpszValue);
2709 }
2397 return NULL;
2398}
2399
2710 return NULL;
2711}
2712
2400int XMLNode::nChildNode(XMLCSTR name) const
2401{
2713int XMLNode::nChildNode(XMLCSTR name) const {
2402 if (!d) return 0;
2714 if (!d) return 0;
2403 int i,j=0,n=d->nChild;
2404 XMLNode *pc=d->pChild;
2405 for (i=0; i<n; i++)
2406 {
2407 if (xstricmp(pc->d->lpszName, name)==0) j++;
2715 int i, j = 0, n = d->nChild;
2716 XMLNode *pc = d->pChild;
2717 for (i = 0; i < n; i++) {
2718 if (xstricmp(pc->d->lpszName, name) == 0) j++;
2408 pc++;
2409 }
2410 return j;
2411}
2412
2719 pc++;
2720 }
2721 return j;
2722}
2723
2413XMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const
2414{
2724XMLNode XMLNode::getChildNode(XMLCSTR name, int *j) const {
2415 if (!d) return emptyXMLNode;
2725 if (!d) return emptyXMLNode;
2416 int i=0,n=d->nChild;
2417 if (j) i=*j;
2418 XMLNode *pc=d->pChild+i;
2419 for (; i<n; i++)
2420 {
2421 if (!xstricmp(pc->d->lpszName, name))
2422 {
2423 if (j) *j=i+1;
2726 int i = 0, n = d->nChild;
2727 if (j) i = *j;
2728 XMLNode *pc = d->pChild + i;
2729 for (; i < n; i++) {
2730 if (!xstricmp(pc->d->lpszName, name)) {
2731 if (j) *j = i + 1;
2424 return *pc;
2425 }
2426 pc++;
2427 }
2428 return emptyXMLNode;
2429}
2430
2732 return *pc;
2733 }
2734 pc++;
2735 }
2736 return emptyXMLNode;
2737}
2738
2431XMLNode XMLNode::getChildNode(XMLCSTR name, int j) const
2432{
2739XMLNode XMLNode::getChildNode(XMLCSTR name, int j) const {
2433 if (!d) return emptyXMLNode;
2740 if (!d) return emptyXMLNode;
2434 if (j>=0)
2435 {
2436 int i=0;
2437 while (j-->0) getChildNode(name,&i);
2438 return getChildNode(name,&i);
2741 if (j >= 0) {
2742 int i = 0;
2743 while (j-- > 0) getChildNode(name, &i);
2744 return getChildNode(name, &i);
2439 }
2745 }
2440 int i=d->nChild;
2441 while (i--) if (!xstricmp(name,d->pChild[i].d->lpszName)) break;
2442 if (i<0) return emptyXMLNode;
2746 int i = d->nChild;
2747 while (i--) if (!xstricmp(name, d->pChild[i].d->lpszName)) break;
2748 if (i < 0) return emptyXMLNode;
2443 return getChildNode(i);
2444}
2445
2749 return getChildNode(i);
2750}
2751
2446XMLNode XMLNode::getChildNodeByPath(XMLCSTR _path, char createMissing, XMLCHAR sep)
2447{
2448 XMLSTR path=stringDup(_path);
2449 XMLNode x=getChildNodeByPathNonConst(path,createMissing,sep);
2752XMLNode* XMLNode::getChildNodePtr(XMLCSTR name, int *j) const {
2753 if (!d) return &emptyXMLNode;
2754 int i = 0, n = d->nChild;
2755 int foundIndex = 0;
2756 XMLNode *pc = d->pChild + i;
2757 for (; i < n; i++) {
2758 if (!xstricmp(pc->d->lpszName, name)) {
2759 if (*j == foundIndex) return pc;
2760 foundIndex++;
2761 }
2762 pc++;
2763 }
2764 return &emptyXMLNode;
2765}
2766
2767XMLNode XMLNode::getChildNodeByPath(XMLCSTR _path, char createMissing,
2768 XMLCHAR sep) {
2769 XMLSTR path = stringDup(_path);
2770 XMLNode x = getChildNodeByPathNonConst(path, createMissing, sep);
2450 if (path) free(path);
2451 return x;
2452}
2453
2771 if (path) free(path);
2772 return x;
2773}
2774
2454XMLNode XMLNode::getChildNodeByPathNonConst(XMLSTR path, char createIfMissing, XMLCHAR sep)
2455{
2456 if ((!path)||(!(*path))) return *this;
2457 XMLNode xn,xbase=*this;
2458 XMLCHAR *tend1,sepString[2]; sepString[0]=sep; sepString[1]=0;
2459 tend1=xstrstr(path,sepString);
2460 while(tend1)
2461 {
2462 *tend1=0;
2463 xn=xbase.getChildNode(path);
2464 if (xn.isEmpty())
2465 {
2466 if (createIfMissing) xn=xbase.addChild(path);
2467 else { *tend1=sep; return XMLNode::emptyXMLNode; }
2775XMLNode XMLNode::getChildNodeByPathNonConst(XMLSTR path,
2776 char createIfMissing, XMLCHAR sep) {
2777 if ((!path) || (!(*path))) return *this;
2778 XMLNode xn, xbase = *this;
2779 XMLCHAR *tend1, sepString[2];
2780 sepString[0] = sep;
2781 sepString[1] = 0;
2782 tend1 = xstrstr(path, sepString);
2783 while (tend1) {
2784 *tend1 = 0;
2785 xn = xbase.getChildNode(path);
2786 if (xn.isEmpty()) {
2787 if (createIfMissing) xn = xbase.addChild(path);
2788 else {
2789 *tend1 = sep;
2790 return XMLNode::emptyXMLNode;
2791 }
2468 }
2792 }
2469 *tend1=sep;
2470 xbase=xn;
2471 path=tend1+1;
2472 tend1=xstrstr(path,sepString);
2793 *tend1 = sep;
2794 xbase = xn;
2795 path = tend1 + 1;
2796 tend1 = xstrstr(path, sepString);
2473 }
2797 }
2474 xn=xbase.getChildNode(path);
2475 if (xn.isEmpty()&&createIfMissing) xn=xbase.addChild(path);
2798 xn = xbase.getChildNode(path);
2799 if (xn.isEmpty() && createIfMissing) xn = xbase.addChild(path);
2476 return xn;
2477}
2478
2800 return xn;
2801}
2802
2479XMLElementPosition XMLNode::positionOfText (int i) const { if (i>=d->nText ) i=d->nText-1; return findPosition(d,i,eNodeText ); }
2480XMLElementPosition XMLNode::positionOfClear (int i) const { if (i>=d->nClear) i=d->nClear-1; return findPosition(d,i,eNodeClear); }
2481XMLElementPosition XMLNode::positionOfChildNode(int i) const { if (i>=d->nChild) i=d->nChild-1; return findPosition(d,i,eNodeChild); }
2482XMLElementPosition XMLNode::positionOfText (XMLCSTR lpszValue) const { return positionOfText (indexText (lpszValue)); }
2483XMLElementPosition XMLNode::positionOfClear(XMLCSTR lpszValue) const { return positionOfClear(indexClear(lpszValue)); }
2484XMLElementPosition XMLNode::positionOfClear(XMLClear *a) const { if (a) return positionOfClear(a->lpszValue); return positionOfClear(); }
2485XMLElementPosition XMLNode::positionOfChildNode(XMLNode x) const
2486{
2487 if ((!d)||(!x.d)) return -1;
2488 XMLNodeData *dd=x.d;
2489 XMLNode *pc=d->pChild;
2490 int i=d->nChild;
2491 while (i--) if (pc[i].d==dd) return findPosition(d,i,eNodeChild);
2803XMLElementPosition XMLNode::positionOfText (int i) const {
2804 if (i >= d->nText ) i = d->nText - 1;
2805 return findPosition(d, i, eNodeText );
2806}
2807XMLElementPosition XMLNode::positionOfClear (int i) const {
2808 if (i >= d->nClear) i = d->nClear - 1;
2809 return findPosition(d, i, eNodeClear);
2810}
2811XMLElementPosition XMLNode::positionOfChildNode(int i) const {
2812 if (i >= d->nChild) i = d->nChild - 1;
2813 return findPosition(d, i, eNodeChild);
2814}
2815XMLElementPosition XMLNode::positionOfText (XMLCSTR lpszValue) const {
2816 return positionOfText (indexText (lpszValue));
2817}
2818XMLElementPosition XMLNode::positionOfClear(XMLCSTR lpszValue) const {
2819 return positionOfClear(indexClear(lpszValue));
2820}
2821XMLElementPosition XMLNode::positionOfClear(XMLClear *a) const {
2822 if (a) return positionOfClear(a->lpszValue);
2823 return positionOfClear();
2824}
2825XMLElementPosition XMLNode::positionOfChildNode(XMLNode x) const {
2826 if ((!d) || (!x.d)) return -1;
2827 XMLNodeData *dd = x.d;
2828 XMLNode *pc = d->pChild;
2829 int i = d->nChild;
2830 while (i--) if (pc[i].d == dd) return findPosition(d, i, eNodeChild);
2492 return -1;
2493}
2831 return -1;
2832}
2494XMLElementPosition XMLNode::positionOfChildNode(XMLCSTR name, int count) const
2495{
2833XMLElementPosition XMLNode::positionOfChildNode(XMLCSTR name, int count) const {
2496 if (!name) return positionOfChildNode(count);
2834 if (!name) return positionOfChildNode(count);
2497 int j=0;
2498 do { getChildNode(name,&j); if (j<0) return -1; } while (count--);
2499 return findPosition(d,j-1,eNodeChild);
2835 int j = 0;
2836 do {
2837 getChildNode(name, &j);
2838 if (j < 0) return -1;
2839 } while (count--);
2840 return findPosition(d, j - 1, eNodeChild);
2500}
2501
2841}
2842
2502XMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name,XMLCSTR attributeName,XMLCSTR attributeValue, int *k) const
2503{
2504 int i=0,j;
2505 if (k) i=*k;
2506 XMLNode x;
2507 XMLCSTR t;
2508 do
2509 {
2510 x=getChildNode(name,&i);
2511 if (!x.isEmpty())
2512 {
2513 if (attributeValue)
2514 {
2515 j=0;
2516 do
2517 {
2518 t=x.getAttribute(attributeName,&j);
2519 if (t&&(xstricmp(attributeValue,t)==0)) { if (k) *k=i; return x; }
2520 } while (t);
2521 } else
2522 {
2523 if (x.isAttributeSet(attributeName)) { if (k) *k=i; return x; }
2524 }
2525 }
2526 } while (!x.isEmpty());
2527 return emptyXMLNode;
2843XMLNode XMLNode::getChildNodeWithAttribute(XMLCSTR name, XMLCSTR attributeName,
2844 XMLCSTR attributeValue,
2845 int *k) const {
2846 int i = 0, j;
2847 if (k) i = *k;
2848 XMLNode x;
2849 XMLCSTR t;
2850 do {
2851 x = getChildNode(name, &i);
2852 if (!x.isEmpty()) {
2853 if (attributeValue) {
2854 j = 0;
2855 do {
2856 t = x.getAttribute(attributeName, &j);
2857 if (t && (xstricmp(attributeValue, t) == 0)) {
2858 if (k) *k = i;
2859 return x;
2860 }
2861 } while (t);
2862 } else {
2863 if (x.isAttributeSet(attributeName)) {
2864 if (k) *k = i;
2865 return x;
2866 }
2867 }
2868 }
2869 } while (!x.isEmpty());
2870 return emptyXMLNode;
2528}
2529
2530// Find an attribute on an node.
2871}
2872
2873// Find an attribute on an node.
2531XMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const
2532{
2874XMLCSTR XMLNode::getAttribute(XMLCSTR lpszAttrib, int *j) const {
2533 if (!d) return NULL;
2875 if (!d) return NULL;
2534 int i=0,n=d->nAttribute;
2535 if (j) i=*j;
2536 XMLAttribute *pAttr=d->pAttribute+i;
2537 for (; i<n; i++)
2538 {
2539 if (xstricmp(pAttr->lpszName, lpszAttrib)==0)
2540 {
2541 if (j) *j=i+1;
2876 int i = 0, n = d->nAttribute;
2877 if (j) i = *j;
2878 XMLAttribute *pAttr = d->pAttribute + i;
2879 for (; i < n; i++) {
2880 if (xstricmp(pAttr->lpszName, lpszAttrib) == 0) {
2881 if (j) *j = i + 1;
2542 return pAttr->lpszValue;
2543 }
2544 pAttr++;
2545 }
2546 return NULL;
2547}
2548
2882 return pAttr->lpszValue;
2883 }
2884 pAttr++;
2885 }
2886 return NULL;
2887}
2888
2549char XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const
2550{
2889char XMLNode::isAttributeSet(XMLCSTR lpszAttrib) const {
2551 if (!d) return FALSE;
2890 if (!d) return FALSE;
2552 int i,n=d->nAttribute;
2553 XMLAttribute *pAttr=d->pAttribute;
2554 for (i=0; i<n; i++)
2555 {
2556 if (xstricmp(pAttr->lpszName, lpszAttrib)==0)
2557 {
2891 int i, n = d->nAttribute;
2892 XMLAttribute *pAttr = d->pAttribute;
2893 for (i = 0; i < n; i++) {
2894 if (xstricmp(pAttr->lpszName, lpszAttrib) == 0) {
2558 return TRUE;
2559 }
2560 pAttr++;
2561 }
2562 return FALSE;
2563}
2564
2895 return TRUE;
2896 }
2897 pAttr++;
2898 }
2899 return FALSE;
2900}
2901
2565XMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const
2566{
2902XMLCSTR XMLNode::getAttribute(XMLCSTR name, int j) const {
2567 if (!d) return NULL;
2903 if (!d) return NULL;
2568 int i=0;
2569 while (j-->0) getAttribute(name,&i);
2570 return getAttribute(name,&i);
2904 int i = 0;
2905 while (j-- > 0) getAttribute(name, &i);
2906 return getAttribute(name, &i);
2571}
2572
2907}
2908
2573XMLNodeContents XMLNode::enumContents(int i) const
2574{
2909XMLNodeContents XMLNode::enumContents(int i) const {
2575 XMLNodeContents c;
2910 XMLNodeContents c;
2576 if (!d) { c.etype=eNodeNULL; return c; }
2577 if (i<d->nAttribute)
2578 {
2579 c.etype=eNodeAttribute;
2580 c.attrib=d->pAttribute[i];
2911 if (!d) {
2912 c.etype = eNodeNULL;
2581 return c;
2582 }
2913 return c;
2914 }
2583 i-=d->nAttribute;
2584 c.etype=(XMLElementType)(d->pOrder[i]&3);
2585 i=(d->pOrder[i])>>2;
2586 switch (c.etype)
2587 {
2588 case eNodeChild: c.child = d->pChild[i]; break;
2589 case eNodeText: c.text = d->pText[i]; break;
2590 case eNodeClear: c.clear = d->pClear[i]; break;
2591 default: break;
2915 if (i < d->nAttribute) {
2916 c.etype = eNodeAttribute;
2917 c.attrib = d->pAttribute[i];
2918 return c;
2592 }
2919 }
2920 i -= d->nAttribute;
2921 c.etype = (XMLElementType)(d->pOrder[i] & 3);
2922 i = (d->pOrder[i]) >> 2;
2923 switch (c.etype) {
2924 case eNodeChild:
2925 c.child = d->pChild[i];
2926 break;
2927 case eNodeText:
2928 c.text = d->pText[i];
2929 break;
2930 case eNodeClear:
2931 c.clear = d->pClear[i];
2932 break;
2933 default:
2934 break;
2935 }
2593 return c;
2594}
2595
2936 return c;
2937}
2938
2596XMLCSTR XMLNode::getName() const { if (!d) return NULL; return d->lpszName; }
2597int XMLNode::nText() const { if (!d) return 0; return d->nText; }
2598int XMLNode::nChildNode() const { if (!d) return 0; return d->nChild; }
2599int XMLNode::nAttribute() const { if (!d) return 0; return d->nAttribute; }
2600int XMLNode::nClear() const { if (!d) return 0; return d->nClear; }
2601int XMLNode::nElement() const { if (!d) return 0; return d->nAttribute+d->nChild+d->nText+d->nClear; }
2602XMLClear XMLNode::getClear (int i) const { if ((!d)||(i>=d->nClear )) return emptyXMLClear; return d->pClear[i]; }
2603XMLAttribute XMLNode::getAttribute (int i) const { if ((!d)||(i>=d->nAttribute)) return emptyXMLAttribute; return d->pAttribute[i]; }
2604XMLCSTR XMLNode::getAttributeName (int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszName; }
2605XMLCSTR XMLNode::getAttributeValue(int i) const { if ((!d)||(i>=d->nAttribute)) return NULL; return d->pAttribute[i].lpszValue; }
2606XMLCSTR XMLNode::getText (int i) const { if ((!d)||(i>=d->nText )) return NULL; return d->pText[i]; }
2607XMLNode XMLNode::getChildNode (int i) const { if ((!d)||(i>=d->nChild )) return emptyXMLNode; return d->pChild[i]; }
2608XMLNode XMLNode::getParentNode ( ) const { if ((!d)||(!d->pParent )) return emptyXMLNode; return XMLNode(d->pParent); }
2609char XMLNode::isDeclaration ( ) const { if (!d) return 0; return d->isDeclaration; }
2610char XMLNode::isEmpty ( ) const { return (d==NULL); }
2611XMLNode XMLNode::emptyNode ( ) { return XMLNode::emptyXMLNode; }
2939XMLCSTR XMLNode::getName() const {
2940 if (!d) return NULL;
2941 return d->lpszName;
2942}
2943int XMLNode::nText() const {
2944 if (!d) return 0;
2945 return d->nText;
2946}
2947int XMLNode::nChildNode() const {
2948 if (!d) return 0;
2949 return d->nChild;
2950}
2951int XMLNode::nAttribute() const {
2952 if (!d) return 0;
2953 return d->nAttribute;
2954}
2955int XMLNode::nClear() const {
2956 if (!d) return 0;
2957 return d->nClear;
2958}
2959int XMLNode::nElement() const {
2960 if (!d) return 0;
2961 return d->nAttribute + d->nChild + d->nText + d->nClear;
2962}
2963XMLClear XMLNode::getClear (int i) const {
2964 if ((!d) || (i >= d->nClear )) return emptyXMLClear;
2965 return d->pClear[i];
2966}
2967XMLAttribute XMLNode::getAttribute (int i) const {
2968 if ((!d) || (i >= d->nAttribute)) return emptyXMLAttribute;
2969 return d->pAttribute[i];
2970}
2971XMLCSTR XMLNode::getAttributeName (int i) const {
2972 if ((!d) || (i >= d->nAttribute)) return NULL;
2973 return d->pAttribute[i].lpszName;
2974}
2975XMLCSTR XMLNode::getAttributeValue(int i) const {
2976 if ((!d) || (i >= d->nAttribute)) return NULL;
2977 return d->pAttribute[i].lpszValue;
2978}
2979XMLCSTR XMLNode::getText (int i) const {
2980 if ((!d) || (i >= d->nText )) return NULL;
2981 return d->pText[i];
2982}
2983XMLNode XMLNode::getChildNode (int i) const {
2984 if ((!d) || (i >= d->nChild )) return emptyXMLNode;
2985 return d->pChild[i];
2986}
2987XMLNode XMLNode::getParentNode ( ) const {
2988 if ((!d) || (!d->pParent )) return emptyXMLNode;
2989 return XMLNode(d->pParent);
2990}
2991char XMLNode::isDeclaration ( ) const {
2992 if (!d) return 0;
2993 return d->isDeclaration;
2994}
2995char XMLNode::isEmpty ( ) const {
2996 return (d == NULL);
2997}
2998XMLNode XMLNode::emptyNode ( ) {
2999 return XMLNode::emptyXMLNode;
3000}
2612
3001
2613XMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration, XMLElementPosition pos)
2614 { return addChild_priv(0,stringDup(lpszName),isDeclaration,pos); }
2615XMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration, XMLElementPosition pos)
2616 { return addChild_priv(0,lpszName,isDeclaration,pos); }
2617XMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue)
2618 { return addAttribute_priv(0,stringDup(lpszName),stringDup(lpszValue)); }
2619XMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev)
2620 { return addAttribute_priv(0,lpszName,lpszValuev); }
2621XMLCSTR XMLNode::addText(XMLCSTR lpszValue, XMLElementPosition pos)
2622 { return addText_priv(0,stringDup(lpszValue),pos); }
2623XMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos)
2624 { return addText_priv(0,lpszValue,pos); }
2625XMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos)
2626 { return addClear_priv(0,stringDup(lpszValue),lpszOpen,lpszClose,pos); }
2627XMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen, XMLCSTR lpszClose, XMLElementPosition pos)
2628 { return addClear_priv(0,lpszValue,lpszOpen,lpszClose,pos); }
2629XMLCSTR XMLNode::updateName(XMLCSTR lpszName)
2630 { return updateName_WOSD(stringDup(lpszName)); }
2631XMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute, XMLAttribute *oldAttribute)
2632 { return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),stringDup(newAttribute->lpszName),oldAttribute->lpszName); }
2633XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,int i)
2634 { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),i); }
2635XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue, XMLCSTR lpszNewName,XMLCSTR lpszOldName)
2636 { return updateAttribute_WOSD(stringDup(lpszNewValue),stringDup(lpszNewName),lpszOldName); }
2637XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i)
2638 { return updateText_WOSD(stringDup(lpszNewValue),i); }
2639XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
2640 { return updateText_WOSD(stringDup(lpszNewValue),lpszOldValue); }
2641XMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i)
2642 { return updateClear_WOSD(stringDup(lpszNewContent),i); }
2643XMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue)
2644 { return updateClear_WOSD(stringDup(lpszNewValue),lpszOldValue); }
2645XMLClear *XMLNode::updateClear(XMLClear *newP,XMLClear *oldP)
2646 { return updateClear_WOSD(stringDup(newP->lpszValue),oldP->lpszValue); }
3002XMLNode XMLNode::addChild(XMLCSTR lpszName, char isDeclaration,
3003 XMLElementPosition pos) {
3004 return addChild_priv(0, stringDup(lpszName), isDeclaration, pos);
3005}
3006XMLNode XMLNode::addChild_WOSD(XMLSTR lpszName, char isDeclaration,
3007 XMLElementPosition pos) {
3008 return addChild_priv(0, lpszName, isDeclaration, pos);
3009}
3010XMLAttribute *XMLNode::addAttribute(XMLCSTR lpszName, XMLCSTR lpszValue) {
3011 return addAttribute_priv(0, stringDup(lpszName), stringDup(lpszValue));
3012}
3013XMLAttribute *XMLNode::addAttribute_WOSD(XMLSTR lpszName, XMLSTR lpszValuev) {
3014 return addAttribute_priv(0, lpszName, lpszValuev);
3015}
3016XMLCSTR XMLNode::addText(XMLCSTR lpszValue, XMLElementPosition pos) {
3017 return addText_priv(0, stringDup(lpszValue), pos);
3018}
3019XMLCSTR XMLNode::addText_WOSD(XMLSTR lpszValue, XMLElementPosition pos) {
3020 return addText_priv(0, lpszValue, pos);
3021}
3022XMLClear *XMLNode::addClear(XMLCSTR lpszValue, XMLCSTR lpszOpen,
3023 XMLCSTR lpszClose, XMLElementPosition pos) {
3024 return addClear_priv(0, stringDup(lpszValue), lpszOpen, lpszClose, pos);
3025}
3026XMLClear *XMLNode::addClear_WOSD(XMLSTR lpszValue, XMLCSTR lpszOpen,
3027 XMLCSTR lpszClose, XMLElementPosition pos) {
3028 return addClear_priv(0, lpszValue, lpszOpen, lpszClose, pos);
3029}
3030XMLCSTR XMLNode::updateName(XMLCSTR lpszName) {
3031 return updateName_WOSD(stringDup(lpszName));
3032}
3033XMLAttribute *XMLNode::updateAttribute(XMLAttribute *newAttribute,
3034 XMLAttribute *oldAttribute) {
3035 return updateAttribute_WOSD(stringDup(newAttribute->lpszValue),
3036 stringDup(newAttribute->lpszName),
3037 oldAttribute->lpszName);
3038}
3039XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue,
3040 XMLCSTR lpszNewName, int i) {
3041 return updateAttribute_WOSD(stringDup(lpszNewValue),
3042 stringDup(lpszNewName), i);
3043}
3044XMLAttribute *XMLNode::updateAttribute(XMLCSTR lpszNewValue,
3045 XMLCSTR lpszNewName,
3046 XMLCSTR lpszOldName) {
3047 return updateAttribute_WOSD(stringDup(lpszNewValue),
3048 stringDup(lpszNewName), lpszOldName);
3049}
3050XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, int i) {
3051 return updateText_WOSD(stringDup(lpszNewValue), i);
3052}
3053XMLCSTR XMLNode::updateText(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) {
3054 return updateText_WOSD(stringDup(lpszNewValue), lpszOldValue);
3055}
3056XMLClear *XMLNode::updateClear(XMLCSTR lpszNewContent, int i) {
3057 return updateClear_WOSD(stringDup(lpszNewContent), i);
3058}
3059XMLClear *XMLNode::updateClear(XMLCSTR lpszNewValue, XMLCSTR lpszOldValue) {
3060 return updateClear_WOSD(stringDup(lpszNewValue), lpszOldValue);
3061}
3062XMLClear *XMLNode::updateClear(XMLClear *newP, XMLClear *oldP) {
3063 return updateClear_WOSD(stringDup(newP->lpszValue), oldP->lpszValue);
3064}
2647
3065
2648char XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding, char _guessWideCharChars,
2649 char _dropWhiteSpace, char _removeCommentsInMiddleOfText)
2650{
2651 guessWideCharChars=_guessWideCharChars; dropWhiteSpace=_dropWhiteSpace; removeCommentsInMiddleOfText=_removeCommentsInMiddleOfText;
3066char XMLNode::setGlobalOptions(XMLCharEncoding _characterEncoding,
3067 char _guessWideCharChars,
3068 char _dropWhiteSpace,
3069 char _removeCommentsInMiddleOfText) {
3070 guessWideCharChars = _guessWideCharChars;
3071 dropWhiteSpace = _dropWhiteSpace;
3072 removeCommentsInMiddleOfText = _removeCommentsInMiddleOfText;
2652#ifdef _XMLWIDECHAR
3073#ifdef _XMLWIDECHAR
2653 if (_characterEncoding) characterEncoding=_characterEncoding;
3074 if (_characterEncoding) characterEncoding = _characterEncoding;
2654#else
3075#else
2655 switch(_characterEncoding)
2656 {
2657 case char_encoding_UTF8: characterEncoding=_characterEncoding; XML_ByteTable=XML_utf8ByteTable; break;
2658 case char_encoding_legacy: characterEncoding=_characterEncoding; XML_ByteTable=XML_legacyByteTable; break;
2659 case char_encoding_ShiftJIS: characterEncoding=_characterEncoding; XML_ByteTable=XML_sjisByteTable; break;
2660 case char_encoding_GB2312: characterEncoding=_characterEncoding; XML_ByteTable=XML_gb2312ByteTable; break;
3076 switch (_characterEncoding) {
3077 case char_encoding_UTF8:
3078 characterEncoding = _characterEncoding;
3079 XML_ByteTable = XML_utf8ByteTable;
3080 break;
3081 case char_encoding_legacy:
3082 characterEncoding = _characterEncoding;
3083 XML_ByteTable = XML_legacyByteTable;
3084 break;
3085 case char_encoding_ShiftJIS:
3086 characterEncoding = _characterEncoding;
3087 XML_ByteTable = XML_sjisByteTable;
3088 break;
3089 case char_encoding_GB2312:
3090 characterEncoding = _characterEncoding;
3091 XML_ByteTable = XML_gb2312ByteTable;
3092 break;
2661 case char_encoding_Big5:
3093 case char_encoding_Big5:
2662 case char_encoding_GBK: characterEncoding=_characterEncoding; XML_ByteTable=XML_gbk_big5_ByteTable; break;
2663 default: return 1;
3094 case char_encoding_GBK:
3095 characterEncoding = _characterEncoding;
3096 XML_ByteTable = XML_gbk_big5_ByteTable;
3097 break;
3098 default:
3099 return 1;
2664 }
2665#endif
2666 return 0;
2667}
2668
3100 }
3101#endif
3102 return 0;
3103}
3104
2669XMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf,int l, char useXMLEncodingAttribute)
2670{
3105XMLNode::XMLCharEncoding XMLNode::guessCharEncoding(void *buf, int l,
3106 char useXMLEncodingAttribute) {
2671#ifdef _XMLWIDECHAR
2672 return (XMLCharEncoding)0;
2673#else
3107#ifdef _XMLWIDECHAR
3108 return (XMLCharEncoding)0;
3109#else
2674 if (l<25) return (XMLCharEncoding)0;
2675 if (guessWideCharChars&&(myIsTextWideChar(buf,l))) return (XMLCharEncoding)0;
2676 unsigned char *b=(unsigned char*)buf;
2677 if ((b[0]==0xef)&&(b[1]==0xbb)&&(b[2]==0xbf)) return char_encoding_UTF8;
3110 if (l < 25) return (XMLCharEncoding)0;
3111 if (guessWideCharChars && (myIsTextWideChar(buf, l))) {
3112 return (XMLCharEncoding)0;
3113 }
3114 unsigned char *b = (unsigned char*)buf;
3115 if ((b[0] == 0xef) && (b[1] == 0xbb) && (b[2] == 0xbf)) {
3116 return char_encoding_UTF8;
3117 }
2678
2679 // Match utf-8 model ?
3118
3119 // Match utf-8 model ?
2680 XMLCharEncoding bestGuess=char_encoding_UTF8;
2681 int i=0;
2682 while (i<l)
2683 switch (XML_utf8ByteTable[b[i]])
2684 {
2685 case 4: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2686 case 3: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2687 case 2: i++; if ((i<l)&&(b[i]& 0xC0)!=0x80) { bestGuess=char_encoding_legacy; i=l; } // 10bbbbbb ?
2688 case 1: i++; break;
2689 case 0: i=l;
3120 XMLCharEncoding bestGuess = char_encoding_UTF8;
3121 int i = 0;
3122 while (i < l)
3123 switch (XML_utf8ByteTable[b[i]]) {
3124 case 4:
3125 i++;
3126 if ((i < l) && (b[i]& 0xC0) != 0x80) {
3127 bestGuess = char_encoding_legacy; // 10bbbbbb ?
3128 i = l;
3129 }
3130 case 3:
3131 i++;
3132 if ((i < l) && (b[i]& 0xC0) != 0x80) {
3133 bestGuess = char_encoding_legacy; // 10bbbbbb ?
3134 i = l;
3135 }
3136 case 2:
3137 i++;
3138 if ((i < l) && (b[i]& 0xC0) != 0x80) {
3139 bestGuess = char_encoding_legacy; // 10bbbbbb ?
3140 i = l;
3141 }
3142 case 1:
3143 i++;
3144 break;
3145 case 0:
3146 i = l;
2690 }
2691 if (!useXMLEncodingAttribute) return bestGuess;
2692 // if encoding is specified and different from utf-8 than it's non-utf8
2693 // otherwise it's utf-8
2694 char bb[201];
3147 }
3148 if (!useXMLEncodingAttribute) return bestGuess;
3149 // if encoding is specified and different from utf-8 than it's non-utf8
3150 // otherwise it's utf-8
3151 char bb[201];
2695 l=mmin(l,200);
2696 memcpy(bb,buf,l); // copy buf into bb to be able to do "bb[l]=0"
2697 bb[l]=0;
2698 b=(unsigned char*)strstr(bb,"encoding");
3152 l = mmin(l, 200);
3153 memcpy(bb, buf, l); // copy buf into bb to be able to do "bb[l]=0"
3154 bb[l] = 0;
3155 b = (unsigned char*)strstr(bb, "encoding");
2699 if (!b) return bestGuess;
3156 if (!b) return bestGuess;
2700 b+=8; while XML_isSPACECHAR(*b) b++; if (*b!='=') return bestGuess;
2701 b++; while XML_isSPACECHAR(*b) b++; if ((*b!='\'')&&(*b!='"')) return bestGuess;
2702 b++; while XML_isSPACECHAR(*b) b++;
3157 b += 8;
3158 while XML_isSPACECHAR(*b) b++;
3159 if (*b != '=') return bestGuess;
3160 b++;
3161 while XML_isSPACECHAR(*b) b++;
3162 if ((*b != '\'') && (*b != '"')) return bestGuess;
3163 b++;
3164 while XML_isSPACECHAR(*b) b++;
2703
3165
2704 if ((xstrnicmp((char*)b,"utf-8",5)==0)||
2705 (xstrnicmp((char*)b,"utf8",4)==0))
2706 {
2707 if (bestGuess==char_encoding_legacy) return char_encoding_error;
3166 if ((xstrnicmp((char*)b, "utf-8", 5) == 0) ||
3167 (xstrnicmp((char*)b, "utf8", 4) == 0)) {
3168 if (bestGuess == char_encoding_legacy) return char_encoding_error;
2708 return char_encoding_UTF8;
2709 }
2710
3169 return char_encoding_UTF8;
3170 }
3171
2711 if ((xstrnicmp((char*)b,"shiftjis",8)==0)||
2712 (xstrnicmp((char*)b,"shift-jis",9)==0)||
2713 (xstrnicmp((char*)b,"sjis",4)==0)) return char_encoding_ShiftJIS;
3172 if ((xstrnicmp((char*)b, "shiftjis", 8) == 0) ||
3173 (xstrnicmp((char*)b, "shift-jis", 9) == 0) ||
3174 (xstrnicmp((char*)b, "sjis", 4) == 0)) return char_encoding_ShiftJIS;
2714
3175
2715 if (xstrnicmp((char*)b,"GB2312",6)==0) return char_encoding_GB2312;
2716 if (xstrnicmp((char*)b,"Big5",4)==0) return char_encoding_Big5;
2717 if (xstrnicmp((char*)b,"GBK",3)==0) return char_encoding_GBK;
3176 if (xstrnicmp((char*)b, "GB2312", 6) == 0) return char_encoding_GB2312;
3177 if (xstrnicmp((char*)b, "Big5", 4) == 0) return char_encoding_Big5;
3178 if (xstrnicmp((char*)b, "GBK", 3) == 0) return char_encoding_GBK;
2718
2719 return char_encoding_legacy;
2720#endif
2721}
2722#undef XML_isSPACECHAR
2723
2724//////////////////////////////////////////////////////////
2725// Here starts the base64 conversion functions. //
2726//////////////////////////////////////////////////////////
2727
3179
3180 return char_encoding_legacy;
3181#endif
3182}
3183#undef XML_isSPACECHAR
3184
3185//////////////////////////////////////////////////////////
3186// Here starts the base64 conversion functions. //
3187//////////////////////////////////////////////////////////
3188
2728static const char base64Fillchar = _CXML('='); // used to mark partial words at the end
3189// used to mark partial words at the end
3190static const char base64Fillchar = _CXML('=');
2729
2730// this lookup table defines the base64 encoding
3191
3192// this lookup table defines the base64 encoding
2731XMLCSTR base64EncodeTable=_CXML("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
3193XMLCSTR base64EncodeTable = _CXML("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
2732
2733// Decode Table gives the index of any valid base64 character in the Base64 table]
2734// 96: '=' - 97: space char - 98: illegal char - 99: end of string
2735const unsigned char base64DecodeTable[] = {
3194
3195// Decode Table gives the index of any valid base64 character in the Base64 table]
3196// 96: '=' - 97: space char - 98: illegal char - 99: end of string
3197const unsigned char base64DecodeTable[] = {
2736 99,98,98,98,98,98,98,98,98,97, 97,98,98,97,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //00 -29
2737 98,98,97,98,98,98,98,98,98,98, 98,98,98,62,98,98,98,63,52,53, 54,55,56,57,58,59,60,61,98,98, //30 -59
2738 98,96,98,98,98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24, //60 -89
2739 25,98,98,98,98,98,98,26,27,28, 29,30,31,32,33,34,35,36,37,38, 39,40,41,42,43,44,45,46,47,48, //90 -119
2740 49,50,51,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //120 -149
2741 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //150 -179
2742 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //180 -209
2743 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98,98,98,98,98, //210 -239
2744 98,98,98,98,98,98,98,98,98,98, 98,98,98,98,98,98 //240 -255
3198 99, 98, 98, 98, 98, 98, 98, 98, 98, 97, 97, 98, 98, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //00 -29
3199 98, 98, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 62, 98, 98, 98, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 98, 98, //30 -59
3200 98, 96, 98, 98, 98, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, //60 -89
3201 25, 98, 98, 98, 98, 98, 98, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, //90 -119
3202 49, 50, 51, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //120 -149
3203 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //150 -179
3204 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //180 -209
3205 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, //210 -239
3206 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98 //240 -255
2745};
2746
3207};
3208
2747XMLParserBase64Tool::~XMLParserBase64Tool(){ freeBuffer(); }
3209XMLParserBase64Tool::~XMLParserBase64Tool() {
3210 freeBuffer();
3211}
2748
3212
2749void XMLParserBase64Tool::freeBuffer(){ if (buf) free(buf); buf=NULL; buflen=0; }
3213void XMLParserBase64Tool::freeBuffer() {
3214 if (buf) free(buf);
3215 buf = NULL;
3216 buflen = 0;
3217}
2750
3218
2751int XMLParserBase64Tool::encodeLength(int inlen, char formatted)
2752{
2753 unsigned int i=((inlen-1)/3*4+4+1);
2754 if (formatted) i+=inlen/54;
3219int XMLParserBase64Tool::encodeLength(int inlen, char formatted) {
3220 unsigned int i = ((inlen - 1) / 3 * 4 + 4 + 1);
3221 if (formatted) i += inlen / 54;
2755 return i;
2756}
2757
3222 return i;
3223}
3224
2758XMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen, char formatted)
2759{
2760 int i=encodeLength(inlen,formatted),k=17,eLen=inlen/3,j;
3225XMLSTR XMLParserBase64Tool::encode(unsigned char *inbuf, unsigned int inlen,
3226 char formatted) {
3227 int i = encodeLength(inlen, formatted), k = 17, eLen = inlen / 3, j;
2761 alloc(i*sizeof(XMLCHAR));
3228 alloc(i*sizeof(XMLCHAR));
2762 XMLSTR curr=(XMLSTR)buf;
2763 for(i=0;i<eLen;i++)
2764 {
3229 XMLSTR curr = (XMLSTR)buf;
3230 for (i = 0; i < eLen; i++) {
2765 // Copy next three bytes into lower 24 bits of int, paying attention to sign.
3231 // Copy next three bytes into lower 24 bits of int, paying attention to sign.
2766 j=(inbuf[0]<<16)|(inbuf[1]<<8)|inbuf[2]; inbuf+=3;
3232 j = (inbuf[0] << 16) | (inbuf[1] << 8) | inbuf[2];
3233 inbuf += 3;
2767 // Encode the int into four chars
3234 // Encode the int into four chars
2768 *(curr++)=base64EncodeTable[ j>>18 ];
2769 *(curr++)=base64EncodeTable[(j>>12)&0x3f];
2770 *(curr++)=base64EncodeTable[(j>> 6)&0x3f];
2771 *(curr++)=base64EncodeTable[(j )&0x3f];
2772 if (formatted) { if (!k) { *(curr++)=_CXML('\n'); k=18; } k--; }
3235 *(curr++) = base64EncodeTable[ j>>18 ];
3236 *(curr++) = base64EncodeTable[(j>>12)&0x3f];
3237 *(curr++) = base64EncodeTable[(j>> 6)&0x3f];
3238 *(curr++) = base64EncodeTable[(j )&0x3f];
3239 if (formatted) {
3240 if (!k) {
3241 *(curr++) = _CXML('\n');
3242 k = 18;
3243 }
3244 k--;
3245 }
2773 }
3246 }
2774 eLen=inlen-eLen*3; // 0 - 2.
2775 if (eLen==1)
2776 {
2777 *(curr++)=base64EncodeTable[ inbuf[0]>>2 ];
2778 *(curr++)=base64EncodeTable[(inbuf[0]<<4)&0x3F];
2779 *(curr++)=base64Fillchar;
2780 *(curr++)=base64Fillchar;
2781 } else if (eLen==2)
2782 {
2783 j=(inbuf[0]<<8)|inbuf[1];
2784 *(curr++)=base64EncodeTable[ j>>10 ];
2785 *(curr++)=base64EncodeTable[(j>> 4)&0x3f];
2786 *(curr++)=base64EncodeTable[(j<< 2)&0x3f];
2787 *(curr++)=base64Fillchar;
3247 eLen = inlen - eLen * 3; // 0 - 2.
3248 if (eLen == 1) {
3249 *(curr++) = base64EncodeTable[ inbuf[0] >> 2 ];
3250 *(curr++) = base64EncodeTable[(inbuf[0] << 4) & 0x3F];
3251 *(curr++) = base64Fillchar;
3252 *(curr++) = base64Fillchar;
3253 } else if (eLen == 2) {
3254 j = (inbuf[0] << 8) | inbuf[1];
3255 *(curr++) = base64EncodeTable[ j>>10 ];
3256 *(curr++) = base64EncodeTable[(j>> 4)&0x3f];
3257 *(curr++) = base64EncodeTable[(j<< 2)&0x3f];
3258 *(curr++) = base64Fillchar;
2788 }
3259 }
2789 *(curr++)=0;
3260 *(curr++) = 0;
2790 return (XMLSTR)buf;
2791}
2792
3261 return (XMLSTR)buf;
3262}
3263
2793unsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data,XMLError *xe)
2794{
2795 if (xe) *xe=eXMLErrorNone;
2796 int size=0;
3264unsigned int XMLParserBase64Tool::decodeSize(XMLCSTR data, XMLError *xe) {
3265 if (xe) *xe = eXMLErrorNone;
3266 int size = 0;
2797 unsigned char c;
2798 //skip any extra characters (e.g. newlines or spaces)
3267 unsigned char c;
3268 //skip any extra characters (e.g. newlines or spaces)
2799 while (*data)
2800 {
3269 while (*data) {
2801#ifdef _XMLWIDECHAR
3270#ifdef _XMLWIDECHAR
2802 if (*data>255) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
3271 if (*data > 255) {
3272 if (xe) *xe = eXMLErrorBase64DecodeIllegalCharacter;
3273 return 0;
3274 }
2803#endif
3275#endif
2804 c=base64DecodeTable[(unsigned char)(*data)];
2805 if (c<97) size++;
2806 else if (c==98) { if (xe) *xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
3276 c = base64DecodeTable[(unsigned char)(*data)];
3277 if (c < 97) size++;
3278 else if (c == 98) {
3279 if (xe) *xe = eXMLErrorBase64DecodeIllegalCharacter;
3280 return 0;
3281 }
2807 data++;
2808 }
3282 data++;
3283 }
2809 if (xe&&(size%4!=0)) *xe=eXMLErrorBase64DataSizeIsNotMultipleOf4;
2810 if (size==0) return 0;
2811 do { data--; size--; } while(*data==base64Fillchar); size++;
2812 return (unsigned int)((size*3)/4);
3284 if (xe && (size % 4 != 0)) *xe = eXMLErrorBase64DataSizeIsNotMultipleOf4;
3285 if (size == 0) return 0;
3286 do {
3287 data--;
3288 size--;
3289 } while (*data == base64Fillchar);
3290 size++;
3291 return (unsigned int)((size*3) / 4);
2813}
2814
3292}
3293
2815unsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf, int len, XMLError *xe)
2816{
2817 if (xe) *xe=eXMLErrorNone;
2818 int i=0,p=0;
2819 unsigned char d,c;
2820 for(;;)
2821 {
3294unsigned char XMLParserBase64Tool::decode(XMLCSTR data, unsigned char *buf,
3295 int len, XMLError *xe) {
3296 if (xe) *xe = eXMLErrorNone;
3297 int i = 0, p = 0;
3298 unsigned char d, c;
3299 for (;;) {
2822
2823#ifdef _XMLWIDECHAR
2824#define BASE64DECODE_READ_NEXT_CHAR(c) \
2825 do { \
2826 if (data[i]>255){ c=98; break; } \
2827 c=base64DecodeTable[(unsigned char)data[i++]]; \
2828 }while (c==97); \
2829 if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2830#else
2831#define BASE64DECODE_READ_NEXT_CHAR(c) \
2832 do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \
2833 if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
2834#endif
2835
2836 BASE64DECODE_READ_NEXT_CHAR(c)
3300
3301#ifdef _XMLWIDECHAR
3302#define BASE64DECODE_READ_NEXT_CHAR(c) \
3303 do { \
3304 if (data[i]>255){ c=98; break; } \
3305 c=base64DecodeTable[(unsigned char)data[i++]]; \
3306 }while (c==97); \
3307 if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
3308#else
3309#define BASE64DECODE_READ_NEXT_CHAR(c) \
3310 do { c=base64DecodeTable[(unsigned char)data[i++]]; }while (c==97); \
3311 if(c==98){ if(xe)*xe=eXMLErrorBase64DecodeIllegalCharacter; return 0; }
3312#endif
3313
3314 BASE64DECODE_READ_NEXT_CHAR(c)
2837 if (c==99) { return 2; }
2838 if (c==96)
2839 {
2840 if (p==(int)len) return 2;
2841 if (xe) *xe=eXMLErrorBase64DecodeTruncatedData;
3315 if (c == 99) {
3316 return 2;
3317 }
3318 if (c == 96) {
3319 if (p == (int)len) return 2;
3320 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
2842 return 1;
2843 }
2844
2845 BASE64DECODE_READ_NEXT_CHAR(d)
3321 return 1;
3322 }
3323
3324 BASE64DECODE_READ_NEXT_CHAR(d)
2846 if ((d==99)||(d==96)) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2847 if (p==(int)len) { if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall; return 0; }
2848 buf[p++]=(unsigned char)((c<<2)|((d>>4)&0x3));
3325 if ((d == 99) || (d == 96)) {
3326 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
3327 return 1;
3328 }
3329 if (p == (int)len) {
3330 if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
3331 return 0;
3332 }
3333 buf[p++] = (unsigned char)((c << 2) | ((d >> 4) & 0x3));
2849
2850 BASE64DECODE_READ_NEXT_CHAR(c)
3334
3335 BASE64DECODE_READ_NEXT_CHAR(c)
2851 if (c==99) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2852 if (p==(int)len)
2853 {
2854 if (c==96) return 2;
2855 if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
3336 if (c == 99) {
3337 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
3338 return 1;
3339 }
3340 if (p == (int)len) {
3341 if (c == 96) return 2;
3342 if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
2856 return 0;
2857 }
3343 return 0;
3344 }
2858 if (c==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2859 buf[p++]=(unsigned char)(((d<<4)&0xf0)|((c>>2)&0xf));
3345 if (c == 96) {
3346 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
3347 return 1;
3348 }
3349 buf[p++] = (unsigned char)(((d << 4) & 0xf0) | ((c >> 2) & 0xf));
2860
2861 BASE64DECODE_READ_NEXT_CHAR(d)
3350
3351 BASE64DECODE_READ_NEXT_CHAR(d)
2862 if (d==99 ) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2863 if (p==(int)len)
2864 {
2865 if (d==96) return 2;
2866 if (xe) *xe=eXMLErrorBase64DecodeBufferTooSmall;
3352 if (d == 99 ) {
3353 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
3354 return 1;
3355 }
3356 if (p == (int)len) {
3357 if (d == 96) return 2;
3358 if (xe) *xe = eXMLErrorBase64DecodeBufferTooSmall;
2867 return 0;
2868 }
3359 return 0;
3360 }
2869 if (d==96) { if (xe) *xe=eXMLErrorBase64DecodeTruncatedData; return 1; }
2870 buf[p++]=(unsigned char)(((c<<6)&0xc0)|d);
3361 if (d == 96) {
3362 if (xe) *xe = eXMLErrorBase64DecodeTruncatedData;
3363 return 1;
3364 }
3365 buf[p++] = (unsigned char)(((c << 6) & 0xc0) | d);
2871 }
2872}
2873#undef BASE64DECODE_READ_NEXT_CHAR
2874
3366 }
3367}
3368#undef BASE64DECODE_READ_NEXT_CHAR
3369
2875void XMLParserBase64Tool::alloc(int newsize)
2876{
2877 if ((!buf)&&(newsize)) { buf=malloc(newsize); buflen=newsize; return; }
2878 if (newsize>buflen) { buf=realloc(buf,newsize); buflen=newsize; }
3370void XMLParserBase64Tool::alloc(int newsize) {
3371 if ((!buf) && (newsize)) {
3372 buf = malloc(newsize);
3373 buflen = newsize;
3374 return;
3375 }
3376 if (newsize > buflen) {
3377 buf = realloc(buf, newsize);
3378 buflen = newsize;
3379 }
2879}
2880
3380}
3381
2881unsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe)
2882{
2883 if (xe) *xe=eXMLErrorNone;
2884 unsigned int len=decodeSize(data,xe);
2885 if (outlen) *outlen=len;
3382unsigned char *XMLParserBase64Tool::decode(XMLCSTR data, int *outlen, XMLError *xe) {
3383 if (xe) *xe = eXMLErrorNone;
3384 unsigned int len = decodeSize(data, xe);
3385 if (outlen) *outlen = len;
2886 if (!len) return NULL;
3386 if (!len) return NULL;
2887 alloc(len+1);
2888 if(!decode(data,(unsigned char*)buf,len,xe)){ return NULL; }
3387 alloc(len + 1);
3388 if (!decode(data, (unsigned char*)buf, len, xe)) {
3389 return NULL;
3390 }
2889 return (unsigned char*)buf;
2890}
2891
3391 return (unsigned char*)buf;
3392}
3393