goat3d

view libs/tinyxml2/tinyxml2.h @ 75:76dea247f75c

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