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