codekingpro/portable-devtools
114k
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# if defined(__PS3__)
34# include <stddef.h>
35# endif
36#else
37# include <cctype>
38# include <climits>
39# include <cstdio>
40# include <cstdlib>
41# include <cstring>
42#endif
43#include <stdint.h>
44
45/*
46 gcc:
47 g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
48
49 Formatting, Artistic Style:
50 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
51*/
52
53#if defined( _DEBUG ) || defined (__DEBUG__)
54# ifndef TINYXML2_DEBUG
55# define TINYXML2_DEBUG
56# endif
57#endif
58
59#ifdef _MSC_VER
60# pragma warning(push)
61# pragma warning(disable: 4251)
62#endif
63
64#ifdef _MSC_VER
65# ifdef TINYXML2_EXPORT
66# define TINYXML2_LIB __declspec(dllexport)
67# elif defined(TINYXML2_IMPORT)
68# define TINYXML2_LIB __declspec(dllimport)
69# else
70# define TINYXML2_LIB
71# endif
72#elif __GNUC__ >= 4
73# define TINYXML2_LIB __attribute__((visibility("default")))
74#else
75# define TINYXML2_LIB
76#endif
77
78
79#if !defined(TIXMLASSERT)
80#if defined(TINYXML2_DEBUG)
81# if defined(_MSC_VER)
82# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
83# define TIXMLASSERT( x ) do { if ( !((void)0,(x))) { __debugbreak(); } } while(false)
84# elif defined (ANDROID_NDK)
85# include <android/log.h>
86# define TIXMLASSERT( x ) do { if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } } while(false)
87# else
88# include <assert.h>
89# define TIXMLASSERT assert
90# endif
91#else
92# define TIXMLASSERT( x ) do {} while(false)
93#endif
94#endif
95
96/* Versioning, past 1.0.14:
97 http://semver.org/
98*/
99static const int TIXML2_MAJOR_VERSION = 11;
100static const int TIXML2_MINOR_VERSION = 0;
101static const int TIXML2_PATCH_VERSION = 0;
102
103#define TINYXML2_MAJOR_VERSION 11
104#define TINYXML2_MINOR_VERSION 0
105#define TINYXML2_PATCH_VERSION 0
106
107// A fixed element depth limit is problematic. There needs to be a
108// limit to avoid a stack overflow. However, that limit varies per
109// system, and the capacity of the stack. On the other hand, it's a trivial
110// attack that can result from ill, malicious, or even correctly formed XML,
111// so there needs to be a limit in place.
112static const int TINYXML2_MAX_ELEMENT_DEPTH = 500;
113
114namespace tinyxml2
115{
116class XMLDocument;
117class XMLElement;
118class XMLAttribute;
119class XMLComment;
120class XMLText;
121class XMLDeclaration;
122class XMLUnknown;
123class XMLPrinter;
124
125/*
126 A class that wraps strings. Normally stores the start and end
127 pointers into the XML file itself, and will apply normalization
128 and entity translation if actually read. Can also store (and memory
129 manage) a traditional char[]
130
131 Isn't clear why TINYXML2_LIB is needed; but seems to fix #719
132*/
133class TINYXML2_LIB StrPair
134{
135public:
136 enum Mode {
137 NEEDS_ENTITY_PROCESSING = 0x01,
138 NEEDS_NEWLINE_NORMALIZATION = 0x02,
139 NEEDS_WHITESPACE_COLLAPSING = 0x04,
140
141 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
142 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
143 ATTRIBUTE_NAME = 0,
144 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
145 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
146 COMMENT = NEEDS_NEWLINE_NORMALIZATION
147 };
148
149 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
150 ~StrPair();
151
152 void Set( char* start, char* end, int flags ) {
153 TIXMLASSERT( start );
154 TIXMLASSERT( end );
155 Reset();
156 _start = start;
157 _end = end;
158 _flags = flags | NEEDS_FLUSH;
159 }
160
161 const char* GetStr();
162
163 bool Empty() const {
164 return _start == _end;
165 }
166
167 void SetInternedStr( const char* str ) {
168 Reset();
169 _start = const_cast<char*>(str);
170 }
171
172 void SetStr( const char* str, int flags=0 );
173
174 char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
175 char* ParseName( char* in );
176
177 void TransferTo( StrPair* other );
178 void Reset();
179
180private:
181 void CollapseWhitespace();
182
183 enum {
184 NEEDS_FLUSH = 0x100,
185 NEEDS_DELETE = 0x200
186 };
187
188 int _flags;
189 char* _start;
190 char* _end;
191
192 StrPair( const StrPair& other ); // not supported
193 void operator=( const StrPair& other ); // not supported, use TransferTo()
194};
195
196
197/*
198 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
199 Has a small initial memory pool, so that low or no usage will not
200 cause a call to new/delete
201*/
202template <class T, size_t INITIAL_SIZE>
203class DynArray
204{
205public:
206 DynArray() :
207 _mem( _pool ),
208 _allocated( INITIAL_SIZE ),
209 _size( 0 )
210 {
211 }
212
213 ~DynArray() {
214 if ( _mem != _pool ) {
215 delete [] _mem;
216 }
217 }
218
219 void Clear() {
220 _size = 0;
221 }
222
223 void Push( T t ) {
224 TIXMLASSERT( _size < INT_MAX );
225 EnsureCapacity( _size+1 );
226 _mem[_size] = t;
227 ++_size;
228 }
229
230 T* PushArr( size_t count ) {
231 TIXMLASSERT( _size <= SIZE_MAX - count );
232 EnsureCapacity( _size+count );
233 T* ret = &_mem[_size];
234 _size += count;
235 return ret;
236 }
237
238 T Pop() {
239 TIXMLASSERT( _size > 0 );
240 --_size;
241 return _mem[_size];
242 }
243
244 void PopArr( size_t count ) {
245 TIXMLASSERT( _size >= count );
246 _size -= count;
247 }
248
249 bool Empty() const {
250 return _size == 0;
251 }
252
253 T& operator[](size_t i) {
254 TIXMLASSERT( i < _size );
255 return _mem[i];
256 }
257
258 const T& operator[](size_t i) const {
259 TIXMLASSERT( i < _size );
260 return _mem[i];
261 }
262
263 const T& PeekTop() const {
264 TIXMLASSERT( _size > 0 );
265 return _mem[ _size - 1];
266 }
267
268 size_t Size() const {
269 TIXMLASSERT( _size >= 0 );
270 return _size;
271 }
272
273 size_t Capacity() const {
274 TIXMLASSERT( _allocated >= INITIAL_SIZE );
275 return _allocated;
276 }
277
278 void SwapRemove(size_t i) {
279 TIXMLASSERT(i < _size);
280 TIXMLASSERT(_size > 0);
281 _mem[i] = _mem[_size - 1];
282 --_size;
283 }
284
285 const T* Mem() const {
286 TIXMLASSERT( _mem );
287 return _mem;
288 }
289
290 T* Mem() {
291 TIXMLASSERT( _mem );
292 return _mem;
293 }
294
295private:
296 DynArray( const DynArray& ); // not supported
297 void operator=( const DynArray& ); // not supported
298
299 void EnsureCapacity( size_t cap ) {
300 TIXMLASSERT( cap > 0 );
301 if ( cap > _allocated ) {
302 TIXMLASSERT( cap <= SIZE_MAX / 2 / sizeof(T));
303 const size_t newAllocated = cap * 2;
304 T* newMem = new T[newAllocated];
305 TIXMLASSERT( newAllocated >= _size );
306 memcpy( newMem, _mem, sizeof(T) * _size ); // warning: not using constructors, only works for PODs
307 if ( _mem != _pool ) {
308 delete [] _mem;
309 }
310 _mem = newMem;
311 _allocated = newAllocated;
312 }
313 }
314
315 T* _mem;
316 T _pool[INITIAL_SIZE];
317 size_t _allocated; // objects allocated
318 size_t _size; // number objects in use
319};
320
321
322/*
323 Parent virtual class of a pool for fast allocation
324 and deallocation of objects.
325*/
326class MemPool
327{
328public:
329 MemPool() {}
330 virtual ~MemPool() {}
331
332 virtual size_t ItemSize() const = 0;
333 virtual void* Alloc() = 0;
334 virtual void Free( void* ) = 0;
335 virtual void SetTracked() = 0;
336};
337
338
339/*
340 Template child class to create pools of the correct type.
341*/
342template< size_t ITEM_SIZE >
343class MemPoolT : public MemPool
344{
345public:
346 MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
347 ~MemPoolT() {
348 MemPoolT< ITEM_SIZE >::Clear();
349 }
350
351 void Clear() {
352 // Delete the blocks.
353 while( !_blockPtrs.Empty()) {
354 Block* lastBlock = _blockPtrs.Pop();
355 delete lastBlock;
356 }
357 _root = 0;
358 _currentAllocs = 0;
359 _nAllocs = 0;
360 _maxAllocs = 0;
361 _nUntracked = 0;
362 }
363
364 virtual size_t ItemSize() const override {
365 return ITEM_SIZE;
366 }
367 size_t CurrentAllocs() const {
368 return _currentAllocs;
369 }
370
371 virtual void* Alloc() override{
372 if ( !_root ) {
373 // Need a new block.
374 Block* block = new Block;
375 _blockPtrs.Push( block );
376
377 Item* blockItems = block->items;
378 for( size_t i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
379 blockItems[i].next = &(blockItems[i + 1]);
380 }
381 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
382 _root = blockItems;
383 }
384 Item* const result = _root;
385 TIXMLASSERT( result != 0 );
386 _root = _root->next;
387
388 ++_currentAllocs;
389 if ( _currentAllocs > _maxAllocs ) {
390 _maxAllocs = _currentAllocs;
391 }
392 ++_nAllocs;
393 ++_nUntracked;
394 return result;
395 }
396
397 virtual void Free( void* mem ) override {
398 if ( !mem ) {
399 return;
400 }
401 --_currentAllocs;
402 Item* item = static_cast<Item*>( mem );
403#ifdef TINYXML2_DEBUG
404 memset( item, 0xfe, sizeof( *item ) );
405#endif
406 item->next = _root;
407 _root = item;
408 }
409 void Trace( const char* name ) {
410 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
411 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
412 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
413 }
414
415 void SetTracked() override {
416 --_nUntracked;
417 }
418
419 size_t Untracked() const {
420 return _nUntracked;
421 }
422
423 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
424 // The test file is large, 170k.
425 // Release: VS2010 gcc(no opt)
426 // 1k: 4000
427 // 2k: 4000
428 // 4k: 3900 21000
429 // 16k: 5200
430 // 32k: 4300
431 // 64k: 4000 21000
432 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
433 // in private part if ITEMS_PER_BLOCK is private
434 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
435
436private:
437 MemPoolT( const MemPoolT& ); // not supported
438 void operator=( const MemPoolT& ); // not supported
439
440 union Item {
441 Item* next;
442 char itemData[static_cast<size_t>(ITEM_SIZE)];
443 };
444 struct Block {
445 Item items[ITEMS_PER_BLOCK];
446 };
447 DynArray< Block*, 10 > _blockPtrs;
448 Item* _root;
449
450 size_t _currentAllocs;
451 size_t _nAllocs;
452 size_t _maxAllocs;
453 size_t _nUntracked;
454};
455
456
457
458/**
459 Implements the interface to the "Visitor pattern" (see the Accept() method.)
460 If you call the Accept() method, it requires being passed a XMLVisitor
461 class to handle callbacks. For nodes that contain other nodes (Document, Element)
462 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
463 are simply called with Visit().
464
465 If you return 'true' from a Visit method, recursive parsing will continue. If you return
466 false, <b>no children of this node or its siblings</b> will be visited.
467
468 All flavors of Visit methods have a default implementation that returns 'true' (continue
469 visiting). You need to only override methods that are interesting to you.
470
471 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
472
473 You should never change the document from a callback.
474
475 @sa XMLNode::Accept()
476*/
477class TINYXML2_LIB XMLVisitor
478{
479public:
480 virtual ~XMLVisitor() {}
481
482 /// Visit a document.
483 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
484 return true;
485 }
486 /// Visit a document.
487 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
488 return true;
489 }
490
491 /// Visit an element.
492 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
493 return true;
494 }
495 /// Visit an element.
496 virtual bool VisitExit( const XMLElement& /*element*/ ) {
497 return true;
498 }
499
500 /// Visit a declaration.
501 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
502 return true;
503 }
504 /// Visit a text node.
505 virtual bool Visit( const XMLText& /*text*/ ) {
506 return true;
507 }
508 /// Visit a comment node.
509 virtual bool Visit( const XMLComment& /*comment*/ ) {
510 return true;
511 }
512 /// Visit an unknown node.
513 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
514 return true;
515 }
516};
517
518// WARNING: must match XMLDocument::_errorNames[]
519enum XMLError {
520 XML_SUCCESS = 0,
521 XML_NO_ATTRIBUTE,
522 XML_WRONG_ATTRIBUTE_TYPE,
523 XML_ERROR_FILE_NOT_FOUND,
524 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
525 XML_ERROR_FILE_READ_ERROR,
526 XML_ERROR_PARSING_ELEMENT,
527 XML_ERROR_PARSING_ATTRIBUTE,
528 XML_ERROR_PARSING_TEXT,
529 XML_ERROR_PARSING_CDATA,
530 XML_ERROR_PARSING_COMMENT,
531 XML_ERROR_PARSING_DECLARATION,
532 XML_ERROR_PARSING_UNKNOWN,
533 XML_ERROR_EMPTY_DOCUMENT,
534 XML_ERROR_MISMATCHED_ELEMENT,
535 XML_ERROR_PARSING,
536 XML_CAN_NOT_CONVERT_TEXT,
537 XML_NO_TEXT_NODE,
538 XML_ELEMENT_DEPTH_EXCEEDED,
539
540 XML_ERROR_COUNT
541};
542
543
544/*
545 Utility functionality.
546*/
547class TINYXML2_LIB XMLUtil
548{
549public:
550 static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {
551 TIXMLASSERT( p );
552
553 while( IsWhiteSpace(*p) ) {
554 if (curLineNumPtr && *p == '\n') {
555 ++(*curLineNumPtr);
556 }
557 ++p;
558 }
559 TIXMLASSERT( p );
560 return p;
561 }
562 static char* SkipWhiteSpace( char* const p, int* curLineNumPtr ) {
563 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
564 }
565
566 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
567 // correct, but simple, and usually works.
568 static bool IsWhiteSpace( char p ) {
569 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
570 }
571
572 inline static bool IsNameStartChar( unsigned char ch ) {
573 if ( ch >= 128 ) {
574 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
575 return true;
576 }
577 if ( isalpha( ch ) ) {
578 return true;
579 }
580 return ch == ':' || ch == '_';
581 }
582
583 inline static bool IsNameChar( unsigned char ch ) {
584 return IsNameStartChar( ch )
585 || isdigit( ch )
586 || ch == '.'
587 || ch == '-';
588 }
589
590 inline static bool IsPrefixHex( const char* p) {
591 p = SkipWhiteSpace(p, 0);
592 return p && *p == '0' && ( *(p + 1) == 'x' || *(p + 1) == 'X');
593 }
594
595 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
596 if ( p == q ) {
597 return true;
598 }
599 TIXMLASSERT( p );
600 TIXMLASSERT( q );
601 TIXMLASSERT( nChar >= 0 );
602 return strncmp( p, q, static_cast<size_t>(nChar) ) == 0;
603 }
604
605 inline static bool IsUTF8Continuation( const char p ) {
606 return ( p & 0x80 ) != 0;
607 }
608
609 static const char* ReadBOM( const char* p, bool* hasBOM );
610 // p is the starting location,
611 // the UTF-8 value of the entity will be placed in value, and length filled in.
612 static const char* GetCharacterRef( const char* p, char* value, int* length );
613 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
614
615 // converts primitive types to strings
616 static void ToStr( int v, char* buffer, int bufferSize );
617 static void ToStr( unsigned v, char* buffer, int bufferSize );
618 static void ToStr( bool v, char* buffer, int bufferSize );
619 static void ToStr( float v, char* buffer, int bufferSize );
620 static void ToStr( double v, char* buffer, int bufferSize );
621 static void ToStr(int64_t v, char* buffer, int bufferSize);
622 static void ToStr(uint64_t v, char* buffer, int bufferSize);
623
624 // converts strings to primitive types
625 static bool ToInt( const char* str, int* value );
626 static bool ToUnsigned( const char* str, unsigned* value );
627 static bool ToBool( const char* str, bool* value );
628 static bool ToFloat( const char* str, float* value );
629 static bool ToDouble( const char* str, double* value );
630 static bool ToInt64(const char* str, int64_t* value);
631 static bool ToUnsigned64(const char* str, uint64_t* value);
632 // Changes what is serialized for a boolean value.
633 // Default to "true" and "false". Shouldn't be changed
634 // unless you have a special testing or compatibility need.
635 // Be careful: static, global, & not thread safe.
636 // Be sure to set static const memory as parameters.
637 static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);
638
639private:
640 static const char* writeBoolTrue;
641 static const char* writeBoolFalse;
642};
643
644
645/** XMLNode is a base class for every object that is in the
646 XML Document Object Model (DOM), except XMLAttributes.
647 Nodes have siblings, a parent, and children which can
648 be navigated. A node is always in a XMLDocument.
649 The type of a XMLNode can be queried, and it can
650 be cast to its more defined type.
651
652 A XMLDocument allocates memory for all its Nodes.
653 When the XMLDocument gets deleted, all its Nodes
654 will also be deleted.
655
656 @verbatim
657 A Document can contain: Element (container or leaf)
658 Comment (leaf)
659 Unknown (leaf)
660 Declaration( leaf )
661
662 An Element can contain: Element (container or leaf)
663 Text (leaf)
664 Attributes (not on tree)
665 Comment (leaf)
666 Unknown (leaf)
667
668 @endverbatim
669*/
670class TINYXML2_LIB XMLNode
671{
672 friend class XMLDocument;
673 friend class XMLElement;
674public:
675
676 /// Get the XMLDocument that owns this XMLNode.
677 const XMLDocument* GetDocument() const {
678 TIXMLASSERT( _document );
679 return _document;
680 }
681 /// Get the XMLDocument that owns this XMLNode.
682 XMLDocument* GetDocument() {
683 TIXMLASSERT( _document );
684 return _document;
685 }
686
687 /// Safely cast to an Element, or null.
688 virtual XMLElement* ToElement() {
689 return 0;
690 }
691 /// Safely cast to Text, or null.
692 virtual XMLText* ToText() {
693 return 0;
694 }
695 /// Safely cast to a Comment, or null.
696 virtual XMLComment* ToComment() {
697 return 0;
698 }
699 /// Safely cast to a Document, or null.
700 virtual XMLDocument* ToDocument() {
701 return 0;
702 }
703 /// Safely cast to a Declaration, or null.
704 virtual XMLDeclaration* ToDeclaration() {
705 return 0;
706 }
707 /// Safely cast to an Unknown, or null.
708 virtual XMLUnknown* ToUnknown() {
709 return 0;
710 }
711
712 virtual const XMLElement* ToElement() const {
713 return 0;
714 }
715 virtual const XMLText* ToText() const {
716 return 0;
717 }
718 virtual const XMLComment* ToComment() const {
719 return 0;
720 }
721 virtual const XMLDocument* ToDocument() const {
722 return 0;
723 }
724 virtual const XMLDeclaration* ToDeclaration() const {
725 return 0;
726 }
727 virtual const XMLUnknown* ToUnknown() const {
728 return 0;
729 }
730
731 // ChildElementCount was originally suggested by msteiger on the sourceforge page for TinyXML and modified by KB1SPH for TinyXML-2.
732
733 int ChildElementCount(const char *value) const;
734
735 int ChildElementCount() const;
736
737 /** The meaning of 'value' changes for the specific type.
738 @verbatim
739 Document: empty (NULL is returned, not an empty string)
740 Element: name of the element
741 Comment: the comment text
742 Unknown: the tag contents
743 Text: the text string
744 @endverbatim
745 */
746 const char* Value() const;
747
748 /** Set the Value of an XML node.
749 @sa Value()
750 */
751 void SetValue( const char* val, bool staticMem=false );
752
753 /// Gets the line number the node is in, if the document was parsed from a file.
754 int GetLineNum() const { return _parseLineNum; }
755
756 /// Get the parent of this node on the DOM.
757 const XMLNode* Parent() const {
758 return _parent;
759 }
760
761 XMLNode* Parent() {
762 return _parent;
763 }
764
765 /// Returns true if this node has no children.
766 bool NoChildren() const {
767 return !_firstChild;
768 }
769
770 /// Get the first child node, or null if none exists.
771 const XMLNode* FirstChild() const {
772 return _firstChild;
773 }
774
775 XMLNode* FirstChild() {
776 return _firstChild;
777 }
778
779 /** Get the first child element, or optionally the first child
780 element with the specified name.
781 */
782 const XMLElement* FirstChildElement( const char* name = 0 ) const;
783
784 XMLElement* FirstChildElement( const char* name = 0 ) {
785 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
786 }
787
788 /// Get the last child node, or null if none exists.
789 const XMLNode* LastChild() const {
790 return _lastChild;
791 }
792
793 XMLNode* LastChild() {
794 return _lastChild;
795 }
796
797 /** Get the last child element or optionally the last child
798 element with the specified name.
799 */
800 const XMLElement* LastChildElement( const char* name = 0 ) const;
801
802 XMLElement* LastChildElement( const char* name = 0 ) {
803 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
804 }
805
806 /// Get the previous (left) sibling node of this node.
807 const XMLNode* PreviousSibling() const {
808 return _prev;
809 }
810
811 XMLNode* PreviousSibling() {
812 return _prev;
813 }
814
815 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
816 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
817
818 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
819 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
820 }
821
822 /// Get the next (right) sibling node of this node.
823 const XMLNode* NextSibling() const {
824 return _next;
825 }
826
827 XMLNode* NextSibling() {
828 return _next;
829 }
830
831 /// Get the next (right) sibling element of this node, with an optionally supplied name.
832 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
833
834 XMLElement* NextSiblingElement( const char* name = 0 ) {
835 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
836 }
837
838 /**
839 Add a child node as the last (right) child.
840 If the child node is already part of the document,
841 it is moved from its old location to the new location.
842 Returns the addThis argument or 0 if the node does not
843 belong to the same document.
844 */
845 XMLNode* InsertEndChild( XMLNode* addThis );
846
847 XMLNode* LinkEndChild( XMLNode* addThis ) {
848 return InsertEndChild( addThis );
849 }
850 /**
851 Add a child node as the first (left) child.
852 If the child node is already part of the document,
853 it is moved from its old location to the new location.
854 Returns the addThis argument or 0 if the node does not
855 belong to the same document.
856 */
857 XMLNode* InsertFirstChild( XMLNode* addThis );
858 /**
859 Add a node after the specified child node.
860 If the child node is already part of the document,
861 it is moved from its old location to the new location.
862 Returns the addThis argument or 0 if the afterThis node
863 is not a child of this node, or if the node does not
864 belong to the same document.
865 */
866 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
867
868 /**
869 Delete all the children of this node.
870 */
871 void DeleteChildren();
872
873 /**
874 Delete a child of this node.
875 */
876 void DeleteChild( XMLNode* node );
877
878 /**
879 Make a copy of this node, but not its children.
880 You may pass in a Document pointer that will be
881 the owner of the new Node. If the 'document' is
882 null, then the node returned will be allocated
883 from the current Document. (this->GetDocument())
884
885 Note: if called on a XMLDocument, this will return null.
886 */
887 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
888
889 /**
890 Make a copy of this node and all its children.
891
892 If the 'target' is null, then the nodes will
893 be allocated in the current document. If 'target'
894 is specified, the memory will be allocated in the
895 specified XMLDocument.
896
897 NOTE: This is probably not the correct tool to
898 copy a document, since XMLDocuments can have multiple
899 top level XMLNodes. You probably want to use
900 XMLDocument::DeepCopy()
901 */
902 XMLNode* DeepClone( XMLDocument* target ) const;
903
904 /**
905 Test if 2 nodes are the same, but don't test children.
906 The 2 nodes do not need to be in the same Document.
907
908 Note: if called on a XMLDocument, this will return false.
909 */
910 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
911
912 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
913 XML tree will be conditionally visited and the host will be called back
914 via the XMLVisitor interface.
915
916 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
917 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
918 interface versus any other.)
919
920 The interface has been based on ideas from:
921
922 - http://www.saxproject.org/
923 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
924
925 Which are both good references for "visiting".
926
927 An example of using Accept():
928 @verbatim
929 XMLPrinter printer;
930 tinyxmlDoc.Accept( &printer );
931 const char* xmlcstr = printer.CStr();
932 @endverbatim
933 */
934 virtual bool Accept( XMLVisitor* visitor ) const = 0;
935
936 /**
937 Set user data into the XMLNode. TinyXML-2 in
938 no way processes or interprets user data.
939 It is initially 0.
940 */
941 void SetUserData(void* userData) { _userData = userData; }
942
943 /**
944 Get user data set into the XMLNode. TinyXML-2 in
945 no way processes or interprets user data.
946 It is initially 0.
947 */
948 void* GetUserData() const { return _userData; }
949
950protected:
951 explicit XMLNode( XMLDocument* );
952 virtual ~XMLNode();
953
954 virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
955
956 XMLDocument* _document;
957 XMLNode* _parent;
958 mutable StrPair _value;
959 int _parseLineNum;
960
961 XMLNode* _firstChild;
962 XMLNode* _lastChild;
963
964 XMLNode* _prev;
965 XMLNode* _next;
966
967 void* _userData;
968
969private:
970 MemPool* _memPool;
971 void Unlink( XMLNode* child );
972 static void DeleteNode( XMLNode* node );
973 void InsertChildPreamble( XMLNode* insertThis ) const;
974 const XMLElement* ToElementWithName( const char* name ) const;
975
976 XMLNode( const XMLNode& ); // not supported
977 XMLNode& operator=( const XMLNode& ); // not supported
978};
979
980
981/** XML text.
982
983 Note that a text node can have child element nodes, for example:
984 @verbatim
985 <root>This is <b>bold</b></root>
986 @endverbatim
987
988 A text node can have 2 ways to output the next. "normal" output
989 and CDATA. It will default to the mode it was parsed from the XML file and
990 you generally want to leave it alone, but you can change the output mode with
991 SetCData() and query it with CData().
992*/
993class TINYXML2_LIB XMLText : public XMLNode
994{
995 friend class XMLDocument;
996public:
997 virtual bool Accept( XMLVisitor* visitor ) const override;
998
999 virtual XMLText* ToText() override {
1000 return this;
1001 }
1002 virtual const XMLText* ToText() const override {
1003 return this;
1004 }
1005
1006 /// Declare whether this should be CDATA or standard text.
1007 void SetCData( bool isCData ) {
1008 _isCData = isCData;
1009 }
1010 /// Returns true if this is a CDATA text element.
1011 bool CData() const {
1012 return _isCData;
1013 }
1014
1015 virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
1016 virtual bool ShallowEqual( const XMLNode* compare ) const override;
1017
1018protected:
1019 explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
1020 virtual ~XMLText() {}
1021
1022 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
1023
1024private:
1025 bool _isCData;
1026
1027 XMLText( const XMLText& ); // not supported
1028 XMLText& operator=( const XMLText& ); // not supported
1029};
1030
1031
1032/** An XML Comment. */
1033class TINYXML2_LIB XMLComment : public XMLNode
1034{
1035 friend class XMLDocument;
1036public:
1037 virtual XMLComment* ToComment() override {
1038 return this;
1039 }
1040 virtual const XMLComment* ToComment() const override {
1041 return this;
1042 }
1043
1044 virtual bool Accept( XMLVisitor* visitor ) const override;
1045
1046 virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
1047 virtual bool ShallowEqual( const XMLNode* compare ) const override;
1048
1049protected:
1050 explicit XMLComment( XMLDocument* doc );
1051 virtual ~XMLComment();
1052
1053 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr) override;
1054
1055private:
1056 XMLComment( const XMLComment& ); // not supported
1057 XMLComment& operator=( const XMLComment& ); // not supported
1058};
1059
1060
1061/** In correct XML the declaration is the first entry in the file.
1062 @verbatim
1063 <?xml version="1.0" standalone="yes"?>
1064 @endverbatim
1065
1066 TinyXML-2 will happily read or write files without a declaration,
1067 however.
1068
1069 The text of the declaration isn't interpreted. It is parsed
1070 and written as a string.
1071*/
1072class TINYXML2_LIB XMLDeclaration : public XMLNode
1073{
1074 friend class XMLDocument;
1075public:
1076 virtual XMLDeclaration* ToDeclaration() override {
1077 return this;
1078 }
1079 virtual const XMLDeclaration* ToDeclaration() const override {
1080 return this;
1081 }
1082
1083 virtual bool Accept( XMLVisitor* visitor ) const override;
1084
1085 virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
1086 virtual bool ShallowEqual( const XMLNode* compare ) const override;
1087
1088protected:
1089 explicit XMLDeclaration( XMLDocument* doc );
1090 virtual ~XMLDeclaration();
1091
1092 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
1093
1094private:
1095 XMLDeclaration( const XMLDeclaration& ); // not supported
1096 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
1097};
1098
1099
1100/** Any tag that TinyXML-2 doesn't recognize is saved as an
1101 unknown. It is a tag of text, but should not be modified.
1102 It will be written back to the XML, unchanged, when the file
1103 is saved.
1104
1105 DTD tags get thrown into XMLUnknowns.
1106*/
1107class TINYXML2_LIB XMLUnknown : public XMLNode
1108{
1109 friend class XMLDocument;
1110public:
1111 virtual XMLUnknown* ToUnknown() override {
1112 return this;
1113 }
1114 virtual const XMLUnknown* ToUnknown() const override {
1115 return this;
1116 }
1117
1118 virtual bool Accept( XMLVisitor* visitor ) const override;
1119
1120 virtual XMLNode* ShallowClone( XMLDocument* document ) const override;
1121 virtual bool ShallowEqual( const XMLNode* compare ) const override;
1122
1123protected:
1124 explicit XMLUnknown( XMLDocument* doc );
1125 virtual ~XMLUnknown();
1126
1127 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr ) override;
1128
1129private:
1130 XMLUnknown( const XMLUnknown& ); // not supported
1131 XMLUnknown& operator=( const XMLUnknown& ); // not supported
1132};
1133
1134
1135
1136/** An attribute is a name-value pair. Elements have an arbitrary
1137 number of attributes, each with a unique name.
1138
1139 @note The attributes are not XMLNodes. You may only query the
1140 Next() attribute in a list.
1141*/
1142class TINYXML2_LIB XMLAttribute
1143{
1144 friend class XMLElement;
1145public:
1146 /// The name of the attribute.
1147 const char* Name() const;
1148
1149 /// The value of the attribute.
1150 const char* Value() const;
1151
1152 /// Gets the line number the attribute is in, if the document was parsed from a file.
1153 int GetLineNum() const { return _parseLineNum; }
1154
1155 /// The next attribute in the list.
1156 const XMLAttribute* Next() const {
1157 return _next;
1158 }
1159
1160 /** IntValue interprets the attribute as an integer, and returns the value.
1161 If the value isn't an integer, 0 will be returned. There is no error checking;
1162 use QueryIntValue() if you need error checking.
1163 */
1164 int IntValue() const {
1165 int i = 0;
1166 QueryIntValue(&i);
1167 return i;
1168 }
1169
1170 int64_t Int64Value() const {
1171 int64_t i = 0;
1172 QueryInt64Value(&i);
1173 return i;
1174 }
1175
1176 uint64_t Unsigned64Value() const {
1177 uint64_t i = 0;
1178 QueryUnsigned64Value(&i);
1179 return i;
1180 }
1181
1182 /// Query as an unsigned integer. See IntValue()
1183 unsigned UnsignedValue() const {
1184 unsigned i=0;
1185 QueryUnsignedValue( &i );
1186 return i;
1187 }
1188 /// Query as a boolean. See IntValue()
1189 bool BoolValue() const {
1190 bool b=false;
1191 QueryBoolValue( &b );
1192 return b;
1193 }
1194 /// Query as a double. See IntValue()
1195 double DoubleValue() const {
1196 double d=0;
1197 QueryDoubleValue( &d );
1198 return d;
1199 }
1200 /// Query as a float. See IntValue()
