]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/tinyxml2/tinyxml2.h
359878666de4f92c8ec3fcfe02aedeccbcc8b214
[cpPlugins.git] / lib / cpPlugins / tinyxml2 / tinyxml2.h
1 /*\r
2 Original code by Lee Thomason (www.grinninglizard.com)\r
3 \r
4 This software is provided 'as-is', without any express or implied\r
5 warranty. In no event will the authors be held liable for any\r
6 damages arising from the use of this software.\r
7 \r
8 Permission is granted to anyone to use this software for any\r
9 purpose, including commercial applications, and to alter it and\r
10 redistribute it freely, subject to the following restrictions:\r
11 \r
12 1. The origin of this software must not be misrepresented; you must\r
13 not claim that you wrote the original software. If you use this\r
14 software in a product, an acknowledgment in the product documentation\r
15 would be appreciated but is not required.\r
16 \r
17 2. Altered source versions must be plainly marked as such, and\r
18 must not be misrepresented as being the original software.\r
19 \r
20 3. This notice may not be removed or altered from any source\r
21 distribution.\r
22 */\r
23 \r
24 #ifndef TINYXML2_INCLUDED\r
25 #define TINYXML2_INCLUDED\r
26 \r
27 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)\r
28 #   include <ctype.h>\r
29 #   include <limits.h>\r
30 #   include <stdio.h>\r
31 #   include <stdlib.h>\r
32 #   include <string.h>\r
33 #else\r
34 #   include <cctype>\r
35 #   include <climits>\r
36 #   include <cstdio>\r
37 #   include <cstdlib>\r
38 #   include <cstring>\r
39 #endif\r
40 \r
41 /*\r
42    TODO: intern strings instead of allocation.\r
43 */\r
44 /*\r
45         gcc:\r
46         g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe\r
47 \r
48     Formatting, Artistic Style:\r
49         AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h\r
50 */\r
51 \r
52 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)\r
53 #   ifndef DEBUG\r
54 #       define DEBUG\r
55 #   endif\r
56 #endif\r
57 \r
58 #ifdef _MSC_VER\r
59 #   pragma warning(push)\r
60 #   pragma warning(disable: 4251)\r
61 #endif\r
62 \r
63 #ifdef _WIN32\r
64 #   ifdef TINYXML2_EXPORT\r
65 #       define TINYXML2_LIB __declspec(dllexport)\r
66 #   elif defined(TINYXML2_IMPORT)\r
67 #       define TINYXML2_LIB __declspec(dllimport)\r
68 #   else\r
69 #       define TINYXML2_LIB\r
70 #   endif\r
71 #else\r
72 #   define TINYXML2_LIB\r
73 #endif\r
74 \r
75 \r
76 #if defined(DEBUG)\r
77 #   if defined(_MSC_VER)\r
78 #       // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like\r
79 #       define TIXMLASSERT( x )           if ( !((void)0,(x))) { __debugbreak(); }\r
80 #   elif defined (ANDROID_NDK)\r
81 #       include <android/log.h>\r
82 #       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }\r
83 #   else\r
84 #       include <assert.h>\r
85 #       define TIXMLASSERT                assert\r
86 #   endif\r
87 #else\r
88 #   define TIXMLASSERT( x )               {}\r
89 #endif\r
90 \r
91 \r
92 /* Versioning, past 1.0.14:\r
93         http://semver.org/\r
94 */\r
95 static const int TIXML2_MAJOR_VERSION = 3;\r
96 static const int TIXML2_MINOR_VERSION = 0;\r
97 static const int TIXML2_PATCH_VERSION = 0;\r
98 \r
99 #include <cpPlugins_Export.h>\r
100 #undef TINYXML2_LIB\r
101 #define TINYXML2_LIB cpPlugins_EXPORT\r
102 \r
103 namespace tinyxml2\r
104 {\r
105 class XMLDocument;\r
106 class XMLElement;\r
107 class XMLAttribute;\r
108 class XMLComment;\r
109 class XMLText;\r
110 class XMLDeclaration;\r
111 class XMLUnknown;\r
112 class XMLPrinter;\r
113 \r
114 /*\r
115         A class that wraps strings. Normally stores the start and end\r
116         pointers into the XML file itself, and will apply normalization\r
117         and entity translation if actually read. Can also store (and memory\r
118         manage) a traditional char[]\r
119 */\r
120 class StrPair\r
121 {\r
122 public:\r
123     enum {\r
124         NEEDS_ENTITY_PROCESSING                 = 0x01,\r
125         NEEDS_NEWLINE_NORMALIZATION             = 0x02,\r
126         NEEDS_WHITESPACE_COLLAPSING     = 0x04,\r
127 \r
128         TEXT_ELEMENT                            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\r
129         TEXT_ELEMENT_LEAVE_ENTITIES             = NEEDS_NEWLINE_NORMALIZATION,\r
130         ATTRIBUTE_NAME                          = 0,\r
131         ATTRIBUTE_VALUE                         = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,\r
132         ATTRIBUTE_VALUE_LEAVE_ENTITIES          = NEEDS_NEWLINE_NORMALIZATION,\r
133         COMMENT                                 = NEEDS_NEWLINE_NORMALIZATION\r
134     };\r
135 \r
136     StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}\r
137     ~StrPair();\r
138 \r
139     void Set( char* start, char* end, int flags ) {\r
140         Reset();\r
141         _start  = start;\r
142         _end    = end;\r
143         _flags  = flags | NEEDS_FLUSH;\r
144     }\r
145 \r
146     const char* GetStr();\r
147 \r
148     bool Empty() const {\r
149         return _start == _end;\r
150     }\r
151 \r
152     void SetInternedStr( const char* str ) {\r
153         Reset();\r
154         _start = const_cast<char*>(str);\r
155     }\r
156 \r
157     void SetStr( const char* str, int flags=0 );\r
158 \r
159     char* ParseText( char* in, const char* endTag, int strFlags );\r
160     char* ParseName( char* in );\r
161 \r
162     void TransferTo( StrPair* other );\r
163 \r
164 private:\r
165     void Reset();\r
166     void CollapseWhitespace();\r
167 \r
168     enum {\r
169         NEEDS_FLUSH = 0x100,\r
170         NEEDS_DELETE = 0x200\r
171     };\r
172 \r
173     int     _flags;\r
174     char*   _start;\r
175     char*   _end;\r
176 \r
177     StrPair( const StrPair& other );    // not supported\r
178     void operator=( StrPair& other );   // not supported, use TransferTo()\r
179 };\r
180 \r
181 \r
182 /*\r
183         A dynamic array of Plain Old Data. Doesn't support constructors, etc.\r
184         Has a small initial memory pool, so that low or no usage will not\r
185         cause a call to new/delete\r
186 */\r
187 template <class T, int INITIAL_SIZE>\r
188 class DynArray\r
189 {\r
190 public:\r
191     DynArray() {\r
192         _mem = _pool;\r
193         _allocated = INITIAL_SIZE;\r
194         _size = 0;\r
195     }\r
196 \r
197     ~DynArray() {\r
198         if ( _mem != _pool ) {\r
199             delete [] _mem;\r
200         }\r
201     }\r
202 \r
203     void Clear() {\r
204         _size = 0;\r
205     }\r
206 \r
207     void Push( T t ) {\r
208         TIXMLASSERT( _size < INT_MAX );\r
209         EnsureCapacity( _size+1 );\r
210         _mem[_size++] = t;\r
211     }\r
212 \r
213     T* PushArr( int count ) {\r
214         TIXMLASSERT( count >= 0 );\r
215         TIXMLASSERT( _size <= INT_MAX - count );\r
216         EnsureCapacity( _size+count );\r
217         T* ret = &_mem[_size];\r
218         _size += count;\r
219         return ret;\r
220     }\r
221 \r
222     T Pop() {\r
223         TIXMLASSERT( _size > 0 );\r
224         return _mem[--_size];\r
225     }\r
226 \r
227     void PopArr( int count ) {\r
228         TIXMLASSERT( _size >= count );\r
229         _size -= count;\r
230     }\r
231 \r
232     bool Empty() const                                  {\r
233         return _size == 0;\r
234     }\r
235 \r
236     T& operator[](int i)                                {\r
237         TIXMLASSERT( i>= 0 && i < _size );\r
238         return _mem[i];\r
239     }\r
240 \r
241     const T& operator[](int i) const    {\r
242         TIXMLASSERT( i>= 0 && i < _size );\r
243         return _mem[i];\r
244     }\r
245 \r
246     const T& PeekTop() const            {\r
247         TIXMLASSERT( _size > 0 );\r
248         return _mem[ _size - 1];\r
249     }\r
250 \r
251     int Size() const                                    {\r
252         TIXMLASSERT( _size >= 0 );\r
253         return _size;\r
254     }\r
255 \r
256     int Capacity() const                                {\r
257         TIXMLASSERT( _allocated >= INITIAL_SIZE );\r
258         return _allocated;\r
259     }\r
260 \r
261     const T* Mem() const                                {\r
262         TIXMLASSERT( _mem );\r
263         return _mem;\r
264     }\r
265 \r
266     T* Mem()                                                    {\r
267         TIXMLASSERT( _mem );\r
268         return _mem;\r
269     }\r
270 \r
271 private:\r
272     DynArray( const DynArray& ); // not supported\r
273     void operator=( const DynArray& ); // not supported\r
274 \r
275     void EnsureCapacity( int cap ) {\r
276         TIXMLASSERT( cap > 0 );\r
277         if ( cap > _allocated ) {\r
278             TIXMLASSERT( cap <= INT_MAX / 2 );\r
279             int newAllocated = cap * 2;\r
280             T* newMem = new T[newAllocated];\r
281             memcpy( newMem, _mem, sizeof(T)*_size );    // warning: not using constructors, only works for PODs\r
282             if ( _mem != _pool ) {\r
283                 delete [] _mem;\r
284             }\r
285             _mem = newMem;\r
286             _allocated = newAllocated;\r
287         }\r
288     }\r
289 \r
290     T*  _mem;\r
291     T   _pool[INITIAL_SIZE];\r
292     int _allocated;             // objects allocated\r
293     int _size;                  // number objects in use\r
294 };\r
295 \r
296 \r
297 /*\r
298         Parent virtual class of a pool for fast allocation\r
299         and deallocation of objects.\r
300 */\r
301 class MemPool\r
302 {\r
303 public:\r
304     MemPool() {}\r
305     virtual ~MemPool() {}\r
306 \r
307     virtual int ItemSize() const = 0;\r
308     virtual void* Alloc() = 0;\r
309     virtual void Free( void* ) = 0;\r
310     virtual void SetTracked() = 0;\r
311     virtual void Clear() = 0;\r
312 };\r
313 \r
314 \r
315 /*\r
316         Template child class to create pools of the correct type.\r
317 */\r
318 template< int SIZE >\r
319 class MemPoolT : public MemPool\r
320 {\r
321 public:\r
322     MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)        {}\r
323     ~MemPoolT() {\r
324         Clear();\r
325     }\r
326     \r
327     void Clear() {\r
328         // Delete the blocks.\r
329         while( !_blockPtrs.Empty()) {\r
330             Block* b  = _blockPtrs.Pop();\r
331             delete b;\r
332         }\r
333         _root = 0;\r
334         _currentAllocs = 0;\r
335         _nAllocs = 0;\r
336         _maxAllocs = 0;\r
337         _nUntracked = 0;\r
338     }\r
339 \r
340     virtual int ItemSize() const        {\r
341         return SIZE;\r
342     }\r
343     int CurrentAllocs() const           {\r
344         return _currentAllocs;\r
345     }\r
346 \r
347     virtual void* Alloc() {\r
348         if ( !_root ) {\r
349             // Need a new block.\r
350             Block* block = new Block();\r
351             _blockPtrs.Push( block );\r
352 \r
353             for( int i=0; i<COUNT-1; ++i ) {\r
354                 block->chunk[i].next = &block->chunk[i+1];\r
355             }\r
356             block->chunk[COUNT-1].next = 0;\r
357             _root = block->chunk;\r
358         }\r
359         void* result = _root;\r
360         _root = _root->next;\r
361 \r
362         ++_currentAllocs;\r
363         if ( _currentAllocs > _maxAllocs ) {\r
364             _maxAllocs = _currentAllocs;\r
365         }\r
366         _nAllocs++;\r
367         _nUntracked++;\r
368         return result;\r
369     }\r
370     \r
371     virtual void Free( void* mem ) {\r
372         if ( !mem ) {\r
373             return;\r
374         }\r
375         --_currentAllocs;\r
376         Chunk* chunk = static_cast<Chunk*>( mem );\r
377 #ifdef DEBUG\r
378         memset( chunk, 0xfe, sizeof(Chunk) );\r
379 #endif\r
380         chunk->next = _root;\r
381         _root = chunk;\r
382     }\r
383     void Trace( const char* name ) {\r
384         printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",\r
385                 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );\r
386     }\r
387 \r
388     void SetTracked() {\r
389         _nUntracked--;\r
390     }\r
391 \r
392     int Untracked() const {\r
393         return _nUntracked;\r
394     }\r
395 \r
396         // This number is perf sensitive. 4k seems like a good tradeoff on my machine.\r
397         // The test file is large, 170k.\r
398         // Release:             VS2010 gcc(no opt)\r
399         //              1k:             4000\r
400         //              2k:             4000\r
401         //              4k:             3900    21000\r
402         //              16k:    5200\r
403         //              32k:    4300\r
404         //              64k:    4000    21000\r
405     enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private\r
406 \r
407 private:\r
408     MemPoolT( const MemPoolT& ); // not supported\r
409     void operator=( const MemPoolT& ); // not supported\r
410 \r
411     union Chunk {\r
412         Chunk*  next;\r
413         char    mem[SIZE];\r
414     };\r
415     struct Block {\r
416         Chunk chunk[COUNT];\r
417     };\r
418     DynArray< Block*, 10 > _blockPtrs;\r
419     Chunk* _root;\r
420 \r
421     int _currentAllocs;\r
422     int _nAllocs;\r
423     int _maxAllocs;\r
424     int _nUntracked;\r
425 };\r
426 \r
427 \r
428 \r
429 /**\r
430         Implements the interface to the "Visitor pattern" (see the Accept() method.)\r
431         If you call the Accept() method, it requires being passed a XMLVisitor\r
432         class to handle callbacks. For nodes that contain other nodes (Document, Element)\r
433         you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs\r
434         are simply called with Visit().\r
435 \r
436         If you return 'true' from a Visit method, recursive parsing will continue. If you return\r
437         false, <b>no children of this node or its siblings</b> will be visited.\r
438 \r
439         All flavors of Visit methods have a default implementation that returns 'true' (continue\r
440         visiting). You need to only override methods that are interesting to you.\r
441 \r
442         Generally Accept() is called on the XMLDocument, although all nodes support visiting.\r
443 \r
444         You should never change the document from a callback.\r
445 \r
446         @sa XMLNode::Accept()\r
447 */\r
448 class TINYXML2_LIB XMLVisitor\r
449 {\r
450 public:\r
451     virtual ~XMLVisitor() {}\r
452 \r
453     /// Visit a document.\r
454     virtual bool VisitEnter( const XMLDocument& /*doc*/ )                       {\r
455         return true;\r
456     }\r
457     /// Visit a document.\r
458     virtual bool VisitExit( const XMLDocument& /*doc*/ )                        {\r
459         return true;\r
460     }\r
461 \r
462     /// Visit an element.\r
463     virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )    {\r
464         return true;\r
465     }\r
466     /// Visit an element.\r
467     virtual bool VisitExit( const XMLElement& /*element*/ )                     {\r
468         return true;\r
469     }\r
470 \r
471     /// Visit a declaration.\r
472     virtual bool Visit( const XMLDeclaration& /*declaration*/ )         {\r
473         return true;\r
474     }\r
475     /// Visit a text node.\r
476     virtual bool Visit( const XMLText& /*text*/ )                                       {\r
477         return true;\r
478     }\r
479     /// Visit a comment node.\r
480     virtual bool Visit( const XMLComment& /*comment*/ )                         {\r
481         return true;\r
482     }\r
483     /// Visit an unknown node.\r
484     virtual bool Visit( const XMLUnknown& /*unknown*/ )                         {\r
485         return true;\r
486     }\r
487 };\r
488 \r
489 // WARNING: must match XMLDocument::_errorNames[]\r
490 enum XMLError {\r
491     XML_SUCCESS = 0,\r
492     XML_NO_ERROR = 0,\r
493     XML_NO_ATTRIBUTE,\r
494     XML_WRONG_ATTRIBUTE_TYPE,\r
495     XML_ERROR_FILE_NOT_FOUND,\r
496     XML_ERROR_FILE_COULD_NOT_BE_OPENED,\r
497     XML_ERROR_FILE_READ_ERROR,\r
498     XML_ERROR_ELEMENT_MISMATCH,\r
499     XML_ERROR_PARSING_ELEMENT,\r
500     XML_ERROR_PARSING_ATTRIBUTE,\r
501     XML_ERROR_IDENTIFYING_TAG,\r
502     XML_ERROR_PARSING_TEXT,\r
503     XML_ERROR_PARSING_CDATA,\r
504     XML_ERROR_PARSING_COMMENT,\r
505     XML_ERROR_PARSING_DECLARATION,\r
506     XML_ERROR_PARSING_UNKNOWN,\r
507     XML_ERROR_EMPTY_DOCUMENT,\r
508     XML_ERROR_MISMATCHED_ELEMENT,\r
509     XML_ERROR_PARSING,\r
510     XML_CAN_NOT_CONVERT_TEXT,\r
511     XML_NO_TEXT_NODE,\r
512 \r
513         XML_ERROR_COUNT\r
514 };\r
515 \r
516 \r
517 /*\r
518         Utility functionality.\r
519 */\r
520 class XMLUtil\r
521 {\r
522 public:\r
523     static const char* SkipWhiteSpace( const char* p )  {\r
524         TIXMLASSERT( p );\r
525         while( IsWhiteSpace(*p) ) {\r
526             ++p;\r
527         }\r
528         TIXMLASSERT( p );\r
529         return p;\r
530     }\r
531     static char* SkipWhiteSpace( char* p )                              {\r
532         return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );\r
533     }\r
534 \r
535     // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't\r
536     // correct, but simple, and usually works.\r
537     static bool IsWhiteSpace( char p )                                  {\r
538         return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );\r
539     }\r
540     \r
541     inline static bool IsNameStartChar( unsigned char ch ) {\r
542         if ( ch >= 128 ) {\r
543             // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()\r
544             return true;\r
545         }\r
546         if ( isalpha( ch ) ) {\r
547             return true;\r
548         }\r
549         return ch == ':' || ch == '_';\r
550     }\r
551     \r
552     inline static bool IsNameChar( unsigned char ch ) {\r
553         return IsNameStartChar( ch )\r
554                || isdigit( ch )\r
555                || ch == '.'\r
556                || ch == '-';\r
557     }\r
558 \r
559     inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {\r
560         if ( p == q ) {\r
561             return true;\r
562         }\r
563         return strncmp( p, q, nChar ) == 0;\r
564     }\r
565     \r
566     inline static bool IsUTF8Continuation( char p ) {\r
567         return ( p & 0x80 ) != 0;\r
568     }\r
569 \r
570     static const char* ReadBOM( const char* p, bool* hasBOM );\r
571     // p is the starting location,\r
572     // the UTF-8 value of the entity will be placed in value, and length filled in.\r
573     static const char* GetCharacterRef( const char* p, char* value, int* length );\r
574     static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );\r
575 \r
576     // converts primitive types to strings\r
577     static void ToStr( int v, char* buffer, int bufferSize );\r
578     static void ToStr( unsigned v, char* buffer, int bufferSize );\r
579     static void ToStr( bool v, char* buffer, int bufferSize );\r
580     static void ToStr( float v, char* buffer, int bufferSize );\r
581     static void ToStr( double v, char* buffer, int bufferSize );\r
582 \r
583     // converts strings to primitive types\r
584     static bool ToInt( const char* str, int* value );\r
585     static bool ToUnsigned( const char* str, unsigned* value );\r
586     static bool ToBool( const char* str, bool* value );\r
587     static bool ToFloat( const char* str, float* value );\r
588     static bool ToDouble( const char* str, double* value );\r
589 };\r
590 \r
591 \r
592 /** XMLNode is a base class for every object that is in the\r
593         XML Document Object Model (DOM), except XMLAttributes.\r
594         Nodes have siblings, a parent, and children which can\r
595         be navigated. A node is always in a XMLDocument.\r
596         The type of a XMLNode can be queried, and it can\r
597         be cast to its more defined type.\r
598 \r
599         A XMLDocument allocates memory for all its Nodes.\r
600         When the XMLDocument gets deleted, all its Nodes\r
601         will also be deleted.\r
602 \r
603         @verbatim\r
604         A Document can contain: Element (container or leaf)\r
605                                                         Comment (leaf)\r
606                                                         Unknown (leaf)\r
607                                                         Declaration( leaf )\r
608 \r
609         An Element can contain: Element (container or leaf)\r
610                                                         Text    (leaf)\r
611                                                         Attributes (not on tree)\r
612                                                         Comment (leaf)\r
613                                                         Unknown (leaf)\r
614 \r
615         @endverbatim\r
616 */\r
617 class TINYXML2_LIB XMLNode\r
618 {\r
619     friend class XMLDocument;\r
620     friend class XMLElement;\r
621 public:\r
622 \r
623     /// Get the XMLDocument that owns this XMLNode.\r
624     const XMLDocument* GetDocument() const      {\r
625         TIXMLASSERT( _document );\r
626         return _document;\r
627     }\r
628     /// Get the XMLDocument that owns this XMLNode.\r
629     XMLDocument* GetDocument()                          {\r
630         TIXMLASSERT( _document );\r
631         return _document;\r
632     }\r
633 \r
634     /// Safely cast to an Element, or null.\r
635     virtual XMLElement*         ToElement()             {\r
636         return 0;\r
637     }\r
638     /// Safely cast to Text, or null.\r
639     virtual XMLText*            ToText()                {\r
640         return 0;\r
641     }\r
642     /// Safely cast to a Comment, or null.\r
643     virtual XMLComment*         ToComment()             {\r
644         return 0;\r
645     }\r
646     /// Safely cast to a Document, or null.\r
647     virtual XMLDocument*        ToDocument()    {\r
648         return 0;\r
649     }\r
650     /// Safely cast to a Declaration, or null.\r
651     virtual XMLDeclaration*     ToDeclaration() {\r
652         return 0;\r
653     }\r
654     /// Safely cast to an Unknown, or null.\r
655     virtual XMLUnknown*         ToUnknown()             {\r
656         return 0;\r
657     }\r
658 \r
659     virtual const XMLElement*           ToElement() const               {\r
660         return 0;\r
661     }\r
662     virtual const XMLText*                      ToText() const                  {\r
663         return 0;\r
664     }\r
665     virtual const XMLComment*           ToComment() const               {\r
666         return 0;\r
667     }\r
668     virtual const XMLDocument*          ToDocument() const              {\r
669         return 0;\r
670     }\r
671     virtual const XMLDeclaration*       ToDeclaration() const   {\r
672         return 0;\r
673     }\r
674     virtual const XMLUnknown*           ToUnknown() const               {\r
675         return 0;\r
676     }\r
677 \r
678     /** The meaning of 'value' changes for the specific type.\r
679         @verbatim\r
680         Document:       empty (NULL is returned, not an empty string)\r
681         Element:        name of the element\r
682         Comment:        the comment text\r
683         Unknown:        the tag contents\r
684         Text:           the text string\r
685         @endverbatim\r
686     */\r
687     const char* Value() const;\r
688 \r
689     /** Set the Value of an XML node.\r
690         @sa Value()\r
691     */\r
692     void SetValue( const char* val, bool staticMem=false );\r
693 \r
694     /// Get the parent of this node on the DOM.\r
695     const XMLNode*      Parent() const                  {\r
696         return _parent;\r
697     }\r
698 \r
699     XMLNode* Parent()                                           {\r
700         return _parent;\r
701     }\r
702 \r
703     /// Returns true if this node has no children.\r
704     bool NoChildren() const                                     {\r
705         return !_firstChild;\r
706     }\r
707 \r
708     /// Get the first child node, or null if none exists.\r
709     const XMLNode*  FirstChild() const          {\r
710         return _firstChild;\r
711     }\r
712 \r
713     XMLNode*            FirstChild()                    {\r
714         return _firstChild;\r
715     }\r
716 \r
717     /** Get the first child element, or optionally the first child\r
718         element with the specified name.\r
719     */\r
720     const XMLElement* FirstChildElement( const char* name = 0 ) const;\r
721 \r
722     XMLElement* FirstChildElement( const char* name = 0 )       {\r
723         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));\r
724     }\r
725 \r
726     /// Get the last child node, or null if none exists.\r
727     const XMLNode*      LastChild() const                                               {\r
728         return _lastChild;\r
729     }\r
730 \r
731     XMLNode*            LastChild()                                                             {\r
732         return _lastChild;\r
733     }\r
734 \r
735     /** Get the last child element or optionally the last child\r
736         element with the specified name.\r
737     */\r
738     const XMLElement* LastChildElement( const char* name = 0 ) const;\r
739 \r
740     XMLElement* LastChildElement( const char* name = 0 )        {\r
741         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );\r
742     }\r
743 \r
744     /// Get the previous (left) sibling node of this node.\r
745     const XMLNode*      PreviousSibling() const                                 {\r
746         return _prev;\r
747     }\r
748 \r
749     XMLNode*    PreviousSibling()                                                       {\r
750         return _prev;\r
751     }\r
752 \r
753     /// Get the previous (left) sibling element of this node, with an optionally supplied name.\r
754     const XMLElement*   PreviousSiblingElement( const char* name = 0 ) const ;\r
755 \r
756     XMLElement* PreviousSiblingElement( const char* name = 0 ) {\r
757         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );\r
758     }\r
759 \r
760     /// Get the next (right) sibling node of this node.\r
761     const XMLNode*      NextSibling() const                                             {\r
762         return _next;\r
763     }\r
764 \r
765     XMLNode*    NextSibling()                                                           {\r
766         return _next;\r
767     }\r
768 \r
769     /// Get the next (right) sibling element of this node, with an optionally supplied name.\r
770     const XMLElement*   NextSiblingElement( const char* name = 0 ) const;\r
771 \r
772     XMLElement* NextSiblingElement( const char* name = 0 )      {\r
773         return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );\r
774     }\r
775 \r
776     /**\r
777         Add a child node as the last (right) child.\r
778                 If the child node is already part of the document,\r
779                 it is moved from its old location to the new location.\r
780                 Returns the addThis argument or 0 if the node does not\r
781                 belong to the same document.\r
782     */\r
783     XMLNode* InsertEndChild( XMLNode* addThis );\r
784 \r
785     XMLNode* LinkEndChild( XMLNode* addThis )   {\r
786         return InsertEndChild( addThis );\r
787     }\r
788     /**\r
789         Add a child node as the first (left) child.\r
790                 If the child node is already part of the document,\r
791                 it is moved from its old location to the new location.\r
792                 Returns the addThis argument or 0 if the node does not\r
793                 belong to the same document.\r
794     */\r
795     XMLNode* InsertFirstChild( XMLNode* addThis );\r
796     /**\r
797         Add a node after the specified child node.\r
798                 If the child node is already part of the document,\r
799                 it is moved from its old location to the new location.\r
800                 Returns the addThis argument or 0 if the afterThis node\r
801                 is not a child of this node, or if the node does not\r
802                 belong to the same document.\r
803     */\r
804     XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );\r
805 \r
806     /**\r
807         Delete all the children of this node.\r
808     */\r
809     void DeleteChildren();\r
810 \r
811     /**\r
812         Delete a child of this node.\r
813     */\r
814     void DeleteChild( XMLNode* node );\r
815 \r
816     /**\r
817         Make a copy of this node, but not its children.\r
818         You may pass in a Document pointer that will be\r
819         the owner of the new Node. If the 'document' is\r
820         null, then the node returned will be allocated\r
821         from the current Document. (this->GetDocument())\r
822 \r
823         Note: if called on a XMLDocument, this will return null.\r
824     */\r
825     virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;\r
826 \r
827     /**\r
828         Test if 2 nodes are the same, but don't test children.\r
829         The 2 nodes do not need to be in the same Document.\r
830 \r
831         Note: if called on a XMLDocument, this will return false.\r
832     */\r
833     virtual bool ShallowEqual( const XMLNode* compare ) const = 0;\r
834 \r
835     /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the\r
836         XML tree will be conditionally visited and the host will be called back\r
837         via the XMLVisitor interface.\r
838 \r
839         This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse\r
840         the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this\r
841         interface versus any other.)\r
842 \r
843         The interface has been based on ideas from:\r
844 \r
845         - http://www.saxproject.org/\r
846         - http://c2.com/cgi/wiki?HierarchicalVisitorPattern\r
847 \r
848         Which are both good references for "visiting".\r
849 \r
850         An example of using Accept():\r
851         @verbatim\r
852         XMLPrinter printer;\r
853         tinyxmlDoc.Accept( &printer );\r
854         const char* xmlcstr = printer.CStr();\r
855         @endverbatim\r
856     */\r
857     virtual bool Accept( XMLVisitor* visitor ) const = 0;\r
858 \r
859 protected:\r
860     XMLNode( XMLDocument* );\r
861     virtual ~XMLNode();\r
862 \r
863     virtual char* ParseDeep( char*, StrPair* );\r
864 \r
865     XMLDocument*        _document;\r
866     XMLNode*            _parent;\r
867     mutable StrPair     _value;\r
868 \r
869     XMLNode*            _firstChild;\r
870     XMLNode*            _lastChild;\r
871 \r
872     XMLNode*            _prev;\r
873     XMLNode*            _next;\r
874 \r
875 private:\r
876     MemPool*            _memPool;\r
877     void Unlink( XMLNode* child );\r
878     static void DeleteNode( XMLNode* node );\r
879     void InsertChildPreamble( XMLNode* insertThis ) const;\r
880 \r
881     XMLNode( const XMLNode& );  // not supported\r
882     XMLNode& operator=( const XMLNode& );       // not supported\r
883 };\r
884 \r
885 \r
886 /** XML text.\r
887 \r
888         Note that a text node can have child element nodes, for example:\r
889         @verbatim\r
890         <root>This is <b>bold</b></root>\r
891         @endverbatim\r
892 \r
893         A text node can have 2 ways to output the next. "normal" output\r
894         and CDATA. It will default to the mode it was parsed from the XML file and\r
895         you generally want to leave it alone, but you can change the output mode with\r
896         SetCData() and query it with CData().\r
897 */\r
898 class TINYXML2_LIB XMLText : public XMLNode\r
899 {\r
900     friend class XMLBase;\r
901     friend class XMLDocument;\r
902 public:\r
903     virtual bool Accept( XMLVisitor* visitor ) const;\r
904 \r
905     virtual XMLText* ToText()                   {\r
906         return this;\r
907     }\r
908     virtual const XMLText* ToText() const       {\r
909         return this;\r
910     }\r
911 \r
912     /// Declare whether this should be CDATA or standard text.\r
913     void SetCData( bool isCData )                       {\r
914         _isCData = isCData;\r
915     }\r
916     /// Returns true if this is a CDATA text element.\r
917     bool CData() const                                          {\r
918         return _isCData;\r
919     }\r
920 \r
921     virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
922     virtual bool ShallowEqual( const XMLNode* compare ) const;\r
923 \r
924 protected:\r
925     XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false )     {}\r
926     virtual ~XMLText()                                                                                          {}\r
927 \r
928     char* ParseDeep( char*, StrPair* endTag );\r
929 \r
930 private:\r
931     bool _isCData;\r
932 \r
933     XMLText( const XMLText& );  // not supported\r
934     XMLText& operator=( const XMLText& );       // not supported\r
935 };\r
936 \r
937 \r
938 /** An XML Comment. */\r
939 class TINYXML2_LIB XMLComment : public XMLNode\r
940 {\r
941     friend class XMLDocument;\r
942 public:\r
943     virtual XMLComment* ToComment()                                     {\r
944         return this;\r
945     }\r
946     virtual const XMLComment* ToComment() const         {\r
947         return this;\r
948     }\r
949 \r
950     virtual bool Accept( XMLVisitor* visitor ) const;\r
951 \r
952     virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
953     virtual bool ShallowEqual( const XMLNode* compare ) const;\r
954 \r
955 protected:\r
956     XMLComment( XMLDocument* doc );\r
957     virtual ~XMLComment();\r
958 \r
959     char* ParseDeep( char*, StrPair* endTag );\r
960 \r
961 private:\r
962     XMLComment( const XMLComment& );    // not supported\r
963     XMLComment& operator=( const XMLComment& ); // not supported\r
964 };\r
965 \r
966 \r
967 /** In correct XML the declaration is the first entry in the file.\r
968         @verbatim\r
969                 <?xml version="1.0" standalone="yes"?>\r
970         @endverbatim\r
971 \r
972         TinyXML-2 will happily read or write files without a declaration,\r
973         however.\r
974 \r
975         The text of the declaration isn't interpreted. It is parsed\r
976         and written as a string.\r
977 */\r
978 class TINYXML2_LIB XMLDeclaration : public XMLNode\r
979 {\r
980     friend class XMLDocument;\r
981 public:\r
982     virtual XMLDeclaration*     ToDeclaration()                                 {\r
983         return this;\r
984     }\r
985     virtual const XMLDeclaration* ToDeclaration() const         {\r
986         return this;\r
987     }\r
988 \r
989     virtual bool Accept( XMLVisitor* visitor ) const;\r
990 \r
991     virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
992     virtual bool ShallowEqual( const XMLNode* compare ) const;\r
993 \r
994 protected:\r
995     XMLDeclaration( XMLDocument* doc );\r
996     virtual ~XMLDeclaration();\r
997 \r
998     char* ParseDeep( char*, StrPair* endTag );\r
999 \r
1000 private:\r
1001     XMLDeclaration( const XMLDeclaration& );    // not supported\r
1002     XMLDeclaration& operator=( const XMLDeclaration& ); // not supported\r
1003 };\r
1004 \r
1005 \r
1006 /** Any tag that TinyXML-2 doesn't recognize is saved as an\r
1007         unknown. It is a tag of text, but should not be modified.\r
1008         It will be written back to the XML, unchanged, when the file\r
1009         is saved.\r
1010 \r
1011         DTD tags get thrown into XMLUnknowns.\r
1012 */\r
1013 class TINYXML2_LIB XMLUnknown : public XMLNode\r
1014 {\r
1015     friend class XMLDocument;\r
1016 public:\r
1017     virtual XMLUnknown* ToUnknown()                                     {\r
1018         return this;\r
1019     }\r
1020     virtual const XMLUnknown* ToUnknown() const         {\r
1021         return this;\r
1022     }\r
1023 \r
1024     virtual bool Accept( XMLVisitor* visitor ) const;\r
1025 \r
1026     virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
1027     virtual bool ShallowEqual( const XMLNode* compare ) const;\r
1028 \r
1029 protected:\r
1030     XMLUnknown( XMLDocument* doc );\r
1031     virtual ~XMLUnknown();\r
1032 \r
1033     char* ParseDeep( char*, StrPair* endTag );\r
1034 \r
1035 private:\r
1036     XMLUnknown( const XMLUnknown& );    // not supported\r
1037     XMLUnknown& operator=( const XMLUnknown& ); // not supported\r
1038 };\r
1039 \r
1040 \r
1041 \r
1042 /** An attribute is a name-value pair. Elements have an arbitrary\r
1043         number of attributes, each with a unique name.\r
1044 \r
1045         @note The attributes are not XMLNodes. You may only query the\r
1046         Next() attribute in a list.\r
1047 */\r
1048 class TINYXML2_LIB XMLAttribute\r
1049 {\r
1050     friend class XMLElement;\r
1051 public:\r
1052     /// The name of the attribute.\r
1053     const char* Name() const;\r
1054 \r
1055     /// The value of the attribute.\r
1056     const char* Value() const;\r
1057 \r
1058     /// The next attribute in the list.\r
1059     const XMLAttribute* Next() const {\r
1060         return _next;\r
1061     }\r
1062 \r
1063     /** IntValue interprets the attribute as an integer, and returns the value.\r
1064         If the value isn't an integer, 0 will be returned. There is no error checking;\r
1065         use QueryIntValue() if you need error checking.\r
1066     */\r
1067     int          IntValue() const                               {\r
1068         int i=0;\r
1069         QueryIntValue( &i );\r
1070         return i;\r
1071     }\r
1072     /// Query as an unsigned integer. See IntValue()\r
1073     unsigned UnsignedValue() const                      {\r
1074         unsigned i=0;\r
1075         QueryUnsignedValue( &i );\r
1076         return i;\r
1077     }\r
1078     /// Query as a boolean. See IntValue()\r
1079     bool         BoolValue() const                              {\r
1080         bool b=false;\r
1081         QueryBoolValue( &b );\r
1082         return b;\r
1083     }\r
1084     /// Query as a double. See IntValue()\r
1085     double       DoubleValue() const                    {\r
1086         double d=0;\r
1087         QueryDoubleValue( &d );\r
1088         return d;\r
1089     }\r
1090     /// Query as a float. See IntValue()\r
1091     float        FloatValue() const                             {\r
1092         float f=0;\r
1093         QueryFloatValue( &f );\r
1094         return f;\r
1095     }\r
1096 \r
1097     /** QueryIntValue interprets the attribute as an integer, and returns the value\r
1098         in the provided parameter. The function will return XML_NO_ERROR on success,\r
1099         and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.\r
1100     */\r
1101     XMLError QueryIntValue( int* value ) const;\r
1102     /// See QueryIntValue\r
1103     XMLError QueryUnsignedValue( unsigned int* value ) const;\r
1104     /// See QueryIntValue\r
1105     XMLError QueryBoolValue( bool* value ) const;\r
1106     /// See QueryIntValue\r
1107     XMLError QueryDoubleValue( double* value ) const;\r
1108     /// See QueryIntValue\r
1109     XMLError QueryFloatValue( float* value ) const;\r
1110 \r
1111     /// Set the attribute to a string value.\r
1112     void SetAttribute( const char* value );\r
1113     /// Set the attribute to value.\r
1114     void SetAttribute( int value );\r
1115     /// Set the attribute to value.\r
1116     void SetAttribute( unsigned value );\r
1117     /// Set the attribute to value.\r
1118     void SetAttribute( bool value );\r
1119     /// Set the attribute to value.\r
1120     void SetAttribute( double value );\r
1121     /// Set the attribute to value.\r
1122     void SetAttribute( float value );\r
1123 \r
1124 private:\r
1125     enum { BUF_SIZE = 200 };\r
1126 \r
1127     XMLAttribute() : _next( 0 ), _memPool( 0 ) {}\r
1128     virtual ~XMLAttribute()     {}\r
1129 \r
1130     XMLAttribute( const XMLAttribute& );        // not supported\r
1131     void operator=( const XMLAttribute& );      // not supported\r
1132     void SetName( const char* name );\r
1133 \r
1134     char* ParseDeep( char* p, bool processEntities );\r
1135 \r
1136     mutable StrPair _name;\r
1137     mutable StrPair _value;\r
1138     XMLAttribute*   _next;\r
1139     MemPool*        _memPool;\r
1140 };\r
1141 \r
1142 \r
1143 /** The element is a container class. It has a value, the element name,\r
1144         and can contain other elements, text, comments, and unknowns.\r
1145         Elements also contain an arbitrary number of attributes.\r
1146 */\r
1147 class TINYXML2_LIB XMLElement : public XMLNode\r
1148 {\r
1149     friend class XMLBase;\r
1150     friend class XMLDocument;\r
1151 public:\r
1152     /// Get the name of an element (which is the Value() of the node.)\r
1153     const char* Name() const            {\r
1154         return Value();\r
1155     }\r
1156     /// Set the name of the element.\r
1157     void SetName( const char* str, bool staticMem=false )       {\r
1158         SetValue( str, staticMem );\r
1159     }\r
1160 \r
1161     virtual XMLElement* ToElement()                             {\r
1162         return this;\r
1163     }\r
1164     virtual const XMLElement* ToElement() const {\r
1165         return this;\r
1166     }\r
1167     virtual bool Accept( XMLVisitor* visitor ) const;\r
1168 \r
1169     /** Given an attribute name, Attribute() returns the value\r
1170         for the attribute of that name, or null if none\r
1171         exists. For example:\r
1172 \r
1173         @verbatim\r
1174         const char* value = ele->Attribute( "foo" );\r
1175         @endverbatim\r
1176 \r
1177         The 'value' parameter is normally null. However, if specified,\r
1178         the attribute will only be returned if the 'name' and 'value'\r
1179         match. This allow you to write code:\r
1180 \r
1181         @verbatim\r
1182         if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();\r
1183         @endverbatim\r
1184 \r
1185         rather than:\r
1186         @verbatim\r
1187         if ( ele->Attribute( "foo" ) ) {\r
1188                 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();\r
1189         }\r
1190         @endverbatim\r
1191     */\r
1192     const char* Attribute( const char* name, const char* value=0 ) const;\r
1193 \r
1194     /** Given an attribute name, IntAttribute() returns the value\r
1195         of the attribute interpreted as an integer. 0 will be\r
1196         returned if there is an error. For a method with error\r
1197         checking, see QueryIntAttribute()\r
1198     */\r
1199     int          IntAttribute( const char* name ) const         {\r
1200         int i=0;\r
1201         QueryIntAttribute( name, &i );\r
1202         return i;\r
1203     }\r
1204     /// See IntAttribute()\r
1205     unsigned UnsignedAttribute( const char* name ) const {\r
1206         unsigned i=0;\r
1207         QueryUnsignedAttribute( name, &i );\r
1208         return i;\r
1209     }\r
1210     /// See IntAttribute()\r
1211     bool         BoolAttribute( const char* name ) const        {\r
1212         bool b=false;\r
1213         QueryBoolAttribute( name, &b );\r
1214         return b;\r
1215     }\r
1216     /// See IntAttribute()\r
1217     double       DoubleAttribute( const char* name ) const      {\r
1218         double d=0;\r
1219         QueryDoubleAttribute( name, &d );\r
1220         return d;\r
1221     }\r
1222     /// See IntAttribute()\r
1223     float        FloatAttribute( const char* name ) const       {\r
1224         float f=0;\r
1225         QueryFloatAttribute( name, &f );\r
1226         return f;\r
1227     }\r
1228 \r
1229     /** Given an attribute name, QueryIntAttribute() returns\r
1230         XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion\r
1231         can't be performed, or XML_NO_ATTRIBUTE if the attribute\r
1232         doesn't exist. If successful, the result of the conversion\r
1233         will be written to 'value'. If not successful, nothing will\r
1234         be written to 'value'. This allows you to provide default\r
1235         value:\r
1236 \r
1237         @verbatim\r
1238         int value = 10;\r
1239         QueryIntAttribute( "foo", &value );             // if "foo" isn't found, value will still be 10\r
1240         @endverbatim\r
1241     */\r
1242     XMLError QueryIntAttribute( const char* name, int* value ) const                            {\r
1243         const XMLAttribute* a = FindAttribute( name );\r
1244         if ( !a ) {\r
1245             return XML_NO_ATTRIBUTE;\r
1246         }\r
1247         return a->QueryIntValue( value );\r
1248     }\r
1249     /// See QueryIntAttribute()\r
1250     XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const      {\r
1251         const XMLAttribute* a = FindAttribute( name );\r
1252         if ( !a ) {\r
1253             return XML_NO_ATTRIBUTE;\r
1254         }\r
1255         return a->QueryUnsignedValue( value );\r
1256     }\r
1257     /// See QueryIntAttribute()\r
1258     XMLError QueryBoolAttribute( const char* name, bool* value ) const                          {\r
1259         const XMLAttribute* a = FindAttribute( name );\r
1260         if ( !a ) {\r
1261             return XML_NO_ATTRIBUTE;\r
1262         }\r
1263         return a->QueryBoolValue( value );\r
1264     }\r
1265     /// See QueryIntAttribute()\r
1266     XMLError QueryDoubleAttribute( const char* name, double* value ) const                      {\r
1267         const XMLAttribute* a = FindAttribute( name );\r
1268         if ( !a ) {\r
1269             return XML_NO_ATTRIBUTE;\r
1270         }\r
1271         return a->QueryDoubleValue( value );\r
1272     }\r
1273     /// See QueryIntAttribute()\r
1274     XMLError QueryFloatAttribute( const char* name, float* value ) const                        {\r
1275         const XMLAttribute* a = FindAttribute( name );\r
1276         if ( !a ) {\r
1277             return XML_NO_ATTRIBUTE;\r
1278         }\r
1279         return a->QueryFloatValue( value );\r
1280     }\r
1281 \r
1282         \r
1283     /** Given an attribute name, QueryAttribute() returns\r
1284         XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion\r
1285         can't be performed, or XML_NO_ATTRIBUTE if the attribute\r
1286         doesn't exist. It is overloaded for the primitive types,\r
1287                 and is a generally more convenient replacement of\r
1288                 QueryIntAttribute() and related functions.\r
1289                 \r
1290                 If successful, the result of the conversion\r
1291         will be written to 'value'. If not successful, nothing will\r
1292         be written to 'value'. This allows you to provide default\r
1293         value:\r
1294 \r
1295         @verbatim\r
1296         int value = 10;\r
1297         QueryAttribute( "foo", &value );                // if "foo" isn't found, value will still be 10\r
1298         @endverbatim\r
1299     */\r
1300         int QueryAttribute( const char* name, int* value ) const {\r
1301                 return QueryIntAttribute( name, value );\r
1302         }\r
1303 \r
1304         int QueryAttribute( const char* name, unsigned int* value ) const {\r
1305                 return QueryUnsignedAttribute( name, value );\r
1306         }\r
1307 \r
1308         int QueryAttribute( const char* name, bool* value ) const {\r
1309                 return QueryBoolAttribute( name, value );\r
1310         }\r
1311 \r
1312         int QueryAttribute( const char* name, double* value ) const {\r
1313                 return QueryDoubleAttribute( name, value );\r
1314         }\r
1315 \r
1316         int QueryAttribute( const char* name, float* value ) const {\r
1317                 return QueryFloatAttribute( name, value );\r
1318         }\r
1319 \r
1320         /// Sets the named attribute to value.\r
1321     void SetAttribute( const char* name, const char* value )    {\r
1322         XMLAttribute* a = FindOrCreateAttribute( name );\r
1323         a->SetAttribute( value );\r
1324     }\r
1325     /// Sets the named attribute to value.\r
1326     void SetAttribute( const char* name, int value )                    {\r
1327         XMLAttribute* a = FindOrCreateAttribute( name );\r
1328         a->SetAttribute( value );\r
1329     }\r
1330     /// Sets the named attribute to value.\r
1331     void SetAttribute( const char* name, unsigned value )               {\r
1332         XMLAttribute* a = FindOrCreateAttribute( name );\r
1333         a->SetAttribute( value );\r
1334     }\r
1335     /// Sets the named attribute to value.\r
1336     void SetAttribute( const char* name, bool value )                   {\r
1337         XMLAttribute* a = FindOrCreateAttribute( name );\r
1338         a->SetAttribute( value );\r
1339     }\r
1340     /// Sets the named attribute to value.\r
1341     void SetAttribute( const char* name, double value )         {\r
1342         XMLAttribute* a = FindOrCreateAttribute( name );\r
1343         a->SetAttribute( value );\r
1344     }\r
1345     /// Sets the named attribute to value.\r
1346     void SetAttribute( const char* name, float value )          {\r
1347         XMLAttribute* a = FindOrCreateAttribute( name );\r
1348         a->SetAttribute( value );\r
1349     }\r
1350 \r
1351     /**\r
1352         Delete an attribute.\r
1353     */\r
1354     void DeleteAttribute( const char* name );\r
1355 \r
1356     /// Return the first attribute in the list.\r
1357     const XMLAttribute* FirstAttribute() const {\r
1358         return _rootAttribute;\r
1359     }\r
1360     /// Query a specific attribute in the list.\r
1361     const XMLAttribute* FindAttribute( const char* name ) const;\r
1362 \r
1363     /** Convenience function for easy access to the text inside an element. Although easy\r
1364         and concise, GetText() is limited compared to getting the XMLText child\r
1365         and accessing it directly.\r
1366 \r
1367         If the first child of 'this' is a XMLText, the GetText()\r
1368         returns the character string of the Text node, else null is returned.\r
1369 \r
1370         This is a convenient method for getting the text of simple contained text:\r
1371         @verbatim\r
1372         <foo>This is text</foo>\r
1373                 const char* str = fooElement->GetText();\r
1374         @endverbatim\r
1375 \r
1376         'str' will be a pointer to "This is text".\r
1377 \r
1378         Note that this function can be misleading. If the element foo was created from\r
1379         this XML:\r
1380         @verbatim\r
1381                 <foo><b>This is text</b></foo>\r
1382         @endverbatim\r
1383 \r
1384         then the value of str would be null. The first child node isn't a text node, it is\r
1385         another element. From this XML:\r
1386         @verbatim\r
1387                 <foo>This is <b>text</b></foo>\r
1388         @endverbatim\r
1389         GetText() will return "This is ".\r
1390     */\r
1391     const char* GetText() const;\r
1392 \r
1393     /** Convenience function for easy access to the text inside an element. Although easy\r
1394         and concise, SetText() is limited compared to creating an XMLText child\r
1395         and mutating it directly.\r
1396 \r
1397         If the first child of 'this' is a XMLText, SetText() sets its value to\r
1398                 the given string, otherwise it will create a first child that is an XMLText.\r
1399 \r
1400         This is a convenient method for setting the text of simple contained text:\r
1401         @verbatim\r
1402         <foo>This is text</foo>\r
1403                 fooElement->SetText( "Hullaballoo!" );\r
1404         <foo>Hullaballoo!</foo>\r
1405                 @endverbatim\r
1406 \r
1407         Note that this function can be misleading. If the element foo was created from\r
1408         this XML:\r
1409         @verbatim\r
1410                 <foo><b>This is text</b></foo>\r
1411         @endverbatim\r
1412 \r
1413         then it will not change "This is text", but rather prefix it with a text element:\r
1414         @verbatim\r
1415                 <foo>Hullaballoo!<b>This is text</b></foo>\r
1416         @endverbatim\r
1417                 \r
1418                 For this XML:\r
1419         @verbatim\r
1420                 <foo />\r
1421         @endverbatim\r
1422         SetText() will generate\r
1423         @verbatim\r
1424                 <foo>Hullaballoo!</foo>\r
1425         @endverbatim\r
1426     */\r
1427         void SetText( const char* inText );\r
1428     /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
1429     void SetText( int value );\r
1430     /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
1431     void SetText( unsigned value );  \r
1432     /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
1433     void SetText( bool value );  \r
1434     /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
1435     void SetText( double value );  \r
1436     /// Convenience method for setting text inside an element. See SetText() for important limitations.\r
1437     void SetText( float value );  \r
1438 \r
1439     /**\r
1440         Convenience method to query the value of a child text node. This is probably best\r
1441         shown by example. Given you have a document is this form:\r
1442         @verbatim\r
1443                 <point>\r
1444                         <x>1</x>\r
1445                         <y>1.4</y>\r
1446                 </point>\r
1447         @endverbatim\r
1448 \r
1449         The QueryIntText() and similar functions provide a safe and easier way to get to the\r
1450         "value" of x and y.\r
1451 \r
1452         @verbatim\r
1453                 int x = 0;\r
1454                 float y = 0;    // types of x and y are contrived for example\r
1455                 const XMLElement* xElement = pointElement->FirstChildElement( "x" );\r
1456                 const XMLElement* yElement = pointElement->FirstChildElement( "y" );\r
1457                 xElement->QueryIntText( &x );\r
1458                 yElement->QueryFloatText( &y );\r
1459         @endverbatim\r
1460 \r
1461         @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted\r
1462                          to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.\r
1463 \r
1464     */\r
1465     XMLError QueryIntText( int* ival ) const;\r
1466     /// See QueryIntText()\r
1467     XMLError QueryUnsignedText( unsigned* uval ) const;\r
1468     /// See QueryIntText()\r
1469     XMLError QueryBoolText( bool* bval ) const;\r
1470     /// See QueryIntText()\r
1471     XMLError QueryDoubleText( double* dval ) const;\r
1472     /// See QueryIntText()\r
1473     XMLError QueryFloatText( float* fval ) const;\r
1474 \r
1475     // internal:\r
1476     enum {\r
1477         OPEN,           // <foo>\r
1478         CLOSED,         // <foo/>\r
1479         CLOSING         // </foo>\r
1480     };\r
1481     int ClosingType() const {\r
1482         return _closingType;\r
1483     }\r
1484     virtual XMLNode* ShallowClone( XMLDocument* document ) const;\r
1485     virtual bool ShallowEqual( const XMLNode* compare ) const;\r
1486 \r
1487 protected:\r
1488     char* ParseDeep( char* p, StrPair* endTag );\r
1489 \r
1490 private:\r
1491     XMLElement( XMLDocument* doc );\r
1492     virtual ~XMLElement();\r
1493     XMLElement( const XMLElement& );    // not supported\r
1494     void operator=( const XMLElement& );        // not supported\r
1495 \r
1496     XMLAttribute* FindAttribute( const char* name ) {\r
1497         return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));\r
1498     }\r
1499     XMLAttribute* FindOrCreateAttribute( const char* name );\r
1500     //void LinkAttribute( XMLAttribute* attrib );\r
1501     char* ParseAttributes( char* p );\r
1502     static void DeleteAttribute( XMLAttribute* attribute );\r
1503 \r
1504     enum { BUF_SIZE = 200 };\r
1505     int _closingType;\r
1506     // The attribute list is ordered; there is no 'lastAttribute'\r
1507     // because the list needs to be scanned for dupes before adding\r
1508     // a new attribute.\r
1509     XMLAttribute* _rootAttribute;\r
1510 };\r
1511 \r
1512 \r
1513 enum Whitespace {\r
1514     PRESERVE_WHITESPACE,\r
1515     COLLAPSE_WHITESPACE\r
1516 };\r
1517 \r
1518 \r
1519 /** A Document binds together all the functionality.\r
1520         It can be saved, loaded, and printed to the screen.\r
1521         All Nodes are connected and allocated to a Document.\r
1522         If the Document is deleted, all its Nodes are also deleted.\r
1523 */\r
1524 class TINYXML2_LIB XMLDocument : public XMLNode\r
1525 {\r
1526     friend class XMLElement;\r
1527 public:\r
1528     /// constructor\r
1529     XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );\r
1530     ~XMLDocument();\r
1531 \r
1532     virtual XMLDocument* ToDocument()                           {\r
1533         TIXMLASSERT( this == _document );\r
1534         return this;\r
1535     }\r
1536     virtual const XMLDocument* ToDocument() const       {\r
1537         TIXMLASSERT( this == _document );\r
1538         return this;\r
1539     }\r
1540 \r
1541     /**\r
1542         Parse an XML file from a character string.\r
1543         Returns XML_NO_ERROR (0) on success, or\r
1544         an errorID.\r
1545 \r
1546         You may optionally pass in the 'nBytes', which is\r
1547         the number of bytes which will be parsed. If not\r
1548         specified, TinyXML-2 will assume 'xml' points to a\r
1549         null terminated string.\r
1550     */\r
1551     XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );\r
1552 \r
1553     /**\r
1554         Load an XML file from disk.\r
1555         Returns XML_NO_ERROR (0) on success, or\r
1556         an errorID.\r
1557     */\r
1558     XMLError LoadFile( const char* filename );\r
1559 \r
1560     /**\r
1561         Load an XML file from disk. You are responsible\r
1562         for providing and closing the FILE*. \r
1563      \r
1564         NOTE: The file should be opened as binary ("rb")\r
1565         not text in order for TinyXML-2 to correctly\r
1566         do newline normalization.\r
1567 \r
1568         Returns XML_NO_ERROR (0) on success, or\r
1569         an errorID.\r
1570     */\r
1571     XMLError LoadFile( FILE* );\r
1572 \r
1573     /**\r
1574         Save the XML file to disk.\r
1575         Returns XML_NO_ERROR (0) on success, or\r
1576         an errorID.\r
1577     */\r
1578     XMLError SaveFile( const char* filename, bool compact = false );\r
1579 \r
1580     /**\r
1581         Save the XML file to disk. You are responsible\r
1582         for providing and closing the FILE*.\r
1583 \r
1584         Returns XML_NO_ERROR (0) on success, or\r
1585         an errorID.\r
1586     */\r
1587     XMLError SaveFile( FILE* fp, bool compact = false );\r
1588 \r
1589     bool ProcessEntities() const                {\r
1590         return _processEntities;\r
1591     }\r
1592     Whitespace WhitespaceMode() const   {\r
1593         return _whitespace;\r
1594     }\r
1595 \r
1596     /**\r
1597         Returns true if this document has a leading Byte Order Mark of UTF8.\r
1598     */\r
1599     bool HasBOM() const {\r
1600         return _writeBOM;\r
1601     }\r
1602     /** Sets whether to write the BOM when writing the file.\r
1603     */\r
1604     void SetBOM( bool useBOM ) {\r
1605         _writeBOM = useBOM;\r
1606     }\r
1607 \r
1608     /** Return the root element of DOM. Equivalent to FirstChildElement().\r
1609         To get the first node, use FirstChild().\r
1610     */\r
1611     XMLElement* RootElement()                           {\r
1612         return FirstChildElement();\r
1613     }\r
1614     const XMLElement* RootElement() const       {\r
1615         return FirstChildElement();\r
1616     }\r
1617 \r
1618     /** Print the Document. If the Printer is not provided, it will\r
1619         print to stdout. If you provide Printer, this can print to a file:\r
1620         @verbatim\r
1621         XMLPrinter printer( fp );\r
1622         doc.Print( &printer );\r
1623         @endverbatim\r
1624 \r
1625         Or you can use a printer to print to memory:\r
1626         @verbatim\r
1627         XMLPrinter printer;\r
1628         doc.Print( &printer );\r
1629         // printer.CStr() has a const char* to the XML\r
1630         @endverbatim\r
1631     */\r
1632     void Print( XMLPrinter* streamer=0 ) const;\r
1633     virtual bool Accept( XMLVisitor* visitor ) const;\r
1634 \r
1635     /**\r
1636         Create a new Element associated with\r
1637         this Document. The memory for the Element\r
1638         is managed by the Document.\r
1639     */\r
1640     XMLElement* NewElement( const char* name );\r
1641     /**\r
1642         Create a new Comment associated with\r
1643         this Document. The memory for the Comment\r
1644         is managed by the Document.\r
1645     */\r
1646     XMLComment* NewComment( const char* comment );\r
1647     /**\r
1648         Create a new Text associated with\r
1649         this Document. The memory for the Text\r
1650         is managed by the Document.\r
1651     */\r
1652     XMLText* NewText( const char* text );\r
1653     /**\r
1654         Create a new Declaration associated with\r
1655         this Document. The memory for the object\r
1656         is managed by the Document.\r
1657 \r
1658         If the 'text' param is null, the standard\r
1659         declaration is used.:\r
1660         @verbatim\r
1661                 <?xml version="1.0" encoding="UTF-8"?>\r
1662         @endverbatim\r
1663     */\r
1664     XMLDeclaration* NewDeclaration( const char* text=0 );\r
1665     /**\r
1666         Create a new Unknown associated with\r
1667         this Document. The memory for the object\r
1668         is managed by the Document.\r
1669     */\r
1670     XMLUnknown* NewUnknown( const char* text );\r
1671 \r
1672     /**\r
1673         Delete a node associated with this document.\r
1674         It will be unlinked from the DOM.\r
1675     */\r
1676     void DeleteNode( XMLNode* node );\r
1677 \r
1678     void SetError( XMLError error, const char* str1, const char* str2 );\r
1679 \r
1680     /// Return true if there was an error parsing the document.\r
1681     bool Error() const {\r
1682         return _errorID != XML_NO_ERROR;\r
1683     }\r
1684     /// Return the errorID.\r
1685     XMLError  ErrorID() const {\r
1686         return _errorID;\r
1687     }\r
1688         const char* ErrorName() const;\r
1689 \r
1690     /// Return a possibly helpful diagnostic location or string.\r
1691     const char* GetErrorStr1() const {\r
1692         return _errorStr1;\r
1693     }\r
1694     /// Return a possibly helpful secondary diagnostic location or string.\r
1695     const char* GetErrorStr2() const {\r
1696         return _errorStr2;\r
1697     }\r
1698     /// If there is an error, print it to stdout.\r
1699     void PrintError() const;\r
1700     \r
1701     /// Clear the document, resetting it to the initial state.\r
1702     void Clear();\r
1703 \r
1704     // internal\r
1705     char* Identify( char* p, XMLNode** node );\r
1706 \r
1707     virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const    {\r
1708         return 0;\r
1709     }\r
1710     virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const       {\r
1711         return false;\r
1712     }\r
1713 \r
1714 private:\r
1715     XMLDocument( const XMLDocument& );  // not supported\r
1716     void operator=( const XMLDocument& );       // not supported\r
1717 \r
1718     bool        _writeBOM;\r
1719     bool        _processEntities;\r
1720     XMLError    _errorID;\r
1721     Whitespace  _whitespace;\r
1722     const char* _errorStr1;\r
1723     const char* _errorStr2;\r
1724     char*       _charBuffer;\r
1725 \r
1726     MemPoolT< sizeof(XMLElement) >       _elementPool;\r
1727     MemPoolT< sizeof(XMLAttribute) > _attributePool;\r
1728     MemPoolT< sizeof(XMLText) >          _textPool;\r
1729     MemPoolT< sizeof(XMLComment) >       _commentPool;\r
1730 \r
1731         static const char* _errorNames[XML_ERROR_COUNT];\r
1732 \r
1733     void Parse();\r
1734 };\r
1735 \r
1736 \r
1737 /**\r
1738         A XMLHandle is a class that wraps a node pointer with null checks; this is\r
1739         an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2\r
1740         DOM structure. It is a separate utility class.\r
1741 \r
1742         Take an example:\r
1743         @verbatim\r
1744         <Document>\r
1745                 <Element attributeA = "valueA">\r
1746                         <Child attributeB = "value1" />\r
1747                         <Child attributeB = "value2" />\r
1748                 </Element>\r
1749         </Document>\r
1750         @endverbatim\r
1751 \r
1752         Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very\r
1753         easy to write a *lot* of code that looks like:\r
1754 \r
1755         @verbatim\r
1756         XMLElement* root = document.FirstChildElement( "Document" );\r
1757         if ( root )\r
1758         {\r
1759                 XMLElement* element = root->FirstChildElement( "Element" );\r
1760                 if ( element )\r
1761                 {\r
1762                         XMLElement* child = element->FirstChildElement( "Child" );\r
1763                         if ( child )\r
1764                         {\r
1765                                 XMLElement* child2 = child->NextSiblingElement( "Child" );\r
1766                                 if ( child2 )\r
1767                                 {\r
1768                                         // Finally do something useful.\r
1769         @endverbatim\r
1770 \r
1771         And that doesn't even cover "else" cases. XMLHandle addresses the verbosity\r
1772         of such code. A XMLHandle checks for null pointers so it is perfectly safe\r
1773         and correct to use:\r
1774 \r
1775         @verbatim\r
1776         XMLHandle docHandle( &document );\r
1777         XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();\r
1778         if ( child2 )\r
1779         {\r
1780                 // do something useful\r
1781         @endverbatim\r
1782 \r
1783         Which is MUCH more concise and useful.\r
1784 \r
1785         It is also safe to copy handles - internally they are nothing more than node pointers.\r
1786         @verbatim\r
1787         XMLHandle handleCopy = handle;\r
1788         @endverbatim\r
1789 \r
1790         See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.\r
1791 */\r
1792 class TINYXML2_LIB XMLHandle\r
1793 {\r
1794 public:\r
1795     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.\r
1796     XMLHandle( XMLNode* node )                                                                                          {\r
1797         _node = node;\r
1798     }\r
1799     /// Create a handle from a node.\r
1800     XMLHandle( XMLNode& node )                                                                                          {\r
1801         _node = &node;\r
1802     }\r
1803     /// Copy constructor\r
1804     XMLHandle( const XMLHandle& ref )                                                                           {\r
1805         _node = ref._node;\r
1806     }\r
1807     /// Assignment\r
1808     XMLHandle& operator=( const XMLHandle& ref )                                                        {\r
1809         _node = ref._node;\r
1810         return *this;\r
1811     }\r
1812 \r
1813     /// Get the first child of this handle.\r
1814     XMLHandle FirstChild()                                                                                                      {\r
1815         return XMLHandle( _node ? _node->FirstChild() : 0 );\r
1816     }\r
1817     /// Get the first child element of this handle.\r
1818     XMLHandle FirstChildElement( const char* name = 0 )                                         {\r
1819         return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );\r
1820     }\r
1821     /// Get the last child of this handle.\r
1822     XMLHandle LastChild()                                                                                                       {\r
1823         return XMLHandle( _node ? _node->LastChild() : 0 );\r
1824     }\r
1825     /// Get the last child element of this handle.\r
1826     XMLHandle LastChildElement( const char* name = 0 )                                          {\r
1827         return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );\r
1828     }\r
1829     /// Get the previous sibling of this handle.\r
1830     XMLHandle PreviousSibling()                                                                                         {\r
1831         return XMLHandle( _node ? _node->PreviousSibling() : 0 );\r
1832     }\r
1833     /// Get the previous sibling element of this handle.\r
1834     XMLHandle PreviousSiblingElement( const char* name = 0 )                            {\r
1835         return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\r
1836     }\r
1837     /// Get the next sibling of this handle.\r
1838     XMLHandle NextSibling()                                                                                                     {\r
1839         return XMLHandle( _node ? _node->NextSibling() : 0 );\r
1840     }\r
1841     /// Get the next sibling element of this handle.\r
1842     XMLHandle NextSiblingElement( const char* name = 0 )                                        {\r
1843         return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );\r
1844     }\r
1845 \r
1846     /// Safe cast to XMLNode. This can return null.\r
1847     XMLNode* ToNode()                                                   {\r
1848         return _node;\r
1849     }\r
1850     /// Safe cast to XMLElement. This can return null.\r
1851     XMLElement* ToElement()                                     {\r
1852         return ( ( _node == 0 ) ? 0 : _node->ToElement() );\r
1853     }\r
1854     /// Safe cast to XMLText. This can return null.\r
1855     XMLText* ToText()                                                   {\r
1856         return ( ( _node == 0 ) ? 0 : _node->ToText() );\r
1857     }\r
1858     /// Safe cast to XMLUnknown. This can return null.\r
1859     XMLUnknown* ToUnknown()                                     {\r
1860         return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );\r
1861     }\r
1862     /// Safe cast to XMLDeclaration. This can return null.\r
1863     XMLDeclaration* ToDeclaration()                     {\r
1864         return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );\r
1865     }\r
1866 \r
1867 private:\r
1868     XMLNode* _node;\r
1869 };\r
1870 \r
1871 \r
1872 /**\r
1873         A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the\r
1874         same in all regards, except for the 'const' qualifiers. See XMLHandle for API.\r
1875 */\r
1876 class TINYXML2_LIB XMLConstHandle\r
1877 {\r
1878 public:\r
1879     XMLConstHandle( const XMLNode* node )                                                                                       {\r
1880         _node = node;\r
1881     }\r
1882     XMLConstHandle( const XMLNode& node )                                                                                       {\r
1883         _node = &node;\r
1884     }\r
1885     XMLConstHandle( const XMLConstHandle& ref )                                                                         {\r
1886         _node = ref._node;\r
1887     }\r
1888 \r
1889     XMLConstHandle& operator=( const XMLConstHandle& ref )                                                      {\r
1890         _node = ref._node;\r
1891         return *this;\r
1892     }\r
1893 \r
1894     const XMLConstHandle FirstChild() const                                                                                     {\r
1895         return XMLConstHandle( _node ? _node->FirstChild() : 0 );\r
1896     }\r
1897     const XMLConstHandle FirstChildElement( const char* name = 0 ) const                                {\r
1898         return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );\r
1899     }\r
1900     const XMLConstHandle LastChild()    const                                                                           {\r
1901         return XMLConstHandle( _node ? _node->LastChild() : 0 );\r
1902     }\r
1903     const XMLConstHandle LastChildElement( const char* name = 0 ) const                         {\r
1904         return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );\r
1905     }\r
1906     const XMLConstHandle PreviousSibling() const                                                                        {\r
1907         return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );\r
1908     }\r
1909     const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const           {\r
1910         return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );\r
1911     }\r
1912     const XMLConstHandle NextSibling() const                                                                            {\r
1913         return XMLConstHandle( _node ? _node->NextSibling() : 0 );\r
1914     }\r
1915     const XMLConstHandle NextSiblingElement( const char* name = 0 ) const                       {\r
1916         return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );\r
1917     }\r
1918 \r
1919 \r
1920     const XMLNode* ToNode() const                               {\r
1921         return _node;\r
1922     }\r
1923     const XMLElement* ToElement() const                 {\r
1924         return ( ( _node == 0 ) ? 0 : _node->ToElement() );\r
1925     }\r
1926     const XMLText* ToText() const                               {\r
1927         return ( ( _node == 0 ) ? 0 : _node->ToText() );\r
1928     }\r
1929     const XMLUnknown* ToUnknown() const                 {\r
1930         return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );\r
1931     }\r
1932     const XMLDeclaration* ToDeclaration() const {\r
1933         return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );\r
1934     }\r
1935 \r
1936 private:\r
1937     const XMLNode* _node;\r
1938 };\r
1939 \r
1940 \r
1941 /**\r
1942         Printing functionality. The XMLPrinter gives you more\r
1943         options than the XMLDocument::Print() method.\r
1944 \r
1945         It can:\r
1946         -# Print to memory.\r
1947         -# Print to a file you provide.\r
1948         -# Print XML without a XMLDocument.\r
1949 \r
1950         Print to Memory\r
1951 \r
1952         @verbatim\r
1953         XMLPrinter printer;\r
1954         doc.Print( &printer );\r
1955         SomeFunction( printer.CStr() );\r
1956         @endverbatim\r
1957 \r
1958         Print to a File\r
1959 \r
1960         You provide the file pointer.\r
1961         @verbatim\r
1962         XMLPrinter printer( fp );\r
1963         doc.Print( &printer );\r
1964         @endverbatim\r
1965 \r
1966         Print without a XMLDocument\r
1967 \r
1968         When loading, an XML parser is very useful. However, sometimes\r
1969         when saving, it just gets in the way. The code is often set up\r
1970         for streaming, and constructing the DOM is just overhead.\r
1971 \r
1972         The Printer supports the streaming case. The following code\r
1973         prints out a trivially simple XML file without ever creating\r
1974         an XML document.\r
1975 \r
1976         @verbatim\r
1977         XMLPrinter printer( fp );\r
1978         printer.OpenElement( "foo" );\r
1979         printer.PushAttribute( "foo", "bar" );\r
1980         printer.CloseElement();\r
1981         @endverbatim\r
1982 */\r
1983 class TINYXML2_LIB XMLPrinter : public XMLVisitor\r
1984 {\r
1985 public:\r
1986     /** Construct the printer. If the FILE* is specified,\r
1987         this will print to the FILE. Else it will print\r
1988         to memory, and the result is available in CStr().\r
1989         If 'compact' is set to true, then output is created\r
1990         with only required whitespace and newlines.\r
1991     */\r
1992     XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );\r
1993     virtual ~XMLPrinter()       {}\r
1994 \r
1995     /** If streaming, write the BOM and declaration. */\r
1996     void PushHeader( bool writeBOM, bool writeDeclaration );\r
1997     /** If streaming, start writing an element.\r
1998         The element must be closed with CloseElement()\r
1999     */\r
2000     void OpenElement( const char* name, bool compactMode=false );\r
2001     /// If streaming, add an attribute to an open element.\r
2002     void PushAttribute( const char* name, const char* value );\r
2003     void PushAttribute( const char* name, int value );\r
2004     void PushAttribute( const char* name, unsigned value );\r
2005     void PushAttribute( const char* name, bool value );\r
2006     void PushAttribute( const char* name, double value );\r
2007     /// If streaming, close the Element.\r
2008     virtual void CloseElement( bool compactMode=false );\r
2009 \r
2010     /// Add a text node.\r
2011     void PushText( const char* text, bool cdata=false );\r
2012     /// Add a text node from an integer.\r
2013     void PushText( int value );\r
2014     /// Add a text node from an unsigned.\r
2015     void PushText( unsigned value );\r
2016     /// Add a text node from a bool.\r
2017     void PushText( bool value );\r
2018     /// Add a text node from a float.\r
2019     void PushText( float value );\r
2020     /// Add a text node from a double.\r
2021     void PushText( double value );\r
2022 \r
2023     /// Add a comment\r
2024     void PushComment( const char* comment );\r
2025 \r
2026     void PushDeclaration( const char* value );\r
2027     void PushUnknown( const char* value );\r
2028 \r
2029     virtual bool VisitEnter( const XMLDocument& /*doc*/ );\r
2030     virtual bool VisitExit( const XMLDocument& /*doc*/ )                        {\r
2031         return true;\r
2032     }\r
2033 \r
2034     virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );\r
2035     virtual bool VisitExit( const XMLElement& element );\r
2036 \r
2037     virtual bool Visit( const XMLText& text );\r
2038     virtual bool Visit( const XMLComment& comment );\r
2039     virtual bool Visit( const XMLDeclaration& declaration );\r
2040     virtual bool Visit( const XMLUnknown& unknown );\r
2041 \r
2042     /**\r
2043         If in print to memory mode, return a pointer to\r
2044         the XML file in memory.\r
2045     */\r
2046     const char* CStr() const {\r
2047         return _buffer.Mem();\r
2048     }\r
2049     /**\r
2050         If in print to memory mode, return the size\r
2051         of the XML file in memory. (Note the size returned\r
2052         includes the terminating null.)\r
2053     */\r
2054     int CStrSize() const {\r
2055         return _buffer.Size();\r
2056     }\r
2057     /**\r
2058         If in print to memory mode, reset the buffer to the\r
2059         beginning.\r
2060     */\r
2061     void ClearBuffer() {\r
2062         _buffer.Clear();\r
2063         _buffer.Push(0);\r
2064     }\r
2065 \r
2066 protected:\r
2067         virtual bool CompactMode( const XMLElement& )   { return _compactMode; }\r
2068 \r
2069         /** Prints out the space before an element. You may override to change\r
2070             the space and tabs used. A PrintSpace() override should call Print().\r
2071         */\r
2072     virtual void PrintSpace( int depth );\r
2073     void Print( const char* format, ... );\r
2074 \r
2075     void SealElementIfJustOpened();\r
2076     bool _elementJustOpened;\r
2077     DynArray< const char*, 10 > _stack;\r
2078 \r
2079 private:\r
2080     void PrintString( const char*, bool restrictedEntitySet );  // prints out, after detecting entities.\r
2081 \r
2082     bool _firstElement;\r
2083     FILE* _fp;\r
2084     int _depth;\r
2085     int _textDepth;\r
2086     bool _processEntities;\r
2087         bool _compactMode;\r
2088 \r
2089     enum {\r
2090         ENTITY_RANGE = 64,\r
2091         BUF_SIZE = 200\r
2092     };\r
2093     bool _entityFlag[ENTITY_RANGE];\r
2094     bool _restrictedEntityFlag[ENTITY_RANGE];\r
2095 \r
2096     DynArray< char, 20 > _buffer;\r
2097 };\r
2098 \r
2099 \r
2100 }       // tinyxml2\r
2101 \r
2102 #if defined(_MSC_VER)\r
2103 #   pragma warning(pop)\r
2104 #endif\r
2105 \r
2106 #endif // TINYXML2_INCLUDED\r