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