TinyXML-2  2.1.0
tinyxml2.h
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
 All Classes Functions