TinyXML-2
2.1.0
|
00001 /* 00002 Original code by Lee Thomason (www.grinninglizard.com) 00003 00004 This software is provided 'as-is', without any express or implied 00005 warranty. In no event will the authors be held liable for any 00006 damages arising from the use of this software. 00007 00008 Permission is granted to anyone to use this software for any 00009 purpose, including commercial applications, and to alter it and 00010 redistribute it freely, subject to the following restrictions: 00011 00012 1. The origin of this software must not be misrepresented; you must 00013 not claim that you wrote the original software. If you use this 00014 software in a product, an acknowledgment in the product documentation 00015 would be appreciated but is not required. 00016 00017 00018 2. Altered source versions must be plainly marked as such, and 00019 must not be misrepresented as being the original software. 00020 00021 3. This notice may not be removed or altered from any source 00022 distribution. 00023 */ 00024 00025 #ifndef TINYXML2_INCLUDED 00026 #define TINYXML2_INCLUDED 00027 00028 #if defined(ANDROID_NDK) || defined(__BORLANDC__) 00029 # include <ctype.h> 00030 # include <limits.h> 00031 # include <stdio.h> 00032 # include <stdlib.h> 00033 # include <string.h> 00034 # include <stdarg.h> 00035 #else 00036 # include <cctype> 00037 # include <climits> 00038 # include <cstdio> 00039 # include <cstdlib> 00040 # include <cstring> 00041 # include <cstdarg> 00042 #endif 00043 00044 /* 00045 TODO: intern strings instead of allocation. 00046 */ 00047 /* 00048 gcc: 00049 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe 00050 00051 Formatting, Artistic Style: 00052 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h 00053 */ 00054 00055 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) 00056 # ifndef DEBUG 00057 # define DEBUG 00058 # endif 00059 #endif 00060 00061 #ifdef _MSC_VER 00062 # pragma warning(push) 00063 # pragma warning(disable: 4251) 00064 #endif 00065 00066 #ifdef _WIN32 00067 # ifdef TINYXML2_EXPORT 00068 # define TINYXML2_LIB __declspec(dllexport) 00069 # elif defined(TINYXML2_IMPORT) 00070 # define TINYXML2_LIB __declspec(dllimport) 00071 # else 00072 # define TINYXML2_LIB 00073 # endif 00074 #else 00075 # define TINYXML2_LIB 00076 #endif 00077 00078 00079 #if defined(DEBUG) 00080 # if defined(_MSC_VER) 00081 # define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak() 00082 # elif defined (ANDROID_NDK) 00083 # include <android/log.h> 00084 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } 00085 # else 00086 # include <assert.h> 00087 # define TIXMLASSERT assert 00088 # endif 00089 # else 00090 # define TIXMLASSERT( x ) {} 00091 #endif 00092 00093 00094 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) 00095 // Microsoft visual studio, version 2005 and higher. 00096 /*int _snprintf_s( 00097 char *buffer, 00098 size_t sizeOfBuffer, 00099 size_t count, 00100 const char *format [, 00101 argument] ... 00102 );*/ 00103 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) 00104 { 00105 va_list va; 00106 va_start( va, format ); 00107 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); 00108 va_end( va ); 00109 return result; 00110 } 00111 #define TIXML_SSCANF sscanf_s 00112 #else 00113 // GCC version 3 and higher 00114 //#warning( "Using sn* functions." ) 00115 #define TIXML_SNPRINTF snprintf 00116 #define TIXML_SSCANF sscanf 00117 #endif 00118 00119 /* Versioning, past 1.0.14: 00120 http://semver.org/ 00121 */ 00122 static const int TIXML2_MAJOR_VERSION = 2; 00123 static const int TIXML2_MINOR_VERSION = 1; 00124 static const int TIXML2_PATCH_VERSION = 0; 00125 00126 namespace tinyxml2 00127 { 00128 class XMLDocument; 00129 class XMLElement; 00130 class XMLAttribute; 00131 class XMLComment; 00132 class XMLText; 00133 class XMLDeclaration; 00134 class XMLUnknown; 00135 class XMLPrinter; 00136 00137 /* 00138 A class that wraps strings. Normally stores the start and end 00139 pointers into the XML file itself, and will apply normalization 00140 and entity translation if actually read. Can also store (and memory 00141 manage) a traditional char[] 00142 */ 00143 class StrPair 00144 { 00145 public: 00146 enum { 00147 NEEDS_ENTITY_PROCESSING = 0x01, 00148 NEEDS_NEWLINE_NORMALIZATION = 0x02, 00149 COLLAPSE_WHITESPACE = 0x04, 00150 00151 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 00152 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 00153 ATTRIBUTE_NAME = 0, 00154 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 00155 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 00156 COMMENT = NEEDS_NEWLINE_NORMALIZATION 00157 }; 00158 00159 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} 00160 ~StrPair(); 00161 00162 void Set( char* start, char* end, int flags ) { 00163 Reset(); 00164 _start = start; 00165 _end = end; 00166 _flags = flags | NEEDS_FLUSH; 00167 } 00168 00169 const char* GetStr(); 00170 00171 bool Empty() const { 00172 return _start == _end; 00173 } 00174 00175 void SetInternedStr( const char* str ) { 00176 Reset(); 00177 _start = const_cast<char*>(str); 00178 } 00179 00180 void SetStr( const char* str, int flags=0 ); 00181 00182 char* ParseText( char* in, const char* endTag, int strFlags ); 00183 char* ParseName( char* in ); 00184 00185 private: 00186 void Reset(); 00187 void CollapseWhitespace(); 00188 00189 enum { 00190 NEEDS_FLUSH = 0x100, 00191 NEEDS_DELETE = 0x200 00192 }; 00193 00194 // After parsing, if *_end != 0, it can be set to zero. 00195 int _flags; 00196 char* _start; 00197 char* _end; 00198 }; 00199 00200 00201 /* 00202 A dynamic array of Plain Old Data. Doesn't support constructors, etc. 00203 Has a small initial memory pool, so that low or no usage will not 00204 cause a call to new/delete 00205 */ 00206 template <class T, int INIT> 00207 class DynArray 00208 { 00209 public: 00210 DynArray< T, INIT >() { 00211 _mem = _pool; 00212 _allocated = INIT; 00213 _size = 0; 00214 } 00215 00216 ~DynArray() { 00217 if ( _mem != _pool ) { 00218 delete [] _mem; 00219 } 00220 } 00221 00222 void Clear() { 00223 _size = 0; 00224 } 00225 00226 void Push( T t ) { 00227 EnsureCapacity( _size+1 ); 00228 _mem[_size++] = t; 00229 } 00230 00231 T* PushArr( int count ) { 00232 EnsureCapacity( _size+count ); 00233 T* ret = &_mem[_size]; 00234 _size += count; 00235 return ret; 00236 } 00237 00238 T Pop() { 00239 return _mem[--_size]; 00240 } 00241 00242 void PopArr( int count ) { 00243 TIXMLASSERT( _size >= count ); 00244 _size -= count; 00245 } 00246 00247 bool Empty() const { 00248 return _size == 0; 00249 } 00250 00251 T& operator[](int i) { 00252 TIXMLASSERT( i>= 0 && i < _size ); 00253 return _mem[i]; 00254 } 00255 00256 const T& operator[](int i) const { 00257 TIXMLASSERT( i>= 0 && i < _size ); 00258 return _mem[i]; 00259 } 00260 00261 const T& PeekTop() const { 00262 TIXMLASSERT( _size > 0 ); 00263 return _mem[ _size - 1]; 00264 } 00265 00266 int Size() const { 00267 return _size; 00268 } 00269 00270 int Capacity() const { 00271 return _allocated; 00272 } 00273 00274 const T* Mem() const { 00275 return _mem; 00276 } 00277 00278 T* Mem() { 00279 return _mem; 00280 } 00281 00282 private: 00283 void EnsureCapacity( int cap ) { 00284 if ( cap > _allocated ) { 00285 int newAllocated = cap * 2; 00286 T* newMem = new T[newAllocated]; 00287 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs 00288 if ( _mem != _pool ) { 00289 delete [] _mem; 00290 } 00291 _mem = newMem; 00292 _allocated = newAllocated; 00293 } 00294 } 00295 00296 T* _mem; 00297 T _pool[INIT]; 00298 int _allocated; // objects allocated 00299 int _size; // number objects in use 00300 }; 00301 00302 00303 /* 00304 Parent virtual class of a pool for fast allocation 00305 and deallocation of objects. 00306 */ 00307 class MemPool 00308 { 00309 public: 00310 MemPool() {} 00311 virtual ~MemPool() {} 00312 00313 virtual int ItemSize() const = 0; 00314 virtual void* Alloc() = 0; 00315 virtual void Free( void* ) = 0; 00316 virtual void SetTracked() = 0; 00317 }; 00318 00319 00320 /* 00321 Template child class to create pools of the correct type. 00322 */ 00323 template< int SIZE > 00324 class MemPoolT : public MemPool 00325 { 00326 public: 00327 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} 00328 ~MemPoolT() { 00329 // Delete the blocks. 00330 for( int i=0; i<_blockPtrs.Size(); ++i ) { 00331 delete _blockPtrs[i]; 00332 } 00333 } 00334 00335 virtual int ItemSize() const { 00336 return SIZE; 00337 } 00338 int CurrentAllocs() const { 00339 return _currentAllocs; 00340 } 00341 00342 virtual void* Alloc() { 00343 if ( !_root ) { 00344 // Need a new block. 00345 Block* block = new Block(); 00346 _blockPtrs.Push( block ); 00347 00348 for( int i=0; i<COUNT-1; ++i ) { 00349 block->chunk[i].next = &block->chunk[i+1]; 00350 } 00351 block->chunk[COUNT-1].next = 0; 00352 _root = block->chunk; 00353 } 00354 void* result = _root; 00355 _root = _root->next; 00356 00357 ++_currentAllocs; 00358 if ( _currentAllocs > _maxAllocs ) { 00359 _maxAllocs = _currentAllocs; 00360 } 00361 _nAllocs++; 00362 _nUntracked++; 00363 return result; 00364 } 00365 virtual void Free( void* mem ) { 00366 if ( !mem ) { 00367 return; 00368 } 00369 --_currentAllocs; 00370 Chunk* chunk = (Chunk*)mem; 00371 #ifdef DEBUG 00372 memset( chunk, 0xfe, sizeof(Chunk) ); 00373 #endif 00374 chunk->next = _root; 00375 _root = chunk; 00376 } 00377 void Trace( const char* name ) { 00378 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", 00379 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); 00380 } 00381 00382 void SetTracked() { 00383 _nUntracked--; 00384 } 00385 00386 int Untracked() const { 00387 return _nUntracked; 00388 } 00389 00390 // This number is perf sensitive. 4k seems like a good tradeoff on my machine. 00391 // The test file is large, 170k. 00392 // Release: VS2010 gcc(no opt) 00393 // 1k: 4000 00394 // 2k: 4000 00395 // 4k: 3900 21000 00396 // 16k: 5200 00397 // 32k: 4300 00398 // 64k: 4000 21000 00399 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private 00400 00401 private: 00402 union Chunk { 00403 Chunk* next; 00404 char mem[SIZE]; 00405 }; 00406 struct Block { 00407 Chunk chunk[COUNT]; 00408 }; 00409 DynArray< Block*, 10 > _blockPtrs; 00410 Chunk* _root; 00411 00412 int _currentAllocs; 00413 int _nAllocs; 00414 int _maxAllocs; 00415 int _nUntracked; 00416 }; 00417 00418 00419 00439 class TINYXML2_LIB XMLVisitor 00440 { 00441 public: 00442 virtual ~XMLVisitor() {} 00443 00445 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { 00446 return true; 00447 } 00449 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { 00450 return true; 00451 } 00452 00454 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { 00455 return true; 00456 } 00458 virtual bool VisitExit( const XMLElement& /*element*/ ) { 00459 return true; 00460 } 00461 00463 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { 00464 return true; 00465 } 00467 virtual bool Visit( const XMLText& /*text*/ ) { 00468 return true; 00469 } 00471 virtual bool Visit( const XMLComment& /*comment*/ ) { 00472 return true; 00473 } 00475 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { 00476 return true; 00477 } 00478 }; 00479 00480 00481 /* 00482 Utility functionality. 00483 */ 00484 class XMLUtil 00485 { 00486 public: 00487 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't 00488 // correct, but simple, and usually works. 00489 static const char* SkipWhiteSpace( const char* p ) { 00490 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { 00491 ++p; 00492 } 00493 return p; 00494 } 00495 static char* SkipWhiteSpace( char* p ) { 00496 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) { 00497 ++p; 00498 } 00499 return p; 00500 } 00501 static bool IsWhiteSpace( char p ) { 00502 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) ); 00503 } 00504 00505 inline static bool IsNameStartChar( unsigned char ch ) { 00506 return ( ( ch < 128 ) ? isalpha( ch ) : 1 ) 00507 || ch == ':' 00508 || ch == '_'; 00509 } 00510 00511 inline static bool IsNameChar( unsigned char ch ) { 00512 return IsNameStartChar( ch ) 00513 || isdigit( ch ) 00514 || ch == '.' 00515 || ch == '-'; 00516 } 00517 00518 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { 00519 int n = 0; 00520 if ( p == q ) { 00521 return true; 00522 } 00523 while( *p && *q && *p == *q && n<nChar ) { 00524 ++p; 00525 ++q; 00526 ++n; 00527 } 00528 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) { 00529 return true; 00530 } 00531 return false; 00532 } 00533 00534 inline static int IsUTF8Continuation( const char p ) { 00535 return p & 0x80; 00536 } 00537 00538 static const char* ReadBOM( const char* p, bool* hasBOM ); 00539 // p is the starting location, 00540 // the UTF-8 value of the entity will be placed in value, and length filled in. 00541 static const char* GetCharacterRef( const char* p, char* value, int* length ); 00542 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); 00543 00544 // converts primitive types to strings 00545 static void ToStr( int v, char* buffer, int bufferSize ); 00546 static void ToStr( unsigned v, char* buffer, int bufferSize ); 00547 static void ToStr( bool v, char* buffer, int bufferSize ); 00548 static void ToStr( float v, char* buffer, int bufferSize ); 00549 static void ToStr( double v, char* buffer, int bufferSize ); 00550 00551 // converts strings to primitive types 00552 static bool ToInt( const char* str, int* value ); 00553 static bool ToUnsigned( const char* str, unsigned* value ); 00554 static bool ToBool( const char* str, bool* value ); 00555 static bool ToFloat( const char* str, float* value ); 00556 static bool ToDouble( const char* str, double* value ); 00557 }; 00558 00559 00585 class TINYXML2_LIB XMLNode 00586 { 00587 friend class XMLDocument; 00588 friend class XMLElement; 00589 public: 00590 00592 const XMLDocument* GetDocument() const { 00593 return _document; 00594 } 00596 XMLDocument* GetDocument() { 00597 return _document; 00598 } 00599 00601 virtual XMLElement* ToElement() { 00602 return 0; 00603 } 00605 virtual XMLText* ToText() { 00606 return 0; 00607 } 00609 virtual XMLComment* ToComment() { 00610 return 0; 00611 } 00613 virtual XMLDocument* ToDocument() { 00614 return 0; 00615 } 00617 virtual XMLDeclaration* ToDeclaration() { 00618 return 0; 00619 } 00621 virtual XMLUnknown* ToUnknown() { 00622 return 0; 00623 } 00624 00625 virtual const XMLElement* ToElement() const { 00626 return 0; 00627 } 00628 virtual const XMLText* ToText() const { 00629 return 0; 00630 } 00631 virtual const XMLComment* ToComment() const { 00632 return 0; 00633 } 00634 virtual const XMLDocument* ToDocument() const { 00635 return 0; 00636 } 00637 virtual const XMLDeclaration* ToDeclaration() const { 00638 return 0; 00639 } 00640 virtual const XMLUnknown* ToUnknown() const { 00641 return 0; 00642 } 00643 00653 const char* Value() const; 00654 00658 void SetValue( const char* val, bool staticMem=false ); 00659 00661 const XMLNode* Parent() const { 00662 return _parent; 00663 } 00664 00665 XMLNode* Parent() { 00666 return _parent; 00667 } 00668 00670 bool NoChildren() const { 00671 return !_firstChild; 00672 } 00673 00675 const XMLNode* FirstChild() const { 00676 return _firstChild; 00677 } 00678 00679 XMLNode* FirstChild() { 00680 return _firstChild; 00681 } 00682 00686 const XMLElement* FirstChildElement( const char* value=0 ) const; 00687 00688 XMLElement* FirstChildElement( const char* value=0 ) { 00689 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); 00690 } 00691 00693 const XMLNode* LastChild() const { 00694 return _lastChild; 00695 } 00696 00697 XMLNode* LastChild() { 00698 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); 00699 } 00700 00704 const XMLElement* LastChildElement( const char* value=0 ) const; 00705 00706 XMLElement* LastChildElement( const char* value=0 ) { 00707 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); 00708 } 00709 00711 const XMLNode* PreviousSibling() const { 00712 return _prev; 00713 } 00714 00715 XMLNode* PreviousSibling() { 00716 return _prev; 00717 } 00718 00720 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; 00721 00722 XMLElement* PreviousSiblingElement( const char* value=0 ) { 00723 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); 00724 } 00725 00727 const XMLNode* NextSibling() const { 00728 return _next; 00729 } 00730 00731 XMLNode* NextSibling() { 00732 return _next; 00733 } 00734 00736 const XMLElement* NextSiblingElement( const char* value=0 ) const; 00737 00738 XMLElement* NextSiblingElement( const char* value=0 ) { 00739 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); 00740 } 00741 00749 XMLNode* InsertEndChild( XMLNode* addThis ); 00750 00751 XMLNode* LinkEndChild( XMLNode* addThis ) { 00752 return InsertEndChild( addThis ); 00753 } 00761 XMLNode* InsertFirstChild( XMLNode* addThis ); 00770 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); 00771 00775 void DeleteChildren(); 00776 00780 void DeleteChild( XMLNode* node ); 00781 00791 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; 00792 00799 virtual bool ShallowEqual( const XMLNode* compare ) const = 0; 00800 00823 virtual bool Accept( XMLVisitor* visitor ) const = 0; 00824 00825 // internal 00826 virtual char* ParseDeep( char*, StrPair* ); 00827 00828 protected: 00829 XMLNode( XMLDocument* ); 00830 virtual ~XMLNode(); 00831 XMLNode( const XMLNode& ); // not supported 00832 XMLNode& operator=( const XMLNode& ); // not supported 00833 00834 XMLDocument* _document; 00835 XMLNode* _parent; 00836 mutable StrPair _value; 00837 00838 XMLNode* _firstChild; 00839 XMLNode* _lastChild; 00840 00841 XMLNode* _prev; 00842 XMLNode* _next; 00843 00844 private: 00845 MemPool* _memPool; 00846 void Unlink( XMLNode* child ); 00847 }; 00848 00849 00862 class TINYXML2_LIB XMLText : public XMLNode 00863 { 00864 friend class XMLBase; 00865 friend class XMLDocument; 00866 public: 00867 virtual bool Accept( XMLVisitor* visitor ) const; 00868 00869 virtual XMLText* ToText() { 00870 return this; 00871 } 00872 virtual const XMLText* ToText() const { 00873 return this; 00874 } 00875 00877 void SetCData( bool isCData ) { 00878 _isCData = isCData; 00879 } 00881 bool CData() const { 00882 return _isCData; 00883 } 00884 00885 char* ParseDeep( char*, StrPair* endTag ); 00886 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 00887 virtual bool ShallowEqual( const XMLNode* compare ) const; 00888 00889 protected: 00890 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} 00891 virtual ~XMLText() {} 00892 XMLText( const XMLText& ); // not supported 00893 XMLText& operator=( const XMLText& ); // not supported 00894 00895 private: 00896 bool _isCData; 00897 }; 00898 00899 00901 class TINYXML2_LIB XMLComment : public XMLNode 00902 { 00903 friend class XMLDocument; 00904 public: 00905 virtual XMLComment* ToComment() { 00906 return this; 00907 } 00908 virtual const XMLComment* ToComment() const { 00909 return this; 00910 } 00911 00912 virtual bool Accept( XMLVisitor* visitor ) const; 00913 00914 char* ParseDeep( char*, StrPair* endTag ); 00915 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 00916 virtual bool ShallowEqual( const XMLNode* compare ) const; 00917 00918 protected: 00919 XMLComment( XMLDocument* doc ); 00920 virtual ~XMLComment(); 00921 XMLComment( const XMLComment& ); // not supported 00922 XMLComment& operator=( const XMLComment& ); // not supported 00923 00924 private: 00925 }; 00926 00927 00939 class TINYXML2_LIB XMLDeclaration : public XMLNode 00940 { 00941 friend class XMLDocument; 00942 public: 00943 virtual XMLDeclaration* ToDeclaration() { 00944 return this; 00945 } 00946 virtual const XMLDeclaration* ToDeclaration() const { 00947 return this; 00948 } 00949 00950 virtual bool Accept( XMLVisitor* visitor ) const; 00951 00952 char* ParseDeep( char*, StrPair* endTag ); 00953 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 00954 virtual bool ShallowEqual( const XMLNode* compare ) const; 00955 00956 protected: 00957 XMLDeclaration( XMLDocument* doc ); 00958 virtual ~XMLDeclaration(); 00959 XMLDeclaration( const XMLDeclaration& ); // not supported 00960 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported 00961 }; 00962 00963 00971 class TINYXML2_LIB XMLUnknown : public XMLNode 00972 { 00973 friend class XMLDocument; 00974 public: 00975 virtual XMLUnknown* ToUnknown() { 00976 return this; 00977 } 00978 virtual const XMLUnknown* ToUnknown() const { 00979 return this; 00980 } 00981 00982 virtual bool Accept( XMLVisitor* visitor ) const; 00983 00984 char* ParseDeep( char*, StrPair* endTag ); 00985 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 00986 virtual bool ShallowEqual( const XMLNode* compare ) const; 00987 00988 protected: 00989 XMLUnknown( XMLDocument* doc ); 00990 virtual ~XMLUnknown(); 00991 XMLUnknown( const XMLUnknown& ); // not supported 00992 XMLUnknown& operator=( const XMLUnknown& ); // not supported 00993 }; 00994 00995 00996 enum XMLError { 00997 XML_NO_ERROR = 0, 00998 XML_SUCCESS = 0, 00999 01000 XML_NO_ATTRIBUTE, 01001 XML_WRONG_ATTRIBUTE_TYPE, 01002 01003 XML_ERROR_FILE_NOT_FOUND, 01004 XML_ERROR_FILE_COULD_NOT_BE_OPENED, 01005 XML_ERROR_FILE_READ_ERROR, 01006 XML_ERROR_ELEMENT_MISMATCH, 01007 XML_ERROR_PARSING_ELEMENT, 01008 XML_ERROR_PARSING_ATTRIBUTE, 01009 XML_ERROR_IDENTIFYING_TAG, 01010 XML_ERROR_PARSING_TEXT, 01011 XML_ERROR_PARSING_CDATA, 01012 XML_ERROR_PARSING_COMMENT, 01013 XML_ERROR_PARSING_DECLARATION, 01014 XML_ERROR_PARSING_UNKNOWN, 01015 XML_ERROR_EMPTY_DOCUMENT, 01016 XML_ERROR_MISMATCHED_ELEMENT, 01017 XML_ERROR_PARSING, 01018 01019 XML_CAN_NOT_CONVERT_TEXT, 01020 XML_NO_TEXT_NODE 01021 }; 01022 01023 01030 class TINYXML2_LIB XMLAttribute 01031 { 01032 friend class XMLElement; 01033 public: 01035 const char* Name() const; 01036 01038 const char* Value() const; 01039 01041 const XMLAttribute* Next() const { 01042 return _next; 01043 } 01044 01049 int IntValue() const { 01050 int i=0; 01051 QueryIntValue( &i ); 01052 return i; 01053 } 01055 unsigned UnsignedValue() const { 01056 unsigned i=0; 01057 QueryUnsignedValue( &i ); 01058 return i; 01059 } 01061 bool BoolValue() const { 01062 bool b=false; 01063 QueryBoolValue( &b ); 01064 return b; 01065 } 01067 double DoubleValue() const { 01068 double d=0; 01069 QueryDoubleValue( &d ); 01070 return d; 01071 } 01073 float FloatValue() const { 01074 float f=0; 01075 QueryFloatValue( &f ); 01076 return f; 01077 } 01078 01083 XMLError QueryIntValue( int* value ) const; 01085 XMLError QueryUnsignedValue( unsigned int* value ) const; 01087 XMLError QueryBoolValue( bool* value ) const; 01089 XMLError QueryDoubleValue( double* value ) const; 01091 XMLError QueryFloatValue( float* value ) const; 01092 01094 void SetAttribute( const char* value ); 01096 void SetAttribute( int value ); 01098 void SetAttribute( unsigned value ); 01100 void SetAttribute( bool value ); 01102 void SetAttribute( double value ); 01104 void SetAttribute( float value ); 01105 01106 private: 01107 enum { BUF_SIZE = 200 }; 01108 01109 XMLAttribute() : _next( 0 ), _memPool( 0 ) {} 01110 virtual ~XMLAttribute() {} 01111 01112 XMLAttribute( const XMLAttribute& ); // not supported 01113 void operator=( const XMLAttribute& ); // not supported 01114 void SetName( const char* name ); 01115 01116 char* ParseDeep( char* p, bool processEntities ); 01117 01118 mutable StrPair _name; 01119 mutable StrPair _value; 01120 XMLAttribute* _next; 01121 MemPool* _memPool; 01122 }; 01123 01124 01129 class TINYXML2_LIB XMLElement : public XMLNode 01130 { 01131 friend class XMLBase; 01132 friend class XMLDocument; 01133 public: 01135 const char* Name() const { 01136 return Value(); 01137 } 01139 void SetName( const char* str, bool staticMem=false ) { 01140 SetValue( str, staticMem ); 01141 } 01142 01143 virtual XMLElement* ToElement() { 01144 return this; 01145 } 01146 virtual const XMLElement* ToElement() const { 01147 return this; 01148 } 01149 virtual bool Accept( XMLVisitor* visitor ) const; 01150 01174 const char* Attribute( const char* name, const char* value=0 ) const; 01175 01181 int IntAttribute( const char* name ) const { 01182 int i=0; 01183 QueryIntAttribute( name, &i ); 01184 return i; 01185 } 01187 unsigned UnsignedAttribute( const char* name ) const { 01188 unsigned i=0; 01189 QueryUnsignedAttribute( name, &i ); 01190 return i; 01191 } 01193 bool BoolAttribute( const char* name ) const { 01194 bool b=false; 01195 QueryBoolAttribute( name, &b ); 01196 return b; 01197 } 01199 double DoubleAttribute( const char* name ) const { 01200 double d=0; 01201 QueryDoubleAttribute( name, &d ); 01202 return d; 01203 } 01205 float FloatAttribute( const char* name ) const { 01206 float f=0; 01207 QueryFloatAttribute( name, &f ); 01208 return f; 01209 } 01210 01224 XMLError QueryIntAttribute( const char* name, int* value ) const { 01225 const XMLAttribute* a = FindAttribute( name ); 01226 if ( !a ) { 01227 return XML_NO_ATTRIBUTE; 01228 } 01229 return a->QueryIntValue( value ); 01230 } 01232 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { 01233 const XMLAttribute* a = FindAttribute( name ); 01234 if ( !a ) { 01235 return XML_NO_ATTRIBUTE; 01236 } 01237 return a->QueryUnsignedValue( value ); 01238 } 01240 XMLError QueryBoolAttribute( const char* name, bool* value ) const { 01241 const XMLAttribute* a = FindAttribute( name ); 01242 if ( !a ) { 01243 return XML_NO_ATTRIBUTE; 01244 } 01245 return a->QueryBoolValue( value ); 01246 } 01248 XMLError QueryDoubleAttribute( const char* name, double* value ) const { 01249 const XMLAttribute* a = FindAttribute( name ); 01250 if ( !a ) { 01251 return XML_NO_ATTRIBUTE; 01252 } 01253 return a->QueryDoubleValue( value ); 01254 } 01256 XMLError QueryFloatAttribute( const char* name, float* value ) const { 01257 const XMLAttribute* a = FindAttribute( name ); 01258 if ( !a ) { 01259 return XML_NO_ATTRIBUTE; 01260 } 01261 return a->QueryFloatValue( value ); 01262 } 01263 01264 01282 int QueryAttribute( const char* name, int* value ) const { 01283 return QueryIntAttribute( name, value ); 01284 } 01285 01286 int QueryAttribute( const char* name, unsigned int* value ) const { 01287 return QueryUnsignedAttribute( name, value ); 01288 } 01289 01290 int QueryAttribute( const char* name, bool* value ) const { 01291 return QueryBoolAttribute( name, value ); 01292 } 01293 01294 int QueryAttribute( const char* name, double* value ) const { 01295 return QueryDoubleAttribute( name, value ); 01296 } 01297 01298 int QueryAttribute( const char* name, float* value ) const { 01299 return QueryFloatAttribute( name, value ); 01300 } 01301 01303 void SetAttribute( const char* name, const char* value ) { 01304 XMLAttribute* a = FindOrCreateAttribute( name ); 01305 a->SetAttribute( value ); 01306 } 01308 void SetAttribute( const char* name, int value ) { 01309 XMLAttribute* a = FindOrCreateAttribute( name ); 01310 a->SetAttribute( value ); 01311 } 01313 void SetAttribute( const char* name, unsigned value ) { 01314 XMLAttribute* a = FindOrCreateAttribute( name ); 01315 a->SetAttribute( value ); 01316 } 01318 void SetAttribute( const char* name, bool value ) { 01319 XMLAttribute* a = FindOrCreateAttribute( name ); 01320 a->SetAttribute( value ); 01321 } 01323 void SetAttribute( const char* name, double value ) { 01324 XMLAttribute* a = FindOrCreateAttribute( name ); 01325 a->SetAttribute( value ); 01326 } 01328 void SetAttribute( const char* name, float value ) { 01329 XMLAttribute* a = FindOrCreateAttribute( name ); 01330 a->SetAttribute( value ); 01331 } 01332 01336 void DeleteAttribute( const char* name ); 01337 01339 const XMLAttribute* FirstAttribute() const { 01340 return _rootAttribute; 01341 } 01343 const XMLAttribute* FindAttribute( const char* name ) const; 01344 01373 const char* GetText() const; 01374 01409 void SetText( const char* inText ); 01411 void SetText( int value ); 01413 void SetText( unsigned value ); 01415 void SetText( bool value ); 01417 void SetText( double value ); 01419 void SetText( float value ); 01420 01447 XMLError QueryIntText( int* ival ) const; 01449 XMLError QueryUnsignedText( unsigned* uval ) const; 01451 XMLError QueryBoolText( bool* bval ) const; 01453 XMLError QueryDoubleText( double* dval ) const; 01455 XMLError QueryFloatText( float* fval ) const; 01456 01457 // internal: 01458 enum { 01459 OPEN, // <foo> 01460 CLOSED, // <foo/> 01461 CLOSING // </foo> 01462 }; 01463 int ClosingType() const { 01464 return _closingType; 01465 } 01466 char* ParseDeep( char* p, StrPair* endTag ); 01467 virtual XMLNode* ShallowClone( XMLDocument* document ) const; 01468 virtual bool ShallowEqual( const XMLNode* compare ) const; 01469 01470 private: 01471 XMLElement( XMLDocument* doc ); 01472 virtual ~XMLElement(); 01473 XMLElement( const XMLElement& ); // not supported 01474 void operator=( const XMLElement& ); // not supported 01475 01476 XMLAttribute* FindAttribute( const char* name ); 01477 XMLAttribute* FindOrCreateAttribute( const char* name ); 01478 //void LinkAttribute( XMLAttribute* attrib ); 01479 char* ParseAttributes( char* p ); 01480 01481 enum { BUF_SIZE = 200 }; 01482 int _closingType; 01483 // The attribute list is ordered; there is no 'lastAttribute' 01484 // because the list needs to be scanned for dupes before adding 01485 // a new attribute. 01486 XMLAttribute* _rootAttribute; 01487 }; 01488 01489 01490 enum Whitespace { 01491 PRESERVE_WHITESPACE, 01492 COLLAPSE_WHITESPACE 01493 }; 01494 01495 01501 class TINYXML2_LIB XMLDocument : public XMLNode 01502 { 01503 friend class XMLElement; 01504 public: 01506 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); 01507 ~XMLDocument(); 01508 01509 virtual XMLDocument* ToDocument() { 01510 return this; 01511 } 01512 virtual const XMLDocument* ToDocument() const { 01513 return this; 01514 } 01515 01526 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); 01527 01533 XMLError LoadFile( const char* filename ); 01534 01542 XMLError LoadFile( FILE* ); 01543 01549 XMLError SaveFile( const char* filename, bool compact = false ); 01550 01558 XMLError SaveFile( FILE* fp, bool compact = false ); 01559 01560 bool ProcessEntities() const { 01561 return _processEntities; 01562 } 01563 Whitespace WhitespaceMode() const { 01564 return _whitespace; 01565 } 01566 01570 bool HasBOM() const { 01571 return _writeBOM; 01572 } 01575 void SetBOM( bool useBOM ) { 01576 _writeBOM = useBOM; 01577 } 01578 01582 XMLElement* RootElement() { 01583 return FirstChildElement(); 01584 } 01585 const XMLElement* RootElement() const { 01586 return FirstChildElement(); 01587 } 01588 01603 void Print( XMLPrinter* streamer=0 ) const; 01604 virtual bool Accept( XMLVisitor* visitor ) const; 01605 01611 XMLElement* NewElement( const char* name ); 01617 XMLComment* NewComment( const char* comment ); 01623 XMLText* NewText( const char* text ); 01635 XMLDeclaration* NewDeclaration( const char* text=0 ); 01641 XMLUnknown* NewUnknown( const char* text ); 01642 01647 void DeleteNode( XMLNode* node ) { 01648 node->_parent->DeleteChild( node ); 01649 } 01650 01651 void SetError( XMLError error, const char* str1, const char* str2 ); 01652 01654 bool Error() const { 01655 return _errorID != XML_NO_ERROR; 01656 } 01658 XMLError ErrorID() const { 01659 return _errorID; 01660 } 01662 const char* GetErrorStr1() const { 01663 return _errorStr1; 01664 } 01666 const char* GetErrorStr2() const { 01667 return _errorStr2; 01668 } 01670 void PrintError() const; 01671 01673 void Clear(); 01674 01675 // internal 01676 char* Identify( char* p, XMLNode** node ); 01677 01678 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { 01679 return 0; 01680 } 01681 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { 01682 return false; 01683 } 01684 01685 private: 01686 XMLDocument( const XMLDocument& ); // not supported 01687 void operator=( const XMLDocument& ); // not supported 01688 01689 bool _writeBOM; 01690 bool _processEntities; 01691 XMLError _errorID; 01692 Whitespace _whitespace; 01693 const char* _errorStr1; 01694 const char* _errorStr2; 01695 char* _charBuffer; 01696 01697 MemPoolT< sizeof(XMLElement) > _elementPool; 01698 MemPoolT< sizeof(XMLAttribute) > _attributePool; 01699 MemPoolT< sizeof(XMLText) > _textPool; 01700 MemPoolT< sizeof(XMLComment) > _commentPool; 01701 }; 01702 01703 01759 class TINYXML2_LIB XMLHandle 01760 { 01761 public: 01763 XMLHandle( XMLNode* node ) { 01764 _node = node; 01765 } 01767 XMLHandle( XMLNode& node ) { 01768 _node = &node; 01769 } 01771 XMLHandle( const XMLHandle& ref ) { 01772 _node = ref._node; 01773 } 01775 XMLHandle& operator=( const XMLHandle& ref ) { 01776 _node = ref._node; 01777 return *this; 01778 } 01779 01781 XMLHandle FirstChild() { 01782 return XMLHandle( _node ? _node->FirstChild() : 0 ); 01783 } 01785 XMLHandle FirstChildElement( const char* value=0 ) { 01786 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 ); 01787 } 01789 XMLHandle LastChild() { 01790 return XMLHandle( _node ? _node->LastChild() : 0 ); 01791 } 01793 XMLHandle LastChildElement( const char* _value=0 ) { 01794 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 ); 01795 } 01797 XMLHandle PreviousSibling() { 01798 return XMLHandle( _node ? _node->PreviousSibling() : 0 ); 01799 } 01801 XMLHandle PreviousSiblingElement( const char* _value=0 ) { 01802 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); 01803 } 01805 XMLHandle NextSibling() { 01806 return XMLHandle( _node ? _node->NextSibling() : 0 ); 01807 } 01809 XMLHandle NextSiblingElement( const char* _value=0 ) { 01810 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); 01811 } 01812 01814 XMLNode* ToNode() { 01815 return _node; 01816 } 01818 XMLElement* ToElement() { 01819 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); 01820 } 01822 XMLText* ToText() { 01823 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); 01824 } 01826 XMLUnknown* ToUnknown() { 01827 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); 01828 } 01830 XMLDeclaration* ToDeclaration() { 01831 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); 01832 } 01833 01834 private: 01835 XMLNode* _node; 01836 }; 01837 01838 01843 class TINYXML2_LIB XMLConstHandle 01844 { 01845 public: 01846 XMLConstHandle( const XMLNode* node ) { 01847 _node = node; 01848 } 01849 XMLConstHandle( const XMLNode& node ) { 01850 _node = &node; 01851 } 01852 XMLConstHandle( const XMLConstHandle& ref ) { 01853 _node = ref._node; 01854 } 01855 01856 XMLConstHandle& operator=( const XMLConstHandle& ref ) { 01857 _node = ref._node; 01858 return *this; 01859 } 01860 01861 const XMLConstHandle FirstChild() const { 01862 return XMLConstHandle( _node ? _node->FirstChild() : 0 ); 01863 } 01864 const XMLConstHandle FirstChildElement( const char* value=0 ) const { 01865 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 ); 01866 } 01867 const XMLConstHandle LastChild() const { 01868 return XMLConstHandle( _node ? _node->LastChild() : 0 ); 01869 } 01870 const XMLConstHandle LastChildElement( const char* _value=0 ) const { 01871 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 ); 01872 } 01873 const XMLConstHandle PreviousSibling() const { 01874 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); 01875 } 01876 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { 01877 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); 01878 } 01879 const XMLConstHandle NextSibling() const { 01880 return XMLConstHandle( _node ? _node->NextSibling() : 0 ); 01881 } 01882 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { 01883 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); 01884 } 01885 01886 01887 const XMLNode* ToNode() const { 01888 return _node; 01889 } 01890 const XMLElement* ToElement() const { 01891 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); 01892 } 01893 const XMLText* ToText() const { 01894 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); 01895 } 01896 const XMLUnknown* ToUnknown() const { 01897 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); 01898 } 01899 const XMLDeclaration* ToDeclaration() const { 01900 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); 01901 } 01902 01903 private: 01904 const XMLNode* _node; 01905 }; 01906 01907 01950 class TINYXML2_LIB XMLPrinter : public XMLVisitor 01951 { 01952 public: 01959 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); 01960 virtual ~XMLPrinter() {} 01961 01963 void PushHeader( bool writeBOM, bool writeDeclaration ); 01967 void OpenElement( const char* name, bool compactMode=false ); 01969 void PushAttribute( const char* name, const char* value ); 01970 void PushAttribute( const char* name, int value ); 01971 void PushAttribute( const char* name, unsigned value ); 01972 void PushAttribute( const char* name, bool value ); 01973 void PushAttribute( const char* name, double value ); 01975 virtual void CloseElement( bool compactMode=false ); 01976 01978 void PushText( const char* text, bool cdata=false ); 01980 void PushText( int value ); 01982 void PushText( unsigned value ); 01984 void PushText( bool value ); 01986 void PushText( float value ); 01988 void PushText( double value ); 01989 01991 void PushComment( const char* comment ); 01992 01993 void PushDeclaration( const char* value ); 01994 void PushUnknown( const char* value ); 01995 01996 virtual bool VisitEnter( const XMLDocument& /*doc*/ ); 01997 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { 01998 return true; 01999 } 02000 02001 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); 02002 virtual bool VisitExit( const XMLElement& element ); 02003 02004 virtual bool Visit( const XMLText& text ); 02005 virtual bool Visit( const XMLComment& comment ); 02006 virtual bool Visit( const XMLDeclaration& declaration ); 02007 virtual bool Visit( const XMLUnknown& unknown ); 02008 02013 const char* CStr() const { 02014 return _buffer.Mem(); 02015 } 02021 int CStrSize() const { 02022 return _buffer.Size(); 02023 } 02028 void ClearBuffer() { 02029 _buffer.Clear(); 02030 _buffer.Push(0); 02031 } 02032 02033 protected: 02034 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }; 02035 02039 virtual void PrintSpace( int depth ); 02040 void Print( const char* format, ... ); 02041 02042 void SealElement(); 02043 bool _elementJustOpened; 02044 DynArray< const char*, 10 > _stack; 02045 02046 private: 02047 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. 02048 02049 bool _firstElement; 02050 FILE* _fp; 02051 int _depth; 02052 int _textDepth; 02053 bool _processEntities; 02054 bool _compactMode; 02055 02056 enum { 02057 ENTITY_RANGE = 64, 02058 BUF_SIZE = 200 02059 }; 02060 bool _entityFlag[ENTITY_RANGE]; 02061 bool _restrictedEntityFlag[ENTITY_RANGE]; 02062 02063 DynArray< char, 20 > _buffer; 02064 #ifdef _MSC_VER 02065 DynArray< char, 20 > _accumulator; 02066 #endif 02067 }; 02068 02069 02070 } // tinyxml2 02071 02072 #if defined(_MSC_VER) 02073 # pragma warning(pop) 02074 #endif 02075 02076 #endif // TINYXML2_INCLUDED