OPTPiX SpriteStudio SDK
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
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__)
28 # include <ctype.h>
29 # include <limits.h>
30 # include <stdio.h>
31 # include <stdlib.h>
32 # include <string.h>
33 # include <stdarg.h>
34 #else
35 # include <cctype>
36 # include <climits>
37 # include <cstdio>
38 # include <cstdlib>
39 # include <cstring>
40 # include <cstdarg>
41 #endif
42 
43 /*
44  TODO: intern strings instead of allocation.
45 */
46 /*
47  gcc:
48  g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
49 
50  Formatting, Artistic Style:
51  AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
52 */
53 
54 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
55 # ifndef DEBUG
56 # define DEBUG
57 # endif
58 #endif
59 
60 
61 #if defined(DEBUG)
62 # if defined(_MSC_VER)
63 # define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64 # elif defined (ANDROID_NDK)
65 # include <android/log.h>
66 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67 # else
68 # include <assert.h>
69 # define TIXMLASSERT assert
70 # endif
71 # else
72 # define TIXMLASSERT( x ) {}
73 #endif
74 
75 
76 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
77 // Microsoft visual studio, version 2005 and higher.
78 /*int _snprintf_s(
79  char *buffer,
80  size_t sizeOfBuffer,
81  size_t count,
82  const char *format [,
83  argument] ...
84 );*/
85 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86 {
87  va_list va;
88  va_start( va, format );
89  int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90  va_end( va );
91  return result;
92 }
93 #define TIXML_SSCANF sscanf_s
94 #else
95 // GCC version 3 and higher
96 //#warning( "Using sn* functions." )
97 #define TIXML_SNPRINTF snprintf
98 #define TIXML_SSCANF sscanf
99 #endif
100 
101 static const int TIXML2_MAJOR_VERSION = 1;
102 static const int TIXML2_MINOR_VERSION = 0;
103 static const int TIXML2_PATCH_VERSION = 11;
104 
105 namespace tinyxml2
106 {
107 class XMLDocument;
108 class XMLElement;
109 class XMLAttribute;
110 class XMLComment;
111 class XMLNode;
112 class XMLText;
113 class XMLDeclaration;
114 class XMLUnknown;
115 
116 class XMLPrinter;
117 
118 /*
119  A class that wraps strings. Normally stores the start and end
120  pointers into the XML file itself, and will apply normalization
121  and entity translation if actually read. Can also store (and memory
122  manage) a traditional char[]
123 */
124 class StrPair
125 {
126 public:
127  enum {
128  NEEDS_ENTITY_PROCESSING = 0x01,
129  NEEDS_NEWLINE_NORMALIZATION = 0x02,
130  COLLAPSE_WHITESPACE = 0x04,
131 
132  TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
133  TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
134  ATTRIBUTE_NAME = 0,
135  ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136  ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137  COMMENT = NEEDS_NEWLINE_NORMALIZATION
138  };
139 
140  StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
141  ~StrPair();
142 
143  void Set( char* start, char* end, int flags ) {
144  Reset();
145  _start = start;
146  _end = end;
147  _flags = flags | NEEDS_FLUSH;
148  }
149 
150  const char* GetStr();
151 
152  bool Empty() const {
153  return _start == _end;
154  }
155 
156  void SetInternedStr( const char* str ) {
157  Reset();
158  _start = const_cast<char*>(str);
159  }
160 
161  void SetStr( const char* str, int flags=0 );
162 
163  char* ParseText( char* in, const char* endTag, int strFlags );
164  char* ParseName( char* in );
165 
166 private:
167  void Reset();
168  void CollapseWhitespace();
169 
170  enum {
171  NEEDS_FLUSH = 0x100,
172  NEEDS_DELETE = 0x200
173  };
174 
175  // After parsing, if *_end != 0, it can be set to zero.
176  int _flags;
177  char* _start;
178  char* _end;
179 };
180 
181 
182 /*
183  A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184  Has a small initial memory pool, so that low or no usage will not
185  cause a call to new/delete
186 */
187 template <class T, int INIT>
188 class DynArray
189 {
190 public:
192  _mem = _pool;
193  _allocated = INIT;
194  _size = 0;
195  }
196 
197  ~DynArray() {
198  if ( _mem != _pool ) {
199  delete [] _mem;
200  }
201  }
202 
203  void Push( T t ) {
204  EnsureCapacity( _size+1 );
205  _mem[_size++] = t;
206  }
207 
208  T* PushArr( int count ) {
209  EnsureCapacity( _size+count );
210  T* ret = &_mem[_size];
211  _size += count;
212  return ret;
213  }
214 
215  T Pop() {
216  return _mem[--_size];
217  }
218 
219  void PopArr( int count ) {
220  TIXMLASSERT( _size >= count );
221  _size -= count;
222  }
223 
224  bool Empty() const {
225  return _size == 0;
226  }
227 
228  T& operator[](int i) {
229  TIXMLASSERT( i>= 0 && i < _size );
230  return _mem[i];
231  }
232 
233  const T& operator[](int i) const {
234  TIXMLASSERT( i>= 0 && i < _size );
235  return _mem[i];
236  }
237 
238  int Size() const {
239  return _size;
240  }
241 
242  int Capacity() const {
243  return _allocated;
244  }
245 
246  const T* Mem() const {
247  return _mem;
248  }
249 
250  T* Mem() {
251  return _mem;
252  }
253 
254 private:
255  void EnsureCapacity( int cap ) {
256  if ( cap > _allocated ) {
257  int newAllocated = cap * 2;
258  T* newMem = new T[newAllocated];
259  memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
260  if ( _mem != _pool ) {
261  delete [] _mem;
262  }
263  _mem = newMem;
264  _allocated = newAllocated;
265  }
266  }
267 
268  T* _mem;
269  T _pool[INIT];
270  int _allocated; // objects allocated
271  int _size; // number objects in use
272 };
273 
274 
275 /*
276  Parent virtual class of a pool for fast allocation
277  and deallocation of objects.
278 */
279 class MemPool
280 {
281 public:
282  MemPool() {}
283  virtual ~MemPool() {}
284 
285  virtual int ItemSize() const = 0;
286  virtual void* Alloc() = 0;
287  virtual void Free( void* ) = 0;
288  virtual void SetTracked() = 0;
289 };
290 
291 
292 /*
293  Template child class to create pools of the correct type.
294 */
295 template< int SIZE >
296 class MemPoolT : public MemPool
297 {
298 public:
299  MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
300  ~MemPoolT() {
301  // Delete the blocks.
302  for( int i=0; i<_blockPtrs.Size(); ++i ) {
303  delete _blockPtrs[i];
304  }
305  }
306 
307  virtual int ItemSize() const {
308  return SIZE;
309  }
310  int CurrentAllocs() const {
311  return _currentAllocs;
312  }
313 
314  virtual void* Alloc() {
315  if ( !_root ) {
316  // Need a new block.
317  Block* block = new Block();
318  _blockPtrs.Push( block );
319 
320  for( int i=0; i<COUNT-1; ++i ) {
321  block->chunk[i].next = &block->chunk[i+1];
322  }
323  block->chunk[COUNT-1].next = 0;
324  _root = block->chunk;
325  }
326  void* result = _root;
327  _root = _root->next;
328 
329  ++_currentAllocs;
330  if ( _currentAllocs > _maxAllocs ) {
331  _maxAllocs = _currentAllocs;
332  }
333  _nAllocs++;
334  _nUntracked++;
335  return result;
336  }
337  virtual void Free( void* mem ) {
338  if ( !mem ) {
339  return;
340  }
341  --_currentAllocs;
342  Chunk* chunk = (Chunk*)mem;
343 #ifdef DEBUG
344  memset( chunk, 0xfe, sizeof(Chunk) );
345 #endif
346  chunk->next = _root;
347  _root = chunk;
348  }
349  void Trace( const char* name ) {
350  printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
351  name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
352  }
353 
354  void SetTracked() {
355  _nUntracked--;
356  }
357 
358  int Untracked() const {
359  return _nUntracked;
360  }
361 
362  // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
363  // The test file is large, 170k.
364  // Release: VS2010 gcc(no opt)
365  // 1k: 4000
366  // 2k: 4000
367  // 4k: 3900 21000
368  // 16k: 5200
369  // 32k: 4300
370  // 64k: 4000 21000
371  enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
372 
373 private:
374  union Chunk {
375  Chunk* next;
376  char mem[SIZE];
377  };
378  struct Block {
379  Chunk chunk[COUNT];
380  };
381  DynArray< Block*, 10 > _blockPtrs;
382  Chunk* _root;
383 
384  int _currentAllocs;
385  int _nAllocs;
386  int _maxAllocs;
387  int _nUntracked;
388 };
389 
390 
391 
412 {
413 public:
414  virtual ~XMLVisitor() {}
415 
417  virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
418  return true;
419  }
421  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
422  return true;
423  }
424 
426  virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
427  return true;
428  }
430  virtual bool VisitExit( const XMLElement& /*element*/ ) {
431  return true;
432  }
433 
435  virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
436  return true;
437  }
439  virtual bool Visit( const XMLText& /*text*/ ) {
440  return true;
441  }
443  virtual bool Visit( const XMLComment& /*comment*/ ) {
444  return true;
445  }
447  virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
448  return true;
449  }
450 };
451 
452 
453 /*
454  Utility functionality.
455 */
456 class XMLUtil
457 {
458 public:
459  // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
460  // correct, but simple, and usually works.
461  static const char* SkipWhiteSpace( const char* p ) {
462  while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
463  ++p;
464  }
465  return p;
466  }
467  static char* SkipWhiteSpace( char* p ) {
468  while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
469  ++p;
470  }
471  return p;
472  }
473  static bool IsWhiteSpace( char p ) {
474  return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
475  }
476 
477  inline static bool IsNameStartChar( unsigned char ch ) {
478  return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
479  || ch == ':'
480  || ch == '_';
481  }
482 
483  inline static bool IsNameChar( unsigned char ch ) {
484  return IsNameStartChar( ch )
485  || isdigit( ch )
486  || ch == '.'
487  || ch == '-';
488  }
489 
490  inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
491  int n = 0;
492  if ( p == q ) {
493  return true;
494  }
495  while( *p && *q && *p == *q && n<nChar ) {
496  ++p;
497  ++q;
498  ++n;
499  }
500  if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
501  return true;
502  }
503  return false;
504  }
505 
506  inline static int IsUTF8Continuation( const char p ) {
507  return p & 0x80;
508  }
509 
510  static const char* ReadBOM( const char* p, bool* hasBOM );
511  // p is the starting location,
512  // the UTF-8 value of the entity will be placed in value, and length filled in.
513  static const char* GetCharacterRef( const char* p, char* value, int* length );
514  static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
515 
516  // converts primitive types to strings
517  static void ToStr( int v, char* buffer, int bufferSize );
518  static void ToStr( unsigned v, char* buffer, int bufferSize );
519  static void ToStr( bool v, char* buffer, int bufferSize );
520  static void ToStr( float v, char* buffer, int bufferSize );
521  static void ToStr( double v, char* buffer, int bufferSize );
522 
523  // converts strings to primitive types
524  static bool ToInt( const char* str, int* value );
525  static bool ToUnsigned( const char* str, unsigned* value );
526  static bool ToBool( const char* str, bool* value );
527  static bool ToFloat( const char* str, float* value );
528  static bool ToDouble( const char* str, double* value );
529 };
530 
531 
557 class XMLNode
558 {
559  friend class XMLDocument;
560  friend class XMLElement;
561 public:
562 
564  const XMLDocument* GetDocument() const {
565  return _document;
566  }
569  return _document;
570  }
571 
573  virtual XMLElement* ToElement() {
574  return 0;
575  }
577  virtual XMLText* ToText() {
578  return 0;
579  }
581  virtual XMLComment* ToComment() {
582  return 0;
583  }
585  virtual XMLDocument* ToDocument() {
586  return 0;
587  }
590  return 0;
591  }
593  virtual XMLUnknown* ToUnknown() {
594  return 0;
595  }
596 
597  virtual const XMLElement* ToElement() const {
598  return 0;
599  }
600  virtual const XMLText* ToText() const {
601  return 0;
602  }
603  virtual const XMLComment* ToComment() const {
604  return 0;
605  }
606  virtual const XMLDocument* ToDocument() const {
607  return 0;
608  }
609  virtual const XMLDeclaration* ToDeclaration() const {
610  return 0;
611  }
612  virtual const XMLUnknown* ToUnknown() const {
613  return 0;
614  }
615 
625  const char* Value() const {
626  return _value.GetStr();
627  }
628 
632  void SetValue( const char* val, bool staticMem=false );
633 
635  const XMLNode* Parent() const {
636  return _parent;
637  }
638 
639  XMLNode* Parent() {
640  return _parent;
641  }
642 
644  bool NoChildren() const {
645  return !_firstChild;
646  }
647 
649  const XMLNode* FirstChild() const {
650  return _firstChild;
651  }
652 
653  XMLNode* FirstChild() {
654  return _firstChild;
655  }
656 
660  const XMLElement* FirstChildElement( const char* value=0 ) const;
661 
662  XMLElement* FirstChildElement( const char* value=0 ) {
663  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
664  }
665 
667  const XMLNode* LastChild() const {
668  return _lastChild;
669  }
670 
671  XMLNode* LastChild() {
672  return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
673  }
674 
678  const XMLElement* LastChildElement( const char* value=0 ) const;
679 
680  XMLElement* LastChildElement( const char* value=0 ) {
681  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
682  }
683 
685  const XMLNode* PreviousSibling() const {
686  return _prev;
687  }
688 
689  XMLNode* PreviousSibling() {
690  return _prev;
691  }
692 
694  const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
695 
696  XMLElement* PreviousSiblingElement( const char* value=0 ) {
697  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
698  }
699 
701  const XMLNode* NextSibling() const {
702  return _next;
703  }
704 
705  XMLNode* NextSibling() {
706  return _next;
707  }
708 
710  const XMLElement* NextSiblingElement( const char* value=0 ) const;
711 
712  XMLElement* NextSiblingElement( const char* value=0 ) {
713  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
714  }
715 
719  XMLNode* InsertEndChild( XMLNode* addThis );
720 
721  XMLNode* LinkEndChild( XMLNode* addThis ) {
722  return InsertEndChild( addThis );
723  }
727  XMLNode* InsertFirstChild( XMLNode* addThis );
731  XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
732 
736  void DeleteChildren();
737 
741  void DeleteChild( XMLNode* node );
742 
752  virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
753 
760  virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
761 
784  virtual bool Accept( XMLVisitor* visitor ) const = 0;
785 
786  // internal
787  virtual char* ParseDeep( char*, StrPair* );
788 
789 protected:
790  XMLNode( XMLDocument* );
791  virtual ~XMLNode();
792  XMLNode( const XMLNode& ); // not supported
793  XMLNode& operator=( const XMLNode& ); // not supported
794 
795  XMLDocument* _document;
796  XMLNode* _parent;
797  mutable StrPair _value;
798 
799  XMLNode* _firstChild;
800  XMLNode* _lastChild;
801 
802  XMLNode* _prev;
803  XMLNode* _next;
804 
805 private:
806  MemPool* _memPool;
807  void Unlink( XMLNode* child );
808 };
809 
810 
823 class XMLText : public XMLNode
824 {
825  friend class XMLBase;
826  friend class XMLDocument;
827 public:
828  virtual bool Accept( XMLVisitor* visitor ) const;
829 
830  virtual XMLText* ToText() {
831  return this;
832  }
833  virtual const XMLText* ToText() const {
834  return this;
835  }
836 
838  void SetCData( bool isCData ) {
839  _isCData = isCData;
840  }
842  bool CData() const {
843  return _isCData;
844  }
845 
846  char* ParseDeep( char*, StrPair* endTag );
847  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
848  virtual bool ShallowEqual( const XMLNode* compare ) const;
849 
850 protected:
851  XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
852  virtual ~XMLText() {}
853  XMLText( const XMLText& ); // not supported
854  XMLText& operator=( const XMLText& ); // not supported
855 
856 private:
857  bool _isCData;
858 };
859 
860 
862 class XMLComment : public XMLNode
863 {
864  friend class XMLDocument;
865 public:
866  virtual XMLComment* ToComment() {
867  return this;
868  }
869  virtual const XMLComment* ToComment() const {
870  return this;
871  }
872 
873  virtual bool Accept( XMLVisitor* visitor ) const;
874 
875  char* ParseDeep( char*, StrPair* endTag );
876  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
877  virtual bool ShallowEqual( const XMLNode* compare ) const;
878 
879 protected:
880  XMLComment( XMLDocument* doc );
881  virtual ~XMLComment();
882  XMLComment( const XMLComment& ); // not supported
883  XMLComment& operator=( const XMLComment& ); // not supported
884 
885 private:
886 };
887 
888 
900 class XMLDeclaration : public XMLNode
901 {
902  friend class XMLDocument;
903 public:
905  return this;
906  }
907  virtual const XMLDeclaration* ToDeclaration() const {
908  return this;
909  }
910 
911  virtual bool Accept( XMLVisitor* visitor ) const;
912 
913  char* ParseDeep( char*, StrPair* endTag );
914  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
915  virtual bool ShallowEqual( const XMLNode* compare ) const;
916 
917 protected:
918  XMLDeclaration( XMLDocument* doc );
919  virtual ~XMLDeclaration();
920  XMLDeclaration( const XMLDeclaration& ); // not supported
921  XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
922 };
923 
924 
932 class XMLUnknown : public XMLNode
933 {
934  friend class XMLDocument;
935 public:
936  virtual XMLUnknown* ToUnknown() {
937  return this;
938  }
939  virtual const XMLUnknown* ToUnknown() const {
940  return this;
941  }
942 
943  virtual bool Accept( XMLVisitor* visitor ) const;
944 
945  char* ParseDeep( char*, StrPair* endTag );
946  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947  virtual bool ShallowEqual( const XMLNode* compare ) const;
948 
949 protected:
950  XMLUnknown( XMLDocument* doc );
951  virtual ~XMLUnknown();
952  XMLUnknown( const XMLUnknown& ); // not supported
953  XMLUnknown& operator=( const XMLUnknown& ); // not supported
954 };
955 
956 
957 enum XMLError {
958  XML_NO_ERROR = 0,
959  XML_SUCCESS = 0,
960 
961  XML_NO_ATTRIBUTE,
962  XML_WRONG_ATTRIBUTE_TYPE,
963 
964  XML_ERROR_FILE_NOT_FOUND,
965  XML_ERROR_FILE_COULD_NOT_BE_OPENED,
966  XML_ERROR_FILE_READ_ERROR,
967  XML_ERROR_ELEMENT_MISMATCH,
968  XML_ERROR_PARSING_ELEMENT,
969  XML_ERROR_PARSING_ATTRIBUTE,
970  XML_ERROR_IDENTIFYING_TAG,
971  XML_ERROR_PARSING_TEXT,
972  XML_ERROR_PARSING_CDATA,
973  XML_ERROR_PARSING_COMMENT,
974  XML_ERROR_PARSING_DECLARATION,
975  XML_ERROR_PARSING_UNKNOWN,
976  XML_ERROR_EMPTY_DOCUMENT,
977  XML_ERROR_MISMATCHED_ELEMENT,
978  XML_ERROR_PARSING,
979 
980  XML_CAN_NOT_CONVERT_TEXT,
981  XML_NO_TEXT_NODE
982 };
983 
984 
992 {
993  friend class XMLElement;
994 public:
996  const char* Name() const {
997  return _name.GetStr();
998  }
1000  const char* Value() const {
1001  return _value.GetStr();
1002  }
1004  const XMLAttribute* Next() const {
1005  return _next;
1006  }
1007 
1012  int IntValue() const {
1013  int i=0;
1014  QueryIntValue( &i );
1015  return i;
1016  }
1018  unsigned UnsignedValue() const {
1019  unsigned i=0;
1020  QueryUnsignedValue( &i );
1021  return i;
1022  }
1024  bool BoolValue() const {
1025  bool b=false;
1026  QueryBoolValue( &b );
1027  return b;
1028  }
1030  double DoubleValue() const {
1031  double d=0;
1032  QueryDoubleValue( &d );
1033  return d;
1034  }
1036  float FloatValue() const {
1037  float f=0;
1038  QueryFloatValue( &f );
1039  return f;
1040  }
1041 
1046  XMLError QueryIntValue( int* value ) const;
1048  XMLError QueryUnsignedValue( unsigned int* value ) const;
1050  XMLError QueryBoolValue( bool* value ) const;
1052  XMLError QueryDoubleValue( double* value ) const;
1054  XMLError QueryFloatValue( float* value ) const;
1055 
1057  void SetAttribute( const char* value );
1059  void SetAttribute( int value );
1061  void SetAttribute( unsigned value );
1063  void SetAttribute( bool value );
1065  void SetAttribute( double value );
1067  void SetAttribute( float value );
1068 
1069 private:
1070  enum { BUF_SIZE = 200 };
1071 
1072  XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
1073  virtual ~XMLAttribute() {}
1074 
1075  XMLAttribute( const XMLAttribute& ); // not supported
1076  void operator=( const XMLAttribute& ); // not supported
1077  void SetName( const char* name );
1078 
1079  char* ParseDeep( char* p, bool processEntities );
1080 
1081  mutable StrPair _name;
1082  mutable StrPair _value;
1083  XMLAttribute* _next;
1084  MemPool* _memPool;
1085 };
1086 
1087 
1092 class XMLElement : public XMLNode
1093 {
1094  friend class XMLBase;
1095  friend class XMLDocument;
1096 public:
1098  const char* Name() const {
1099  return Value();
1100  }
1102  void SetName( const char* str, bool staticMem=false ) {
1103  SetValue( str, staticMem );
1104  }
1105 
1106  virtual XMLElement* ToElement() {
1107  return this;
1108  }
1109  virtual const XMLElement* ToElement() const {
1110  return this;
1111  }
1112  virtual bool Accept( XMLVisitor* visitor ) const;
1113 
1137  const char* Attribute( const char* name, const char* value=0 ) const;
1138 
1144  int IntAttribute( const char* name ) const {
1145  int i=0;
1146  QueryIntAttribute( name, &i );
1147  return i;
1148  }
1150  unsigned UnsignedAttribute( const char* name ) const {
1151  unsigned i=0;
1152  QueryUnsignedAttribute( name, &i );
1153  return i;
1154  }
1156  bool BoolAttribute( const char* name ) const {
1157  bool b=false;
1158  QueryBoolAttribute( name, &b );
1159  return b;
1160  }
1162  double DoubleAttribute( const char* name ) const {
1163  double d=0;
1164  QueryDoubleAttribute( name, &d );
1165  return d;
1166  }
1168  float FloatAttribute( const char* name ) const {
1169  float f=0;
1170  QueryFloatAttribute( name, &f );
1171  return f;
1172  }
1173 
1187  XMLError QueryIntAttribute( const char* name, int* value ) const {
1188  const XMLAttribute* a = FindAttribute( name );
1189  if ( !a ) {
1190  return XML_NO_ATTRIBUTE;
1191  }
1192  return a->QueryIntValue( value );
1193  }
1195  XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
1196  const XMLAttribute* a = FindAttribute( name );
1197  if ( !a ) {
1198  return XML_NO_ATTRIBUTE;
1199  }
1200  return a->QueryUnsignedValue( value );
1201  }
1203  XMLError QueryBoolAttribute( const char* name, bool* value ) const {
1204  const XMLAttribute* a = FindAttribute( name );
1205  if ( !a ) {
1206  return XML_NO_ATTRIBUTE;
1207  }
1208  return a->QueryBoolValue( value );
1209  }
1211  XMLError QueryDoubleAttribute( const char* name, double* value ) const {
1212  const XMLAttribute* a = FindAttribute( name );
1213  if ( !a ) {
1214  return XML_NO_ATTRIBUTE;
1215  }
1216  return a->QueryDoubleValue( value );
1217  }
1219  XMLError QueryFloatAttribute( const char* name, float* value ) const {
1220  const XMLAttribute* a = FindAttribute( name );
1221  if ( !a ) {
1222  return XML_NO_ATTRIBUTE;
1223  }
1224  return a->QueryFloatValue( value );
1225  }
1226 
1227 
1245  int QueryAttribute( const char* name, int* value ) const {
1246  return QueryIntAttribute( name, value );
1247  }
1248 
1249  int QueryAttribute( const char* name, unsigned int* value ) const {
1250  return QueryUnsignedAttribute( name, value );
1251  }
1252 
1253  int QueryAttribute( const char* name, bool* value ) const {
1254  return QueryBoolAttribute( name, value );
1255  }
1256 
1257  int QueryAttribute( const char* name, double* value ) const {
1258  return QueryDoubleAttribute( name, value );
1259  }
1260 
1261  int QueryAttribute( const char* name, float* value ) const {
1262  return QueryFloatAttribute( name, value );
1263  }
1264 
1266  void SetAttribute( const char* name, const char* value ) {
1267  XMLAttribute* a = FindOrCreateAttribute( name );
1268  a->SetAttribute( value );
1269  }
1271  void SetAttribute( const char* name, int value ) {
1272  XMLAttribute* a = FindOrCreateAttribute( name );
1273  a->SetAttribute( value );
1274  }
1276  void SetAttribute( const char* name, unsigned value ) {
1277  XMLAttribute* a = FindOrCreateAttribute( name );
1278  a->SetAttribute( value );
1279  }
1281  void SetAttribute( const char* name, bool value ) {
1282  XMLAttribute* a = FindOrCreateAttribute( name );
1283  a->SetAttribute( value );
1284  }
1286  void SetAttribute( const char* name, double value ) {
1287  XMLAttribute* a = FindOrCreateAttribute( name );
1288  a->SetAttribute( value );
1289  }
1290 
1294  void DeleteAttribute( const char* name );
1295 
1297  const XMLAttribute* FirstAttribute() const {
1298  return _rootAttribute;
1299  }
1301  const XMLAttribute* FindAttribute( const char* name ) const;
1302 
1331  const char* GetText() const;
1332 
1359  XMLError QueryIntText( int* ival ) const;
1361  XMLError QueryUnsignedText( unsigned* uval ) const;
1363  XMLError QueryBoolText( bool* bval ) const;
1365  XMLError QueryDoubleText( double* dval ) const;
1367  XMLError QueryFloatText( float* fval ) const;
1368 
1369  // internal:
1370  enum {
1371  OPEN, // <foo>
1372  CLOSED, // <foo/>
1373  CLOSING // </foo>
1374  };
1375  int ClosingType() const {
1376  return _closingType;
1377  }
1378  char* ParseDeep( char* p, StrPair* endTag );
1379  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1380  virtual bool ShallowEqual( const XMLNode* compare ) const;
1381 
1382 private:
1383  XMLElement( XMLDocument* doc );
1384  virtual ~XMLElement();
1385  XMLElement( const XMLElement& ); // not supported
1386  void operator=( const XMLElement& ); // not supported
1387 
1388  XMLAttribute* FindAttribute( const char* name );
1389  XMLAttribute* FindOrCreateAttribute( const char* name );
1390  //void LinkAttribute( XMLAttribute* attrib );
1391  char* ParseAttributes( char* p );
1392 
1393  int _closingType;
1394  // The attribute list is ordered; there is no 'lastAttribute'
1395  // because the list needs to be scanned for dupes before adding
1396  // a new attribute.
1397  XMLAttribute* _rootAttribute;
1398 };
1399 
1400 
1401 enum Whitespace {
1402  PRESERVE_WHITESPACE,
1403  COLLAPSE_WHITESPACE
1404 };
1405 
1406 
1412 class XMLDocument : public XMLNode
1413 {
1414  friend class XMLElement;
1415 public:
1417  XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1418  ~XMLDocument();
1419 
1421  return this;
1422  }
1423  virtual const XMLDocument* ToDocument() const {
1424  return this;
1425  }
1426 
1437  XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
1438 
1444  XMLError LoadFile( const char* filename );
1445 
1453  XMLError LoadFile( FILE* );
1454 
1460  XMLError SaveFile( const char* filename, bool compact = false );
1461 
1469  XMLError SaveFile( FILE* fp, bool compact = false );
1470 
1471  bool ProcessEntities() const {
1472  return _processEntities;
1473  }
1474  Whitespace WhitespaceMode() const {
1475  return _whitespace;
1476  }
1477 
1481  bool HasBOM() const {
1482  return _writeBOM;
1483  }
1486  void SetBOM( bool useBOM ) {
1487  _writeBOM = useBOM;
1488  }
1489 
1494  return FirstChildElement();
1495  }
1496  const XMLElement* RootElement() const {
1497  return FirstChildElement();
1498  }
1499 
1514  void Print( XMLPrinter* streamer=0 );
1515  virtual bool Accept( XMLVisitor* visitor ) const;
1516 
1522  XMLElement* NewElement( const char* name );
1528  XMLComment* NewComment( const char* comment );
1534  XMLText* NewText( const char* text );
1546  XMLDeclaration* NewDeclaration( const char* text=0 );
1552  XMLUnknown* NewUnknown( const char* text );
1553 
1558  void DeleteNode( XMLNode* node ) {
1559  node->_parent->DeleteChild( node );
1560  }
1561 
1562  void SetError( XMLError error, const char* str1, const char* str2 );
1563 
1565  bool Error() const {
1566  return _errorID != XML_NO_ERROR;
1567  }
1569  XMLError ErrorID() const {
1570  return _errorID;
1571  }
1573  const char* GetErrorStr1() const {
1574  return _errorStr1;
1575  }
1577  const char* GetErrorStr2() const {
1578  return _errorStr2;
1579  }
1581  void PrintError() const;
1582 
1584  void Clear();
1585 
1586  // internal
1587  char* Identify( char* p, XMLNode** node );
1588 
1589  virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1590  return 0;
1591  }
1592  virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1593  return false;
1594  }
1595 
1596 private:
1597  XMLDocument( const XMLDocument& ); // not supported
1598  void operator=( const XMLDocument& ); // not supported
1599 
1600  bool _writeBOM;
1601  bool _processEntities;
1602  XMLError _errorID;
1603  Whitespace _whitespace;
1604  const char* _errorStr1;
1605  const char* _errorStr2;
1606  char* _charBuffer;
1607 
1608  MemPoolT< sizeof(XMLElement) > _elementPool;
1609  MemPoolT< sizeof(XMLAttribute) > _attributePool;
1610  MemPoolT< sizeof(XMLText) > _textPool;
1611  MemPoolT< sizeof(XMLComment) > _commentPool;
1612 };
1613 
1614 
1671 {
1672 public:
1674  XMLHandle( XMLNode* node ) {
1675  _node = node;
1676  }
1678  XMLHandle( XMLNode& node ) {
1679  _node = &node;
1680  }
1682  XMLHandle( const XMLHandle& ref ) {
1683  _node = ref._node;
1684  }
1686  XMLHandle& operator=( const XMLHandle& ref ) {
1687  _node = ref._node;
1688  return *this;
1689  }
1690 
1693  return XMLHandle( _node ? _node->FirstChild() : 0 );
1694  }
1696  XMLHandle FirstChildElement( const char* value=0 ) {
1697  return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
1698  }
1701  return XMLHandle( _node ? _node->LastChild() : 0 );
1702  }
1704  XMLHandle LastChildElement( const char* _value=0 ) {
1705  return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
1706  }
1709  return XMLHandle( _node ? _node->PreviousSibling() : 0 );
1710  }
1712  XMLHandle PreviousSiblingElement( const char* _value=0 ) {
1713  return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
1714  }
1717  return XMLHandle( _node ? _node->NextSibling() : 0 );
1718  }
1720  XMLHandle NextSiblingElement( const char* _value=0 ) {
1721  return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
1722  }
1723 
1726  return _node;
1727  }
1730  return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
1731  }
1734  return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
1735  }
1738  return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
1739  }
1742  return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
1743  }
1744 
1745 private:
1746  XMLNode* _node;
1747 };
1748 
1749 
1755 {
1756 public:
1757  XMLConstHandle( const XMLNode* node ) {
1758  _node = node;
1759  }
1760  XMLConstHandle( const XMLNode& node ) {
1761  _node = &node;
1762  }
1763  XMLConstHandle( const XMLConstHandle& ref ) {
1764  _node = ref._node;
1765  }
1766 
1767  XMLConstHandle& operator=( const XMLConstHandle& ref ) {
1768  _node = ref._node;
1769  return *this;
1770  }
1771 
1772  const XMLConstHandle FirstChild() const {
1773  return XMLConstHandle( _node ? _node->FirstChild() : 0 );
1774  }
1775  const XMLConstHandle FirstChildElement( const char* value=0 ) const {
1776  return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
1777  }
1778  const XMLConstHandle LastChild() const {
1779  return XMLConstHandle( _node ? _node->LastChild() : 0 );
1780  }
1781  const XMLConstHandle LastChildElement( const char* _value=0 ) const {
1782  return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
1783  }
1784  const XMLConstHandle PreviousSibling() const {
1785  return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
1786  }
1787  const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
1788  return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
1789  }
1790  const XMLConstHandle NextSibling() const {
1791  return XMLConstHandle( _node ? _node->NextSibling() : 0 );
1792  }
1793  const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
1794  return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
1795  }
1796 
1797 
1798  const XMLNode* ToNode() const {
1799  return _node;
1800  }
1801  const XMLElement* ToElement() const {
1802  return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
1803  }
1804  const XMLText* ToText() const {
1805  return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
1806  }
1807  const XMLUnknown* ToUnknown() const {
1808  return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
1809  }
1810  const XMLDeclaration* ToDeclaration() const {
1811  return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
1812  }
1813 
1814 private:
1815  const XMLNode* _node;
1816 };
1817 
1818 
1861 class XMLPrinter : public XMLVisitor
1862 {
1863 public:
1870  XMLPrinter( FILE* file=0, bool compact = false );
1871  ~XMLPrinter() {}
1872 
1874  void PushHeader( bool writeBOM, bool writeDeclaration );
1878  void OpenElement( const char* name );
1880  void PushAttribute( const char* name, const char* value );
1881  void PushAttribute( const char* name, int value );
1882  void PushAttribute( const char* name, unsigned value );
1883  void PushAttribute( const char* name, bool value );
1884  void PushAttribute( const char* name, double value );
1886  void CloseElement();
1887 
1889  void PushText( const char* text, bool cdata=false );
1891  void PushText( int value );
1893  void PushText( unsigned value );
1895  void PushText( bool value );
1897  void PushText( float value );
1899  void PushText( double value );
1900 
1902  void PushComment( const char* comment );
1903 
1904  void PushDeclaration( const char* value );
1905  void PushUnknown( const char* value );
1906 
1907  virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1908  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1909  return true;
1910  }
1911 
1912  virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1913  virtual bool VisitExit( const XMLElement& element );
1914 
1915  virtual bool Visit( const XMLText& text );
1916  virtual bool Visit( const XMLComment& comment );
1917  virtual bool Visit( const XMLDeclaration& declaration );
1918  virtual bool Visit( const XMLUnknown& unknown );
1919 
1924  const char* CStr() const {
1925  return _buffer.Mem();
1926  }
1932  int CStrSize() const {
1933  return _buffer.Size();
1934  }
1935 
1936 private:
1937  void SealElement();
1938  void PrintSpace( int depth );
1939  void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1940  void Print( const char* format, ... );
1941 
1942  bool _elementJustOpened;
1943  bool _firstElement;
1944  FILE* _fp;
1945  int _depth;
1946  int _textDepth;
1947  bool _processEntities;
1948  bool _compactMode;
1949 
1950  enum {
1951  ENTITY_RANGE = 64,
1952  BUF_SIZE = 200
1953  };
1954  bool _entityFlag[ENTITY_RANGE];
1955  bool _restrictedEntityFlag[ENTITY_RANGE];
1956 
1957  DynArray< const char*, 10 > _stack;
1958  DynArray< char, 20 > _buffer;
1959 #ifdef _MSC_VER
1960  DynArray< char, 20 > _accumulator;
1961 #endif
1962 };
1963 
1964 
1965 } // tinyxml2
1966 
1967 
1968 #endif // TINYXML2_INCLUDED