TinyXML-2  7.0.0
tinyxml2.h
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 #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  TODO: intern strings instead of allocation.
47 */
48 /*
49  gcc:
50  g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
51 
52  Formatting, Artistic Style:
53  AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
54 */
55 
56 #if defined( _DEBUG ) || defined (__DEBUG__)
57 # ifndef TINYXML2_DEBUG
58 # define TINYXML2_DEBUG
59 # endif
60 #endif
61 
62 #ifdef _MSC_VER
63 # pragma warning(push)
64 # pragma warning(disable: 4251)
65 #endif
66 
67 #ifdef _WIN32
68 # ifdef TINYXML2_EXPORT
69 # define TINYXML2_LIB __declspec(dllexport)
70 # elif defined(TINYXML2_IMPORT)
71 # define TINYXML2_LIB __declspec(dllimport)
72 # else
73 # define TINYXML2_LIB
74 # endif
75 #elif __GNUC__ >= 4
76 # define TINYXML2_LIB __attribute__((visibility("default")))
77 #else
78 # define TINYXML2_LIB
79 #endif
80 
81 
82 #if defined(TINYXML2_DEBUG)
83 # if defined(_MSC_VER)
84 # // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
85 # define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
86 # elif defined (ANDROID_NDK)
87 # include <android/log.h>
88 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89 # else
90 # include <assert.h>
91 # define TIXMLASSERT assert
92 # endif
93 #else
94 # define TIXMLASSERT( x ) {}
95 #endif
96 
97 
98 /* Versioning, past 1.0.14:
99  http://semver.org/
100 */
101 static const int TIXML2_MAJOR_VERSION = 7;
102 static const int TIXML2_MINOR_VERSION = 0;
103 static const int TIXML2_PATCH_VERSION = 0;
104 
105 #define TINYXML2_MAJOR_VERSION 7
106 #define TINYXML2_MINOR_VERSION 0
107 #define TINYXML2_PATCH_VERSION 0
108 
109 // A fixed element depth limit is problematic. There needs to be a
110 // limit to avoid a stack overflow. However, that limit varies per
111 // system, and the capacity of the stack. On the other hand, it's a trivial
112 // attack that can result from ill, malicious, or even correctly formed XML,
113 // so there needs to be a limit in place.
114 static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;
115 
116 namespace tinyxml2
117 {
118 class XMLDocument;
119 class XMLElement;
120 class XMLAttribute;
121 class XMLComment;
122 class XMLText;
123 class XMLDeclaration;
124 class XMLUnknown;
125 class XMLPrinter;
126 
127 /*
128  A class that wraps strings. Normally stores the start and end
129  pointers into the XML file itself, and will apply normalization
130  and entity translation if actually read. Can also store (and memory
131  manage) a traditional char[]
132 */
133 class StrPair
134 {
135 public:
136  enum {
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 
180 private:
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 */
202 template <class T, int INITIAL_SIZE>
203 class DynArray
204 {
205 public:
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( int count ) {
231  TIXMLASSERT( count >= 0 );
232  TIXMLASSERT( _size <= INT_MAX - count );
233  EnsureCapacity( _size+count );
234  T* ret = &_mem[_size];
235  _size += count;
236  return ret;
237  }
238 
239  T Pop() {
240  TIXMLASSERT( _size > 0 );
241  --_size;
242  return _mem[_size];
243  }
244 
245  void PopArr( int count ) {
246  TIXMLASSERT( _size >= count );
247  _size -= count;
248  }
249 
250  bool Empty() const {
251  return _size == 0;
252  }
253 
254  T& operator[](int i) {
255  TIXMLASSERT( i>= 0 && i < _size );
256  return _mem[i];
257  }
258 
259  const T& operator[](int i) const {
260  TIXMLASSERT( i>= 0 && i < _size );
261  return _mem[i];
262  }
263 
264  const T& PeekTop() const {
265  TIXMLASSERT( _size > 0 );
266  return _mem[ _size - 1];
267  }
268 
269  int Size() const {
270  TIXMLASSERT( _size >= 0 );
271  return _size;
272  }
273 
274  int Capacity() const {
275  TIXMLASSERT( _allocated >= INITIAL_SIZE );
276  return _allocated;
277  }
278 
279  void SwapRemove(int i) {
280  TIXMLASSERT(i >= 0 && i < _size);
281  TIXMLASSERT(_size > 0);
282  _mem[i] = _mem[_size - 1];
283  --_size;
284  }
285 
286  const T* Mem() const {
287  TIXMLASSERT( _mem );
288  return _mem;
289  }
290 
291  T* Mem() {
292  TIXMLASSERT( _mem );
293  return _mem;
294  }
295 
296 private:
297  DynArray( const DynArray& ); // not supported
298  void operator=( const DynArray& ); // not supported
299 
300  void EnsureCapacity( int cap ) {
301  TIXMLASSERT( cap > 0 );
302  if ( cap > _allocated ) {
303  TIXMLASSERT( cap <= INT_MAX / 2 );
304  int newAllocated = cap * 2;
305  T* newMem = new T[newAllocated];
306  TIXMLASSERT( newAllocated >= _size );
307  memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
308  if ( _mem != _pool ) {
309  delete [] _mem;
310  }
311  _mem = newMem;
312  _allocated = newAllocated;
313  }
314  }
315 
316  T* _mem;
317  T _pool[INITIAL_SIZE];
318  int _allocated; // objects allocated
319  int _size; // number objects in use
320 };
321 
322 
323 /*
324  Parent virtual class of a pool for fast allocation
325  and deallocation of objects.
326 */
327 class MemPool
328 {
329 public:
330  MemPool() {}
331  virtual ~MemPool() {}
332 
333  virtual int ItemSize() const = 0;
334  virtual void* Alloc() = 0;
335  virtual void Free( void* ) = 0;
336  virtual void SetTracked() = 0;
337 };
338 
339 
340 /*
341  Template child class to create pools of the correct type.
342 */
343 template< int ITEM_SIZE >
344 class MemPoolT : public MemPool
345 {
346 public:
347  MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
348  ~MemPoolT() {
349  MemPoolT< ITEM_SIZE >::Clear();
350  }
351 
352  void Clear() {
353  // Delete the blocks.
354  while( !_blockPtrs.Empty()) {
355  Block* lastBlock = _blockPtrs.Pop();
356  delete lastBlock;
357  }
358  _root = 0;
359  _currentAllocs = 0;
360  _nAllocs = 0;
361  _maxAllocs = 0;
362  _nUntracked = 0;
363  }
364 
365  virtual int ItemSize() const {
366  return ITEM_SIZE;
367  }
368  int CurrentAllocs() const {
369  return _currentAllocs;
370  }
371 
372  virtual void* Alloc() {
373  if ( !_root ) {
374  // Need a new block.
375  Block* block = new Block();
376  _blockPtrs.Push( block );
377 
378  Item* blockItems = block->items;
379  for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
380  blockItems[i].next = &(blockItems[i + 1]);
381  }
382  blockItems[ITEMS_PER_BLOCK - 1].next = 0;
383  _root = blockItems;
384  }
385  Item* const result = _root;
386  TIXMLASSERT( result != 0 );
387  _root = _root->next;
388 
389  ++_currentAllocs;
390  if ( _currentAllocs > _maxAllocs ) {
391  _maxAllocs = _currentAllocs;
392  }
393  ++_nAllocs;
394  ++_nUntracked;
395  return result;
396  }
397 
398  virtual void Free( void* mem ) {
399  if ( !mem ) {
400  return;
401  }
402  --_currentAllocs;
403  Item* item = static_cast<Item*>( mem );
404 #ifdef TINYXML2_DEBUG
405  memset( item, 0xfe, sizeof( *item ) );
406 #endif
407  item->next = _root;
408  _root = item;
409  }
410  void Trace( const char* name ) {
411  printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
412  name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
413  ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
414  }
415 
416  void SetTracked() {
417  --_nUntracked;
418  }
419 
420  int Untracked() const {
421  return _nUntracked;
422  }
423 
424  // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
425  // The test file is large, 170k.
426  // Release: VS2010 gcc(no opt)
427  // 1k: 4000
428  // 2k: 4000
429  // 4k: 3900 21000
430  // 16k: 5200
431  // 32k: 4300
432  // 64k: 4000 21000
433  // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
434  // in private part if ITEMS_PER_BLOCK is private
435  enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
436 
437 private:
438  MemPoolT( const MemPoolT& ); // not supported
439  void operator=( const MemPoolT& ); // not supported
440 
441  union Item {
442  Item* next;
443  char itemData[ITEM_SIZE];
444  };
445  struct Block {
446  Item items[ITEMS_PER_BLOCK];
447  };
448  DynArray< Block*, 10 > _blockPtrs;
449  Item* _root;
450 
451  int _currentAllocs;
452  int _nAllocs;
453  int _maxAllocs;
454  int _nUntracked;
455 };
456 
457 
458 
478 class TINYXML2_LIB XMLVisitor
479 {
480 public:
481  virtual ~XMLVisitor() {}
482 
484  virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
485  return true;
486  }
488  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
489  return true;
490  }
491 
493  virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
494  return true;
495  }
497  virtual bool VisitExit( const XMLElement& /*element*/ ) {
498  return true;
499  }
500 
502  virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
503  return true;
504  }
506  virtual bool Visit( const XMLText& /*text*/ ) {
507  return true;
508  }
510  virtual bool Visit( const XMLComment& /*comment*/ ) {
511  return true;
512  }
514  virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
515  return true;
516  }
517 };
518 
519 // WARNING: must match XMLDocument::_errorNames[]
520 enum XMLError {
521  XML_SUCCESS = 0,
522  XML_NO_ATTRIBUTE,
523  XML_WRONG_ATTRIBUTE_TYPE,
524  XML_ERROR_FILE_NOT_FOUND,
525  XML_ERROR_FILE_COULD_NOT_BE_OPENED,
526  XML_ERROR_FILE_READ_ERROR,
527  XML_ERROR_PARSING_ELEMENT,
528  XML_ERROR_PARSING_ATTRIBUTE,
529  XML_ERROR_PARSING_TEXT,
530  XML_ERROR_PARSING_CDATA,
531  XML_ERROR_PARSING_COMMENT,
532  XML_ERROR_PARSING_DECLARATION,
533  XML_ERROR_PARSING_UNKNOWN,
534  XML_ERROR_EMPTY_DOCUMENT,
535  XML_ERROR_MISMATCHED_ELEMENT,
536  XML_ERROR_PARSING,
537  XML_CAN_NOT_CONVERT_TEXT,
538  XML_NO_TEXT_NODE,
539  XML_ELEMENT_DEPTH_EXCEEDED,
540 
541  XML_ERROR_COUNT
542 };
543 
544 
545 /*
546  Utility functionality.
547 */
548 class TINYXML2_LIB XMLUtil
549 {
550 public:
551  static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {
552  TIXMLASSERT( p );
553 
554  while( IsWhiteSpace(*p) ) {
555  if (curLineNumPtr && *p == '\n') {
556  ++(*curLineNumPtr);
557  }
558  ++p;
559  }
560  TIXMLASSERT( p );
561  return p;
562  }
563  static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) {
564  return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
565  }
566 
567  // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
568  // correct, but simple, and usually works.
569  static bool IsWhiteSpace( char p ) {
570  return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
571  }
572 
573  inline static bool IsNameStartChar( unsigned char ch ) {
574  if ( ch >= 128 ) {
575  // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
576  return true;
577  }
578  if ( isalpha( ch ) ) {
579  return true;
580  }
581  return ch == ':' || ch == '_';
582  }
583 
584  inline static bool IsNameChar( unsigned char ch ) {
585  return IsNameStartChar( ch )
586  || isdigit( ch )
587  || ch == '.'
588  || ch == '-';
589  }
590 
591  inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
592  if ( p == q ) {
593  return true;
594  }
595  TIXMLASSERT( p );
596  TIXMLASSERT( q );
597  TIXMLASSERT( nChar >= 0 );
598  return strncmp( p, q, nChar ) == 0;
599  }
600 
601  inline static bool IsUTF8Continuation( char p ) {
602  return ( p & 0x80 ) != 0;
603  }
604 
605  static const char* ReadBOM( const char* p, bool* hasBOM );
606  // p is the starting location,
607  // the UTF-8 value of the entity will be placed in value, and length filled in.
608  static const char* GetCharacterRef( const char* p, char* value, int* length );
609  static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
610 
611  // converts primitive types to strings
612  static void ToStr( int v, char* buffer, int bufferSize );
613  static void ToStr( unsigned v, char* buffer, int bufferSize );
614  static void ToStr( bool v, char* buffer, int bufferSize );
615  static void ToStr( float v, char* buffer, int bufferSize );
616  static void ToStr( double v, char* buffer, int bufferSize );
617  static void ToStr(int64_t v, char* buffer, int bufferSize);
618 
619  // converts strings to primitive types
620  static bool ToInt( const char* str, int* value );
621  static bool ToUnsigned( const char* str, unsigned* value );
622  static bool ToBool( const char* str, bool* value );
623  static bool ToFloat( const char* str, float* value );
624  static bool ToDouble( const char* str, double* value );
625  static bool ToInt64(const char* str, int64_t* value);
626 
627  // Changes what is serialized for a boolean value.
628  // Default to "true" and "false". Shouldn't be changed
629  // unless you have a special testing or compatibility need.
630  // Be careful: static, global, & not thread safe.
631  // Be sure to set static const memory as parameters.
632  static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);
633 
634 private:
635  static const char* writeBoolTrue;
636  static const char* writeBoolFalse;
637 };
638 
639 
665 class TINYXML2_LIB XMLNode
666 {
667  friend class XMLDocument;
668  friend class XMLElement;
669 public:
670 
672  const XMLDocument* GetDocument() const {
673  TIXMLASSERT( _document );
674  return _document;
675  }
678  TIXMLASSERT( _document );
679  return _document;
680  }
681 
683  virtual XMLElement* ToElement() {
684  return 0;
685  }
687  virtual XMLText* ToText() {
688  return 0;
689  }
691  virtual XMLComment* ToComment() {
692  return 0;
693  }
695  virtual XMLDocument* ToDocument() {
696  return 0;
697  }
700  return 0;
701  }
703  virtual XMLUnknown* ToUnknown() {
704  return 0;
705  }
706 
707  virtual const XMLElement* ToElement() const {
708  return 0;
709  }
710  virtual const XMLText* ToText() const {
711  return 0;
712  }
713  virtual const XMLComment* ToComment() const {
714  return 0;
715  }
716  virtual const XMLDocument* ToDocument() const {
717  return 0;
718  }
719  virtual const XMLDeclaration* ToDeclaration() const {
720  return 0;
721  }
722  virtual const XMLUnknown* ToUnknown() const {
723  return 0;
724  }
725 
735  const char* Value() const;
736 
740  void SetValue( const char* val, bool staticMem=false );
741 
743  int GetLineNum() const { return _parseLineNum; }
744 
746  const XMLNode* Parent() const {
747  return _parent;
748  }
749 
750  XMLNode* Parent() {
751  return _parent;
752  }
753 
755  bool NoChildren() const {
756  return !_firstChild;
757  }
758 
760  const XMLNode* FirstChild() const {
761  return _firstChild;
762  }
763 
764  XMLNode* FirstChild() {
765  return _firstChild;
766  }
767 
771  const XMLElement* FirstChildElement( const char* name = 0 ) const;
772 
773  XMLElement* FirstChildElement( const char* name = 0 ) {
774  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
775  }
776 
778  const XMLNode* LastChild() const {
779  return _lastChild;
780  }
781 
782  XMLNode* LastChild() {
783  return _lastChild;
784  }
785 
789  const XMLElement* LastChildElement( const char* name = 0 ) const;
790 
791  XMLElement* LastChildElement( const char* name = 0 ) {
792  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
793  }
794 
796  const XMLNode* PreviousSibling() const {
797  return _prev;
798  }
799 
800  XMLNode* PreviousSibling() {
801  return _prev;
802  }
803 
805  const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
806 
807  XMLElement* PreviousSiblingElement( const char* name = 0 ) {
808  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
809  }
810 
812  const XMLNode* NextSibling() const {
813  return _next;
814  }
815 
816  XMLNode* NextSibling() {
817  return _next;
818  }
819 
821  const XMLElement* NextSiblingElement( const char* name = 0 ) const;
822 
823  XMLElement* NextSiblingElement( const char* name = 0 ) {
824  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
825  }
826 
834  XMLNode* InsertEndChild( XMLNode* addThis );
835 
836  XMLNode* LinkEndChild( XMLNode* addThis ) {
837  return InsertEndChild( addThis );
838  }
846  XMLNode* InsertFirstChild( XMLNode* addThis );
855  XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
856 
860  void DeleteChildren();
861 
865  void DeleteChild( XMLNode* node );
866 
876  virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
877 
891  XMLNode* DeepClone( XMLDocument* target ) const;
892 
899  virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
900 
923  virtual bool Accept( XMLVisitor* visitor ) const = 0;
924 
930  void SetUserData(void* userData) { _userData = userData; }
931 
937  void* GetUserData() const { return _userData; }
938 
939 protected:
940  explicit XMLNode( XMLDocument* );
941  virtual ~XMLNode();
942 
943  virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
944 
945  XMLDocument* _document;
946  XMLNode* _parent;
947  mutable StrPair _value;
948  int _parseLineNum;
949 
950  XMLNode* _firstChild;
951  XMLNode* _lastChild;
952 
953  XMLNode* _prev;
954  XMLNode* _next;
955 
956  void* _userData;
957 
958 private:
959  MemPool* _memPool;
960  void Unlink( XMLNode* child );
961  static void DeleteNode( XMLNode* node );
962  void InsertChildPreamble( XMLNode* insertThis ) const;
963  const XMLElement* ToElementWithName( const char* name ) const;
964 
965  XMLNode( const XMLNode& ); // not supported
966  XMLNode& operator=( const XMLNode& ); // not supported
967 };
968 
969 
982 class TINYXML2_LIB XMLText : public XMLNode
983 {
984  friend class XMLDocument;
985 public:
986  virtual bool Accept( XMLVisitor* visitor ) const;
987 
988  virtual XMLText* ToText() {
989  return this;
990  }
991  virtual const XMLText* ToText() const {
992  return this;
993  }
994 
996  void SetCData( bool isCData ) {
997  _isCData = isCData;
998  }
1000  bool CData() const {
1001  return _isCData;
1002  }
1003 
1004  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1005  virtual bool ShallowEqual( const XMLNode* compare ) const;
1006 
1007 protected:
1008  explicit XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
1009  virtual ~XMLText() {}
1010 
1011  char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1012 
1013 private:
1014  bool _isCData;
1015 
1016  XMLText( const XMLText& ); // not supported
1017  XMLText& operator=( const XMLText& ); // not supported
1018 };
1019 
1020 
1022 class TINYXML2_LIB XMLComment : public XMLNode
1023 {
1024  friend class XMLDocument;
1025 public:
1026  virtual XMLComment* ToComment() {
1027  return this;
1028  }
1029  virtual const XMLComment* ToComment() const {
1030  return this;
1031  }
1032 
1033  virtual bool Accept( XMLVisitor* visitor ) const;
1034 
1035  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1036  virtual bool ShallowEqual( const XMLNode* compare ) const;
1037 
1038 protected:
1039  explicit XMLComment( XMLDocument* doc );
1040  virtual ~XMLComment();
1041 
1042  char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
1043 
1044 private:
1045  XMLComment( const XMLComment& ); // not supported
1046  XMLComment& operator=( const XMLComment& ); // not supported
1047 };
1048 
1049 
1061 class TINYXML2_LIB XMLDeclaration : public XMLNode
1062 {
1063  friend class XMLDocument;
1064 public:
1066  return this;
1067  }
1068  virtual const XMLDeclaration* ToDeclaration() const {
1069  return this;
1070  }
1071 
1072  virtual bool Accept( XMLVisitor* visitor ) const;
1073 
1074  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1075  virtual bool ShallowEqual( const XMLNode* compare ) const;
1076 
1077 protected:
1078  explicit XMLDeclaration( XMLDocument* doc );
1079  virtual ~XMLDeclaration();
1080 
1081  char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1082 
1083 private:
1084  XMLDeclaration( const XMLDeclaration& ); // not supported
1085  XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
1086 };
1087 
1088 
1096 class TINYXML2_LIB XMLUnknown : public XMLNode
1097 {
1098  friend class XMLDocument;
1099 public:
1100  virtual XMLUnknown* ToUnknown() {
1101  return this;
1102  }
1103  virtual const XMLUnknown* ToUnknown() const {
1104  return this;
1105  }
1106 
1107  virtual bool Accept( XMLVisitor* visitor ) const;
1108 
1109  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1110  virtual bool ShallowEqual( const XMLNode* compare ) const;
1111 
1112 protected:
1113  explicit XMLUnknown( XMLDocument* doc );
1114  virtual ~XMLUnknown();
1115 
1116  char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1117 
1118 private:
1119  XMLUnknown( const XMLUnknown& ); // not supported
1120  XMLUnknown& operator=( const XMLUnknown& ); // not supported
1121 };
1122 
1123 
1124 
1131 class TINYXML2_LIB XMLAttribute
1132 {
1133  friend class XMLElement;
1134 public:
1136  const char* Name() const;
1137 
1139  const char* Value() const;
1140 
1142  int GetLineNum() const { return _parseLineNum; }
1143 
1145  const XMLAttribute* Next() const {
1146  return _next;
1147  }
1148 
1153  int IntValue() const {
1154  int i = 0;
1155  QueryIntValue(&i);
1156  return i;
1157  }
1158 
1159  int64_t Int64Value() const {
1160  int64_t i = 0;
1161  QueryInt64Value(&i);
1162  return i;
1163  }
1164 
1166  unsigned UnsignedValue() const {
1167  unsigned i=0;
1168  QueryUnsignedValue( &i );
1169  return i;
1170  }
1172  bool BoolValue() const {
1173  bool b=false;
1174  QueryBoolValue( &b );
1175  return b;
1176  }
1178  double DoubleValue() const {
1179  double d=0;
1180  QueryDoubleValue( &d );
1181  return d;
1182  }
1184  float FloatValue() const {
1185  float f=0;
1186  QueryFloatValue( &f );
1187  return f;
1188  }
1189 
1194  XMLError QueryIntValue( int* value ) const;
1196  XMLError QueryUnsignedValue( unsigned int* value ) const;
1198  XMLError QueryInt64Value(int64_t* value) const;
1200  XMLError QueryBoolValue( bool* value ) const;
1202  XMLError QueryDoubleValue( double* value ) const;
1204  XMLError QueryFloatValue( float* value ) const;
1205 
1207  void SetAttribute( const char* value );
1209  void SetAttribute( int value );
1211  void SetAttribute( unsigned value );
1213  void SetAttribute(int64_t value);
1215  void SetAttribute( bool value );
1217  void SetAttribute( double value );
1219  void SetAttribute( float value );
1220 
1221 private:
1222  enum { BUF_SIZE = 200 };
1223 
1224  XMLAttribute() : _name(), _value(),_parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
1225  virtual ~XMLAttribute() {}
1226 
1227  XMLAttribute( const XMLAttribute& ); // not supported
1228  void operator=( const XMLAttribute& ); // not supported
1229  void SetName( const char* name );
1230 
1231  char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
1232 
1233  mutable StrPair _name;
1234  mutable StrPair _value;
1235  int _parseLineNum;
1236  XMLAttribute* _next;
1237  MemPool* _memPool;
1238 };
1239 
1240 
1245 class TINYXML2_LIB XMLElement : public XMLNode
1246 {
1247  friend class XMLDocument;
1248 public:
1250  const char* Name() const {
1251  return Value();
1252  }
1254  void SetName( const char* str, bool staticMem=false ) {
1255  SetValue( str, staticMem );
1256  }
1257 
1258  virtual XMLElement* ToElement() {
1259  return this;
1260  }
1261  virtual const XMLElement* ToElement() const {
1262  return this;
1263  }
1264  virtual bool Accept( XMLVisitor* visitor ) const;
1265 
1289  const char* Attribute( const char* name, const char* value=0 ) const;
1290 
1297  int IntAttribute(const char* name, int defaultValue = 0) const;
1299  unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
1301  int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
1303  bool BoolAttribute(const char* name, bool defaultValue = false) const;
1305  double DoubleAttribute(const char* name, double defaultValue = 0) const;
1307  float FloatAttribute(const char* name, float defaultValue = 0) const;
1308 
1322  XMLError QueryIntAttribute( const char* name, int* value ) const {
1323  const XMLAttribute* a = FindAttribute( name );
1324  if ( !a ) {
1325  return XML_NO_ATTRIBUTE;
1326  }
1327  return a->QueryIntValue( value );
1328  }
1329 
1331  XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
1332  const XMLAttribute* a = FindAttribute( name );
1333  if ( !a ) {
1334  return XML_NO_ATTRIBUTE;
1335  }
1336  return a->QueryUnsignedValue( value );
1337  }
1338 
1340  XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1341  const XMLAttribute* a = FindAttribute(name);
1342  if (!a) {
1343  return XML_NO_ATTRIBUTE;
1344  }
1345  return a->QueryInt64Value(value);
1346  }
1347 
1349  XMLError QueryBoolAttribute( const char* name, bool* value ) const {
1350  const XMLAttribute* a = FindAttribute( name );
1351  if ( !a ) {
1352  return XML_NO_ATTRIBUTE;
1353  }
1354  return a->QueryBoolValue( value );
1355  }
1357  XMLError QueryDoubleAttribute( const char* name, double* value ) const {
1358  const XMLAttribute* a = FindAttribute( name );
1359  if ( !a ) {
1360  return XML_NO_ATTRIBUTE;
1361  }
1362  return a->QueryDoubleValue( value );
1363  }
1365  XMLError QueryFloatAttribute( const char* name, float* value ) const {
1366  const XMLAttribute* a = FindAttribute( name );
1367  if ( !a ) {
1368  return XML_NO_ATTRIBUTE;
1369  }
1370  return a->QueryFloatValue( value );
1371  }
1372 
1374  XMLError QueryStringAttribute(const char* name, const char** value) const {
1375  const XMLAttribute* a = FindAttribute(name);
1376  if (!a) {
1377  return XML_NO_ATTRIBUTE;
1378  }
1379  *value = a->Value();
1380  return XML_SUCCESS;
1381  }
1382 
1383 
1384 
1402  XMLError QueryAttribute( const char* name, int* value ) const {
1403  return QueryIntAttribute( name, value );
1404  }
1405 
1406  XMLError QueryAttribute( const char* name, unsigned int* value ) const {
1407  return QueryUnsignedAttribute( name, value );
1408  }
1409 
1410  XMLError QueryAttribute(const char* name, int64_t* value) const {
1411  return QueryInt64Attribute(name, value);
1412  }
1413 
1414  XMLError QueryAttribute( const char* name, bool* value ) const {
1415  return QueryBoolAttribute( name, value );
1416  }
1417 
1418  XMLError QueryAttribute( const char* name, double* value ) const {
1419  return QueryDoubleAttribute( name, value );
1420  }
1421 
1422  XMLError QueryAttribute( const char* name, float* value ) const {
1423  return QueryFloatAttribute( name, value );
1424  }
1425 
1427  void SetAttribute( const char* name, const char* value ) {
1428  XMLAttribute* a = FindOrCreateAttribute( name );
1429  a->SetAttribute( value );
1430  }
1432  void SetAttribute( const char* name, int value ) {
1433  XMLAttribute* a = FindOrCreateAttribute( name );
1434  a->SetAttribute( value );
1435  }
1437  void SetAttribute( const char* name, unsigned value ) {
1438  XMLAttribute* a = FindOrCreateAttribute( name );
1439  a->SetAttribute( value );
1440  }
1441 
1443  void SetAttribute(const char* name, int64_t value) {
1444  XMLAttribute* a = FindOrCreateAttribute(name);
1445  a->SetAttribute(value);
1446  }
1447 
1449  void SetAttribute( const char* name, bool value ) {
1450  XMLAttribute* a = FindOrCreateAttribute( name );
1451  a->SetAttribute( value );
1452  }
1454  void SetAttribute( const char* name, double value ) {
1455  XMLAttribute* a = FindOrCreateAttribute( name );
1456  a->SetAttribute( value );
1457  }
1459  void SetAttribute( const char* name, float value ) {
1460  XMLAttribute* a = FindOrCreateAttribute( name );
1461  a->SetAttribute( value );
1462  }
1463 
1467  void DeleteAttribute( const char* name );
1468 
1470  const XMLAttribute* FirstAttribute() const {
1471  return _rootAttribute;
1472  }
1474  const XMLAttribute* FindAttribute( const char* name ) const;
1475 
1504  const char* GetText() const;
1505 
1540  void SetText( const char* inText );
1542  void SetText( int value );
1544  void SetText( unsigned value );
1546  void SetText(int64_t value);
1548  void SetText( bool value );
1550  void SetText( double value );
1552  void SetText( float value );
1553 
1580  XMLError QueryIntText( int* ival ) const;
1582  XMLError QueryUnsignedText( unsigned* uval ) const;
1584  XMLError QueryInt64Text(int64_t* uval) const;
1586  XMLError QueryBoolText( bool* bval ) const;
1588  XMLError QueryDoubleText( double* dval ) const;
1590  XMLError QueryFloatText( float* fval ) const;
1591 
1592  int IntText(int defaultValue = 0) const;
1593 
1595  unsigned UnsignedText(unsigned defaultValue = 0) const;
1597  int64_t Int64Text(int64_t defaultValue = 0) const;
1599  bool BoolText(bool defaultValue = false) const;
1601  double DoubleText(double defaultValue = 0) const;
1603  float FloatText(float defaultValue = 0) const;
1604 
1605  // internal:
1606  enum ElementClosingType {
1607  OPEN, // <foo>
1608  CLOSED, // <foo/>
1609  CLOSING // </foo>
1610  };
1611  ElementClosingType ClosingType() const {
1612  return _closingType;
1613  }
1614  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1615  virtual bool ShallowEqual( const XMLNode* compare ) const;
1616 
1617 protected:
1618  char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
1619 
1620 private:
1621  XMLElement( XMLDocument* doc );
1622  virtual ~XMLElement();
1623  XMLElement( const XMLElement& ); // not supported
1624  void operator=( const XMLElement& ); // not supported
1625 
1626  XMLAttribute* FindOrCreateAttribute( const char* name );
1627  char* ParseAttributes( char* p, int* curLineNumPtr );
1628  static void DeleteAttribute( XMLAttribute* attribute );
1629  XMLAttribute* CreateAttribute();
1630 
1631  enum { BUF_SIZE = 200 };
1632  ElementClosingType _closingType;
1633  // The attribute list is ordered; there is no 'lastAttribute'
1634  // because the list needs to be scanned for dupes before adding
1635  // a new attribute.
1636  XMLAttribute* _rootAttribute;
1637 };
1638 
1639 
1640 enum Whitespace {
1641  PRESERVE_WHITESPACE,
1642  COLLAPSE_WHITESPACE
1643 };
1644 
1645 
1651 class TINYXML2_LIB XMLDocument : public XMLNode
1652 {
1653  friend class XMLElement;
1654  // Gives access to SetError and Push/PopDepth, but over-access for everything else.
1655  // Wishing C++ had "internal" scope.
1656  friend class XMLNode;
1657  friend class XMLText;
1658  friend class XMLComment;
1659  friend class XMLDeclaration;
1660  friend class XMLUnknown;
1661 public:
1663  XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
1664  ~XMLDocument();
1665 
1667  TIXMLASSERT( this == _document );
1668  return this;
1669  }
1670  virtual const XMLDocument* ToDocument() const {
1671  TIXMLASSERT( this == _document );
1672  return this;
1673  }
1674 
1685  XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
1686 
1692  XMLError LoadFile( const char* filename );
1693 
1705  XMLError LoadFile( FILE* );
1706 
1712  XMLError SaveFile( const char* filename, bool compact = false );
1713 
1721  XMLError SaveFile( FILE* fp, bool compact = false );
1722 
1723  bool ProcessEntities() const {
1724  return _processEntities;
1725  }
1726  Whitespace WhitespaceMode() const {
1727  return _whitespaceMode;
1728  }
1729 
1733  bool HasBOM() const {
1734  return _writeBOM;
1735  }
1738  void SetBOM( bool useBOM ) {
1739  _writeBOM = useBOM;
1740  }
1741 
1746  return FirstChildElement();
1747  }
1748  const XMLElement* RootElement() const {
1749  return FirstChildElement();
1750  }
1751 
1766  void Print( XMLPrinter* streamer=0 ) const;
1767  virtual bool Accept( XMLVisitor* visitor ) const;
1768 
1774  XMLElement* NewElement( const char* name );
1780  XMLComment* NewComment( const char* comment );
1786  XMLText* NewText( const char* text );
1798  XMLDeclaration* NewDeclaration( const char* text=0 );
1804  XMLUnknown* NewUnknown( const char* text );
1805 
1810  void DeleteNode( XMLNode* node );
1811 
1812  void ClearError() {
1813  SetError(XML_SUCCESS, 0, 0);
1814  }
1815 
1817  bool Error() const {
1818  return _errorID != XML_SUCCESS;
1819  }
1821  XMLError ErrorID() const {
1822  return _errorID;
1823  }
1824  const char* ErrorName() const;
1825  static const char* ErrorIDToName(XMLError errorID);
1826 
1830  const char* ErrorStr() const;
1831 
1833  void PrintError() const;
1834 
1836  int ErrorLineNum() const
1837  {
1838  return _errorLineNum;
1839  }
1840 
1842  void Clear();
1843 
1851  void DeepCopy(XMLDocument* target) const;
1852 
1853  // internal
1854  char* Identify( char* p, XMLNode** node );
1855 
1856  // internal
1857  void MarkInUse(XMLNode*);
1858 
1859  virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1860  return 0;
1861  }
1862  virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1863  return false;
1864  }
1865 
1866 private:
1867  XMLDocument( const XMLDocument& ); // not supported
1868  void operator=( const XMLDocument& ); // not supported
1869 
1870  bool _writeBOM;
1871  bool _processEntities;
1872  XMLError _errorID;
1873  Whitespace _whitespaceMode;
1874  mutable StrPair _errorStr;
1875  int _errorLineNum;
1876  char* _charBuffer;
1877  int _parseCurLineNum;
1878  int _parsingDepth;
1879  // Memory tracking does add some overhead.
1880  // However, the code assumes that you don't
1881  // have a bunch of unlinked nodes around.
1882  // Therefore it takes less memory to track
1883  // in the document vs. a linked list in the XMLNode,
1884  // and the performance is the same.
1885  DynArray<XMLNode*, 10> _unlinked;
1886 
1887  MemPoolT< sizeof(XMLElement) > _elementPool;
1888  MemPoolT< sizeof(XMLAttribute) > _attributePool;
1889  MemPoolT< sizeof(XMLText) > _textPool;
1890  MemPoolT< sizeof(XMLComment) > _commentPool;
1891 
1892  static const char* _errorNames[XML_ERROR_COUNT];
1893 
1894  void Parse();
1895 
1896  void SetError( XMLError error, int lineNum, const char* format, ... );
1897 
1898  // Something of an obvious security hole, once it was discovered.
1899  // Either an ill-formed XML or an excessively deep one can overflow
1900  // the stack. Track stack depth, and error out if needed.
1901  class DepthTracker {
1902  public:
1903  explicit DepthTracker(XMLDocument * document) {
1904  this->_document = document;
1905  document->PushDepth();
1906  }
1907  ~DepthTracker() {
1908  _document->PopDepth();
1909  }
1910  private:
1911  XMLDocument * _document;
1912  };
1913  void PushDepth();
1914  void PopDepth();
1915 
1916  template<class NodeType, int PoolElementSize>
1917  NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
1918 };
1919 
1920 template<class NodeType, int PoolElementSize>
1921 inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )
1922 {
1923  TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
1924  TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );
1925  NodeType* returnNode = new (pool.Alloc()) NodeType( this );
1926  TIXMLASSERT( returnNode );
1927  returnNode->_memPool = &pool;
1928 
1929  _unlinked.Push(returnNode);
1930  return returnNode;
1931 }
1932 
1988 class TINYXML2_LIB XMLHandle
1989 {
1990 public:
1992  explicit XMLHandle( XMLNode* node ) : _node( node ) {
1993  }
1995  explicit XMLHandle( XMLNode& node ) : _node( &node ) {
1996  }
1998  XMLHandle( const XMLHandle& ref ) : _node( ref._node ) {
1999  }
2001  XMLHandle& operator=( const XMLHandle& ref ) {
2002  _node = ref._node;
2003  return *this;
2004  }
2005 
2008  return XMLHandle( _node ? _node->FirstChild() : 0 );
2009  }
2011  XMLHandle FirstChildElement( const char* name = 0 ) {
2012  return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
2013  }
2016  return XMLHandle( _node ? _node->LastChild() : 0 );
2017  }
2019  XMLHandle LastChildElement( const char* name = 0 ) {
2020  return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
2021  }
2024  return XMLHandle( _node ? _node->PreviousSibling() : 0 );
2025  }
2027  XMLHandle PreviousSiblingElement( const char* name = 0 ) {
2028  return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2029  }
2032  return XMLHandle( _node ? _node->NextSibling() : 0 );
2033  }
2035  XMLHandle NextSiblingElement( const char* name = 0 ) {
2036  return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2037  }
2038 
2041  return _node;
2042  }
2045  return ( _node ? _node->ToElement() : 0 );
2046  }
2049  return ( _node ? _node->ToText() : 0 );
2050  }
2053  return ( _node ? _node->ToUnknown() : 0 );
2054  }
2057  return ( _node ? _node->ToDeclaration() : 0 );
2058  }
2059 
2060 private:
2061  XMLNode* _node;
2062 };
2063 
2064 
2069 class TINYXML2_LIB XMLConstHandle
2070 {
2071 public:
2072  explicit XMLConstHandle( const XMLNode* node ) : _node( node ) {
2073  }
2074  explicit XMLConstHandle( const XMLNode& node ) : _node( &node ) {
2075  }
2076  XMLConstHandle( const XMLConstHandle& ref ) : _node( ref._node ) {
2077  }
2078 
2079  XMLConstHandle& operator=( const XMLConstHandle& ref ) {
2080  _node = ref._node;
2081  return *this;
2082  }
2083 
2084  const XMLConstHandle FirstChild() const {
2085  return XMLConstHandle( _node ? _node->FirstChild() : 0 );
2086  }
2087  const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
2088  return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
2089  }
2090  const XMLConstHandle LastChild() const {
2091  return XMLConstHandle( _node ? _node->LastChild() : 0 );
2092  }
2093  const XMLConstHandle LastChildElement( const char* name = 0 ) const {
2094  return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
2095  }
2096  const XMLConstHandle PreviousSibling() const {
2097  return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
2098  }
2099  const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
2100  return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
2101  }
2102  const XMLConstHandle NextSibling() const {
2103  return XMLConstHandle( _node ? _node->NextSibling() : 0 );
2104  }
2105  const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
2106  return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
2107  }
2108 
2109 
2110  const XMLNode* ToNode() const {
2111  return _node;
2112  }
2113  const XMLElement* ToElement() const {
2114  return ( _node ? _node->ToElement() : 0 );
2115  }
2116  const XMLText* ToText() const {
2117  return ( _node ? _node->ToText() : 0 );
2118  }
2119  const XMLUnknown* ToUnknown() const {
2120  return ( _node ? _node->ToUnknown() : 0 );
2121  }
2122  const XMLDeclaration* ToDeclaration() const {
2123  return ( _node ? _node->ToDeclaration() : 0 );
2124  }
2125 
2126 private:
2127  const XMLNode* _node;
2128 };
2129 
2130 
2173 class TINYXML2_LIB XMLPrinter : public XMLVisitor
2174 {
2175 public:
2182  XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
2183  virtual ~XMLPrinter() {}
2184 
2186  void PushHeader( bool writeBOM, bool writeDeclaration );
2190  void OpenElement( const char* name, bool compactMode=false );
2192  void PushAttribute( const char* name, const char* value );
2193  void PushAttribute( const char* name, int value );
2194  void PushAttribute( const char* name, unsigned value );
2195  void PushAttribute(const char* name, int64_t value);
2196  void PushAttribute( const char* name, bool value );
2197  void PushAttribute( const char* name, double value );
2199  virtual void CloseElement( bool compactMode=false );
2200 
2202  void PushText( const char* text, bool cdata=false );
2204  void PushText( int value );
2206  void PushText( unsigned value );
2208  void PushText(int64_t value);
2210  void PushText( bool value );
2212  void PushText( float value );
2214  void PushText( double value );
2215 
2217  void PushComment( const char* comment );
2218 
2219  void PushDeclaration( const char* value );
2220  void PushUnknown( const char* value );
2221 
2222  virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2223  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2224  return true;
2225  }
2226 
2227  virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2228  virtual bool VisitExit( const XMLElement& element );
2229 
2230  virtual bool Visit( const XMLText& text );
2231  virtual bool Visit( const XMLComment& comment );
2232  virtual bool Visit( const XMLDeclaration& declaration );
2233  virtual bool Visit( const XMLUnknown& unknown );
2234 
2239  const char* CStr() const {
2240  return _buffer.Mem();
2241  }
2247  int CStrSize() const {
2248  return _buffer.Size();
2249  }
2254  void ClearBuffer() {
2255  _buffer.Clear();
2256  _buffer.Push(0);
2257  _firstElement = true;
2258  }
2259 
2260 protected:
2261  virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
2262 
2266  virtual void PrintSpace( int depth );
2267  void Print( const char* format, ... );
2268  void Write( const char* data, size_t size );
2269  inline void Write( const char* data ) { Write( data, strlen( data ) ); }
2270  void Putc( char ch );
2271 
2272  void SealElementIfJustOpened();
2273  bool _elementJustOpened;
2274  DynArray< const char*, 10 > _stack;
2275 
2276 private:
2277  void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
2278 
2279  bool _firstElement;
2280  FILE* _fp;
2281  int _depth;
2282  int _textDepth;
2283  bool _processEntities;
2284  bool _compactMode;
2285 
2286  enum {
2287  ENTITY_RANGE = 64,
2288  BUF_SIZE = 200
2289  };
2290  bool _entityFlag[ENTITY_RANGE];
2291  bool _restrictedEntityFlag[ENTITY_RANGE];
2292 
2293  DynArray< char, 20 > _buffer;
2294 
2295  // Prohibit cloning, intentionally not implemented
2296  XMLPrinter( const XMLPrinter& );
2297  XMLPrinter& operator=( const XMLPrinter& );
2298 };
2299 
2300 
2301 } // tinyxml2
2302 
2303 #if defined(_MSC_VER)
2304 # pragma warning(pop)
2305 #endif
2306 
2307 #endif // TINYXML2_INCLUDED
XMLError QueryInt64Attribute(const char *name, int64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1340
XMLError QueryIntValue(int *value) const
XMLError QueryBoolAttribute(const char *name, bool *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1349
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:488
virtual XMLNode * ShallowClone(XMLDocument *) const
Definition: tinyxml2.h:1859
virtual bool ShallowEqual(const XMLNode *) const
Definition: tinyxml2.h:1862
XMLHandle FirstChildElement(const char *name=0)
Get the first child element of this handle.
Definition: tinyxml2.h:2011
XMLText * ToText()
Safe cast to XMLText. This can return null.
Definition: tinyxml2.h:2048
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
const char * CStr() const
Definition: tinyxml2.h:2239
XMLError ErrorID() const
Return the errorID.
Definition: tinyxml2.h:1821
XMLElement * ToElement()
Safe cast to XMLElement. This can return null.
Definition: tinyxml2.h:2044
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:683
XMLError QueryStringAttribute(const char *name, const char **value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1374
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:687
XMLError QueryUnsignedAttribute(const char *name, unsigned int *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1331
int CStrSize() const
Definition: tinyxml2.h:2247
float FloatValue() const
Query as a float. See IntValue()
Definition: tinyxml2.h:1184
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:1666
XMLUnknown * ToUnknown()
Safe cast to XMLUnknown. This can return null.
Definition: tinyxml2.h:2052
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1250
XMLHandle(const XMLHandle &ref)
Copy constructor.
Definition: tinyxml2.h:1998
XMLHandle FirstChild()
Get the first child of this handle.
Definition: tinyxml2.h:2007
void SetCData(bool isCData)
Declare whether this should be CDATA or standard text.
Definition: tinyxml2.h:996
void SetUserData(void *userData)
Definition: tinyxml2.h:930
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:812
unsigned UnsignedValue() const
Query as an unsigned integer. See IntValue()
Definition: tinyxml2.h:1166
XMLHandle LastChildElement(const char *name=0)
Get the last child element of this handle.
Definition: tinyxml2.h:2019
XMLHandle LastChild()
Get the last child of this handle.
Definition: tinyxml2.h:2015
Definition: tinyxml2.h:1988
Definition: tinyxml2.h:1061
XMLElement * RootElement()
Definition: tinyxml2.h:1745
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:988
XMLHandle(XMLNode &node)
Create a handle from a node.
Definition: tinyxml2.h:1995
void SetName(const char *str, bool staticMem=false)
Set the name of the element.
Definition: tinyxml2.h:1254
void SetBOM(bool useBOM)
Definition: tinyxml2.h:1738
XMLHandle(XMLNode *node)
Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Definition: tinyxml2.h:1992
void ClearBuffer()
Definition: tinyxml2.h:2254
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:1026
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:1258
bool HasBOM() const
Definition: tinyxml2.h:1733
Definition: tinyxml2.h:116
XMLError QueryFloatAttribute(const char *name, float *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1365
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
XMLNode * ToNode()
Safe cast to XMLNode. This can return null.
Definition: tinyxml2.h:2040
bool BoolValue() const
Query as a boolean. See IntValue()
Definition: tinyxml2.h:1172
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:760
Definition: tinyxml2.h:1022
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:1065
virtual bool Visit(const XMLDeclaration &)
Visit a declaration.
Definition: tinyxml2.h:502
virtual bool Visit(const XMLUnknown &)
Visit an unknown node.
Definition: tinyxml2.h:514
void SetAttribute(const char *name, unsigned value)
Sets the named attribute to value.
Definition: tinyxml2.h:1437
XMLError QueryDoubleAttribute(const char *name, double *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1357
Definition: tinyxml2.h:1245
XMLError QueryInt64Value(int64_t *value) const
See QueryIntValue.
XMLHandle NextSibling()
Get the next sibling of this handle.
Definition: tinyxml2.h:2031
int GetLineNum() const
Gets the line number the attribute is in, if the document was parsed from a file. ...
Definition: tinyxml2.h:1142
int IntValue() const
Definition: tinyxml2.h:1153
virtual XMLUnknown * ToUnknown()
Safely cast to an Unknown, or null.
Definition: tinyxml2.h:1100
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:1000
XMLHandle PreviousSibling()
Get the previous sibling of this handle.
Definition: tinyxml2.h:2023
Definition: tinyxml2.h:2069
XMLHandle & operator=(const XMLHandle &ref)
Assignment.
Definition: tinyxml2.h:2001
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2223
virtual bool VisitEnter(const XMLElement &, const XMLAttribute *)
Visit an element.
Definition: tinyxml2.h:493
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1817
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:484
Definition: tinyxml2.h:1096
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:695
const XMLNode * LastChild() const
Get the last child node, or null if none exists.
Definition: tinyxml2.h:778
Definition: tinyxml2.h:1131
XMLError QueryAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1402
void SetAttribute(const char *name, bool value)
Sets the named attribute to value.
Definition: tinyxml2.h:1449
XMLDeclaration * ToDeclaration()
Safe cast to XMLDeclaration. This can return null.
Definition: tinyxml2.h:2056
void SetAttribute(const char *value)
Set the attribute to a string value.
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1427
virtual bool VisitExit(const XMLElement &)
Visit an element.
Definition: tinyxml2.h:497
Definition: tinyxml2.h:2173
Definition: tinyxml2.h:1651
void * GetUserData() const
Definition: tinyxml2.h:937
void SetAttribute(const char *name, int64_t value)
Sets the named attribute to value.
Definition: tinyxml2.h:1443
const char * Value() const
The value of the attribute.
void SetAttribute(const char *name, double value)
Sets the named attribute to value.
Definition: tinyxml2.h:1454
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
const XMLNode * Parent() const
Get the parent of this node on the DOM.
Definition: tinyxml2.h:746
virtual bool Visit(const XMLComment &)
Visit a comment node.
Definition: tinyxml2.h:510
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
const XMLNode * PreviousSibling() const
Get the previous (left) sibling node of this node.
Definition: tinyxml2.h:796
XMLHandle NextSiblingElement(const char *name=0)
Get the next sibling element of this handle.
Definition: tinyxml2.h:2035
Definition: tinyxml2.h:665
XMLError QueryIntAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1322
int GetLineNum() const
Gets the line number the node is in, if the document was parsed from a file.
Definition: tinyxml2.h:743
virtual bool Visit(const XMLText &)
Visit a text node.
Definition: tinyxml2.h:506
Definition: tinyxml2.h:982
Definition: tinyxml2.h:478
int ErrorLineNum() const
Return the line where the error occurred, or zero if unknown.
Definition: tinyxml2.h:1836
XMLDocument * GetDocument()
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:677
virtual XMLUnknown * ToUnknown()
Safely cast to an Unknown, or null.
Definition: tinyxml2.h:703
void SetAttribute(const char *name, float value)
Sets the named attribute to value.
Definition: tinyxml2.h:1459
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1145
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:755
double DoubleValue() const
Query as a double. See IntValue()
Definition: tinyxml2.h:1178
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:699
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:672
XMLHandle PreviousSiblingElement(const char *name=0)
Get the previous sibling element of this handle.
Definition: tinyxml2.h:2027
void SetAttribute(const char *name, int value)
Sets the named attribute to value.
Definition: tinyxml2.h:1432
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1470
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:691