CMU462 Library Documentation  1.0
15-462/15-662: Computer Graphics (Fall 2015)
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 # 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 #ifdef _MSC_VER
61 # pragma warning(push)
62 # pragma warning(disable: 4251)
63 #endif
64 
65 #ifdef _WIN32
66 # ifdef TINYXML2_EXPORT
67 # define TINYXML2_LIB __declspec(dllexport)
68 # elif defined(TINYXML2_IMPORT)
69 # define TINYXML2_LIB __declspec(dllimport)
70 # else
71 # define TINYXML2_LIB
72 # endif
73 #else
74 # define TINYXML2_LIB
75 #endif
76 
77 
78 #if defined(DEBUG)
79 # if defined(_MSC_VER)
80 # // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
81 # define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
82 # elif defined (ANDROID_NDK)
83 # include <android/log.h>
84 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85 # else
86 # include <assert.h>
87 # define TIXMLASSERT assert
88 # endif
89 # else
90 # define TIXMLASSERT( x ) {}
91 #endif
92 
93 
94 /* Versioning, past 1.0.14:
95  http://semver.org/
96 */
97 static const int TIXML2_MAJOR_VERSION = 3;
98 static const int TIXML2_MINOR_VERSION = 0;
99 static const int TIXML2_PATCH_VERSION = 0;
100 
101 namespace tinyxml2
102 {
103 class XMLDocument;
104 class XMLElement;
105 class XMLAttribute;
106 class XMLComment;
107 class XMLText;
108 class XMLDeclaration;
109 class XMLUnknown;
110 class XMLPrinter;
111 
112 /*
113  A class that wraps strings. Normally stores the start and end
114  pointers into the XML file itself, and will apply normalization
115  and entity translation if actually read. Can also store (and memory
116  manage) a traditional char[]
117 */
118 class StrPair
119 {
120 public:
121  enum {
122  NEEDS_ENTITY_PROCESSING = 0x01,
123  NEEDS_NEWLINE_NORMALIZATION = 0x02,
124  NEEDS_WHITESPACE_COLLAPSING = 0x04,
125 
126  TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
127  TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
128  ATTRIBUTE_NAME = 0,
129  ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
130  ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
131  COMMENT = NEEDS_NEWLINE_NORMALIZATION
132  };
133 
134  StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
135  ~StrPair();
136 
137  void Set( char* start, char* end, int flags ) {
138  Reset();
139  _start = start;
140  _end = end;
141  _flags = flags | NEEDS_FLUSH;
142  }
143 
144  const char* GetStr();
145 
146  bool Empty() const {
147  return _start == _end;
148  }
149 
150  void SetInternedStr( const char* str ) {
151  Reset();
152  _start = const_cast<char*>(str);
153  }
154 
155  void SetStr( const char* str, int flags=0 );
156 
157  char* ParseText( char* in, const char* endTag, int strFlags );
158  char* ParseName( char* in );
159 
160  void TransferTo( StrPair* other );
161 
162 private:
163  void Reset();
164  void CollapseWhitespace();
165 
166  enum {
167  NEEDS_FLUSH = 0x100,
168  NEEDS_DELETE = 0x200
169  };
170 
171  // After parsing, if *_end != 0, it can be set to zero.
172  int _flags;
173  char* _start;
174  char* _end;
175 
176  StrPair( const StrPair& other ); // not supported
177  void operator=( StrPair& other ); // not supported, use TransferTo()
178 };
179 
180 
181 /*
182  A dynamic array of Plain Old Data. Doesn't support constructors, etc.
183  Has a small initial memory pool, so that low or no usage will not
184  cause a call to new/delete
185 */
186 template <class T, int INITIAL_SIZE>
187 class DynArray
188 {
189 public:
190  DynArray() {
191  _mem = _pool;
192  _allocated = INITIAL_SIZE;
193  _size = 0;
194  }
195 
196  ~DynArray() {
197  if ( _mem != _pool ) {
198  delete [] _mem;
199  }
200  }
201 
202  void Clear() {
203  _size = 0;
204  }
205 
206  void Push( T t ) {
207  TIXMLASSERT( _size < INT_MAX );
208  EnsureCapacity( _size+1 );
209  _mem[_size++] = t;
210  }
211 
212  T* PushArr( int count ) {
213  TIXMLASSERT( count >= 0 );
214  TIXMLASSERT( _size <= INT_MAX - count );
215  EnsureCapacity( _size+count );
216  T* ret = &_mem[_size];
217  _size += count;
218  return ret;
219  }
220 
221  T Pop() {
222  TIXMLASSERT( _size > 0 );
223  return _mem[--_size];
224  }
225 
226  void PopArr( int count ) {
227  TIXMLASSERT( _size >= count );
228  _size -= count;
229  }
230 
231  bool Empty() const {
232  return _size == 0;
233  }
234 
235  T& operator[](int i) {
236  TIXMLASSERT( i>= 0 && i < _size );
237  return _mem[i];
238  }
239 
240  const T& operator[](int i) const {
241  TIXMLASSERT( i>= 0 && i < _size );
242  return _mem[i];
243  }
244 
245  const T& PeekTop() const {
246  TIXMLASSERT( _size > 0 );
247  return _mem[ _size - 1];
248  }
249 
250  int Size() const {
251  TIXMLASSERT( _size >= 0 );
252  return _size;
253  }
254 
255  int Capacity() const {
256  TIXMLASSERT( _allocated >= INITIAL_SIZE );
257  return _allocated;
258  }
259 
260  const T* Mem() const {
261  TIXMLASSERT( _mem );
262  return _mem;
263  }
264 
265  T* Mem() {
266  TIXMLASSERT( _mem );
267  return _mem;
268  }
269 
270 private:
271  DynArray( const DynArray& ); // not supported
272  void operator=( const DynArray& ); // not supported
273 
274  void EnsureCapacity( int cap ) {
275  TIXMLASSERT( cap > 0 );
276  if ( cap > _allocated ) {
277  TIXMLASSERT( cap <= INT_MAX / 2 );
278  int newAllocated = cap * 2;
279  T* newMem = new T[newAllocated];
280  memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
281  if ( _mem != _pool ) {
282  delete [] _mem;
283  }
284  _mem = newMem;
285  _allocated = newAllocated;
286  }
287  }
288 
289  T* _mem;
290  T _pool[INITIAL_SIZE];
291  int _allocated; // objects allocated
292  int _size; // number objects in use
293 };
294 
295 
296 /*
297  Parent virtual class of a pool for fast allocation
298  and deallocation of objects.
299 */
300 class MemPool
301 {
302 public:
303  MemPool() {}
304  virtual ~MemPool() {}
305 
306  virtual int ItemSize() const = 0;
307  virtual void* Alloc() = 0;
308  virtual void Free( void* ) = 0;
309  virtual void SetTracked() = 0;
310  virtual void Clear() = 0;
311 };
312 
313 
314 /*
315  Template child class to create pools of the correct type.
316 */
317 template< int SIZE >
318 class MemPoolT : public MemPool
319 {
320 public:
321  MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
322  ~MemPoolT() {
323  Clear();
324  }
325 
326  void Clear() {
327  // Delete the blocks.
328  while( !_blockPtrs.Empty()) {
329  Block* b = _blockPtrs.Pop();
330  delete b;
331  }
332  _root = 0;
333  _currentAllocs = 0;
334  _nAllocs = 0;
335  _maxAllocs = 0;
336  _nUntracked = 0;
337  }
338 
339  virtual int ItemSize() const {
340  return SIZE;
341  }
342  int CurrentAllocs() const {
343  return _currentAllocs;
344  }
345 
346  virtual void* Alloc() {
347  if ( !_root ) {
348  // Need a new block.
349  Block* block = new Block();
350  _blockPtrs.Push( block );
351 
352  for( int i=0; i<COUNT-1; ++i ) {
353  block->chunk[i].next = &block->chunk[i+1];
354  }
355  block->chunk[COUNT-1].next = 0;
356  _root = block->chunk;
357  }
358  void* result = _root;
359  _root = _root->next;
360 
361  ++_currentAllocs;
362  if ( _currentAllocs > _maxAllocs ) {
363  _maxAllocs = _currentAllocs;
364  }
365  _nAllocs++;
366  _nUntracked++;
367  return result;
368  }
369 
370  virtual void Free( void* mem ) {
371  if ( !mem ) {
372  return;
373  }
374  --_currentAllocs;
375  Chunk* chunk = static_cast<Chunk*>( mem );
376 #ifdef DEBUG
377  memset( chunk, 0xfe, sizeof(Chunk) );
378 #endif
379  chunk->next = _root;
380  _root = chunk;
381  }
382  void Trace( const char* name ) {
383  printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
384  name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
385  }
386 
387  void SetTracked() {
388  _nUntracked--;
389  }
390 
391  int Untracked() const {
392  return _nUntracked;
393  }
394 
395  // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
396  // The test file is large, 170k.
397  // Release: VS2010 gcc(no opt)
398  // 1k: 4000
399  // 2k: 4000
400  // 4k: 3900 21000
401  // 16k: 5200
402  // 32k: 4300
403  // 64k: 4000 21000
404  enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
405 
406 private:
407  MemPoolT( const MemPoolT& ); // not supported
408  void operator=( const MemPoolT& ); // not supported
409 
410  union Chunk {
411  Chunk* next;
412  char mem[SIZE];
413  };
414  struct Block {
415  Chunk chunk[COUNT];
416  };
417  DynArray< Block*, 10 > _blockPtrs;
418  Chunk* _root;
419 
420  int _currentAllocs;
421  int _nAllocs;
422  int _maxAllocs;
423  int _nUntracked;
424 };
425 
426 
427 
447 class TINYXML2_LIB XMLVisitor
448 {
449 public:
450  virtual ~XMLVisitor() {}
451 
453  virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
454  return true;
455  }
457  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
458  return true;
459  }
460 
462  virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
463  return true;
464  }
466  virtual bool VisitExit( const XMLElement& /*element*/ ) {
467  return true;
468  }
469 
471  virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
472  return true;
473  }
475  virtual bool Visit( const XMLText& /*text*/ ) {
476  return true;
477  }
479  virtual bool Visit( const XMLComment& /*comment*/ ) {
480  return true;
481  }
483  virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
484  return true;
485  }
486 };
487 
488 // WARNING: must match XMLDocument::_errorNames[]
489 enum XMLError {
490  XML_SUCCESS = 0,
491  XML_NO_ERROR = 0,
492  XML_NO_ATTRIBUTE,
493  XML_WRONG_ATTRIBUTE_TYPE,
494  XML_ERROR_FILE_NOT_FOUND,
495  XML_ERROR_FILE_COULD_NOT_BE_OPENED,
496  XML_ERROR_FILE_READ_ERROR,
497  XML_ERROR_ELEMENT_MISMATCH,
498  XML_ERROR_PARSING_ELEMENT,
499  XML_ERROR_PARSING_ATTRIBUTE,
500  XML_ERROR_IDENTIFYING_TAG,
501  XML_ERROR_PARSING_TEXT,
502  XML_ERROR_PARSING_CDATA,
503  XML_ERROR_PARSING_COMMENT,
504  XML_ERROR_PARSING_DECLARATION,
505  XML_ERROR_PARSING_UNKNOWN,
506  XML_ERROR_EMPTY_DOCUMENT,
507  XML_ERROR_MISMATCHED_ELEMENT,
508  XML_ERROR_PARSING,
509  XML_CAN_NOT_CONVERT_TEXT,
510  XML_NO_TEXT_NODE,
511 
512  XML_ERROR_COUNT
513 };
514 
515 
516 /*
517  Utility functionality.
518 */
519 class XMLUtil
520 {
521 public:
522  static const char* SkipWhiteSpace( const char* p ) {
523  TIXMLASSERT( p );
524  while( IsWhiteSpace(*p) ) {
525  ++p;
526  }
527  TIXMLASSERT( p );
528  return p;
529  }
530  static char* SkipWhiteSpace( char* p ) {
531  return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
532  }
533 
534  // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
535  // correct, but simple, and usually works.
536  static bool IsWhiteSpace( char p ) {
537  return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
538  }
539 
540  inline static bool IsNameStartChar( unsigned char ch ) {
541  if ( ch >= 128 ) {
542  // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
543  return true;
544  }
545  if ( isalpha( ch ) ) {
546  return true;
547  }
548  return ch == ':' || ch == '_';
549  }
550 
551  inline static bool IsNameChar( unsigned char ch ) {
552  return IsNameStartChar( ch )
553  || isdigit( ch )
554  || ch == '.'
555  || ch == '-';
556  }
557 
558  inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
559  if ( p == q ) {
560  return true;
561  }
562  int n = 0;
563  while( *p && *q && *p == *q && n<nChar ) {
564  ++p;
565  ++q;
566  ++n;
567  }
568  if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
569  return true;
570  }
571  return false;
572  }
573 
574  inline static bool IsUTF8Continuation( char p ) {
575  return ( p & 0x80 ) != 0;
576  }
577 
578  static const char* ReadBOM( const char* p, bool* hasBOM );
579  // p is the starting location,
580  // the UTF-8 value of the entity will be placed in value, and length filled in.
581  static const char* GetCharacterRef( const char* p, char* value, int* length );
582  static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
583 
584  // converts primitive types to strings
585  static void ToStr( int v, char* buffer, int bufferSize );
586  static void ToStr( unsigned v, char* buffer, int bufferSize );
587  static void ToStr( bool v, char* buffer, int bufferSize );
588  static void ToStr( float v, char* buffer, int bufferSize );
589  static void ToStr( double v, char* buffer, int bufferSize );
590 
591  // converts strings to primitive types
592  static bool ToInt( const char* str, int* value );
593  static bool ToUnsigned( const char* str, unsigned* value );
594  static bool ToBool( const char* str, bool* value );
595  static bool ToFloat( const char* str, float* value );
596  static bool ToDouble( const char* str, double* value );
597 };
598 
599 
625 class TINYXML2_LIB XMLNode
626 {
627  friend class XMLDocument;
628  friend class XMLElement;
629 public:
630 
632  const XMLDocument* GetDocument() const {
633  TIXMLASSERT( _document );
634  return _document;
635  }
637  XMLDocument* GetDocument() {
638  TIXMLASSERT( _document );
639  return _document;
640  }
641 
643  virtual XMLElement* ToElement() {
644  return 0;
645  }
647  virtual XMLText* ToText() {
648  return 0;
649  }
651  virtual XMLComment* ToComment() {
652  return 0;
653  }
655  virtual XMLDocument* ToDocument() {
656  return 0;
657  }
659  virtual XMLDeclaration* ToDeclaration() {
660  return 0;
661  }
663  virtual XMLUnknown* ToUnknown() {
664  return 0;
665  }
666 
667  virtual const XMLElement* ToElement() const {
668  return 0;
669  }
670  virtual const XMLText* ToText() const {
671  return 0;
672  }
673  virtual const XMLComment* ToComment() const {
674  return 0;
675  }
676  virtual const XMLDocument* ToDocument() const {
677  return 0;
678  }
679  virtual const XMLDeclaration* ToDeclaration() const {
680  return 0;
681  }
682  virtual const XMLUnknown* ToUnknown() const {
683  return 0;
684  }
685 
695  const char* Value() const;
696 
700  void SetValue( const char* val, bool staticMem=false );
701 
703  const XMLNode* Parent() const {
704  return _parent;
705  }
706 
707  XMLNode* Parent() {
708  return _parent;
709  }
710 
712  bool NoChildren() const {
713  return !_firstChild;
714  }
715 
717  const XMLNode* FirstChild() const {
718  return _firstChild;
719  }
720 
721  XMLNode* FirstChild() {
722  return _firstChild;
723  }
724 
728  const XMLElement* FirstChildElement( const char* name = 0 ) const;
729 
730  XMLElement* FirstChildElement( const char* name = 0 ) {
731  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
732  }
733 
735  const XMLNode* LastChild() const {
736  return _lastChild;
737  }
738 
739  XMLNode* LastChild() {
740  return _lastChild;
741  }
742 
746  const XMLElement* LastChildElement( const char* name = 0 ) const;
747 
748  XMLElement* LastChildElement( const char* name = 0 ) {
749  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
750  }
751 
753  const XMLNode* PreviousSibling() const {
754  return _prev;
755  }
756 
757  XMLNode* PreviousSibling() {
758  return _prev;
759  }
760 
762  const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
763 
764  XMLElement* PreviousSiblingElement( const char* name = 0 ) {
765  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
766  }
767 
769  const XMLNode* NextSibling() const {
770  return _next;
771  }
772 
773  XMLNode* NextSibling() {
774  return _next;
775  }
776 
778  const XMLElement* NextSiblingElement( const char* name = 0 ) const;
779 
780  XMLElement* NextSiblingElement( const char* name = 0 ) {
781  return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
782  }
783 
791  XMLNode* InsertEndChild( XMLNode* addThis );
792 
793  XMLNode* LinkEndChild( XMLNode* addThis ) {
794  return InsertEndChild( addThis );
795  }
803  XMLNode* InsertFirstChild( XMLNode* addThis );
812  XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
813 
817  void DeleteChildren();
818 
822  void DeleteChild( XMLNode* node );
823 
833  virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
834 
841  virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
842 
865  virtual bool Accept( XMLVisitor* visitor ) const = 0;
866 
867 protected:
868  XMLNode( XMLDocument* );
869  virtual ~XMLNode();
870 
871  virtual char* ParseDeep( char*, StrPair* );
872 
873  XMLDocument* _document;
874  XMLNode* _parent;
875  mutable StrPair _value;
876 
877  XMLNode* _firstChild;
878  XMLNode* _lastChild;
879 
880  XMLNode* _prev;
881  XMLNode* _next;
882 
883 private:
884  MemPool* _memPool;
885  void Unlink( XMLNode* child );
886  static void DeleteNode( XMLNode* node );
887  void InsertChildPreamble( XMLNode* insertThis ) const;
888 
889  XMLNode( const XMLNode& ); // not supported
890  XMLNode& operator=( const XMLNode& ); // not supported
891 };
892 
893 
906 class TINYXML2_LIB XMLText : public XMLNode
907 {
908  friend class XMLBase;
909  friend class XMLDocument;
910 public:
911  virtual bool Accept( XMLVisitor* visitor ) const;
912 
913  virtual XMLText* ToText() {
914  return this;
915  }
916  virtual const XMLText* ToText() const {
917  return this;
918  }
919 
921  void SetCData( bool isCData ) {
922  _isCData = isCData;
923  }
925  bool CData() const {
926  return _isCData;
927  }
928 
929  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
930  virtual bool ShallowEqual( const XMLNode* compare ) const;
931 
932 protected:
933  XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
934  virtual ~XMLText() {}
935 
936  char* ParseDeep( char*, StrPair* endTag );
937 
938 private:
939  bool _isCData;
940 
941  XMLText( const XMLText& ); // not supported
942  XMLText& operator=( const XMLText& ); // not supported
943 };
944 
945 
947 class TINYXML2_LIB XMLComment : public XMLNode
948 {
949  friend class XMLDocument;
950 public:
951  virtual XMLComment* ToComment() {
952  return this;
953  }
954  virtual const XMLComment* ToComment() const {
955  return this;
956  }
957 
958  virtual bool Accept( XMLVisitor* visitor ) const;
959 
960  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
961  virtual bool ShallowEqual( const XMLNode* compare ) const;
962 
963 protected:
964  XMLComment( XMLDocument* doc );
965  virtual ~XMLComment();
966 
967  char* ParseDeep( char*, StrPair* endTag );
968 
969 private:
970  XMLComment( const XMLComment& ); // not supported
971  XMLComment& operator=( const XMLComment& ); // not supported
972 };
973 
974 
986 class TINYXML2_LIB XMLDeclaration : public XMLNode
987 {
988  friend class XMLDocument;
989 public:
990  virtual XMLDeclaration* ToDeclaration() {
991  return this;
992  }
993  virtual const XMLDeclaration* ToDeclaration() const {
994  return this;
995  }
996 
997  virtual bool Accept( XMLVisitor* visitor ) const;
998 
999  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1000  virtual bool ShallowEqual( const XMLNode* compare ) const;
1001 
1002 protected:
1003  XMLDeclaration( XMLDocument* doc );
1004  virtual ~XMLDeclaration();
1005 
1006  char* ParseDeep( char*, StrPair* endTag );
1007 
1008 private:
1009  XMLDeclaration( const XMLDeclaration& ); // not supported
1010  XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
1011 };
1012 
1013 
1021 class TINYXML2_LIB XMLUnknown : public XMLNode
1022 {
1023  friend class XMLDocument;
1024 public:
1025  virtual XMLUnknown* ToUnknown() {
1026  return this;
1027  }
1028  virtual const XMLUnknown* ToUnknown() const {
1029  return this;
1030  }
1031 
1032  virtual bool Accept( XMLVisitor* visitor ) const;
1033 
1034  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1035  virtual bool ShallowEqual( const XMLNode* compare ) const;
1036 
1037 protected:
1038  XMLUnknown( XMLDocument* doc );
1039  virtual ~XMLUnknown();
1040 
1041  char* ParseDeep( char*, StrPair* endTag );
1042 
1043 private:
1044  XMLUnknown( const XMLUnknown& ); // not supported
1045  XMLUnknown& operator=( const XMLUnknown& ); // not supported
1046 };
1047 
1048 
1049 
1056 class TINYXML2_LIB XMLAttribute
1057 {
1058  friend class XMLElement;
1059 public:
1061  const char* Name() const;
1062 
1064  const char* Value() const;
1065 
1067  const XMLAttribute* Next() const {
1068  return _next;
1069  }
1070 
1075  int IntValue() const {
1076  int i=0;
1077  QueryIntValue( &i );
1078  return i;
1079  }
1081  unsigned UnsignedValue() const {
1082  unsigned i=0;
1083  QueryUnsignedValue( &i );
1084  return i;
1085  }
1087  bool BoolValue() const {
1088  bool b=false;
1089  QueryBoolValue( &b );
1090  return b;
1091  }
1093  double DoubleValue() const {
1094  double d=0;
1095  QueryDoubleValue( &d );
1096  return d;
1097  }
1099  float FloatValue() const {
1100  float f=0;
1101  QueryFloatValue( &f );
1102  return f;
1103  }
1104 
1109  XMLError QueryIntValue( int* value ) const;
1111  XMLError QueryUnsignedValue( unsigned int* value ) const;
1113  XMLError QueryBoolValue( bool* value ) const;
1115  XMLError QueryDoubleValue( double* value ) const;
1117  XMLError QueryFloatValue( float* value ) const;
1118 
1120  void SetAttribute( const char* value );
1122  void SetAttribute( int value );
1124  void SetAttribute( unsigned value );
1126  void SetAttribute( bool value );
1128  void SetAttribute( double value );
1130  void SetAttribute( float value );
1131 
1132 private:
1133  enum { BUF_SIZE = 200 };
1134 
1135  XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
1136  virtual ~XMLAttribute() {}
1137 
1138  XMLAttribute( const XMLAttribute& ); // not supported
1139  void operator=( const XMLAttribute& ); // not supported
1140  void SetName( const char* name );
1141 
1142  char* ParseDeep( char* p, bool processEntities );
1143 
1144  mutable StrPair _name;
1145  mutable StrPair _value;
1146  XMLAttribute* _next;
1147  MemPool* _memPool;
1148 };
1149 
1150 
1155 class TINYXML2_LIB XMLElement : public XMLNode
1156 {
1157  friend class XMLBase;
1158  friend class XMLDocument;
1159 public:
1161  const char* Name() const {
1162  return Value();
1163  }
1165  void SetName( const char* str, bool staticMem=false ) {
1166  SetValue( str, staticMem );
1167  }
1168 
1169  virtual XMLElement* ToElement() {
1170  return this;
1171  }
1172  virtual const XMLElement* ToElement() const {
1173  return this;
1174  }
1175  virtual bool Accept( XMLVisitor* visitor ) const;
1176 
1200  const char* Attribute( const char* name, const char* value=0 ) const;
1201 
1207  int IntAttribute( const char* name ) const {
1208  int i=0;
1209  QueryIntAttribute( name, &i );
1210  return i;
1211  }
1213  unsigned UnsignedAttribute( const char* name ) const {
1214  unsigned i=0;
1215  QueryUnsignedAttribute( name, &i );
1216  return i;
1217  }
1219  bool BoolAttribute( const char* name ) const {
1220  bool b=false;
1221  QueryBoolAttribute( name, &b );
1222  return b;
1223  }
1225  double DoubleAttribute( const char* name ) const {
1226  double d=0;
1227  QueryDoubleAttribute( name, &d );
1228  return d;
1229  }
1231  float FloatAttribute( const char* name ) const {
1232  float f=0;
1233  QueryFloatAttribute( name, &f );
1234  return f;
1235  }
1236 
1250  XMLError QueryIntAttribute( const char* name, int* value ) const {
1251  const XMLAttribute* a = FindAttribute( name );
1252  if ( !a ) {
1253  return XML_NO_ATTRIBUTE;
1254  }
1255  return a->QueryIntValue( value );
1256  }
1258  XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
1259  const XMLAttribute* a = FindAttribute( name );
1260  if ( !a ) {
1261  return XML_NO_ATTRIBUTE;
1262  }
1263  return a->QueryUnsignedValue( value );
1264  }
1266  XMLError QueryBoolAttribute( const char* name, bool* value ) const {
1267  const XMLAttribute* a = FindAttribute( name );
1268  if ( !a ) {
1269  return XML_NO_ATTRIBUTE;
1270  }
1271  return a->QueryBoolValue( value );
1272  }
1274  XMLError QueryDoubleAttribute( const char* name, double* value ) const {
1275  const XMLAttribute* a = FindAttribute( name );
1276  if ( !a ) {
1277  return XML_NO_ATTRIBUTE;
1278  }
1279  return a->QueryDoubleValue( value );
1280  }
1282  XMLError QueryFloatAttribute( const char* name, float* value ) const {
1283  const XMLAttribute* a = FindAttribute( name );
1284  if ( !a ) {
1285  return XML_NO_ATTRIBUTE;
1286  }
1287  return a->QueryFloatValue( value );
1288  }
1289 
1290 
1308  int QueryAttribute( const char* name, int* value ) const {
1309  return QueryIntAttribute( name, value );
1310  }
1311 
1312  int QueryAttribute( const char* name, unsigned int* value ) const {
1313  return QueryUnsignedAttribute( name, value );
1314  }
1315 
1316  int QueryAttribute( const char* name, bool* value ) const {
1317  return QueryBoolAttribute( name, value );
1318  }
1319 
1320  int QueryAttribute( const char* name, double* value ) const {
1321  return QueryDoubleAttribute( name, value );
1322  }
1323 
1324  int QueryAttribute( const char* name, float* value ) const {
1325  return QueryFloatAttribute( name, value );
1326  }
1327 
1329  void SetAttribute( const char* name, const char* value ) {
1330  XMLAttribute* a = FindOrCreateAttribute( name );
1331  a->SetAttribute( value );
1332  }
1334  void SetAttribute( const char* name, int value ) {
1335  XMLAttribute* a = FindOrCreateAttribute( name );
1336  a->SetAttribute( value );
1337  }
1339  void SetAttribute( const char* name, unsigned value ) {
1340  XMLAttribute* a = FindOrCreateAttribute( name );
1341  a->SetAttribute( value );
1342  }
1344  void SetAttribute( const char* name, bool value ) {
1345  XMLAttribute* a = FindOrCreateAttribute( name );
1346  a->SetAttribute( value );
1347  }
1349  void SetAttribute( const char* name, double value ) {
1350  XMLAttribute* a = FindOrCreateAttribute( name );
1351  a->SetAttribute( value );
1352  }
1354  void SetAttribute( const char* name, float value ) {
1355  XMLAttribute* a = FindOrCreateAttribute( name );
1356  a->SetAttribute( value );
1357  }
1358 
1362  void DeleteAttribute( const char* name );
1363 
1365  const XMLAttribute* FirstAttribute() const {
1366  return _rootAttribute;
1367  }
1369  const XMLAttribute* FindAttribute( const char* name ) const;
1370 
1399  const char* GetText() const;
1400 
1435  void SetText( const char* inText );
1437  void SetText( int value );
1439  void SetText( unsigned value );
1441  void SetText( bool value );
1443  void SetText( double value );
1445  void SetText( float value );
1446 
1473  XMLError QueryIntText( int* ival ) const;
1475  XMLError QueryUnsignedText( unsigned* uval ) const;
1477  XMLError QueryBoolText( bool* bval ) const;
1479  XMLError QueryDoubleText( double* dval ) const;
1481  XMLError QueryFloatText( float* fval ) const;
1482 
1483  // internal:
1484  enum {
1485  OPEN, // <foo>
1486  CLOSED, // <foo/>
1487  CLOSING // </foo>
1488  };
1489  int ClosingType() const {
1490  return _closingType;
1491  }
1492  virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1493  virtual bool ShallowEqual( const XMLNode* compare ) const;
1494 
1495 protected:
1496  char* ParseDeep( char* p, StrPair* endTag );
1497 
1498 private:
1499  XMLElement( XMLDocument* doc );
1500  virtual ~XMLElement();
1501  XMLElement( const XMLElement& ); // not supported
1502  void operator=( const XMLElement& ); // not supported
1503 
1504  XMLAttribute* FindAttribute( const char* name ) {
1505  return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1506  }
1507  XMLAttribute* FindOrCreateAttribute( const char* name );
1508  //void LinkAttribute( XMLAttribute* attrib );
1509  char* ParseAttributes( char* p );
1510  static void DeleteAttribute( XMLAttribute* attribute );
1511 
1512  enum { BUF_SIZE = 200 };
1513  int _closingType;
1514  // The attribute list is ordered; there is no 'lastAttribute'
1515  // because the list needs to be scanned for dupes before adding
1516  // a new attribute.
1517  XMLAttribute* _rootAttribute;
1518 };
1519 
1520 
1521 enum Whitespace {
1522  PRESERVE_WHITESPACE,
1523  COLLAPSE_WHITESPACE
1524 };
1525 
1526 
1532 class TINYXML2_LIB XMLDocument : public XMLNode
1533 {
1534  friend class XMLElement;
1535 public:
1537  XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1538  ~XMLDocument();
1539 
1540  virtual XMLDocument* ToDocument() {
1541  TIXMLASSERT( this == _document );
1542  return this;
1543  }
1544  virtual const XMLDocument* ToDocument() const {
1545  TIXMLASSERT( this == _document );
1546  return this;
1547  }
1548 
1559  XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
1560 
1566  XMLError LoadFile( const char* filename );
1567 
1579  XMLError LoadFile( FILE* );
1580 
1586  XMLError SaveFile( const char* filename, bool compact = false );
1587 
1595  XMLError SaveFile( FILE* fp, bool compact = false );
1596 
1597  bool ProcessEntities() const {
1598  return _processEntities;
1599  }
1600  Whitespace WhitespaceMode() const {
1601  return _whitespace;
1602  }
1603 
1607  bool HasBOM() const {
1608  return _writeBOM;
1609  }
1612  void SetBOM( bool useBOM ) {
1613  _writeBOM = useBOM;
1614  }
1615 
1619  XMLElement* RootElement() {
1620  return FirstChildElement();
1621  }
1622  const XMLElement* RootElement() const {
1623  return FirstChildElement();
1624  }
1625 
1640  void Print( XMLPrinter* streamer=0 ) const;
1641  virtual bool Accept( XMLVisitor* visitor ) const;
1642 
1648  XMLElement* NewElement( const char* name );
1654  XMLComment* NewComment( const char* comment );
1660  XMLText* NewText( const char* text );
1672  XMLDeclaration* NewDeclaration( const char* text=0 );
1678  XMLUnknown* NewUnknown( const char* text );
1679 
1684  void DeleteNode( XMLNode* node );
1685 
1686  void SetError( XMLError error, const char* str1, const char* str2 );
1687 
1689  bool Error() const {
1690  return _errorID != XML_NO_ERROR;
1691  }
1693  XMLError ErrorID() const {
1694  return _errorID;
1695  }
1696  const char* ErrorName() const;
1697 
1699  const char* GetErrorStr1() const {
1700  return _errorStr1;
1701  }
1703  const char* GetErrorStr2() const {
1704  return _errorStr2;
1705  }
1707  void PrintError() const;
1708 
1710  void Clear();
1711 
1712  // internal
1713  char* Identify( char* p, XMLNode** node );
1714 
1715  virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1716  return 0;
1717  }
1718  virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1719  return false;
1720  }
1721 
1722 private:
1723  XMLDocument( const XMLDocument& ); // not supported
1724  void operator=( const XMLDocument& ); // not supported
1725 
1726  bool _writeBOM;
1727  bool _processEntities;
1728  XMLError _errorID;
1729  Whitespace _whitespace;
1730  const char* _errorStr1;
1731  const char* _errorStr2;
1732  char* _charBuffer;
1733 
1734  MemPoolT< sizeof(XMLElement) > _elementPool;
1735  MemPoolT< sizeof(XMLAttribute) > _attributePool;
1736  MemPoolT< sizeof(XMLText) > _textPool;
1737  MemPoolT< sizeof(XMLComment) > _commentPool;
1738 
1739  static const char* _errorNames[XML_ERROR_COUNT];
1740 
1741  void Parse();
1742 };
1743 
1744 
1800 class TINYXML2_LIB XMLHandle
1801 {
1802 public:
1804  XMLHandle( XMLNode* node ) {
1805  _node = node;
1806  }
1808  XMLHandle( XMLNode& node ) {
1809  _node = &node;
1810  }
1812  XMLHandle( const XMLHandle& ref ) {
1813  _node = ref._node;
1814  }
1816  XMLHandle& operator=( const XMLHandle& ref ) {
1817  _node = ref._node;
1818  return *this;
1819  }
1820 
1822  XMLHandle FirstChild() {
1823  return XMLHandle( _node ? _node->FirstChild() : 0 );
1824  }
1826  XMLHandle FirstChildElement( const char* name = 0 ) {
1827  return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
1828  }
1830  XMLHandle LastChild() {
1831  return XMLHandle( _node ? _node->LastChild() : 0 );
1832  }
1834  XMLHandle LastChildElement( const char* name = 0 ) {
1835  return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
1836  }
1838  XMLHandle PreviousSibling() {
1839  return XMLHandle( _node ? _node->PreviousSibling() : 0 );
1840  }
1842  XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1843  return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
1844  }
1846  XMLHandle NextSibling() {
1847  return XMLHandle( _node ? _node->NextSibling() : 0 );
1848  }
1850  XMLHandle NextSiblingElement( const char* name = 0 ) {
1851  return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
1852  }
1853 
1855  XMLNode* ToNode() {
1856  return _node;
1857  }
1859  XMLElement* ToElement() {
1860  return ( ( _node == 0 ) ? 0 : _node->ToElement() );
1861  }
1863  XMLText* ToText() {
1864  return ( ( _node == 0 ) ? 0 : _node->ToText() );
1865  }
1867  XMLUnknown* ToUnknown() {
1868  return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
1869  }
1871  XMLDeclaration* ToDeclaration() {
1872  return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
1873  }
1874 
1875 private:
1876  XMLNode* _node;
1877 };
1878 
1879 
1884 class TINYXML2_LIB XMLConstHandle
1885 {
1886 public:
1887  XMLConstHandle( const XMLNode* node ) {
1888  _node = node;
1889  }
1890  XMLConstHandle( const XMLNode& node ) {
1891  _node = &node;
1892  }
1893  XMLConstHandle( const XMLConstHandle& ref ) {
1894  _node = ref._node;
1895  }
1896 
1897  XMLConstHandle& operator=( const XMLConstHandle& ref ) {
1898  _node = ref._node;
1899  return *this;
1900  }
1901 
1902  const XMLConstHandle FirstChild() const {
1903  return XMLConstHandle( _node ? _node->FirstChild() : 0 );
1904  }
1905  const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1906  return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
1907  }
1908  const XMLConstHandle LastChild() const {
1909  return XMLConstHandle( _node ? _node->LastChild() : 0 );
1910  }
1911  const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1912  return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
1913  }
1914  const XMLConstHandle PreviousSibling() const {
1915  return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
1916  }
1917  const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1918  return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
1919  }
1920  const XMLConstHandle NextSibling() const {
1921  return XMLConstHandle( _node ? _node->NextSibling() : 0 );
1922  }
1923  const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1924  return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
1925  }
1926 
1927 
1928  const XMLNode* ToNode() const {
1929  return _node;
1930  }
1931  const XMLElement* ToElement() const {
1932  return ( ( _node == 0 ) ? 0 : _node->ToElement() );
1933  }
1934  const XMLText* ToText() const {
1935  return ( ( _node == 0 ) ? 0 : _node->ToText() );
1936  }
1937  const XMLUnknown* ToUnknown() const {
1938  return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
1939  }
1940  const XMLDeclaration* ToDeclaration() const {
1941  return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
1942  }
1943 
1944 private:
1945  const XMLNode* _node;
1946 };
1947 
1948 
1991 class TINYXML2_LIB XMLPrinter : public XMLVisitor
1992 {
1993 public:
2000  XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
2001  virtual ~XMLPrinter() {}
2002 
2004  void PushHeader( bool writeBOM, bool writeDeclaration );
2008  void OpenElement( const char* name, bool compactMode=false );
2010  void PushAttribute( const char* name, const char* value );
2011  void PushAttribute( const char* name, int value );
2012  void PushAttribute( const char* name, unsigned value );
2013  void PushAttribute( const char* name, bool value );
2014  void PushAttribute( const char* name, double value );
2016  virtual void CloseElement( bool compactMode=false );
2017 
2019  void PushText( const char* text, bool cdata=false );
2021  void PushText( int value );
2023  void PushText( unsigned value );
2025  void PushText( bool value );
2027  void PushText( float value );
2029  void PushText( double value );
2030 
2032  void PushComment( const char* comment );
2033 
2034  void PushDeclaration( const char* value );
2035  void PushUnknown( const char* value );
2036 
2037  virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2038  virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2039  return true;
2040  }
2041 
2042  virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2043  virtual bool VisitExit( const XMLElement& element );
2044 
2045  virtual bool Visit( const XMLText& text );
2046  virtual bool Visit( const XMLComment& comment );
2047  virtual bool Visit( const XMLDeclaration& declaration );
2048  virtual bool Visit( const XMLUnknown& unknown );
2049 
2054  const char* CStr() const {
2055  return _buffer.Mem();
2056  }
2062  int CStrSize() const {
2063  return _buffer.Size();
2064  }
2069  void ClearBuffer() {
2070  _buffer.Clear();
2071  _buffer.Push(0);
2072  }
2073 
2074 protected:
2075  virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
2076 
2080  virtual void PrintSpace( int depth );
2081  void Print( const char* format, ... );
2082 
2083  void SealElementIfJustOpened();
2084  bool _elementJustOpened;
2085  DynArray< const char*, 10 > _stack;
2086 
2087 private:
2088  void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
2089 
2090  bool _firstElement;
2091  FILE* _fp;
2092  int _depth;
2093  int _textDepth;
2094  bool _processEntities;
2095  bool _compactMode;
2096 
2097  enum {
2098  ENTITY_RANGE = 64,
2099  BUF_SIZE = 200
2100  };
2101  bool _entityFlag[ENTITY_RANGE];
2102  bool _restrictedEntityFlag[ENTITY_RANGE];
2103 
2104  DynArray< char, 20 > _buffer;
2105 };
2106 
2107 
2108 } // tinyxml2
2109 
2110 #if defined(_MSC_VER)
2111 # pragma warning(pop)
2112 #endif
2113 
2114 #endif // TINYXML2_INCLUDED
Definition: tinyxml2.cpp:114