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