ovr_sdk

view 3rdParty/TinyXml/tinyxml2.h @ 0:1b39a1b46319

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