[EXPLORER]
[reactos.git] / reactos / base / shell / explorer / utility / xmlstorage.h
1
2 //
3 // XML storage C++ classes version 1.3
4 //
5 // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Martin Fuchs <martin-fuchs@gmx.net>
6 //
7
8 /// \file xmlstorage.h
9 /// XMLStorage header file
10
11
12 /*
13
14 All rights reserved.
15
16 Redistribution and use in source and binary forms, with or without
17 modification, are permitted provided that the following conditions are met:
18
19 * Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
21 * Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in
23 the documentation and/or other materials provided with the
24 distribution.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 POSSIBILITY OF SUCH DAMAGE.
37
38 */
39
40 #ifndef _XMLSTORAGE_H
41
42
43 #ifdef UNICODE
44 #ifndef _UNICODE
45 #define _UNICODE
46 #endif
47 #else
48 #ifdef _UNICODE
49 #define UNICODE
50 #endif
51 #endif
52
53 #ifndef _WIN32
54 #ifdef UNICODE
55 #error no UNICODE build in Unix version available
56 #endif
57 #ifndef XS_STRING_UTF8
58 #define XS_STRING_UTF8
59 #endif
60 #endif
61
62
63 #if _MSC_VER>=1400 // VS2005 or higher
64 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
65 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
66 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
67 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
68 #endif
69 #endif
70
71
72 #ifdef XS_USE_XERCES
73
74 #ifndef UNICODE
75 #ifndef XS_STRING_UTF8
76 #define XS_STRING_UTF8
77 #endif
78 #endif
79
80 #include <xercesc/parsers/SAXParser.hpp>
81 #include <xercesc/sax/HandlerBase.hpp>
82
83 using XERCES_CPP_NAMESPACE_QUALIFIER Locator;
84 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser;
85 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase;
86 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource;
87 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList;
88 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException;
89
90 typedef XMLCh XML_Char;
91
92 #elif defined(XS_USE_EXPAT)
93
94 #include <expat/expat.h>
95
96 #endif
97
98
99 #ifdef _MSC_VER
100 #pragma warning(disable: 4786)
101
102 #ifndef XS_NO_COMMENT
103
104 #ifdef XS_USE_XERCES
105 #ifdef _DEBUG
106 #pragma comment(lib, "xerces-c_2D")
107 #else
108 #pragma comment(lib, "xerces-c_2")
109 #endif
110 #elif defined(XS_USE_EXPAT)
111 #ifdef XML_STATIC
112 #ifndef _DEBUG
113 #pragma comment(lib, "libexpatMT")
114 #endif
115 #else
116 #pragma comment(lib, "libexpat")
117 #endif
118 #endif
119
120 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
121 #if defined(_DEBUG) && defined(_DLL) // DEBUG version only supported with MSVCRTD
122 #if _MSC_VER==1500
123 #pragma comment(lib, "xmlstorage-vc9d")
124 #elif _MSC_VER==1400
125 #pragma comment(lib, "xmlstorage-vc8d")
126 #else
127 #pragma comment(lib, "xmlstorage-vc6d")
128 #endif
129 #else
130 #ifdef _DLL
131 #if _MSC_VER==1500
132 #pragma comment(lib, "xmlstorage-vc9")
133 #elif _MSC_VER==1400
134 #pragma comment(lib, "xmlstorage-vc8")
135 #else
136 #pragma comment(lib, "xmlstorage-vc6")
137 #endif
138 #elif defined(_MT)
139 #if _MSC_VER==1500
140 #pragma comment(lib, "xmlstorage-vc9t")
141 #elif _MSC_VER==1400
142 #pragma comment(lib, "xmlstorage-vc8t")
143 #else
144 #pragma comment(lib, "xmlstorage-vc6t")
145 #endif
146 #else
147 // -ML is no more supported since VS2005.
148 #pragma comment(lib, "xmlstorage-vc6l")
149 #endif
150 #endif
151 #endif // _STRING_DEFINED
152
153 #endif // XS_NO_COMMENT
154
155 #endif // _MSC_VER
156
157
158 #ifdef _WIN32
159
160 //#include <windows.h> // for LPCTSTR
161 //#include <tchar.h>
162 #include <malloc.h>
163
164 #ifndef _MSC_VER
165 #include <stdio.h> // vsnprintf(), snprintf()
166 #endif
167
168 #else // _WIN32
169
170 #include <wchar.h>
171 #include <stdlib.h>
172 #include <string.h> // strcasecmp()
173 #include <stdarg.h>
174
175 typedef char CHAR;
176 #ifdef _WCHAR_T_DEFINED
177 #define __wchar_t wchar_t
178 #endif
179
180 typedef __wchar_t WCHAR;
181 typedef unsigned char UCHAR;
182 typedef char* LPSTR;
183 typedef const char* LPCSTR;
184 typedef WCHAR* LPWSTR;
185 typedef const WCHAR* LPCWSTR;
186
187 #ifndef UNICODE
188 #define TEXT(x) x
189 typedef char TCHAR;
190 typedef unsigned char _TUCHAR;
191 typedef CHAR* PTSTR;
192 typedef CHAR* LPTSTR;
193 typedef const CHAR* LPCTSTR;
194
195 #define _ttoi atoi
196 #define _tfopen fopen
197 #define _tcstod strtod
198 #define _tcslen strlen
199 #define _tcsstr strstr
200 #define _snprintf snprintf
201 #define _sntprintf snprintf
202 #define _vsnprintf vsnprintf
203 #define _vsntprintf vsnprintf
204 #define _stricmp strcasecmp
205 #define _tcsicmp strcasecmp
206 #define strnicmp strncasecmp
207 #define _tcsnicmp strncasecmp
208 #endif // UNICODE
209
210 #endif // _WIN32
211
212 #ifdef __BORLANDC__
213 #define _stricmp stricmp
214 #endif
215
216
217 #include <fstream>
218 #include <sstream>
219 #include <string>
220 #include <stack>
221 #include <list>
222 #include <map>
223
224
225 #ifndef BUFFER_LEN
226 #define BUFFER_LEN 2048
227 #endif
228
229
230 namespace XMLStorage {
231
232
233 #ifndef XS_String
234
235 #ifdef XS_STRING_UTF8
236 #define XS_CHAR char
237 #define XS_TEXT(x) x
238 #define LPXSSTR LPSTR
239 #define LPCXSSTR LPCSTR
240 #define XS_cmp strcmp
241 #define XS_icmp _stricmp
242 #define XS_ncmp strncmp
243 #define XS_nicmp strnicmp
244 #define XS_toi atoi
245 #define XS_tod strtod
246 #define XS_len strlen
247 #define XS_snprintf _snprintf
248 #define XS_vsnprintf _vsnprintf
249 #define XS_strstr strstr
250 #else
251 #define XS_CHAR TCHAR
252 #define XS_TEXT(x) TEXT(x)
253 #define LPXSSTR LPTSTR
254 #define LPCXSSTR LPCTSTR
255 #define XS_cmp _tcscmp
256 #define XS_icmp _tcsicmp
257 #define XS_ncmp _tcsncmp
258 #define XS_nicmp _tcsnicmp
259 #define XS_toi _ttoi
260 #define XS_tod _tcstod
261 #define XS_len _tcslen
262 #define XS_snprintf _sntprintf
263 #define XS_vsnprintf _vsntprintf
264 #define XS_strstr _tcsstr
265 #endif
266
267 #ifndef COUNTOF
268 #if _MSC_VER>=1400
269 #define COUNTOF _countof
270 #else
271 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
272 #endif
273 #endif
274
275
276 extern const char* get_xmlsym_end_utf8(const char* p);
277
278
279 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
280
281 #define XS_String String
282
283 #else // _STRING_DEFINED, !XS_STRING_UTF8
284
285 /// string class for TCHAR strings
286
287 struct XS_String
288 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
289 : public std::wstring
290 #else
291 : public std::string
292 #endif
293 {
294 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
295 typedef std::wstring super;
296 #else
297 typedef std::string super;
298 #endif
299
300 XS_String() {}
301
302 XS_String(LPCXSSTR s) {if (s) super::assign(s);}
303 XS_String(LPCXSSTR s, size_t l) : super(s, l) {}
304
305 XS_String(const super& other) : super(other) {}
306 XS_String(const XS_String& other) : super(other) {}
307
308 #ifdef _WIN32
309 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
310 XS_String(LPCSTR s) {assign(s);}
311 XS_String(LPCSTR s, size_t l) {assign(s, l);}
312 XS_String(const std::string& s) {assign(s.c_str());}
313 XS_String& operator=(LPCSTR s) {assign(s); return *this;}
314 void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();}
315 void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();}
316 #else
317 XS_String(LPCWSTR s) {assign(s);}
318 XS_String(LPCWSTR s, size_t l) {assign(s, l);}
319 XS_String(const std::wstring& ws) {assign(ws.c_str());}
320 XS_String& operator=(LPCWSTR s) {assign(s); return *this;}
321 #ifdef XS_STRING_UTF8
322 void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
323 void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
324 #else // if !UNICODE && !XS_STRING_UTF8
325 void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
326 void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
327 #endif
328 #endif
329 #endif // _WIN32
330
331 #ifdef __ISSD_H
332 // XS_String(const _ISSD RString& s) {assign(s.c_str());}
333 // void assign(const _ISSD RString& s) {assign(s.c_str());}
334 XS_String& operator=(const _ISSD RString& s) {assign(s); return *this;}
335 #endif
336
337 #ifdef XS_STRING_UTF8
338 void assign(const XS_String& s) {assign(s.c_str());}
339 #endif
340
341 XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;}
342 XS_String& operator=(const super& s) {super::assign(s); return *this;}
343 void assign(LPCXSSTR s) {super::assign(s);}
344 void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}
345
346 operator LPCXSSTR() const {return c_str();}
347
348 #ifdef _WIN32
349 #ifdef XS_STRING_UTF8
350 operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));}
351 #elif defined(UNICODE)
352 operator std::string() const {size_t bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));}
353 #else
354 operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));}
355 #endif
356 #endif
357
358 XS_String& printf(LPCXSSTR fmt, ...)
359 {
360 va_list l;
361 XS_CHAR b[BUFFER_LEN];
362
363 va_start(l, fmt);
364 super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
365 va_end(l);
366
367 return *this;
368 }
369
370 XS_String& vprintf(LPCXSSTR fmt, va_list l)
371 {
372 XS_CHAR b[BUFFER_LEN];
373
374 super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
375
376 return *this;
377 }
378
379 XS_String& appendf(LPCXSSTR fmt, ...)
380 {
381 va_list l;
382 XS_CHAR b[BUFFER_LEN];
383
384 va_start(l, fmt);
385 super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
386 va_end(l);
387
388 return *this;
389 }
390
391 XS_String& vappendf(LPCXSSTR fmt, va_list l)
392 {
393 XS_CHAR b[BUFFER_LEN];
394
395 super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
396
397 return *this;
398 }
399 };
400
401 #endif // _STRING_DEFINED, !XS_STRING_UTF8
402
403 #endif // XS_String
404
405
406 #define XS_EMPTY_STR XS_TEXT("")
407 #define XS_TRUE_STR XS_TEXT("true")
408 #define XS_FALSE_STR XS_TEXT("false")
409 #define XS_INTFMT_STR XS_TEXT("%d")
410 #define XS_FLOATFMT_STR XS_TEXT("%f")
411
412 #define XS_KEY_STR XS_TEXT("key")
413 #define XS_VALUE_STR XS_TEXT("value")
414 #define XS_PROPERTY_STR XS_TEXT("property")
415
416 // work around GCC's wide string constant bug
417 #ifdef __GNUC__
418 extern const LPCXSSTR XS_EMPTY;
419 extern const LPCXSSTR XS_TRUE;
420 extern const LPCXSSTR XS_FALSE;
421 extern const LPCXSSTR XS_INTFMT;
422 extern const LPCXSSTR XS_FLOATFMT;
423 #else
424 #define XS_EMPTY XS_EMPTY_STR
425 #define XS_TRUE XS_TRUE_STR
426 #define XS_FALSE XS_FALSE_STR
427 #define XS_INTFMT XS_INTFMT_STR
428 #define XS_FLOATFMT XS_FLOATFMT_STR
429 #endif
430
431 extern const XS_String XS_KEY;
432 extern const XS_String XS_VALUE;
433 extern const XS_String XS_PROPERTY;
434
435 #define CDATA_START "<![CDATA["
436 #define CDATA_END "]]>"
437
438
439 #ifndef XS_STRING_UTF8
440
441 // from UTF-8 to XS internal string encoding
442 inline void assign_utf8(XS_String& s, const char* str, size_t lutf8)
443 {
444 #ifdef UNICODE
445 LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8);
446 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, buffer, (int)lutf8);
447 #else
448 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8);
449 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, wbuffer, (int)lutf8);
450
451 int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
452 l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0);
453 #endif
454
455 s.assign(buffer, l);
456 }
457
458 // from UTF-8 to XS internal string encoding
459 inline void assign_utf8(XS_String& s, const char* str)
460 {
461 assign_utf8(s, str, strlen(str));
462 }
463
464 // from XS internal string encoding to UTF-8
465 inline std::string get_utf8(LPCTSTR s, size_t l)
466 {
467 #ifdef UNICODE
468 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
469 l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0);
470 #else
471 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
472 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
473
474 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
475 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
476 #endif
477
478 return std::string(buffer, l);
479 }
480
481 #ifdef UNICODE
482 // from XS internal string encoding to UTF-8
483 inline std::string get_utf8(const char* s, size_t l)
484 {
485 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
486 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
487
488 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
489 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
490
491 return std::string(buffer, l);
492 }
493 #endif
494
495 // from XS internal string encoding to UTF-8
496 inline std::string get_utf8(const XS_String& s)
497 {
498 return get_utf8(s.c_str(), s.length());
499 }
500
501 #endif // XS_STRING_UTF8
502
503 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false);
504 extern XS_String DecodeXMLString(const std::string& str);
505
506
507 #ifdef __GNUC__
508 #include <ext/stdio_filebuf.h>
509 #define FILE_FILEBUF __gnu_cxx::stdio_filebuf<char>
510 #elif defined(_MSC_VER)
511 #define FILE_FILEBUF std::filebuf
512 #endif
513
514 #ifdef FILE_FILEBUF
515
516 /// base class for XMLStorage::tifstream and XMLStorage::tofstream
517 struct FileHolder
518 {
519 FileHolder(LPCTSTR path, LPCTSTR mode)
520 {
521 //@@ _MS_VER: temporarily needed for the ReactOS build environment
522 #if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER) // secure CRT functions using VS 2005
523 if (_tfopen_s(&_pfile, path, mode) != 0)
524 _pfile = NULL;
525 #else
526 _pfile = _tfopen(path, mode);
527 #endif
528 }
529
530 ~FileHolder()
531 {
532 if (_pfile)
533 fclose(_pfile);
534 }
535
536 protected:
537 FILE* _pfile;
538 };
539
540 /// input file stream with ANSI/UNICODE file names
541 struct tifstream : public std::istream, FileHolder
542 {
543 typedef std::istream super;
544
545 tifstream(LPCTSTR path)
546 : super(&_buf),
547 FileHolder(path, TEXT("rb")), // binary mode is important for XMLReader::read_buffer() with MinGW libraries
548 #ifdef __GNUC__
549 _buf(_pfile, std::ios::in)
550 #else
551 _buf()
552 #endif
553 {
554 if (!_pfile)
555 setstate(badbit);
556 #ifdef _MSC_VER
557 else
558 _buf.open(fileno(_pfile));
559 #endif
560 }
561
562 protected:
563 FILE_FILEBUF _buf;
564 };
565
566 /// output file stream with ANSI/UNICODE file names
567 struct tofstream : public std::ostream, FileHolder
568 {
569 typedef std::ostream super;
570
571 tofstream(LPCTSTR path)
572 : super(&_buf),
573 FileHolder(path, TEXT("wb")),
574 #ifdef __GNUC__
575 _buf(_pfile, std::ios::out)
576 #else
577 _buf()
578 #endif
579 {
580 if (!_pfile)
581 setstate(badbit);
582 #ifdef _MSC_VER
583 else
584 _buf.open(fileno(_pfile));
585 #endif
586 }
587
588 ~tofstream()
589 {
590 flush();
591 }
592
593 protected:
594 FILE_FILEBUF _buf;
595 };
596
597 #else // FILE_FILEBUF
598
599 #ifdef UNICODE
600 #error UNICODE not supported for this platform
601 #endif
602
603 struct tifstream : public std::ifstream
604 {
605 typedef std::ifstream super;
606
607 tifstream(const char* path)
608 : super(path, std::ios::in|std::ios::binary)
609 {
610 }
611 };
612
613 struct tofstream : public std::ofstream
614 {
615 typedef std::ofstream super;
616
617 tofstream(const char* path)
618 : super(path, std::ios::out|std::ios::binary)
619 {
620 }
621 };
622
623 #endif
624
625
626 // write XML files with 2 spaces indenting
627 #define XML_INDENT_SPACE " "
628
629
630 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
631
632 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/ // Are Expat/Xerces XML strings UTF-16 encoded?
633 typedef XS_String String_from_XML_Char;
634
635 #elif defined(XS_STRING_UTF8)
636 typedef XS_String String_from_XML_Char;
637
638 #else
639
640 /// converter from Expat/Xerces strings to XMLStorage internal strings
641 struct String_from_XML_Char : public XS_String
642 {
643 String_from_XML_Char(const XML_Char* str)
644 {
645 assign_utf8(*this, str);
646 }
647 };
648
649 #endif
650
651 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
652
653
654 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
655
656 // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
657 inline bool operator==(const XS_String& s1, const char* s2)
658 {
659 LPCWSTR p = s1;
660 const unsigned char* q = (const unsigned char*)s2;
661
662 while(*p && *q)
663 if (*p++ != *q++)
664 return false;
665
666 return *p == *q;
667 };
668
669 #endif
670
671
672 /// XML Error with message and location
673 struct XMLError
674 {
675 XMLError()
676 : _line(0),
677 _column(0),
678 _error_code(0)
679 {
680 }
681
682 std::string str() const;
683 friend std::ostream& operator<<(std::ostream&, const XMLError& err);
684
685 XS_String _message;
686 XS_String _systemId;
687 int _line;
688 int _column;
689 int _error_code;
690 };
691
692 /// list of XMLError entries
693 struct XMLErrorList : public std::list<XMLError>
694 {
695 XS_String str() const;
696 };
697
698
699 #ifdef XMLNODE_LOCATION
700 /// location of XML Node including XML file name
701 struct XMLLocation
702 {
703 XMLLocation()
704 : _pdisplay_path(NULL),
705 _line(0),
706 _column(0)
707 {
708 }
709
710 XMLLocation(const char* display_path, int line, int column)
711 : _pdisplay_path(display_path),
712 _line(line),
713 _column(column)
714 {
715 }
716
717 std::string str() const;
718
719 protected:
720 const char* _pdisplay_path; // character pointer for fast reference
721 int _line;
722 int _column;
723 };
724 #endif
725
726
727 enum PRETTY_FLAGS {
728 PRETTY_PLAIN = 0,
729 PRETTY_LINEFEED = 1,
730 PRETTY_INDENT = 2
731 };
732
733
734 /// XML Stylesheet entry
735 struct StyleSheet
736 {
737 std::string _href; // CDATA #REQUIRED
738 std::string _type; // CDATA #REQUIRED
739 std::string _title; // CDATA #IMPLIED
740 std::string _media; // CDATA #IMPLIED
741 std::string _charset; // CDATA #IMPLIED
742 bool _alternate; // (yes|no) "no"
743
744 StyleSheet() : _alternate(false) {}
745
746 StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false)
747 : _href(href),
748 _type(type),
749 _alternate(alternate)
750 {
751 }
752
753 bool empty() const {return _href.empty();}
754 void print(std::ostream& out) const;
755 };
756
757 /// list of StyleSheet entries
758 struct StyleSheetList : public std::list<StyleSheet>
759 {
760 void set(const StyleSheet& stylesheet)
761 {
762 clear();
763 push_back(stylesheet);
764 }
765 };
766
767
768 /// XML document type description
769 struct DocType
770 {
771 std::string _name;
772
773 // External Document Types are noted, but not parsed.
774 std::string _public;
775 std::string _system;
776
777 // Internal DTDs are not supported.
778
779 void parse(const char* str);
780 bool empty() const {return _name.empty();}
781 };
782
783 /// Management of XML file headers and formating
784 struct XMLFormat
785 {
786 XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType())
787 : _pretty(pretty),
788 _endl("\n"),
789 _version(xml_version),
790 _encoding(encoding),
791 _doctype(doctype),
792 _standalone(-1)
793 {
794 }
795
796 void print_header(std::ostream& out, bool lf=true) const;
797
798 PRETTY_FLAGS _pretty;
799 const char* _endl; // line ending string: "\n" or "\r\n"
800
801 std::string _version;
802 std::string _encoding;
803
804 DocType _doctype;
805
806 StyleSheetList _stylesheets;
807
808 // std::string _additional;
809
810 int _standalone;
811 };
812
813
814 enum WRITE_MODE {
815 FORMAT_PLAIN, /// write XML without any white space
816 FORMAT_SMART, /// preserve original white space and comments if present; pretty print otherwise
817 FORMAT_ORIGINAL, /// write XML stream preserving original white space and comments
818 FORMAT_PRETTY /// pretty print node to stream without preserving original white space
819 };
820
821
822 struct XMLNode;
823
824 struct XPathElement
825 {
826 XPathElement() : _child_idx(-1) {}
827
828 XPathElement(const XS_String& child_name, int child_idx=-1)
829 : _child_name(child_name), _child_idx(child_idx) {}
830
831 XPathElement(const XS_String& child_name, int child_idx, const XS_String& attr_name, const XS_String& attr_value)
832 : _child_name(child_name), _child_idx(child_idx),
833 _attr_name(attr_name), _attr_value(attr_value)
834 {
835 }
836
837 XS_String _child_name;
838 int _child_idx;
839
840 XS_String _attr_name;
841 XS_String _attr_value;
842
843 const char* parse(const char* path);
844
845 XMLNode* find(XMLNode* node) const;
846 const XMLNode* const_find(const XMLNode* node) const;
847
848 bool matches(const XMLNode& node, int& n) const;
849 };
850
851 struct XPath : std::list<XPathElement>
852 {
853 XPath() : _absolute(false) {}
854 XPath(const char* path) {init(path);}
855 XPath(const std::string path) {init(path.c_str());}
856
857 void init(const char* path);
858
859 bool _absolute;
860 };
861
862
863 /// in memory representation of an XML node
864 struct XMLNode : public XS_String
865 {
866 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
867 /// map of XML node attributes
868 // optimized read access without temporary A/U conversion when using ASCII attribute names
869 struct AttributeMap : public std::map<XS_String, XS_String>
870 {
871 typedef std::map<XS_String, XS_String> super;
872
873 const_iterator find(const char* x) const
874 {
875 for(const_iterator it=begin(); it!=end(); ++it)
876 if (it->first == x)
877 return it;
878
879 return end();
880 }
881
882 const_iterator find(const key_type& x) const
883 {
884 return super::find(x);
885 }
886
887 iterator find(const key_type& x)
888 {
889 return super::find(x);
890 }
891
892 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
893 {
894 const_iterator found = find(x);
895
896 if (found != end())
897 return found->second;
898 else
899 return def;
900 }
901 };
902 #else
903 /// map of XML node attributes
904 struct AttributeMap : public std::map<XS_String, XS_String>
905 {
906 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
907 {
908 const_iterator found = find(x);
909
910 if (found != end())
911 return found->second;
912 else
913 return def;
914 }
915 };
916 #endif
917
918 /// internal children node list
919 struct Children : public std::list<XMLNode*>
920 {
921 typedef std::list<XMLNode*> super;
922
923 Children()
924 {
925 }
926
927 Children(Children& other)
928 {
929 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
930 push_back(*it);
931 }
932
933 void assign(Children& other)
934 {
935 clear();
936 move(other);
937 }
938
939 void move(Children& other)
940 {
941 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
942 push_back(*it);
943
944 other.reset();
945 }
946
947 Children& operator=(Children& other)
948 {
949 assign(other);
950 return *this;
951 }
952
953 void copy(const Children& other)
954 {
955 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
956 push_back(new XMLNode(**it));
957 }
958
959 void clear()
960 {
961 while(!empty()) {
962 XMLNode* node = back();
963 pop_back();
964
965 node->clear();
966 delete node;
967 }
968 }
969
970 bool remove(XMLNode* node)
971 {
972 for(iterator it=begin(); it!=end(); ++it)
973 if (*it == node) {
974 erase(it);
975 return true;
976 }
977
978 return false;
979 }
980
981 private:
982 void reset()
983 {
984 super::clear();
985 }
986 };
987
988 // access to protected class members for XMLPos and XMLReader
989 friend struct XMLPos;
990 friend struct const_XMLPos;
991 friend struct XMLReaderBase;
992 friend struct XPathElement;
993
994 XMLNode(const XS_String& name)
995 : XS_String(name),
996 _cdata_content(false)
997 {
998 }
999
1000 XMLNode(const XS_String& name, const std::string& leading)
1001 : XS_String(name),
1002 _leading(leading),
1003 _cdata_content(false)
1004 {
1005 }
1006
1007 XMLNode(const XMLNode& other)
1008 : XS_String(other),
1009 _attributes(other._attributes),
1010 _leading(other._leading),
1011 _content(other._content),
1012 _end_leading(other._end_leading),
1013 _trailing(other._trailing),
1014 #ifdef XMLNODE_LOCATION
1015 _location(other._location),
1016 #endif
1017 _cdata_content(false)
1018 {
1019 for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
1020 _children.push_back(new XMLNode(**it));
1021 }
1022
1023 enum COPY_FLAGS {COPY_NOCHILDREN};
1024
1025 XMLNode(const XMLNode& other, COPY_FLAGS copy_no_children)
1026 : XS_String(other),
1027 _attributes(other._attributes),
1028 _leading(other._leading),
1029 _content(other._content),
1030 _end_leading(other._end_leading),
1031 _trailing(other._trailing),
1032 #ifdef XMLNODE_LOCATION
1033 _location(other._location),
1034 #endif
1035 _cdata_content(false)
1036 {
1037 // assert(copy_no_children==COPY_NOCHILDREN);
1038 }
1039
1040 virtual ~XMLNode()
1041 {
1042 while(!_children.empty()) {
1043 delete _children.back();
1044 _children.pop_back();
1045 }
1046 }
1047
1048 void clear()
1049 {
1050 _leading.erase();
1051 _content.erase();
1052 _end_leading.erase();
1053 _trailing.erase();
1054
1055 _attributes.clear();
1056 _children.clear();
1057
1058 XS_String::erase();
1059 }
1060
1061 XMLNode& operator=(const XMLNode& other)
1062 {
1063 _children.clear();
1064 _children.copy(other._children);
1065
1066 _attributes = other._attributes;
1067
1068 _leading = other._leading;
1069 _content = other._content;
1070 _end_leading = other._end_leading;
1071 _trailing = other._trailing;
1072
1073 return *this;
1074 }
1075
1076 /// add a new child node
1077 void add_child(XMLNode* child)
1078 {
1079 _children.push_back(child);
1080 }
1081
1082 /// remove all children named 'name'
1083 void remove_children(const XS_String& name)
1084 {
1085 Children::iterator it, next=_children.begin();
1086
1087 while((it=next++) != _children.end())
1088 if (**it == name)
1089 _children.erase(it);
1090 }
1091
1092 /// write access to an attribute
1093 void put(const XS_String& attr_name, const XS_String& value)
1094 {
1095 _attributes[attr_name] = value;
1096 }
1097
1098 /// index operator write access to an attribute
1099 XS_String& operator[](const XS_String& attr_name)
1100 {
1101 return _attributes[attr_name];
1102 }
1103
1104 /// read only access to an attribute
1105 template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
1106 {
1107 AttributeMap::const_iterator found = _attributes.find(attr_name);
1108
1109 if (found != _attributes.end())
1110 return found->second;
1111 else
1112 return def;
1113 }
1114
1115 /// remove the attribute 'attr_name'
1116 void erase(const XS_String& attr_name)
1117 {
1118 _attributes.erase(attr_name);
1119 }
1120
1121 /// convenient value access in children node
1122 XS_String subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0) const
1123 {
1124 const XMLNode* node = XPathElement(child_name, n).const_find(this);
1125
1126 if (node)
1127 return node->get(attr_name);
1128 else
1129 return XS_String();
1130 }
1131
1132 /// convenient storage of distinct values in children node
1133 XS_String& subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0)
1134 {
1135 XMLNode* node = XPathElement(child_name, n).find(this);
1136
1137 if (!node) {
1138 node = new XMLNode(child_name);
1139 add_child(node);
1140 }
1141
1142 return (*node)[attr_name];
1143 }
1144
1145 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1146 /// convenient value access in children node
1147 XS_String subvalue(const char* child_name, const char* attr_name, int n=0) const
1148 {
1149 const XMLNode* node = XPathElement(child_name, n).const_find(this);
1150
1151 if (node)
1152 return node->get(attr_name);
1153 else
1154 return XS_String();
1155 }
1156
1157 /// convenient storage of distinct values in children node
1158 XS_String& subvalue(const char* child_name, const XS_String& attr_name, int n=0)
1159 {
1160 XMLNode* node = XPathElement(child_name, n).find(this);
1161
1162 if (!node) {
1163 node = new XMLNode(child_name);
1164 add_child(node);
1165 }
1166
1167 return (*node)[attr_name];
1168 }
1169 #endif
1170
1171 const Children& get_children() const
1172 {
1173 return _children;
1174 }
1175
1176 Children& get_children()
1177 {
1178 return _children;
1179 }
1180
1181 const AttributeMap& get_attributes() const
1182 {
1183 return _attributes;
1184 }
1185
1186 AttributeMap& get_attributes()
1187 {
1188 return _attributes;
1189 }
1190
1191 /// read element node content
1192 XS_String get_content() const
1193 {
1194 return DecodeXMLString(_content);
1195 }
1196
1197 /// read content of a subnode specified by an XPath expression
1198 XS_String get_sub_content(const XPath& xpath) const
1199 {
1200 const XMLNode* node = find_relative(xpath);
1201
1202 if (node)
1203 return node->get_content();
1204 else
1205 return XS_EMPTY_STR;
1206 }
1207
1208 /// set element node content
1209 void set_content(const XS_String& s, bool cdata=false)
1210 {
1211 _content.assign(EncodeXMLString(s.c_str(), cdata));
1212 }
1213
1214 /// set content of a subnode specified by an XPath expression
1215 bool set_sub_content(const XPath& xpath, const XS_String& s, bool cdata=false)
1216 {
1217 XMLNode* node = create_relative(xpath);
1218
1219 if (node) {
1220 node->set_content(s, cdata);
1221 return true;
1222 } else
1223 return false;
1224 }
1225
1226 #ifdef XMLNODE_LOCATION
1227 const XMLLocation& get_location() const {return _location;}
1228 #endif
1229
1230 /// write node with children tree to output stream
1231 bool write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
1232 {
1233 switch(mode) {
1234 case FORMAT_PLAIN:
1235 plain_write_worker(out);
1236 break;
1237
1238 case FORMAT_PRETTY:
1239 pretty_write_worker(out, format, indent);
1240 break;
1241
1242 case FORMAT_ORIGINAL:
1243 original_write_worker(out);
1244 break;
1245
1246 default: // FORMAT_SMART
1247 smart_write_worker(out, format, indent);
1248 }
1249
1250 return out.good();
1251 }
1252
1253 /// count the nodes matching the given relative XPath expression
1254 int count(const XPath& xpath) const
1255 {
1256 return count(xpath.begin(), xpath.end());
1257 }
1258
1259 /// count the nodes matching the given relative XPath expression
1260 int count(XPath::const_iterator from, const XPath::const_iterator& to) const;
1261
1262 /// copy matching tree nodes using the given XPath filter expression
1263 bool filter(const XPath& xpath, XMLNode& target) const;
1264
1265 /// XPath find function (const)
1266 const XMLNode* find_relative(const XPath& xpath) const;
1267
1268 /// XPath find function
1269 XMLNode* find_relative(const XPath& xpath);
1270
1271 XMLNode* get_first_child() const
1272 {
1273 if (!_children.empty())
1274 return _children.front();
1275 else
1276 return NULL;
1277 }
1278
1279 protected:
1280 Children _children;
1281 AttributeMap _attributes;
1282
1283 std::string _leading; // UTF-8 encoded
1284 std::string _content; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
1285 std::string _end_leading; // UTF-8 encoded
1286 std::string _trailing; // UTF-8 encoded
1287
1288 #ifdef XMLNODE_LOCATION
1289 XMLLocation _location;
1290 #endif
1291
1292 bool _cdata_content;
1293
1294 /// relative XPath create function
1295 XMLNode* create_relative(const XPath& xpath);
1296
1297 /// create a new node tree using the given XPath filter expression
1298 XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const;
1299
1300 void original_write_worker(std::ostream& out) const;
1301 void plain_write_worker(std::ostream& out) const;
1302 void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
1303 void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
1304 };
1305
1306
1307 /// iterator access to children nodes with name filtering
1308 struct XMLChildrenFilter
1309 {
1310 XMLChildrenFilter(XMLNode::Children& children, const XS_String& name)
1311 : _begin(children.begin(), children.end(), name),
1312 _end(children.end(), children.end(), name)
1313 {
1314 }
1315
1316 XMLChildrenFilter(XMLNode* node, const XS_String& name)
1317 : _begin(node->get_children().begin(), node->get_children().end(), name),
1318 _end(node->get_children().end(), node->get_children().end(), name)
1319 {
1320 }
1321
1322 /// internal iterator class
1323 struct iterator
1324 {
1325 typedef XMLNode::Children::iterator BaseIterator;
1326 typedef iterator myType;
1327
1328 iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
1329 : _cur(begin),
1330 _end(end),
1331 _filter_name(filter_name)
1332 {
1333 search_next();
1334 }
1335
1336 operator BaseIterator()
1337 {
1338 return _cur;
1339 }
1340
1341 const XMLNode* operator*() const
1342 {
1343 return *_cur;
1344 }
1345
1346 XMLNode* operator*()
1347 {
1348 return *_cur;
1349 }
1350
1351 myType& operator++()
1352 {
1353 ++_cur;
1354 search_next();
1355
1356 return *this;
1357 }
1358
1359 myType operator++(int)
1360 {
1361 myType ret = *this;
1362
1363 ++_cur;
1364 search_next();
1365
1366 return ret;
1367 }
1368
1369 bool operator==(const myType& other) const
1370 {
1371 return _cur == other._cur;
1372 }
1373
1374 bool operator!=(const myType& other) const
1375 {
1376 return _cur != other._cur;
1377 }
1378
1379 protected:
1380 BaseIterator _cur;
1381 BaseIterator _end;
1382 XS_String _filter_name;
1383
1384 void search_next()
1385 {
1386 while(_cur!=_end && **_cur!=_filter_name)
1387 ++_cur;
1388 }
1389 };
1390
1391 iterator begin()
1392 {
1393 return _begin;
1394 }
1395
1396 iterator end()
1397 {
1398 return _end;
1399 }
1400
1401 protected:
1402 iterator _begin;
1403 iterator _end;
1404 };
1405
1406
1407 /// read only iterator access to children nodes with name filtering
1408 struct const_XMLChildrenFilter
1409 {
1410 const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name)
1411 : _begin(children.begin(), children.end(), name),
1412 _end(children.end(), children.end(), name)
1413 {
1414 }
1415
1416 const_XMLChildrenFilter(const XMLNode* node, const XS_String& name)
1417 : _begin(node->get_children().begin(), node->get_children().end(), name),
1418 _end(node->get_children().end(), node->get_children().end(), name)
1419 {
1420 }
1421
1422 /// internal iterator class
1423 struct const_iterator
1424 {
1425 typedef XMLNode::Children::const_iterator BaseIterator;
1426 typedef const_iterator myType;
1427
1428 const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
1429 : _cur(begin),
1430 _end(end),
1431 _filter_name(filter_name)
1432 {
1433 search_next();
1434 }
1435
1436 operator BaseIterator()
1437 {
1438 return _cur;
1439 }
1440
1441 const XMLNode* operator*() const
1442 {
1443 return *_cur;
1444 }
1445
1446 myType& operator++()
1447 {
1448 ++_cur;
1449 search_next();
1450
1451 return *this;
1452 }
1453
1454 myType operator++(int)
1455 {
1456 myType ret = *this;
1457
1458 ++_cur;
1459 search_next();
1460
1461 return ret;
1462 }
1463
1464 bool operator==(const myType& other) const
1465 {
1466 return _cur == other._cur;
1467 }
1468
1469 bool operator!=(const myType& other) const
1470 {
1471 return _cur != other._cur;
1472 }
1473
1474 protected:
1475 BaseIterator _cur;
1476 BaseIterator _end;
1477 XS_String _filter_name;
1478
1479 void search_next()
1480 {
1481 while(_cur!=_end && **_cur!=_filter_name)
1482 ++_cur;
1483 }
1484 };
1485
1486 const_iterator begin()
1487 {
1488 return _begin;
1489 }
1490
1491 const_iterator end()
1492 {
1493 return _end;
1494 }
1495
1496 protected:
1497 const_iterator _begin;
1498 const_iterator _end;
1499 };
1500
1501
1502 /// iterator for XML trees
1503 struct XMLPos
1504 {
1505 XMLPos(XMLNode* root)
1506 : _root(root),
1507 _cur(root)
1508 {
1509 }
1510
1511 XMLPos(const XMLPos& other)
1512 : _root(other._root),
1513 _cur(other._cur)
1514 { // don't copy _stack
1515 }
1516
1517 XMLPos(XMLNode* node, const XS_String& name)
1518 : _root(node),
1519 _cur(node)
1520 {
1521 smart_create(name);
1522 }
1523
1524 XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
1525 : _root(node),
1526 _cur(node)
1527 {
1528 smart_create(name, attr_name, attr_value);
1529 }
1530
1531 XMLPos(const XMLPos& other, const XS_String& name)
1532 : _root(other._root),
1533 _cur(other._cur)
1534 {
1535 smart_create(name);
1536 }
1537
1538 XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
1539 : _root(other._root),
1540 _cur(other._cur)
1541 {
1542 smart_create(name, attr_name, attr_value);
1543 }
1544
1545 /// access to current node
1546 XMLNode& cur()
1547 {
1548 return *_cur;
1549 }
1550
1551 const XMLNode& cur() const
1552 {
1553 return *_cur;
1554 }
1555
1556 /// automatic access to current node
1557 operator const XMLNode*() const {return _cur;}
1558 operator XMLNode*() {return _cur;}
1559
1560 const XMLNode* operator->() const {return _cur;}
1561 XMLNode* operator->() {return _cur;}
1562
1563 const XMLNode& operator*() const {return *_cur;}
1564 XMLNode& operator*() {return *_cur;}
1565
1566 /// attribute access
1567 XS_String get(const XS_String& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
1568 {
1569 return _cur->get(attr_name, def);
1570 }
1571
1572 /// attribute setting
1573 void put(const XS_String& attr_name, const XS_String& value)
1574 {
1575 _cur->put(attr_name, value);
1576 }
1577
1578 /// index operator attribute access
1579 template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
1580 XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
1581 const XS_String& operator[](const XS_String& attr_name) const {return (*_cur)[attr_name];}
1582
1583 /// insert children when building tree
1584 void add_down(XMLNode* child)
1585 {
1586 _cur->add_child(child);
1587 go_to(child);
1588 }
1589
1590 /// go back to previous position
1591 bool back()
1592 {
1593 if (!_stack.empty()) {
1594 _cur = _stack.top();
1595 _stack.pop();
1596 return true;
1597 } else
1598 return false;
1599 }
1600
1601 /// go down to first child
1602 bool go_down()
1603 {
1604 XMLNode* node = _cur->get_first_child();
1605
1606 if (node) {
1607 go_to(node);
1608 return true;
1609 } else
1610 return false;
1611 }
1612
1613 /// search for child and go down
1614 bool go_down(const XS_String& child_name, int n=0)
1615 {
1616 XMLNode* node = XPathElement(child_name, n).find(_cur);
1617
1618 if (node) {
1619 go_to(node);
1620 return true;
1621 } else
1622 return false;
1623 }
1624
1625 /// iterate to the next matching child
1626 bool iterate(const XS_String& child_name, size_t& cnt)
1627 {
1628 XMLNode* node = XPathElement(child_name, cnt).find(_cur);
1629
1630 if (node) {
1631 go_to(node);
1632 ++cnt;
1633 return true;
1634 } else
1635 return false;
1636 }
1637
1638 /// move to the position defined by xpath in XML tree
1639 bool go(const XPath& xpath);
1640
1641 /// create child nodes using XPath notation and move to the deepest child
1642 bool create_relative(const XPath& xpath)
1643 {
1644 XMLNode* node = _cur->create_relative(xpath);
1645 if (!node)
1646 return false; // invalid path specified
1647
1648 go_to(node);
1649 return true;
1650 }
1651
1652 /// create node and move to it
1653 void create(const XS_String& name)
1654 {
1655 add_down(new XMLNode(name));
1656 }
1657
1658 /// create node with string content
1659 void create_node_content(const XS_String& node_name, const XS_String& content)
1660 {
1661 XMLNode* pNode = new XMLNode(node_name);
1662 pNode->set_content(content);
1663 _cur->add_child(pNode);
1664 }
1665
1666 /// create node if not already existing and move to it
1667 void smart_create(const XS_String& child_name)
1668 {
1669 XMLNode* node = XPathElement(child_name).find(_cur);
1670
1671 if (node)
1672 go_to(node);
1673 else
1674 add_down(new XMLNode(child_name));
1675 }
1676
1677 /// search matching child node identified by key name and an attribute value
1678 void smart_create(const XS_String& child_name, const XS_String& attr_name, const XS_String& attr_value)
1679 {
1680 XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
1681
1682 if (node)
1683 go_to(node);
1684 else {
1685 node = new XMLNode(child_name);
1686 add_down(node);
1687 (*node)[attr_name] = attr_value;
1688 }
1689 }
1690
1691 /// count the nodes matching the given relative XPath expression
1692 int count(const XPath& xpath) const
1693 {
1694 return _cur->count(xpath);
1695 }
1696
1697 /// create a new node tree using the given XPath filter expression
1698 int filter(const XPath& xpath, XMLNode& target) const
1699 {
1700 return _cur->filter(xpath, target);
1701 }
1702
1703 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1704 /// search for child and go down
1705 bool go_down(const char* child_name, int n=0)
1706 {
1707 XMLNode* node = XPathElement(child_name, n).find(_cur);
1708
1709 if (node) {
1710 go_to(node);
1711 return true;
1712 } else
1713 return false;
1714 }
1715
1716 /// create node and move to it
1717 void create(const char* child_name)
1718 {
1719 add_down(new XMLNode(child_name));
1720 }
1721
1722 /// create node if not already existing and move to it
1723 void smart_create(const char* child_name)
1724 {
1725 XMLNode* node = XPathElement(child_name).find(_cur);
1726
1727 if (node)
1728 go_to(node);
1729 else
1730 add_down(new XMLNode(child_name));
1731 }
1732
1733 /// search matching child node identified by key name and an attribute value
1734 template<typename T, typename U>
1735 void smart_create(const char* child_name, const T& attr_name, const U& attr_value)
1736 {
1737 XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
1738
1739 if (node)
1740 go_to(node);
1741 else {
1742 node = new XMLNode(child_name);
1743 add_down(node);
1744 (*node)[attr_name] = attr_value;
1745 }
1746 }
1747 #endif
1748
1749 /// delete current node and go back to previous position
1750 bool delete_this()
1751 {
1752 if (!_stack.empty()) {
1753 XMLNode* pLast = _stack.top();
1754
1755 if (pLast->_children.remove(_cur)) {
1756 _cur = _stack.top();
1757 return true;
1758 }
1759 }
1760
1761 return false;
1762 }
1763
1764 /// remove all children named 'name'
1765 void remove_children(const XS_String& name)
1766 {
1767 _cur->remove_children(name);
1768 }
1769
1770 /// remove the attribute 'attr_name' from the current node
1771 void erase(const XS_String& attr_name)
1772 {
1773 _cur->erase(attr_name);
1774 }
1775
1776 XS_String& str() {return *_cur;}
1777 const XS_String& str() const {return *_cur;}
1778
1779 // property (key/value pair) setter functions
1780 void set_property(const XS_String& key, int value, const XS_String& name=XS_PROPERTY);
1781 void set_property(const XS_String& key, double value, const XS_String& name=XS_PROPERTY);
1782 void set_property(const XS_String& key, const XS_String& value, const XS_String& name=XS_PROPERTY);
1783 void set_property(const XS_String& key, const struct XMLBool& value, const XS_String& name=XS_PROPERTY);
1784
1785 void set_property(const XS_String& key, const char* value, const XS_String& name=XS_PROPERTY)
1786 {set_property(key, XS_String(value), name);}
1787
1788 protected:
1789 friend struct const_XMLPos; // access to _root
1790
1791 XMLNode* _root;
1792 XMLNode* _cur;
1793 std::stack<XMLNode*> _stack;
1794
1795 /// go to specified node
1796 void go_to(XMLNode* child)
1797 {
1798 _stack.push(_cur);
1799 _cur = child;
1800 }
1801 };
1802
1803
1804 /// iterator for XML trees
1805 struct const_XMLPos
1806 {
1807 const_XMLPos(const XMLNode* root)
1808 : _root(root),
1809 _cur(root)
1810 {
1811 }
1812
1813 const_XMLPos(const const_XMLPos& other)
1814 : _root(other._root),
1815 _cur(other._cur)
1816 { // don't copy _stack
1817 }
1818
1819 const_XMLPos(const XMLPos& other)
1820 : _root(other._root),
1821 _cur(other._cur)
1822 { // don't copy _stack
1823 }
1824
1825 /// access to current node
1826 const XMLNode& cur() const
1827 {
1828 return *_cur;
1829 }
1830
1831 /// automatic access to current node
1832 operator const XMLNode*() const {return _cur;}
1833
1834 const XMLNode* operator->() const {return _cur;}
1835
1836 const XMLNode& operator*() const {return *_cur;}
1837
1838 /// attribute access
1839 XS_String get(const XS_String& attr_name) const
1840 {
1841 return _cur->get(attr_name);
1842 }
1843
1844 /// index operator attribute access
1845 template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
1846 XS_String operator[](const XS_String& attr_name) const {return _cur->get(attr_name);}
1847
1848 /// go back to previous position
1849 bool back()
1850 {
1851 if (!_stack.empty()) {
1852 _cur = _stack.top();
1853 _stack.pop();
1854 return true;
1855 } else
1856 return false;
1857 }
1858
1859 /// go down to first child
1860 bool go_down()
1861 {
1862 const XMLNode* node = _cur->get_first_child();
1863
1864 if (node) {
1865 go_to(node);
1866 return true;
1867 } else
1868 return false;
1869 }
1870
1871 /// search for child and go down
1872 bool go_down(const XS_String& child_name, int n=0)
1873 {
1874 const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
1875
1876 if (node) {
1877 go_to(node);
1878 return true;
1879 } else
1880 return false;
1881 }
1882
1883 /// iterate to the next matching child
1884 bool iterate(const XS_String& child_name, size_t& cnt)
1885 {
1886 const XMLNode* node = XPathElement(child_name, cnt).const_find(_cur);
1887
1888 if (node) {
1889 go_to(node);
1890 ++cnt;
1891 return true;
1892 } else
1893 return false;
1894 }
1895
1896 /// move to the position defined by xpath in XML tree
1897 bool go(const XPath& xpath);
1898
1899 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1900 /// search for child and go down
1901 bool go_down(const char* child_name, int n=0)
1902 {
1903 const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
1904
1905 if (node) {
1906 go_to(node);
1907 return true;
1908 } else
1909 return false;
1910 }
1911 #endif
1912
1913 const XS_String& str() const {return *_cur;}
1914
1915 protected:
1916 const XMLNode* _root;
1917 const XMLNode* _cur;
1918 std::stack<const XMLNode*> _stack;
1919
1920 /// go to specified node
1921 void go_to(const XMLNode* child)
1922 {
1923 _stack.push(_cur);
1924 _cur = child;
1925 }
1926 };
1927
1928
1929 /// type converter for boolean data
1930 struct XMLBool
1931 {
1932 XMLBool(bool value=false)
1933 : _value(value)
1934 {
1935 }
1936
1937 XMLBool(LPCXSSTR value, bool def=false)
1938 {
1939 if (value && *value)//@@ also handle white space and return def instead of false
1940 _value = !XS_icmp(value, XS_TRUE);
1941 else
1942 _value = def;
1943 }
1944
1945 XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false)
1946 {
1947 const XS_String& value = node->get(attr_name);
1948
1949 if (!value.empty())
1950 _value = !XS_icmp(value.c_str(), XS_TRUE);
1951 else
1952 _value = def;
1953 }
1954
1955 operator bool() const
1956 {
1957 return _value;
1958 }
1959
1960 bool operator!() const
1961 {
1962 return !_value;
1963 }
1964
1965 operator LPCXSSTR() const
1966 {
1967 return _value? XS_TRUE: XS_FALSE;
1968 }
1969
1970 protected:
1971 bool _value;
1972
1973 private:
1974 void operator=(const XMLBool&); // disallow assignment operations
1975 };
1976
1977 /// type converter for boolean data with write access
1978 struct XMLBoolRef
1979 {
1980 XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false)
1981 : _ref((*node)[attr_name])
1982 {
1983 if (_ref.empty())
1984 assign(def);
1985 }
1986
1987 operator bool() const
1988 {
1989 return !XS_icmp(_ref.c_str(), XS_TRUE);
1990 }
1991
1992 bool operator!() const
1993 {
1994 return XS_icmp(_ref.c_str(), XS_TRUE)? true: false;
1995 }
1996
1997 XMLBoolRef& operator=(bool value)
1998 {
1999 assign(value);
2000
2001 return *this;
2002 }
2003
2004 void assign(bool value)
2005 {
2006 _ref.assign(value? XS_TRUE: XS_FALSE);
2007 }
2008
2009 void toggle()
2010 {
2011 assign(!operator bool());
2012 }
2013
2014 protected:
2015 XS_String& _ref;
2016 };
2017
2018
2019 /// type converter for integer data
2020 struct XMLInt
2021 {
2022 XMLInt(int value)
2023 : _value(value)
2024 {
2025 }
2026
2027 XMLInt(LPCXSSTR value, int def=0)
2028 {
2029 if (value && *value)//@@ also handle white space and return def instead of 0
2030 _value = XS_toi(value);
2031 else
2032 _value = def;
2033 }
2034
2035 XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0)
2036 {
2037 const XS_String& value = node->get(attr_name);
2038
2039 if (!value.empty())
2040 _value = XS_toi(value.c_str());
2041 else
2042 _value = def;
2043 }
2044
2045 operator int() const
2046 {
2047 return _value;
2048 }
2049
2050 operator XS_String() const
2051 {
2052 XS_CHAR buffer[32];
2053 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
2054 return XS_String(buffer);
2055 }
2056
2057 protected:
2058 int _value;
2059
2060 private:
2061 void operator=(const XMLInt&); // disallow assignment operations
2062 };
2063
2064 /// type converter for integer data with write access
2065 struct XMLIntRef
2066 {
2067 XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0)
2068 : _ref((*node)[attr_name])
2069 {
2070 if (_ref.empty())
2071 assign(def);
2072 }
2073
2074 XMLIntRef& operator=(int value)
2075 {
2076 assign(value);
2077
2078 return *this;
2079 }
2080
2081 operator int() const
2082 {
2083 return XS_toi(_ref.c_str());
2084 }
2085
2086 void assign(int value)
2087 {
2088 XS_CHAR buffer[32];
2089 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
2090 _ref.assign(buffer);
2091 }
2092
2093 protected:
2094 XS_String& _ref;
2095 };
2096
2097
2098 /// type converter for numeric data
2099 struct XMLDouble
2100 {
2101 XMLDouble(double value)
2102 : _value(value)
2103 {
2104 }
2105
2106 XMLDouble(LPCXSSTR value, double def=0.)
2107 {
2108 LPTSTR end;
2109
2110 if (value && *value)//@@ also handle white space and return def instead of 0
2111 _value = XS_tod(value, &end);
2112 else
2113 _value = def;
2114 }
2115
2116 XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
2117 {
2118 LPTSTR end;
2119 const XS_String& value = node->get(attr_name);
2120
2121 if (!value.empty())
2122 _value = XS_tod(value.c_str(), &end);
2123 else
2124 _value = def;
2125 }
2126
2127 operator double() const
2128 {
2129 return _value;
2130 }
2131
2132 operator XS_String() const
2133 {
2134 XS_CHAR buffer[32];
2135 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
2136 return XS_String(buffer);
2137 }
2138
2139 protected:
2140 double _value;
2141
2142 private:
2143 void operator=(const XMLDouble&); // disallow assignment operations
2144 };
2145
2146 /// type converter for numeric data with write access
2147 struct XMLDoubleRef
2148 {
2149 XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
2150 : _ref((*node)[attr_name])
2151 {
2152 if (_ref.empty())
2153 assign(def);
2154 }
2155
2156 XMLDoubleRef& operator=(double value)
2157 {
2158 assign(value);
2159
2160 return *this;
2161 }
2162
2163 operator double() const
2164 {
2165 LPTSTR end;
2166 return XS_tod(_ref.c_str(), &end);
2167 }
2168
2169 void assign(double value)
2170 {
2171 XS_CHAR buffer[32];
2172 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
2173 _ref.assign(buffer);
2174 }
2175
2176 protected:
2177 XS_String& _ref;
2178 };
2179
2180
2181 /// type converter for string data
2182 struct XMLString
2183 {
2184 XMLString(const XS_String& value)
2185 : _value(value)
2186 {
2187 }
2188
2189 XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY)
2190 {
2191 if (value && *value)
2192 _value = value;
2193 else
2194 _value = def;
2195 }
2196
2197 XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
2198 {
2199 const XS_String& value = node->get(attr_name);
2200
2201 if (!value.empty())
2202 _value = value;
2203 else
2204 _value = def;
2205 }
2206
2207 operator const XS_String&() const
2208 {
2209 return _value;
2210 }
2211
2212 const XS_String& c_str() const
2213 {
2214 return _value;
2215 }
2216
2217 protected:
2218 XS_String _value;
2219
2220 private:
2221 void operator=(const XMLString&); // disallow assignment operations
2222 };
2223
2224 /// type converter for string data with write access
2225 struct XMLStringRef
2226 {
2227 XMLStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
2228 : _ref((*node)[attr_name])
2229 {
2230 if (_ref.empty())
2231 assign(def);
2232 }
2233
2234 XMLStringRef(const XS_String& node_name, XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
2235 : _ref(node->subvalue(node_name, attr_name))
2236 {
2237 if (_ref.empty())
2238 assign(def);
2239 }
2240
2241 XMLStringRef& operator=(const XS_String& value)
2242 {
2243 assign(value);
2244
2245 return *this;
2246 }
2247
2248 operator const XS_String&() const
2249 {
2250 return _ref;
2251 }
2252
2253 void assign(const XS_String& value)
2254 {
2255 _ref.assign(value);
2256 }
2257
2258 protected:
2259 XS_String& _ref;
2260 };
2261
2262
2263 // read option (for example configuration) values from XML node attributes
2264 template<typename T>
2265 inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
2266 {
2267 const XS_String& val = cfg.get(key);
2268
2269 if (!val.empty())
2270 var = val;
2271 }
2272
2273 // read integer option values from XML node attributes
2274 template<>
2275 inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
2276 {
2277 const XS_String& val = cfg.get(key);
2278
2279 if (!val.empty())
2280 var = XS_toi(val.c_str());
2281 }
2282
2283
2284 inline void XMLPos::set_property(const XS_String& key, int value, const XS_String& name)
2285 {
2286 smart_create(name, XS_KEY, key);
2287 XMLIntRef(_cur, XS_VALUE) = value;
2288 back();
2289 }
2290
2291 inline void XMLPos::set_property(const XS_String& key, double value, const XS_String& name)
2292 {
2293 smart_create(name, XS_KEY, key);
2294 XMLDoubleRef(_cur, XS_VALUE) = value;
2295 back();
2296 }
2297
2298 inline void XMLPos::set_property(const XS_String& key, const XS_String& value, const XS_String& name)
2299 {
2300 smart_create(name, XS_KEY, key);
2301 put(XS_VALUE, value);
2302 back();
2303 }
2304
2305 inline void XMLPos::set_property(const XS_String& key, const XMLBool& value, const XS_String& name)
2306 {
2307 smart_create(name, XS_KEY, key);
2308 XMLBoolRef(_cur, XS_VALUE) = value;
2309 back();
2310 }
2311
2312
2313 /// a key/value pair for property data access
2314 struct XMLProperty {
2315 XMLProperty(const XMLNode* node)
2316 : _key(node->get(XS_KEY)),
2317 _value(node->get(XS_VALUE))
2318 {
2319 }
2320
2321 XS_String _key;
2322 XS_String _value;
2323 };
2324
2325
2326 /// utility class to read property settings from a XML tree
2327 struct XMLPropertyReader
2328 {
2329 XMLPropertyReader(const XMLNode::Children& children)
2330 : _filter(children, XS_PROPERTY),
2331 _begin(_filter.begin(), _filter.end()),
2332 _end(_filter.end(), _filter.end())
2333 {
2334 }
2335
2336 XMLPropertyReader(const XMLNode* node)
2337 : _filter(node, XS_PROPERTY),
2338 _begin(_filter.begin(), _filter.end()),
2339 _end(_filter.end(), _filter.end())
2340 {
2341 }
2342
2343 /// internal iterator class
2344 struct const_iterator
2345 {
2346 typedef const_XMLChildrenFilter::const_iterator BaseIterator;
2347 typedef const_iterator myType;
2348
2349 const_iterator(BaseIterator begin, BaseIterator end)
2350 : _cur(begin),
2351 _end(end)
2352 {
2353 }
2354
2355 operator BaseIterator()
2356 {
2357 return _cur;
2358 }
2359
2360 XMLProperty operator*() const
2361 {
2362 return XMLProperty(*_cur);
2363 }
2364
2365 const XMLNode* get_node() const
2366 {
2367 return *_cur;
2368 }
2369
2370 myType& operator++()
2371 {
2372 ++_cur;
2373
2374 return *this;
2375 }
2376
2377 myType operator++(int)
2378 {
2379 myType ret = *this;
2380
2381 ++_cur;
2382
2383 return ret;
2384 }
2385
2386 bool operator==(const myType& other) const
2387 {
2388 return _cur == other._cur;
2389 }
2390
2391 bool operator!=(const myType& other) const
2392 {
2393 return _cur != other._cur;
2394 }
2395
2396 protected:
2397 BaseIterator _cur;
2398 BaseIterator _end;
2399 };
2400
2401 const_iterator begin()
2402 {
2403 return _begin;
2404 }
2405
2406 const_iterator end()
2407 {
2408 return _end;
2409 }
2410
2411 protected:
2412 const_XMLChildrenFilter _filter;
2413
2414 const_iterator _begin;
2415 const_iterator _end;
2416 };
2417
2418
2419 #ifdef _MSC_VER
2420 #pragma warning(disable: 4355)
2421 #endif
2422
2423 /// XML reader base class
2424 struct XMLReaderBase
2425 #ifdef XS_USE_XERCES
2426 : public HandlerBase
2427 #endif
2428 {
2429 #ifdef XS_USE_XERCES
2430
2431 XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false);
2432 virtual ~XMLReaderBase();
2433
2434 void read();
2435
2436 protected:
2437 SAXParser* _parser;
2438 InputSource* _source;
2439 bool _deleteSource;
2440
2441 virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr,
2442 const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr);
2443
2444 // Handlers for the SAX DocumentHandler interface
2445 virtual void setDocumentLocator(const Locator* const locator);
2446 virtual void startElement(const XMLCh* const name, AttributeList& attributes);
2447 virtual void endElement(const XMLCh* const name);
2448 virtual void characters(const XMLCh* const chars, const unsigned int length);
2449 virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
2450
2451 // Handlers for the SAX ErrorHandler interface
2452 virtual void error(const SAXParseException& e);
2453 virtual void fatalError(const SAXParseException& e);
2454 virtual void warning(const SAXParseException& e);
2455 virtual void resetErrors();
2456
2457 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
2458
2459 XMLReaderBase(XMLNode* node);
2460 virtual ~XMLReaderBase();
2461
2462 protected:
2463 XML_Parser _parser;
2464
2465 static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1);
2466 static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
2467 static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
2468 static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len);
2469
2470 static std::string get_expat_error_string(XML_Error error_code);
2471
2472 #else // XS_USE_EXPAT
2473
2474 XMLReaderBase(XMLNode* node)
2475 : _pos(node),
2476 _endl_defined(false),
2477 _utf8(false)
2478 {
2479 _last_tag = TAG_NONE;
2480 }
2481
2482 virtual ~XMLReaderBase();
2483
2484 bool parse();
2485
2486 #endif
2487
2488 public:
2489 #ifndef XS_USE_XERCES
2490 void read();
2491
2492 std::string get_position() const;
2493 #endif
2494 const XMLFormat& get_format() const {return _format;}
2495 const char* get_endl() const {return _endl_defined? _format._endl: "\n";}
2496
2497 const XMLErrorList& get_errors() const {return _errors;}
2498 const XMLErrorList& get_warnings() const {return _warnings;}
2499
2500 void clear_errors() {_errors.clear(); _warnings.clear();}
2501
2502 #ifdef XMLNODE_LOCATION
2503 const char* _display_path; // character pointer for fast reference in XMLLocation
2504
2505 #ifdef XS_USE_XERCES
2506 const Locator* _locator;
2507 #endif
2508
2509 XMLLocation get_location() const;
2510 #endif
2511
2512 protected:
2513 XMLPos _pos;
2514
2515 std::string _content; // UTF-8 encoded
2516 enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
2517
2518 XMLErrorList _errors;
2519 XMLErrorList _warnings;
2520
2521 XMLFormat _format;
2522 bool _endl_defined;
2523
2524 #ifdef XS_USE_XERCES
2525 //@@
2526 #elif defined(XS_USE_EXPAT)
2527 virtual int read_buffer(char* buffer, int len) = 0;
2528 #else
2529 virtual int get() = 0;
2530 int eat_endl();
2531
2532 bool _utf8;
2533 #endif
2534
2535 void finish_read();
2536
2537 virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone);
2538 virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
2539 virtual void EndElementHandler();
2540 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
2541 virtual void DefaultHandler(const XML_Char* s, int len);
2542 #else
2543 virtual void DefaultHandler(const std::string& s);
2544 #endif
2545 };
2546
2547
2548 /// XML file reader
2549
2550 #ifdef XS_USE_XERCES
2551
2552 struct XercesXMLReader : public XMLReaderBase
2553 {
2554 XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false)
2555 : XMLReaderBase(node, source, adoptSource)
2556 {
2557 }
2558
2559 XercesXMLReader(XMLNode* node, LPCTSTR path);
2560 XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string());
2561 };
2562
2563 #define XMLReader XercesXMLReader
2564
2565 #elif defined(XS_USE_EXPAT)
2566
2567 struct ExpatXMLReader : public XMLReaderBase
2568 {
2569 ExpatXMLReader(XMLNode* node, std::istream& in)
2570 : XMLReaderBase(node),
2571 _in(in)
2572 {
2573 }
2574
2575 /// read XML stream into XML tree below _pos
2576 int read_buffer(char* buffer, int len)
2577 {
2578 if (!_in.good())
2579 return -1;
2580
2581 _in.read(buffer, len);
2582
2583 return _in.gcount();
2584 }
2585
2586 protected:
2587 std::istream& _in;
2588 };
2589
2590 #define XMLReader ExpatXMLReader
2591
2592 #else // XS_USE_XERCES, XS_USE_EXPAT
2593
2594 struct XMLReader : public XMLReaderBase
2595 {
2596 XMLReader(XMLNode* node, std::istream& in)
2597 : XMLReaderBase(node),
2598 _in(in)
2599 {
2600 }
2601
2602 /// read one character from XML stream
2603 int get()
2604 {
2605 return _in.get();
2606 }
2607
2608 protected:
2609 std::istream& _in;
2610 };
2611
2612 #endif // XS_USE_XERCES
2613
2614
2615 #if defined(_MSC_VER) && _MSC_VER<1400
2616
2617 struct fast_ostringbuffer : public std::streambuf
2618 {
2619 typedef char _E;
2620 typedef std::char_traits<_E> _Tr;
2621
2622 explicit fast_ostringbuffer()
2623 {_Init(0, 0, std::_Noread);} // optimized for ios::out mode
2624
2625 virtual ~fast_ostringbuffer()
2626 {_Tidy();}
2627
2628 std::string str() const
2629 {if (pptr() != 0)
2630 {std::string _Str(pbase(),
2631 (_Seekhigh<pptr()? pptr(): _Seekhigh) - pbase());
2632 return _Str;}
2633 else
2634 return std::string();}
2635
2636 protected:
2637 virtual int_type overflow(int_type _C = _Tr::eof())
2638 {if (_Tr::eq_int_type(_Tr::eof(), _C))
2639 return _Tr::not_eof(_C);
2640 else if (pptr() != 0 && pptr() < epptr())
2641 {*_Pninc() = _Tr::to_char_type(_C);
2642 return _C;}
2643 else
2644 {size_t _Os = gptr() == 0 ? 0 : epptr() - eback();
2645 size_t _Ns = _Os + _Alsize;
2646 _E *_P = _Al.allocate(_Ns, (void *)0);
2647 if (0 < _Os)
2648 _Tr::copy(_P, eback(), _Os);
2649 else if (_ALSIZE < _Alsize)
2650 _Alsize = _ALSIZE;
2651
2652 if (_Strmode & std::_Allocated)
2653 _Al.deallocate(eback(), _Os);
2654
2655 _Strmode |= std::_Allocated;
2656
2657 if (_Os == 0)
2658 {_Seekhigh = _P;
2659 setp(_P, _P + _Ns);
2660 setg(_P, _P, _P); }
2661 else
2662 {_Seekhigh = _Seekhigh - eback() + _P;
2663 setp(pbase() - eback() + _P, pptr() - eback() + _P, _P + _Ns);
2664 setg(_P, _P, _P);}
2665 *_Pninc() = _Tr::to_char_type(_C);
2666
2667 return _C;}}
2668
2669 void _Init(const _E *_S, size_t _N, std::_Strstate _M)
2670 {_Pendsave = 0, _Seekhigh = 0;
2671 _Alsize = _MINSIZE, _Strmode = _M;
2672 setg(0, 0, 0);
2673 setp(0, 0);}
2674
2675 void _Tidy()
2676 {if (_Strmode & std::_Allocated)
2677 _Al.deallocate(eback(), (pptr() != 0 ? epptr() : egptr()) - eback());
2678 _Seekhigh = 0;
2679 _Strmode &= ~std::_Allocated;}
2680
2681 private:
2682 enum {_ALSIZE = 65536/*512*/, _MINSIZE = 32768/*32*/}; // bigger buffer sizes
2683
2684 _E *_Pendsave, *_Seekhigh;
2685 int _Alsize;
2686 std::_Strstate _Strmode;
2687 std::allocator<_E> _Al;
2688 };
2689
2690 struct fast_ostringstream : public std::iostream
2691 {
2692 typedef std::iostream super;
2693
2694 explicit fast_ostringstream()
2695 : super(&_Sb) {}
2696
2697 std::string str() const
2698 {return _Sb.str();}
2699
2700 private:
2701 fast_ostringbuffer _Sb;
2702 };
2703
2704 #else
2705
2706 typedef std::ostringstream fast_ostringstream;
2707
2708 #endif
2709
2710
2711 /// XML document holder
2712 struct XMLDoc : public XMLNode
2713 {
2714 XMLDoc()
2715 : XMLNode("")
2716 {
2717 }
2718
2719 XMLDoc(LPCTSTR path)
2720 : XMLNode("")
2721 {
2722 read_file(path);
2723 }
2724
2725 #ifdef XS_USE_XERCES
2726 bool read_file(LPCTSTR path)
2727 {
2728 XMLReader reader(this, path);
2729
2730 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2731 return read(reader, std::string(ANS(path)));
2732 #else
2733 return read(reader, XS_String(path));
2734 #endif
2735 }
2736
2737 bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
2738 {
2739 XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
2740
2741 return read(reader, system_id);
2742 }
2743
2744 bool read_buffer(const std::string& in, const std::string& system_id=std::string())
2745 {
2746 return read_buffer(in.c_str(), in.length(), system_id);
2747 }
2748
2749 #else // XS_USE_XERCES
2750
2751 bool read_file(LPCTSTR path)
2752 {
2753 tifstream in(path);
2754 if (!in.good())
2755 return false;
2756
2757 XMLReader reader(this, in);
2758
2759 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2760 return read(reader, std::string(ANS(path)));
2761 #else
2762 return read(reader, XS_String(path));
2763 #endif
2764 }
2765
2766 bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
2767 {
2768 return read_buffer(std::string(buffer, len), system_id);
2769 }
2770
2771 bool read_buffer(const std::string& buffer, const std::string& system_id=std::string())
2772 {
2773 std::istringstream istr(buffer);
2774
2775 return read_stream(istr, system_id);
2776 }
2777
2778 bool read_stream(std::istream& in, const std::string& system_id=std::string())
2779 {
2780 XMLReader reader(this, in);
2781
2782 return read(reader, system_id);
2783 }
2784 #endif // XS_USE_XERCES
2785
2786 bool read(XMLReaderBase& reader, const std::string& display_path)
2787 {
2788 #ifdef XMLNODE_LOCATION
2789 // make a string copy to handle temporary string objects
2790 _display_path = display_path;
2791 reader._display_path = _display_path.c_str();
2792 #endif
2793
2794 reader.clear_errors();
2795 reader.read();
2796
2797 _format = reader.get_format();
2798 _format._endl = reader.get_endl();
2799
2800 if (!reader.get_errors().empty()) {
2801 _errors = reader.get_errors();
2802 return false;
2803 }
2804
2805 return true;
2806 }
2807
2808 /// write XML stream
2809 // FORMAT_SMART: preserving previous white space and comments
2810 bool write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
2811 {
2812 _format.print_header(out, mode!=FORMAT_PLAIN);
2813
2814 if (_children.size() == 1)
2815 _children.front()->write(out, _format, mode);
2816 else if (!_children.empty()) {
2817 //throw Exception("more than one XML root!");
2818 return false;
2819 }
2820
2821 return out.good();
2822 }
2823
2824 /// write XML stream with formating
2825 bool write_formating(std::ostream& out) const
2826 {
2827 return write(out, FORMAT_PRETTY);
2828 }
2829
2830 bool write_file(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
2831 {
2832 tofstream out(path);
2833
2834 return write(out, mode);
2835 }
2836
2837 bool write_formating(LPCTSTR path) const
2838 {
2839 tofstream out(path);
2840
2841 return write_formating(out);
2842 }
2843
2844 XMLFormat _format;
2845 XMLErrorList _errors;
2846
2847 #ifdef XMLNODE_LOCATION
2848 std::string _display_path;
2849 #endif
2850 };
2851
2852
2853 /// XML message wrapper
2854 struct XMLMessage : public XMLDoc
2855 {
2856 XMLMessage(const char* name)
2857 : _pos(this)
2858 {
2859 _pos.create(name);
2860 }
2861
2862 std::string toString() const
2863 {
2864 std::ostringstream out;
2865
2866 write(out);
2867
2868 return out.str();
2869 }
2870
2871 XMLPos _pos;
2872
2873 protected:
2874 XMLMessage()
2875 : _pos(this)
2876 {
2877 }
2878 };
2879
2880
2881 /// helper structure to read XML messages from strings
2882 struct XMLMessageFromString : public XMLMessage
2883 {
2884 XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string())
2885 {
2886 read_buffer(xml_str.c_str(), xml_str.length(), system_id);
2887 }
2888 };
2889
2890
2891 /// Reader for XML Messages
2892 struct XMLMessageReader : public XMLPos
2893 {
2894 XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string())
2895 : XMLPos(&_msg)
2896 {
2897 _msg.read_buffer(xml_str.c_str(), xml_str.length(), system_id);
2898 }
2899
2900 const XMLDoc& get_document()
2901 {
2902 return _msg;
2903 }
2904
2905 protected:
2906 XMLDoc _msg;
2907 };
2908
2909
2910 /// on the fly XML writer
2911 struct XMLWriter
2912 {
2913 XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat())
2914 : _pofstream(NULL),
2915 _out(out),
2916 _format(format)
2917 {
2918 format.print_header(_out, false); // _format._endl is printed in write_pre()
2919 }
2920
2921 XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat())
2922 : _pofstream(new tofstream(path)),
2923 _out(*_pofstream),
2924 _format(format)
2925 {
2926 format.print_header(_out, false); // _format._endl is printed in write_pre()
2927 }
2928
2929 ~XMLWriter()
2930 {
2931 _out << _format._endl;
2932 delete _pofstream;
2933 }
2934
2935 /// create node and move to it
2936 void create(const XS_String& name);
2937
2938 /// go back to previous position
2939 bool back();
2940
2941 /// attribute setting
2942 void put(const XS_String& attr_name, const XS_String& value)
2943 {
2944 if (!_stack.empty())
2945 _stack.top()._attributes[attr_name] = value;
2946 }
2947
2948 /// index operator write access to an attribute
2949 XS_String& operator[](const XS_String& attr_name)
2950 {
2951 if (_stack.empty())
2952 return s_empty_attr;
2953
2954 return _stack.top()._attributes[attr_name];
2955 }
2956
2957 void set_content(const XS_String& s, bool cdata=false)
2958 {
2959 if (!_stack.empty())
2960 _stack.top()._content = EncodeXMLString(s.c_str(), cdata);
2961 }
2962
2963 /// create node with string content
2964 void create_node_content(const XS_String& node_name, const XS_String& content)
2965 {
2966 create(node_name);
2967 set_content(content);
2968 back();
2969 }
2970
2971 // public for access in StackEntry
2972 enum WRITESTATE {
2973 NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
2974 };
2975
2976 protected:
2977 tofstream* _pofstream;
2978 std::ostream& _out;
2979 XMLFormat _format;
2980
2981 typedef XMLNode::AttributeMap AttrMap;
2982
2983 /// container for XMLWriter state information
2984 struct StackEntry {
2985 XS_String _node_name;
2986 AttrMap _attributes;
2987 std::string _content;
2988 WRITESTATE _state;
2989 bool _children;
2990
2991 StackEntry() : _state(NOTHING), _children(false) {}
2992 };
2993
2994 std::stack<StackEntry> _stack;
2995
2996 static XS_String s_empty_attr;
2997
2998 void close_pre(StackEntry& entry);
2999 void write_pre(StackEntry& entry);
3000 void write_attributes(StackEntry& entry);
3001 void write_post(StackEntry& entry);
3002 };
3003
3004
3005 } // namespace XMLStorage
3006
3007 #define _XMLSTORAGE_H
3008 #endif // _XMLSTORAGE_H