move from branch
[reactos.git] / reactos / base / shell / explorer / utility / xmlstorage.h
1
2 //
3 // XML storage classes Version 1.1
4 //
5 // Copyright (c) 2004, 2005, 2006 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 #if _MSC_VER>=1400
44 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
45 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
46 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1
47 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES 1
48 #endif
49 #endif
50
51
52 #ifdef XS_USE_XERCES
53
54 #ifndef UNICODE
55 #ifndef XS_STRING_UTF8
56 #define XS_STRING_UTF8
57 #endif
58 #endif
59
60 #include <xercesc/parsers/SAXParser.hpp>
61 #include <xercesc/sax/HandlerBase.hpp>
62
63 using XERCES_CPP_NAMESPACE_QUALIFIER Locator;
64 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser;
65 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase;
66 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource;
67 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList;
68 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException;
69
70 typedef XMLCh XML_Char;
71
72 #elif defined(XS_USE_EXPAT)
73
74 #include <expat/expat.h>
75
76 #endif
77
78
79 #ifdef _MSC_VER
80 #pragma warning(disable: 4786)
81
82 #ifndef XS_NO_COMMENT
83
84 #ifdef XS_USE_XERCES
85 #ifdef _DEBUG
86 #pragma comment(lib, "xerces-c_2D")
87 #else
88 #pragma comment(lib, "xerces-c_2")
89 #endif
90 #elif defined(XS_USE_EXPAT)
91 #ifdef XML_STATIC
92 #ifndef _DEBUG
93 #pragma comment(lib, "libexpatMT")
94 #endif
95 #else
96 #pragma comment(lib, "libexpat")
97 #endif
98 #endif
99
100 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
101 #if defined(_DEBUG) && defined(_DLL) // DEBUG version only supported with MSVCRTD
102 #if _MSC_VER==1400
103 #pragma comment(lib, "xmlstorage-vc8d")
104 #else
105 #pragma comment(lib, "xmlstorage-vc6d")
106 #endif
107 #else
108 #ifdef _DLL
109 #if _MSC_VER==1400
110 #pragma comment(lib, "xmlstorage-vc8")
111 #else
112 #pragma comment(lib, "xmlstorage-vc6")
113 #endif
114 #elif defined(_MT)
115 #if _MSC_VER==1400
116 #pragma comment(lib, "xmlstorage-vc8t")
117 #else
118 #pragma comment(lib, "xmlstorage-vc6t")
119 #endif
120 #else
121 // -ML is no more supported by VS2005.
122 #pragma comment(lib, "xmlstorage-vc6l")
123 #endif
124 #endif
125 #endif // _STRING_DEFINED
126
127 #endif // XS_NO_COMMENT
128
129 #endif // _MSC_VER
130
131
132 #ifdef UNICODE
133 #ifndef _UNICODE
134 #define _UNICODE
135 #endif
136 #else
137 #ifdef _UNICODE
138 #define UNICODE
139 #endif
140 #endif
141
142 #include <windows.h> // for LPCTSTR
143
144 #include <tchar.h>
145 #include <malloc.h>
146
147 #include <fstream>
148 #include <sstream>
149 #include <string>
150 #include <stack>
151 #include <list>
152 #include <map>
153
154
155 #ifndef BUFFER_LEN
156 #define BUFFER_LEN 2048
157 #endif
158
159
160 namespace XMLStorage {
161
162
163 #ifndef XS_String
164
165 #ifdef XS_STRING_UTF8
166 #define XS_CHAR char
167 #define XS_TEXT(x) x
168 #define LPXSSTR LPSTR
169 #define LPCXSSTR LPCSTR
170 #define XS_cmp strcmp
171 #define XS_icmp stricmp
172 #define XS_ncmp strncmp
173 #define XS_nicmp strnicmp
174 #define XS_toi atoi
175 #define XS_tod strtod
176 #define XS_len strlen
177 #define XS_snprintf _snprintf
178 #define XS_vsnprintf _vsnprintf
179 #define XS_strstr strstr
180 #else
181 #define XS_CHAR TCHAR
182 #define XS_TEXT(x) TEXT(x)
183 #define LPXSSTR LPTSTR
184 #define LPCXSSTR LPCTSTR
185 #define XS_cmp _tcscmp
186 #define XS_icmp _tcsicmp
187 #define XS_ncmp _tcsncmp
188 #define XS_nicmp _tcsnicmp
189 #define XS_toi _ttoi
190 #define XS_tod _tcstod
191 #define XS_len _tcslen
192 #define XS_snprintf _sntprintf
193 #define XS_vsnprintf _vsntprintf
194 #define XS_strstr _tcsstr
195 #endif
196
197 #ifndef COUNTOF
198 #if _MSC_VER>=1400
199 #define COUNTOF _countof
200 #else
201 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
202 #endif
203 #endif
204
205
206 int inline isxmlsym(unsigned char c)
207 {
208 return isalnum(c) || c=='_' || c=='-';
209 }
210
211
212 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
213
214 #define XS_String String
215
216 #else // _STRING_DEFINED, !XS_STRING_UTF8
217
218 /// string class for TCHAR strings
219
220 struct XS_String
221 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
222 : public std::wstring
223 #else
224 : public std::string
225 #endif
226 {
227 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
228 typedef std::wstring super;
229 #else
230 typedef std::string super;
231 #endif
232
233 XS_String() {}
234
235 XS_String(LPCXSSTR s) {if (s) super::assign(s);}
236 XS_String(LPCXSSTR s, size_t l) : super(s, l) {}
237
238 XS_String(const super& other) : super(other) {}
239 XS_String(const XS_String& other) : super(other) {}
240
241 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
242 XS_String(LPCSTR s) {assign(s);}
243 XS_String(LPCSTR s, size_t l) {assign(s, l);}
244 XS_String(const std::string& other) {assign(other.c_str());}
245 XS_String& operator=(LPCSTR s) {assign(s); return *this;}
246 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();}
247 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();}
248 #else
249 XS_String(LPCWSTR s) {assign(s);}
250 XS_String(LPCWSTR s, size_t l) {assign(s, l);}
251 XS_String(const std::wstring& other) {assign(other.c_str());}
252 XS_String& operator=(LPCWSTR s) {assign(s); return *this;}
253 #ifdef XS_STRING_UTF8
254 void assign(const XS_String& s) {assign(s.c_str());}
255 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();}
256 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();}
257 #else // if !UNICODE && !XS_STRING_UTF8
258 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();}
259 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();}
260 #endif
261 #endif
262
263 XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;}
264 XS_String& operator=(const super& s) {super::assign(s); return *this;}
265 void assign(LPCXSSTR s) {super::assign(s);}
266 void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}
267
268 operator LPCXSSTR() const {return c_str();}
269
270 #ifdef XS_STRING_UTF8
271 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));}
272 #elif defined(UNICODE)
273 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));}
274 #else
275 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));}
276 #endif
277
278 XS_String& printf(LPCXSSTR fmt, ...)
279 {
280 va_list l;
281 XS_CHAR b[BUFFER_LEN];
282
283 va_start(l, fmt);
284 super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
285 va_end(l);
286
287 return *this;
288 }
289
290 XS_String& vprintf(LPCXSSTR fmt, va_list l)
291 {
292 XS_CHAR b[BUFFER_LEN];
293
294 super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
295
296 return *this;
297 }
298
299 XS_String& appendf(LPCXSSTR fmt, ...)
300 {
301 va_list l;
302 XS_CHAR b[BUFFER_LEN];
303
304 va_start(l, fmt);
305 super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
306 va_end(l);
307
308 return *this;
309 }
310
311 XS_String& vappendf(LPCXSSTR fmt, va_list l)
312 {
313 XS_CHAR b[BUFFER_LEN];
314
315 super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
316
317 return *this;
318 }
319 };
320
321 #endif // _STRING_DEFINED, !XS_STRING_UTF8
322
323 #endif // XS_String
324
325
326 #define XS_EMPTY_STR XS_TEXT("")
327 #define XS_TRUE_STR XS_TEXT("true")
328 #define XS_FALSE_STR XS_TEXT("false")
329 #define XS_INTFMT_STR XS_TEXT("%d")
330 #define XS_FLOATFMT_STR XS_TEXT("%f")
331
332 // work around GCC's wide string constant bug
333 #ifdef __GNUC__
334 extern const LPCXSSTR XS_EMPTY;
335 extern const LPCXSSTR XS_TRUE;
336 extern const LPCXSSTR XS_FALSE;
337 extern const LPCXSSTR XS_INTFMT;
338 extern const LPCXSSTR XS_FLOATFMT;
339 #else
340 #define XS_EMPTY XS_EMPTY_STR
341 #define XS_TRUE XS_TRUE_STR
342 #define XS_FALSE XS_FALSE_STR
343 #define XS_INTFMT XS_INTFMT_STR
344 #define XS_FLOATFMT XS_FLOATFMT_STR
345 #endif
346
347
348 #ifndef XS_STRING_UTF8
349
350 // from UTF-8 to XS internal string encoding
351 inline void assign_utf8(XS_String& s, const char* str, size_t lutf8)
352 {
353 #ifdef UNICODE
354 LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8);
355 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, buffer, (int)lutf8);
356 #else
357 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8);
358 int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, wbuffer, (int)lutf8);
359
360 int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
361 l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0);
362 #endif
363
364 s.assign(buffer, l);
365 }
366
367 // from UTF-8 to XS internal string encoding
368 inline void assign_utf8(XS_String& s, const char* str)
369 {
370 assign_utf8(s, str, strlen(str));
371 }
372
373 // from XS internal string encoding to UTF-8
374 inline std::string get_utf8(LPCTSTR s, size_t l)
375 {
376 #ifdef UNICODE
377 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
378 l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0);
379 #else
380 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
381 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
382
383 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
384 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
385 #endif
386
387 return std::string(buffer, l);
388 }
389
390 #ifdef UNICODE
391 // from XS internal string encoding to UTF-8
392 inline std::string get_utf8(const char* s, size_t l)
393 {
394 LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
395 l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
396
397 size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
398 l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
399
400 return std::string(buffer, l);
401 }
402 #endif
403
404 // from XS internal string encoding to UTF-8
405 inline std::string get_utf8(const XS_String& s)
406 {
407 return get_utf8(s.c_str(), s.length());
408 }
409
410 #endif // XS_STRING_UTF8
411
412 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false);
413 extern XS_String DecodeXMLString(const XS_String& str);
414
415
416 #ifdef __GNUC__
417 #include <ext/stdio_filebuf.h>
418 typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
419 #else
420 typedef std::filebuf STDIO_FILEBUF;
421 #endif
422
423 /// base class for XMLStorage::tifstream and XMLStorage::tofstream
424 struct FileHolder
425 {
426 FileHolder(LPCTSTR path, LPCTSTR mode)
427 {
428 #ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005
429 if (_tfopen_s(&_pfile, path, mode) != 0)
430 _pfile = NULL;
431 #else
432 _pfile = _tfopen(path, mode);
433 #endif
434 }
435
436 ~FileHolder()
437 {
438 if (_pfile)
439 fclose(_pfile);
440 }
441
442 protected:
443 FILE* _pfile;
444 };
445
446 /// input file stream with ANSI/UNICODE file names
447 struct tifstream : public std::istream, FileHolder
448 {
449 typedef std::istream super;
450
451 tifstream(LPCTSTR path)
452 : super(&_buf),
453 FileHolder(path, TEXT("rb")), // binary mode is important for XMLReader::read_buffer() with MinGW libraries
454 #ifdef __GNUC__
455 _buf(_pfile, std::ios::in)
456 #else
457 _buf(_pfile)
458 #endif
459 {
460 }
461
462 protected:
463 STDIO_FILEBUF _buf;
464 };
465
466 /// output file stream with ANSI/UNICODE file names
467 struct tofstream : public std::ostream, FileHolder
468 {
469 typedef std::ostream super;
470
471 tofstream(LPCTSTR path)
472 : super(&_buf),
473 FileHolder(path, TEXT("wb")),
474 #ifdef __GNUC__
475 _buf(_pfile, std::ios::out)
476 #else
477 _buf(_pfile)
478 #endif
479 {
480 }
481
482 ~tofstream()
483 {
484 flush();
485 }
486
487 protected:
488 STDIO_FILEBUF _buf;
489 };
490
491
492 // write XML files with 2 spaces indenting
493 #define XML_INDENT_SPACE " "
494
495
496 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
497
498 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/ // Are Expat/Xerces XML strings UTF-16 encoded?
499 typedef XS_String String_from_XML_Char;
500
501 #elif defined(XS_STRING_UTF8)
502 typedef XS_String String_from_XML_Char;
503
504 #else
505
506 /// converter from Expat/Xerces strings to XMLStorage internal strings
507 struct String_from_XML_Char : public XS_String
508 {
509 String_from_XML_Char(const XML_Char* str)
510 {
511 assign_utf8(*this, str);
512 }
513 };
514
515 #endif
516
517 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
518
519
520 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
521
522 // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
523 inline bool operator==(const XS_String& s1, const char* s2)
524 {
525 LPCWSTR p = s1;
526 const unsigned char* q = (const unsigned char*)s2;
527
528 while(*p && *q)
529 if (*p++ != *q++)
530 return false;
531
532 return *p == *q;
533 };
534
535 #endif
536
537
538 /// XML Error with message and location
539 struct XMLError
540 {
541 XMLError()
542 : _line(0),
543 _column(0),
544 _error_code(0)
545 {
546 }
547
548 std::string str() const;
549 friend std::ostream& operator<<(std::ostream&, const XMLError& err);
550
551 XS_String _message;
552 XS_String _systemId;
553 int _line;
554 int _column;
555 int _error_code;
556 };
557
558 /// list of XMLError entries
559 struct XMLErrorList : public std::list<XMLError>
560 {
561 XS_String str() const;
562 };
563
564
565 #ifdef XMLNODE_LOCATION
566 /// location of XML Node including XML file name
567 struct XMLLocation
568 {
569 XMLLocation()
570 : _pdisplay_path(NULL),
571 _line(0),
572 _column(0)
573 {
574 }
575
576 XMLLocation(const char* display_path, int line, int column)
577 : _pdisplay_path(display_path),
578 _line(line),
579 _column(column)
580 {
581 }
582
583 std::string str() const;
584
585 protected:
586 const char* _pdisplay_path; // character pointer for fast reference
587 int _line;
588 int _column;
589 };
590 #endif
591
592
593 enum PRETTY_FLAGS {
594 PRETTY_PLAIN = 0,
595 PRETTY_LINEFEED = 1,
596 PRETTY_INDENT = 2
597 };
598
599
600 /// XML Stylesheet entry
601 struct StyleSheet
602 {
603 std::string _href; // CDATA #REQUIRED
604 std::string _type; // CDATA #REQUIRED
605 std::string _title; // CDATA #IMPLIED
606 std::string _media; // CDATA #IMPLIED
607 std::string _charset; // CDATA #IMPLIED
608 bool _alternate; // (yes|no) "no"
609
610 StyleSheet() : _alternate(false) {}
611
612 StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false)
613 : _href(href),
614 _type(type),
615 _alternate(alternate)
616 {
617 }
618
619 bool empty() const {return _href.empty();}
620 void print(std::ostream& out) const;
621 };
622
623 /// list of StyleSheet entries
624 struct StyleSheetList : public std::list<StyleSheet>
625 {
626 void set(const StyleSheet& stylesheet)
627 {
628 clear();
629 push_back(stylesheet);
630 }
631 };
632
633
634 /// XML document type description
635 struct DocType
636 {
637 std::string _name;
638
639 // External Document Types are noted, but not parsed.
640 std::string _public;
641 std::string _system;
642
643 // Internal DTDs are not supported.
644
645 void parse(const char* str);
646 bool empty() const {return _name.empty();}
647 };
648
649 /// Management of XML file headers and formating
650 struct XMLFormat
651 {
652 XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType())
653 : _pretty(pretty),
654 _endl("\n"),
655 _version(xml_version),
656 _encoding(encoding),
657 _doctype(doctype),
658 _standalone(-1)
659 {
660 }
661
662 void print_header(std::ostream& out, bool lf=true) const;
663
664 PRETTY_FLAGS _pretty;
665 const char* _endl; // line ending string: "\n" or "\r\n"
666
667 std::string _version;
668 std::string _encoding;
669
670 DocType _doctype;
671
672 StyleSheetList _stylesheets;
673
674 // std::string _additional;
675
676 int _standalone;
677 };
678
679
680 enum WRITE_MODE {
681 FORMAT_PLAIN, /// write XML without any white space
682 FORMAT_SMART, /// preserve original white space and comments if present; pretty print otherwise
683 FORMAT_ORIGINAL, /// write XML stream preserving original white space and comments
684 FORMAT_PRETTY /// pretty print node to stream without preserving original white space
685 };
686
687
688 /// in memory representation of an XML node
689 struct XMLNode : public XS_String
690 {
691 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
692 /// map of XML node attributes
693 // optimized read access without temporary A/U conversion when using ASCII attribute names
694 struct AttributeMap : public std::map<XS_String, XS_String>
695 {
696 typedef std::map<XS_String, XS_String> super;
697
698 const_iterator find(const char* x) const
699 {
700 for(const_iterator it=begin(); it!=end(); ++it)
701 if (it->first == x)
702 return it;
703
704 return end();
705 }
706
707 const_iterator find(const key_type& x) const
708 {
709 return super::find(x);
710 }
711
712 iterator find(const key_type& x)
713 {
714 return super::find(x);
715 }
716
717 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
718 {
719 const_iterator found = find(x);
720
721 if (found != end())
722 return found->second;
723 else
724 return def;
725 }
726 };
727 #else
728 /// map of XML node attributes
729 struct AttributeMap : public std::map<XS_String, XS_String>
730 {
731 XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
732 {
733 const_iterator found = find(x);
734
735 if (found != end())
736 return found->second;
737 else
738 return def;
739 }
740 };
741 #endif
742
743 /// internal children node list
744 struct Children : public std::list<XMLNode*>
745 {
746 void assign(const Children& other)
747 {
748 clear();
749
750 for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
751 push_back(new XMLNode(**it));
752 }
753
754 void clear()
755 {
756 while(!empty()) {
757 XMLNode* node = back();
758 pop_back();
759
760 node->clear();
761 delete node;
762 }
763 }
764 };
765
766 // access to protected class members for XMLPos and XMLReader
767 friend struct XMLPos;
768 friend struct const_XMLPos;
769 friend struct XMLReaderBase;
770
771 XMLNode(const XS_String& name)
772 : XS_String(name)
773 {
774 }
775
776 XMLNode(const XS_String& name, const std::string& leading)
777 : XS_String(name),
778 _leading(leading)
779 {
780 }
781
782 XMLNode(const XMLNode& other)
783 : XS_String(other),
784 _attributes(other._attributes),
785 _leading(other._leading),
786 _content(other._content),
787 _end_leading(other._end_leading),
788 _trailing(other._trailing)
789 #ifdef XMLNODE_LOCATION
790 , _location(other._location)
791 #endif
792 {
793 for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
794 _children.push_back(new XMLNode(**it));
795 }
796
797 virtual ~XMLNode()
798 {
799 while(!_children.empty()) {
800 delete _children.back();
801 _children.pop_back();
802 }
803 }
804
805 void clear()
806 {
807 _leading.erase();
808 _content.erase();
809 _end_leading.erase();
810 _trailing.erase();
811
812 _attributes.clear();
813 _children.clear();
814
815 XS_String::erase();
816 }
817
818 XMLNode& operator=(const XMLNode& other)
819 {
820 _children.assign(other._children);
821
822 _attributes = other._attributes;
823
824 _leading = other._leading;
825 _content = other._content;
826 _end_leading = other._end_leading;
827 _trailing = other._trailing;
828
829 return *this;
830 }
831
832 /// add a new child node
833 void add_child(XMLNode* child)
834 {
835 _children.push_back(child);
836 }
837
838 /// write access to an attribute
839 void put(const XS_String& attr_name, const XS_String& value)
840 {
841 _attributes[attr_name] = value;
842 }
843
844 /// C++ write access to an attribute
845 XS_String& operator[](const XS_String& attr_name)
846 {
847 return _attributes[attr_name];
848 }
849
850 /// read only access to an attribute
851 template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
852 {
853 AttributeMap::const_iterator found = _attributes.find(attr_name);
854
855 if (found != _attributes.end())
856 return found->second;
857 else
858 return def;
859 }
860
861 /// convenient value access in children node
862 XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const
863 {
864 const XMLNode* node = find(name, n);
865
866 if (node)
867 return node->get(attr_name);
868 else
869 return XS_String();
870 }
871
872 /// convenient storage of distinct values in children node
873 XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
874 {
875 XMLNode* node = find(name, n);
876
877 if (!node) {
878 node = new XMLNode(name);
879 add_child(node);
880 }
881
882 return (*node)[attr_name];
883 }
884
885 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
886 /// convenient value access in children node
887 XS_String subvalue(const char* name, const char* attr_name, int n=0) const
888 {
889 const XMLNode* node = find(name, n);
890
891 if (node)
892 return node->get(attr_name);
893 else
894 return XS_String();
895 }
896
897 /// convenient storage of distinct values in children node
898 XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
899 {
900 XMLNode* node = find(name, n);
901
902 if (!node) {
903 node = new XMLNode(name);
904 add_child(node);
905 }
906
907 return (*node)[attr_name];
908 }
909 #endif
910
911 const Children& get_children() const
912 {
913 return _children;
914 }
915
916 Children& get_children()
917 {
918 return _children;
919 }
920
921 const AttributeMap& get_attributes() const
922 {
923 return _attributes;
924 }
925
926 AttributeMap& get_attributes()
927 {
928 return _attributes;
929 }
930
931 XS_String get_content() const
932 {
933 #ifdef XS_STRING_UTF8
934 const XS_String& ret = _content;
935 #else
936 XS_String ret;
937 assign_utf8(ret, _content.c_str(), _content.length());
938 #endif
939
940 return DecodeXMLString(ret.c_str());
941 }
942
943 void set_content(const XS_String& s, bool cdata=false)
944 {
945 _content.assign(EncodeXMLString(s.c_str(), cdata));
946 }
947
948 #ifdef XMLNODE_LOCATION
949 const XMLLocation& get_location() const {return _location;}
950 #endif
951
952 /// write node with children tree to output stream
953 std::ostream& write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
954 {
955 switch(mode) {
956 case FORMAT_PLAIN:
957 plain_write_worker(out);
958 break;
959
960 case FORMAT_PRETTY:
961 pretty_write_worker(out, format, indent);
962 break;
963
964 case FORMAT_ORIGINAL:
965 write_worker(out, indent);
966 break;
967
968 default: // FORMAT_SMART
969 smart_write_worker(out, format, indent);
970 }
971
972 return out;
973 }
974
975 protected:
976 Children _children;
977 AttributeMap _attributes;
978
979 std::string _leading; // UTF-8 encoded
980 std::string _content; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
981 std::string _end_leading; // UTF-8 encoded
982 std::string _trailing; // UTF-8 encoded
983
984 #ifdef XMLNODE_LOCATION
985 XMLLocation _location;
986 #endif
987
988 XMLNode* get_first_child() const
989 {
990 if (!_children.empty())
991 return _children.front();
992 else
993 return NULL;
994 }
995
996 XMLNode* find(const XS_String& name, int n=0) const
997 {
998 for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
999 if (**it == name)
1000 if (!n--)
1001 return *it;
1002
1003 return NULL;
1004 }
1005
1006 XMLNode* find(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value, int n=0) const
1007 {
1008 for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
1009 const XMLNode& node = **it;
1010
1011 if (node==name && node.get(attr_name)==attr_value)
1012 if (!n--)
1013 return *it;
1014 }
1015
1016 return NULL;
1017 }
1018
1019 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1020 XMLNode* find(const char* name, int n=0) const
1021 {
1022 for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
1023 if (**it == name)
1024 if (!n--)
1025 return *it;
1026
1027 return NULL;
1028 }
1029
1030 template<typename T, typename U>
1031 XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int n=0) const
1032 {
1033 for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
1034 const XMLNode& node = **it;
1035
1036 if (node==name && node.get(attr_name)==attr_value)
1037 if (!n--)
1038 return *it;
1039 }
1040
1041 return NULL;
1042 }
1043 #endif
1044
1045 /// XPath find function (const)
1046 const XMLNode* find_relative(const char* path) const;
1047
1048 /// XPath find function
1049 XMLNode* find_relative(const char* path)
1050 {return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
1051
1052 /// relative XPath create function
1053 XMLNode* create_relative(const char* path);
1054
1055 void write_worker(std::ostream& out, int indent) const;
1056 void plain_write_worker(std::ostream& out) const;
1057 void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
1058 void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
1059 };
1060
1061
1062 /// iterator access to children nodes with name filtering
1063 struct XMLChildrenFilter
1064 {
1065 XMLChildrenFilter(XMLNode::Children& children, const XS_String& name)
1066 : _begin(children.begin(), children.end(), name),
1067 _end(children.end(), children.end(), name)
1068 {
1069 }
1070
1071 XMLChildrenFilter(XMLNode* node, const XS_String& name)
1072 : _begin(node->get_children().begin(), node->get_children().end(), name),
1073 _end(node->get_children().end(), node->get_children().end(), name)
1074 {
1075 }
1076
1077 /// internal iterator class
1078 struct iterator
1079 {
1080 typedef XMLNode::Children::iterator BaseIterator;
1081
1082 iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
1083 : _cur(begin),
1084 _end(end),
1085 _filter_name(filter_name)
1086 {
1087 search_next();
1088 }
1089
1090 operator BaseIterator()
1091 {
1092 return _cur;
1093 }
1094
1095 const XMLNode* operator*() const
1096 {
1097 return *_cur;
1098 }
1099
1100 XMLNode* operator*()
1101 {
1102 return *_cur;
1103 }
1104
1105 iterator& operator++()
1106 {
1107 ++_cur;
1108 search_next();
1109
1110 return *this;
1111 }
1112
1113 iterator operator++(int)
1114 {
1115 iterator ret = *this;
1116
1117 ++_cur;
1118 search_next();
1119
1120 return ret;
1121 }
1122
1123 bool operator==(const BaseIterator& other) const
1124 {
1125 return _cur == other;
1126 }
1127
1128 bool operator!=(const BaseIterator& other) const
1129 {
1130 return _cur != other;
1131 }
1132
1133 protected:
1134 BaseIterator _cur;
1135 BaseIterator _end;
1136 XS_String _filter_name;
1137
1138 void search_next()
1139 {
1140 while(_cur!=_end && **_cur!=_filter_name)
1141 ++_cur;
1142 }
1143 };
1144
1145 iterator begin()
1146 {
1147 return _begin;
1148 }
1149
1150 iterator end()
1151 {
1152 return _end;
1153 }
1154
1155 protected:
1156 iterator _begin;
1157 iterator _end;
1158 };
1159
1160
1161 /// read only iterator access to children nodes with name filtering
1162 struct const_XMLChildrenFilter
1163 {
1164 const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name)
1165 : _begin(children.begin(), children.end(), name),
1166 _end(children.end(), children.end(), name)
1167 {
1168 }
1169
1170 const_XMLChildrenFilter(const XMLNode* node, const XS_String& name)
1171 : _begin(node->get_children().begin(), node->get_children().end(), name),
1172 _end(node->get_children().end(), node->get_children().end(), name)
1173 {
1174 }
1175
1176 /// internal iterator class
1177 struct const_iterator
1178 {
1179 typedef XMLNode::Children::const_iterator BaseIterator;
1180
1181 const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
1182 : _cur(begin),
1183 _end(end),
1184 _filter_name(filter_name)
1185 {
1186 search_next();
1187 }
1188
1189 operator BaseIterator()
1190 {
1191 return _cur;
1192 }
1193
1194 const XMLNode* operator*() const
1195 {
1196 return *_cur;
1197 }
1198
1199 const_iterator& operator++()
1200 {
1201 ++_cur;
1202 search_next();
1203
1204 return *this;
1205 }
1206
1207 const_iterator operator++(int)
1208 {
1209 const_iterator ret = *this;
1210
1211 ++_cur;
1212 search_next();
1213
1214 return ret;
1215 }
1216
1217 bool operator==(const BaseIterator& other) const
1218 {
1219 return _cur == other;
1220 }
1221
1222 bool operator!=(const BaseIterator& other) const
1223 {
1224 return _cur != other;
1225 }
1226
1227 protected:
1228 BaseIterator _cur;
1229 BaseIterator _end;
1230 XS_String _filter_name;
1231
1232 void search_next()
1233 {
1234 while(_cur!=_end && **_cur!=_filter_name)
1235 ++_cur;
1236 }
1237 };
1238
1239 const_iterator begin()
1240 {
1241 return _begin;
1242 }
1243
1244 const_iterator end()
1245 {
1246 return _end;
1247 }
1248
1249 protected:
1250 const_iterator _begin;
1251 const_iterator _end;
1252 };
1253
1254
1255 /// iterator for XML trees
1256 struct XMLPos
1257 {
1258 XMLPos(XMLNode* root)
1259 : _root(root),
1260 _cur(root)
1261 {
1262 }
1263
1264 XMLPos(const XMLPos& other)
1265 : _root(other._root),
1266 _cur(other._cur)
1267 { // don't copy _stack
1268 }
1269
1270 XMLPos(XMLNode* node, const XS_String& name)
1271 : _root(node),
1272 _cur(node)
1273 {
1274 smart_create(name);
1275 }
1276
1277 XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
1278 : _root(node),
1279 _cur(node)
1280 {
1281 smart_create(name, attr_name, attr_value);
1282 }
1283
1284 XMLPos(const XMLPos& other, const XS_String& name)
1285 : _root(other._root),
1286 _cur(other._cur)
1287 {
1288 smart_create(name);
1289 }
1290
1291 XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
1292 : _root(other._root),
1293 _cur(other._cur)
1294 {
1295 smart_create(name, attr_name, attr_value);
1296 }
1297
1298 /// access to current node
1299 XMLNode& cur()
1300 {
1301 return *_cur;
1302 }
1303
1304 const XMLNode& cur() const
1305 {
1306 return *_cur;
1307 }
1308
1309 /// C++ access to current node
1310 operator const XMLNode*() const {return _cur;}
1311 operator XMLNode*() {return _cur;}
1312
1313 const XMLNode* operator->() const {return _cur;}
1314 XMLNode* operator->() {return _cur;}
1315
1316 const XMLNode& operator*() const {return *_cur;}
1317 XMLNode& operator*() {return *_cur;}
1318
1319 /// attribute access
1320 XS_String get(const XS_String& attr_name) const
1321 {
1322 return _cur->get(attr_name);
1323 }
1324
1325 /// attribute setting
1326 void put(const XS_String& attr_name, const XS_String& value)
1327 {
1328 _cur->put(attr_name, value);
1329 }
1330
1331 /// C++ attribute access
1332 template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
1333 XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
1334
1335 /// insert children when building tree
1336 void add_down(XMLNode* child)
1337 {
1338 _cur->add_child(child);
1339 go_to(child);
1340 }
1341
1342 /// go back to previous position
1343 bool back()
1344 {
1345 if (!_stack.empty()) {
1346 _cur = _stack.top();
1347 _stack.pop();
1348 return true;
1349 } else
1350 return false;
1351 }
1352
1353 /// go down to first child
1354 bool go_down()
1355 {
1356 XMLNode* node = _cur->get_first_child();
1357
1358 if (node) {
1359 go_to(node);
1360 return true;
1361 } else
1362 return false;
1363 }
1364
1365 /// search for child and go down
1366 bool go_down(const XS_String& name, int n=0)
1367 {
1368 XMLNode* node = _cur->find(name, n);
1369
1370 if (node) {
1371 go_to(node);
1372 return true;
1373 } else
1374 return false;
1375 }
1376
1377 /// move XPath like to position in XML tree
1378 bool go(const char* path);
1379
1380 /// create child nodes using XPath notation and move to the deepest child
1381 bool create_relative(const char* path)
1382 {
1383 XMLNode* node = _cur->create_relative(path);
1384 if (!node)
1385 return false; // invalid path specified
1386
1387 go_to(node);
1388 return true;
1389 }
1390
1391 /// create node and move to it
1392 void create(const XS_String& name)
1393 {
1394 add_down(new XMLNode(name));
1395 }
1396
1397 /// create node if not already existing and move to it
1398 void smart_create(const XS_String& name)
1399 {
1400 XMLNode* node = _cur->find(name);
1401
1402 if (node)
1403 go_to(node);
1404 else
1405 add_down(new XMLNode(name));
1406 }
1407
1408 /// search matching child node identified by key name and an attribute value
1409 void smart_create(const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
1410 {
1411 XMLNode* node = _cur->find(name, attr_name, attr_value);
1412
1413 if (node)
1414 go_to(node);
1415 else {
1416 node = new XMLNode(name);
1417 add_down(node);
1418 (*node)[attr_name] = attr_value;
1419 }
1420 }
1421
1422 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1423 /// search for child and go down
1424 bool go_down(const char* name, int n=0)
1425 {
1426 XMLNode* node = _cur->find(name, n);
1427
1428 if (node) {
1429 go_to(node);
1430 return true;
1431 } else
1432 return false;
1433 }
1434
1435 /// create node and move to it
1436 void create(const char* name)
1437 {
1438 add_down(new XMLNode(name));
1439 }
1440
1441 /// create node if not already existing and move to it
1442 void smart_create(const char* name)
1443 {
1444 XMLNode* node = _cur->find(name);
1445
1446 if (node)
1447 go_to(node);
1448 else
1449 add_down(new XMLNode(name));
1450 }
1451
1452 /// search matching child node identified by key name and an attribute value
1453 template<typename T, typename U>
1454 void smart_create(const char* name, const T& attr_name, const U& attr_value)
1455 {
1456 XMLNode* node = _cur->find(name, attr_name, attr_value);
1457
1458 if (node)
1459 go_to(node);
1460 else {
1461 XMLNode* node = new XMLNode(name);
1462 add_down(node);
1463 (*node)[attr_name] = attr_value;
1464 }
1465 }
1466 #endif
1467
1468 XS_String& str() {return *_cur;}
1469 const XS_String& str() const {return *_cur;}
1470
1471 protected:
1472 XMLNode* _root;
1473 XMLNode* _cur;
1474 std::stack<XMLNode*> _stack;
1475
1476 /// go to specified node
1477 void go_to(XMLNode* child)
1478 {
1479 _stack.push(_cur);
1480 _cur = child;
1481 }
1482 };
1483
1484
1485 /// iterator for XML trees
1486 struct const_XMLPos
1487 {
1488 const_XMLPos(const XMLNode* root)
1489 : _root(root),
1490 _cur(root)
1491 {
1492 }
1493
1494 const_XMLPos(const const_XMLPos& other)
1495 : _root(other._root),
1496 _cur(other._cur)
1497 { // don't copy _stack
1498 }
1499
1500 /// access to current node
1501 const XMLNode& cur() const
1502 {
1503 return *_cur;
1504 }
1505
1506 /// C++ access to current node
1507 operator const XMLNode*() const {return _cur;}
1508
1509 const XMLNode* operator->() const {return _cur;}
1510
1511 const XMLNode& operator*() const {return *_cur;}
1512
1513 /// attribute access
1514 XS_String get(const XS_String& attr_name) const
1515 {
1516 return _cur->get(attr_name);
1517 }
1518
1519 /// C++ attribute access
1520 template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
1521
1522 /// go back to previous position
1523 bool back()
1524 {
1525 if (!_stack.empty()) {
1526 _cur = _stack.top();
1527 _stack.pop();
1528 return true;
1529 } else
1530 return false;
1531 }
1532
1533 /// go down to first child
1534 bool go_down()
1535 {
1536 const XMLNode* node = _cur->get_first_child();
1537
1538 if (node) {
1539 go_to(node);
1540 return true;
1541 } else
1542 return false;
1543 }
1544
1545 /// search for child and go down
1546 bool go_down(const XS_String& name, int n=0)
1547 {
1548 XMLNode* node = _cur->find(name, n);
1549
1550 if (node) {
1551 go_to(node);
1552 return true;
1553 } else
1554 return false;
1555 }
1556
1557 /// move XPath like to position in XML tree
1558 bool go(const char* path);
1559
1560 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
1561 /// search for child and go down
1562 bool go_down(const char* name, int n=0)
1563 {
1564 XMLNode* node = _cur->find(name, n);
1565
1566 if (node) {
1567 go_to(node);
1568 return true;
1569 } else
1570 return false;
1571 }
1572 #endif
1573
1574 const XS_String& str() const {return *_cur;}
1575
1576 protected:
1577 const XMLNode* _root;
1578 const XMLNode* _cur;
1579 std::stack<const XMLNode*> _stack;
1580
1581 /// go to specified node
1582 void go_to(const XMLNode* child)
1583 {
1584 _stack.push(_cur);
1585 _cur = child;
1586 }
1587 };
1588
1589
1590 /// type converter for boolean data
1591 struct XMLBool
1592 {
1593 XMLBool(bool value=false)
1594 : _value(value)
1595 {
1596 }
1597
1598 XMLBool(LPCXSSTR value, bool def=false)
1599 {
1600 if (value && *value)
1601 _value = !XS_icmp(value, XS_TRUE);
1602 else
1603 _value = def;
1604 }
1605
1606 XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false)
1607 {
1608 const XS_String& value = node->get(attr_name);
1609
1610 if (!value.empty())
1611 _value = !XS_icmp(value.c_str(), XS_TRUE);
1612 else
1613 _value = def;
1614 }
1615
1616 operator bool() const
1617 {
1618 return _value;
1619 }
1620
1621 bool operator!() const
1622 {
1623 return !_value;
1624 }
1625
1626 operator LPCXSSTR() const
1627 {
1628 return _value? XS_TRUE: XS_FALSE;
1629 }
1630
1631 protected:
1632 bool _value;
1633
1634 private:
1635 void operator=(const XMLBool&); // disallow assignment operations
1636 };
1637
1638 /// type converter for boolean data with write access
1639 struct XMLBoolRef
1640 {
1641 XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false)
1642 : _ref((*node)[attr_name])
1643 {
1644 if (_ref.empty())
1645 assign(def);
1646 }
1647
1648 operator bool() const
1649 {
1650 return !XS_icmp(_ref.c_str(), XS_TRUE);
1651 }
1652
1653 bool operator!() const
1654 {
1655 return XS_icmp(_ref.c_str(), XS_TRUE)? true: false;
1656 }
1657
1658 XMLBoolRef& operator=(bool value)
1659 {
1660 assign(value);
1661
1662 return *this;
1663 }
1664
1665 void assign(bool value)
1666 {
1667 _ref.assign(value? XS_TRUE: XS_FALSE);
1668 }
1669
1670 void toggle()
1671 {
1672 assign(!operator bool());
1673 }
1674
1675 protected:
1676 XS_String& _ref;
1677 };
1678
1679
1680 /// type converter for integer data
1681 struct XMLInt
1682 {
1683 XMLInt(int value)
1684 : _value(value)
1685 {
1686 }
1687
1688 XMLInt(LPCXSSTR value, int def=0)
1689 {
1690 if (value && *value)
1691 _value = XS_toi(value);
1692 else
1693 _value = def;
1694 }
1695
1696 XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0)
1697 {
1698 const XS_String& value = node->get(attr_name);
1699
1700 if (!value.empty())
1701 _value = XS_toi(value.c_str());
1702 else
1703 _value = def;
1704 }
1705
1706 operator int() const
1707 {
1708 return _value;
1709 }
1710
1711 operator XS_String() const
1712 {
1713 XS_CHAR buffer[32];
1714 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
1715 return buffer;
1716 }
1717
1718 protected:
1719 int _value;
1720
1721 private:
1722 void operator=(const XMLInt&); // disallow assignment operations
1723 };
1724
1725 /// type converter for integer data with write access
1726 struct XMLIntRef
1727 {
1728 XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0)
1729 : _ref((*node)[attr_name])
1730 {
1731 if (_ref.empty())
1732 assign(def);
1733 }
1734
1735 XMLIntRef& operator=(int value)
1736 {
1737 assign(value);
1738
1739 return *this;
1740 }
1741
1742 operator int() const
1743 {
1744 return XS_toi(_ref.c_str());
1745 }
1746
1747 void assign(int value)
1748 {
1749 XS_CHAR buffer[32];
1750 XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
1751 _ref.assign(buffer);
1752 }
1753
1754 protected:
1755 XS_String& _ref;
1756 };
1757
1758
1759 /// type converter for numeric data
1760 struct XMLDouble
1761 {
1762 XMLDouble(double value)
1763 : _value(value)
1764 {
1765 }
1766
1767 XMLDouble(LPCXSSTR value, double def=0.)
1768 {
1769 LPTSTR end;
1770
1771 if (value && *value)
1772 _value = XS_tod(value, &end);
1773 else
1774 _value = def;
1775 }
1776
1777 XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
1778 {
1779 LPTSTR end;
1780 const XS_String& value = node->get(attr_name);
1781
1782 if (!value.empty())
1783 _value = XS_tod(value.c_str(), &end);
1784 else
1785 _value = def;
1786 }
1787
1788 operator double() const
1789 {
1790 return _value;
1791 }
1792
1793 operator XS_String() const
1794 {
1795 XS_CHAR buffer[32];
1796 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
1797 return buffer;
1798 }
1799
1800 protected:
1801 double _value;
1802
1803 private:
1804 void operator=(const XMLDouble&); // disallow assignment operations
1805 };
1806
1807 /// type converter for numeric data with write access
1808 struct XMLDoubleRef
1809 {
1810 XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
1811 : _ref((*node)[attr_name])
1812 {
1813 if (_ref.empty())
1814 assign(def);
1815 }
1816
1817 XMLDoubleRef& operator=(double value)
1818 {
1819 assign(value);
1820
1821 return *this;
1822 }
1823
1824 operator double() const
1825 {
1826 LPTSTR end;
1827 return XS_tod(_ref.c_str(), &end);
1828 }
1829
1830 void assign(double value)
1831 {
1832 XS_CHAR buffer[32];
1833 XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
1834 _ref.assign(buffer);
1835 }
1836
1837 protected:
1838 XS_String& _ref;
1839 };
1840
1841
1842 /// type converter for string data
1843 struct XMLString
1844 {
1845 XMLString(const XS_String& value)
1846 : _value(value)
1847 {
1848 }
1849
1850 XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY)
1851 {
1852 if (value && *value)
1853 _value = value;
1854 else
1855 _value = def;
1856 }
1857
1858 XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
1859 {
1860 const XS_String& value = node->get(attr_name);
1861
1862 if (!value.empty())
1863 _value = value;
1864 else
1865 _value = def;
1866 }
1867
1868 operator const XS_String&() const
1869 {
1870 return _value;
1871 }
1872
1873 const XS_String& c_str() const
1874 {
1875 return _value;
1876 }
1877
1878 protected:
1879 XS_String _value;
1880
1881 private:
1882 void operator=(const XMLString&); // disallow assignment operations
1883 };
1884
1885 /// type converter for string data with write access
1886 struct XMStringRef
1887 {
1888 XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
1889 : _ref((*node)[attr_name])
1890 {
1891 if (_ref.empty())
1892 assign(def);
1893 }
1894
1895 XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
1896 : _ref(node->subvalue(node_name, attr_name))
1897 {
1898 if (_ref.empty())
1899 assign(def);
1900 }
1901
1902 XMStringRef& operator=(const XS_String& value)
1903 {
1904 assign(value);
1905
1906 return *this;
1907 }
1908
1909 operator const XS_String&() const
1910 {
1911 return _ref;
1912 }
1913
1914 void assign(const XS_String& value)
1915 {
1916 _ref.assign(value);
1917 }
1918
1919 protected:
1920 XS_String& _ref;
1921 };
1922
1923
1924 template<typename T>
1925 inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
1926 {
1927 const XS_String& val = cfg.get(key);
1928
1929 if (!val.empty())
1930 var = val;
1931 }
1932
1933 template<>
1934 inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
1935 {
1936 const XS_String& val = cfg.get(key);
1937
1938 if (!val.empty())
1939 var = XS_toi(val.c_str());
1940 }
1941
1942
1943 #ifdef _MSC_VER
1944 #pragma warning(disable: 4355)
1945 #endif
1946
1947 /// XML reader base class
1948 struct XMLReaderBase
1949 #ifdef XS_USE_XERCES
1950 : public HandlerBase
1951 #endif
1952 {
1953 #ifdef XS_USE_XERCES
1954
1955 XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false);
1956 virtual ~XMLReaderBase();
1957
1958 void read();
1959
1960 protected:
1961 SAXParser* _parser;
1962 InputSource* _source;
1963 bool _deleteSource;
1964
1965 virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr,
1966 const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr);
1967
1968 // Handlers for the SAX DocumentHandler interface
1969 virtual void setDocumentLocator(const Locator* const locator);
1970 virtual void startElement(const XMLCh* const name, AttributeList& attributes);
1971 virtual void endElement(const XMLCh* const name);
1972 virtual void characters(const XMLCh* const chars, const unsigned int length);
1973 virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
1974
1975 // Handlers for the SAX ErrorHandler interface
1976 virtual void error(const SAXParseException& e);
1977 virtual void fatalError(const SAXParseException& e);
1978 virtual void warning(const SAXParseException& e);
1979 virtual void resetErrors();
1980
1981 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
1982
1983 XMLReaderBase(XMLNode* node);
1984 virtual ~XMLReaderBase();
1985
1986 protected:
1987 XML_Parser _parser;
1988
1989 static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1);
1990 static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
1991 static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
1992 static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len);
1993
1994 static std::string get_expat_error_string(XML_Error error_code);
1995
1996 #else // XS_USE_EXPAT
1997
1998 XMLReaderBase(XMLNode* node)
1999 : _pos(node),
2000 _endl_defined(false),
2001 _utf8(false)
2002 {
2003 _last_tag = TAG_NONE;
2004 }
2005
2006 virtual ~XMLReaderBase();
2007
2008 bool parse();
2009
2010 #endif
2011
2012 public:
2013 #ifndef XS_USE_XERCES
2014 void read();
2015
2016 std::string get_position() const;
2017 #endif
2018 const XMLFormat& get_format() const {return _format;}
2019 const char* get_endl() const {return _endl_defined? _format._endl: "\n";}
2020
2021 const XMLErrorList& get_errors() const {return _errors;}
2022 const XMLErrorList& get_warnings() const {return _warnings;}
2023
2024 void clear_errors() {_errors.clear(); _warnings.clear();}
2025
2026 #ifdef XMLNODE_LOCATION
2027 const char* _display_path; // character pointer for fast reference in XMLLocation
2028
2029 #ifdef XS_USE_XERCES
2030 const Locator* _locator;
2031 #endif
2032
2033 XMLLocation get_location() const;
2034 #endif
2035
2036 protected:
2037 XMLPos _pos;
2038
2039 std::string _content; // UTF-8 encoded
2040 enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
2041
2042 XMLErrorList _errors;
2043 XMLErrorList _warnings;
2044
2045 XMLFormat _format;
2046 bool _endl_defined;
2047
2048 #ifdef XS_USE_XERCES
2049 //@@
2050 #elif defined(XS_USE_EXPAT)
2051 virtual int read_buffer(char* buffer, int len) = 0;
2052 #else
2053 virtual int get() = 0;
2054 int eat_endl();
2055
2056 bool _utf8;
2057 #endif
2058
2059 void finish_read();
2060
2061 virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone);
2062 virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
2063 virtual void EndElementHandler();
2064 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
2065 virtual void DefaultHandler(const XML_Char* s, int len);
2066 #else
2067 virtual void DefaultHandler(const std::string& s);
2068 #endif
2069 };
2070
2071
2072 /// XML file reader
2073
2074 #ifdef XS_USE_XERCES
2075
2076 struct XercesXMLReader : public XMLReaderBase
2077 {
2078 XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false)
2079 : XMLReaderBase(node, source, adoptSource)
2080 {
2081 }
2082
2083 XercesXMLReader(XMLNode* node, LPCTSTR path);
2084 XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string());
2085 };
2086
2087 #define XMLReader XercesXMLReader
2088
2089 #elif defined(XS_USE_EXPAT)
2090
2091 struct ExpatXMLReader : public XMLReaderBase
2092 {
2093 ExpatXMLReader(XMLNode* node, std::istream& in)
2094 : XMLReaderBase(node),
2095 _in(in)
2096 {
2097 }
2098
2099 /// read XML stream into XML tree below _pos
2100 int read_buffer(char* buffer, int len)
2101 {
2102 if (!_in.good())
2103 return -1;
2104
2105 _in.read(buffer, len);
2106
2107 return _in.gcount();
2108 }
2109
2110 protected:
2111 std::istream& _in;
2112 };
2113
2114 #define XMLReader ExpatXMLReader
2115
2116 #else // XS_USE_XERCES, XS_USE_EXPAT
2117
2118 struct XMLReader : public XMLReaderBase
2119 {
2120 XMLReader(XMLNode* node, std::istream& in)
2121 : XMLReaderBase(node),
2122 _in(in)
2123 {
2124 }
2125
2126 /// read one character from XML stream
2127 int get()
2128 {
2129 return _in.get();
2130 }
2131
2132 protected:
2133 std::istream& _in;
2134 };
2135
2136 #endif // XS_USE_XERCES
2137
2138
2139 /// XML document holder
2140 struct XMLDoc : public XMLNode
2141 {
2142 XMLDoc()
2143 : XMLNode("")
2144 {
2145 }
2146
2147 XMLDoc(LPCTSTR path)
2148 : XMLNode("")
2149 {
2150 read(path);
2151 }
2152
2153 #ifdef XS_USE_XERCES
2154 bool read(LPCTSTR path)
2155 {
2156 XMLReader reader(this, path);
2157
2158 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2159 return read(reader, std::string(ANS(path)));
2160 #else
2161 return read(reader, XS_String(path));
2162 #endif
2163 }
2164
2165 bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
2166 {
2167 XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
2168
2169 return read(reader, system_id);
2170 }
2171
2172 #else // XS_USE_XERCES
2173
2174 bool read(LPCTSTR path)
2175 {
2176 tifstream in(path);
2177 XMLReader reader(this, in);
2178
2179 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
2180 return read(reader, std::string(ANS(path)));
2181 #else
2182 return read(reader, XS_String(path));
2183 #endif
2184 }
2185
2186 bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
2187 {
2188 std::istringstream in(std::string(buffer, len));
2189
2190 return read(in, system_id);
2191 }
2192
2193 bool read(std::istream& in, const std::string& system_id=std::string())
2194 {
2195 XMLReader reader(this, in);
2196
2197 return read(reader, system_id);
2198 }
2199 #endif // XS_USE_XERCES
2200
2201 bool read(XMLReaderBase& reader, const std::string& display_path)
2202 {
2203 #ifdef XMLNODE_LOCATION
2204 // make a string copy to handle temporary string objects
2205 _display_path = display_path;
2206 reader._display_path = _display_path.c_str();
2207 #endif
2208
2209 reader.clear_errors();
2210 reader.read();
2211
2212 _format = reader.get_format();
2213 _format._endl = reader.get_endl();
2214
2215 if (!reader.get_errors().empty()) {
2216 _errors = reader.get_errors();
2217 return false;
2218 }
2219
2220 return true;
2221 }
2222
2223 /// write XML stream preserving previous white space and comments
2224 std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
2225 {
2226 _format.print_header(out, mode!=FORMAT_PLAIN);
2227
2228 if (!_children.empty())
2229 _children.front()->write(out, _format, mode);
2230
2231 return out;
2232 }
2233
2234 /// write XML stream with formating
2235 std::ostream& write_formating(std::ostream& out) const
2236 {
2237 return write(out, FORMAT_PRETTY);
2238 }
2239
2240 bool write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
2241 {
2242 tofstream out(path);
2243
2244 return write(out, mode).good();
2245 }
2246
2247 bool write_formating(LPCTSTR path) const
2248 {
2249 tofstream out(path);
2250
2251 return write_formating(out).good();
2252 }
2253
2254 XMLFormat _format;
2255 XMLErrorList _errors;
2256
2257 #ifdef XMLNODE_LOCATION
2258 std::string _display_path;
2259 #endif
2260 };
2261
2262
2263 /// XML message wrapper
2264 struct XMLMessage : public XMLDoc
2265 {
2266 XMLMessage(const char* name)
2267 : _pos(this)
2268 {
2269 _pos.create(name);
2270 }
2271
2272 std::string toString() const
2273 {
2274 std::ostringstream out;
2275
2276 write(out);
2277
2278 return out.str();
2279 }
2280
2281 XMLPos _pos;
2282
2283 protected:
2284 XMLMessage()
2285 : _pos(this)
2286 {
2287 }
2288 };
2289
2290
2291 /// helper structure to read XML messages from strings
2292 struct XMLMessageFromString : public XMLMessage
2293 {
2294 XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string())
2295 {
2296 read(xml_str.c_str(), xml_str.length(), system_id);
2297 }
2298 };
2299
2300
2301 /// Reader for XML Messages
2302 struct XMLMessageReader : public XMLPos
2303 {
2304 XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string())
2305 : XMLPos(&_msg)
2306 {
2307 _msg.read(xml_str.c_str(), xml_str.length(), system_id);
2308 }
2309
2310 const XMLDoc& get_document()
2311 {
2312 return _msg;
2313 }
2314
2315 protected:
2316 XMLDoc _msg;
2317 };
2318
2319
2320 /// on the fly XML writer
2321 struct XMLWriter
2322 {
2323 XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat())
2324 : _pofstream(NULL),
2325 _out(out),
2326 _format(format)
2327 {
2328 format.print_header(_out, false); // _format._endl is printed in write_pre()
2329 }
2330
2331 XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat())
2332 : _pofstream(new tofstream(path)),
2333 _out(*_pofstream),
2334 _format(format)
2335 {
2336 format.print_header(_out, false); // _format._endl is printed in write_pre()
2337 }
2338
2339 ~XMLWriter()
2340 {
2341 _out << _format._endl;
2342 delete _pofstream;
2343 }
2344
2345 /// create node and move to it
2346 void create(const XS_String& name)
2347 {
2348 if (!_stack.empty()) {
2349 StackEntry& last = _stack.top();
2350
2351 if (last._state < PRE_CLOSED) {
2352 write_attributes(last);
2353 close_pre(last);
2354 }
2355
2356 ++last._children;
2357 }
2358
2359 StackEntry entry;
2360 entry._node_name = name;
2361 _stack.push(entry);
2362
2363 write_pre(entry);
2364 }
2365
2366 /// go back to previous position
2367 bool back()
2368 {
2369 if (!_stack.empty()) {
2370 write_post(_stack.top());
2371
2372 _stack.pop();
2373 return true;
2374 } else
2375 return false;
2376 }
2377
2378 /// attribute setting
2379 void put(const XS_String& attr_name, const XS_String& value)
2380 {
2381 if (!_stack.empty())
2382 _stack.top()._attributes[attr_name] = value;
2383 }
2384
2385 /// C++ write access to an attribute
2386 XS_String& operator[](const XS_String& attr_name)
2387 {
2388 if (_stack.empty())
2389 return s_empty_attr;
2390
2391 return _stack.top()._attributes[attr_name];
2392 }
2393
2394 void set_content(const XS_String& s, bool cdata=false)
2395 {
2396 if (!_stack.empty())
2397 _stack.top()._content = EncodeXMLString(s.c_str(), cdata);
2398 }
2399
2400 // public for access in StackEntry
2401 enum WRITESTATE {
2402 NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
2403 };
2404
2405 protected:
2406 tofstream* _pofstream;
2407 std::ostream& _out;
2408 const XMLFormat&_format;
2409
2410 typedef XMLNode::AttributeMap AttrMap;
2411
2412 /// container for XMLWriter state information
2413 struct StackEntry {
2414 XS_String _node_name;
2415 AttrMap _attributes;
2416 std::string _content;
2417 WRITESTATE _state;
2418 bool _children;
2419
2420 StackEntry() : _state(NOTHING), _children(false) {}
2421 };
2422
2423 std::stack<StackEntry> _stack;
2424
2425 static XS_String s_empty_attr;
2426
2427 void close_pre(StackEntry& entry)
2428 {
2429 _out << '>';
2430
2431 entry._state = PRE_CLOSED;
2432 }
2433
2434 void write_pre(StackEntry& entry)
2435 {
2436 if (_format._pretty >= PRETTY_LINEFEED)
2437 _out << _format._endl;
2438
2439 if (_format._pretty == PRETTY_INDENT)
2440 for(size_t i=_stack.size(); --i>0; )
2441 _out << XML_INDENT_SPACE;
2442
2443 _out << '<' << EncodeXMLString(entry._node_name);
2444 //entry._state = PRE;
2445 }
2446
2447 void write_attributes(StackEntry& entry)
2448 {
2449 for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it)
2450 _out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
2451
2452 entry._state = ATTRIBUTES;
2453 }
2454
2455 void write_post(StackEntry& entry)
2456 {
2457 if (entry._state < ATTRIBUTES)
2458 write_attributes(entry);
2459
2460 if (entry._children || !entry._content.empty()) {
2461 if (entry._state < PRE_CLOSED)
2462 close_pre(entry);
2463
2464 _out << entry._content;
2465 //entry._state = CONTENT;
2466
2467 if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
2468 _out << _format._endl;
2469
2470 if (_format._pretty==PRETTY_INDENT && entry._content.empty())
2471 for(size_t i=_stack.size(); --i>0; )
2472 _out << XML_INDENT_SPACE;
2473
2474 _out << "</" << EncodeXMLString(entry._node_name) << ">";
2475 } else {
2476 _out << "/>";
2477 }
2478
2479 entry._state = POST;
2480 }
2481 };
2482
2483
2484 } // namespace XMLStorage
2485
2486 #define _XMLSTORAGE_H
2487 #endif // _XMLSTORAGE_H