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