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