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