blob: b0387e9acc8335eb5c3a85fe3f1b270e130cd6e4 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070027#ifdef ANDROID_NDK
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
48 g++ -Wall 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
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# if defined(_MSC_VER)
63# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64# elif defined (ANDROID_NDK)
65# include <android/log.h>
66# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67# else
68# include <assert.h>
69# define TIXMLASSERT assert
70# endif
71# else
72# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// Microsoft visual studio, version 2005 and higher.
78/*int _snprintf_s(
79 char *buffer,
80 size_t sizeOfBuffer,
81 size_t count,
82 const char *format [,
83 argument] ...
84);*/
85inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86{
87 va_list va;
88 va_start( va, format );
89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90 va_end( va );
91 return result;
92}
93#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700103static const int TIXML2_PATCH_VERSION = 8;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
111class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800112class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800113class XMLDeclaration;
114class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800115
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118/*
119 A class that wraps strings. Normally stores the start and end
120 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800121 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800122 manage) a traditional char[]
123*/
Lee Thomason39ede242012-01-20 11:27:56 -0800124class StrPair
125{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700127 enum {
128 NEEDS_ENTITY_PROCESSING = 0x01,
129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
Lee Thomason624d43f2012-10-12 10:58:48 -0700132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason624d43f2012-10-12 10:58:48 -0700134 ATTRIBUTE_NAME = 0,
135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700138 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 // After parsing, if *end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 int _flags;
177 char* _start;
178 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800187template <class T, int INIT>
188class DynArray
189{
190public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700192 _mem = _pool;
193 _allocated = INIT;
194 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700204 EnsureCapacity( _size+1 );
205 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700206 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 EnsureCapacity( _size+count );
210 T* ret = &_mem[_size];
211 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 return ret;
213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 TIXMLASSERT( _size >= count );
221 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700230 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700235 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800253
Lee Thomason2c85a712012-01-31 08:24:24 -0800254private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int newAllocated = cap * 2;
258 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
260 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700261 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
266 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800267
Lee Thomason624d43f2012-10-12 10:58:48 -0700268 T* _mem;
269 T _pool[INIT];
270 int _allocated; // objects allocated
271 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800272};
273
Lee Thomason50adb4c2012-02-13 15:07:09 -0800274
U-Stream\Leeae25a442012-02-17 17:48:16 -0800275/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200276 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800277 and deallocation of objects.
278*/
Lee Thomasond1983222012-02-06 08:41:24 -0800279class MemPool
280{
281public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 MemPool() {}
283 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800284
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 virtual int ItemSize() const = 0;
286 virtual void* Alloc() = 0;
287 virtual void Free( void* ) = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800288};
289
Lee Thomason50adb4c2012-02-13 15:07:09 -0800290
U-Stream\Leeae25a442012-02-17 17:48:16 -0800291/*
292 Template child class to create pools of the correct type.
293*/
Lee Thomasond1983222012-02-06 08:41:24 -0800294template< int SIZE >
295class MemPoolT : public MemPool
296{
297public:
Lee Thomason624d43f2012-10-12 10:58:48 -0700298 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700299 ~MemPoolT() {
300 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700301 for( int i=0; i<_blockPtrs.Size(); ++i ) {
302 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 }
304 }
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const {
307 return SIZE;
308 }
309 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700310 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700311 }
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700314 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700315 // Need a new block.
316 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700317 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800318
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700319 for( int i=0; i<COUNT-1; ++i ) {
320 block->chunk[i].next = &block->chunk[i+1];
321 }
322 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700325 void* result = _root;
326 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800327
Lee Thomason624d43f2012-10-12 10:58:48 -0700328 ++_currentAllocs;
329 if ( _currentAllocs > _maxAllocs ) {
330 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 _nAllocs++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 return result;
334 }
335 virtual void Free( void* mem ) {
336 if ( !mem ) {
337 return;
338 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700341#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 chunk->next = _root;
345 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
347 void Trace( const char* name ) {
348 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700350 }
Lee Thomasond1983222012-02-06 08:41:24 -0800351
Jerome Martinez7921df12012-10-24 11:45:44 +0200352 enum { COUNT = 1024/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
353
Lee Thomasond1983222012-02-06 08:41:24 -0800354private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700355 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700356 Chunk* next;
357 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700358 };
359 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700360 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 DynArray< Block*, 10 > _blockPtrs;
363 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800364
Lee Thomason624d43f2012-10-12 10:58:48 -0700365 int _currentAllocs;
366 int _nAllocs;
367 int _maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800368};
369
Lee Thomason2c85a712012-01-31 08:24:24 -0800370
Lee Thomason56bdd022012-02-09 18:16:58 -0800371
372/**
373 Implements the interface to the "Visitor pattern" (see the Accept() method.)
374 If you call the Accept() method, it requires being passed a XMLVisitor
375 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200376 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800377 are simply called with Visit().
378
379 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200380 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800381
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700382 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800383 visiting). You need to only override methods that are interesting to you.
384
Thomas Roß08bdf502012-05-12 14:21:23 +0200385 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800386
387 You should never change the document from a callback.
388
389 @sa XMLNode::Accept()
390*/
391class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800392{
393public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700394 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800395
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700396 /// Visit a document.
397 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
398 return true;
399 }
400 /// Visit a document.
401 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
402 return true;
403 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800404
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700405 /// Visit an element.
406 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
407 return true;
408 }
409 /// Visit an element.
410 virtual bool VisitExit( const XMLElement& /*element*/ ) {
411 return true;
412 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800413
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700414 /// Visit a declaration.
415 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
416 return true;
417 }
418 /// Visit a text node.
419 virtual bool Visit( const XMLText& /*text*/ ) {
420 return true;
421 }
422 /// Visit a comment node.
423 virtual bool Visit( const XMLComment& /*comment*/ ) {
424 return true;
425 }
426 /// Visit an unknown node.
427 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
428 return true;
429 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800430};
431
432
U-Stream\Leeae25a442012-02-17 17:48:16 -0800433/*
434 Utility functionality.
435*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800436class XMLUtil
437{
Lee Thomasond1983222012-02-06 08:41:24 -0800438public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700439 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
440 // correct, but simple, and usually works.
441 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200442 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700443 ++p;
444 }
445 return p;
446 }
447 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200448 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700449 ++p;
450 }
451 return p;
452 }
453 static bool IsWhiteSpace( char p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200454 return !IsUTF8Continuation(p) && std::isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700455 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800456
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700457 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
458 int n = 0;
459 if ( p == q ) {
460 return true;
461 }
462 while( *p && *q && *p == *q && n<nChar ) {
463 ++p;
464 ++q;
465 ++n;
466 }
467 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
468 return true;
469 }
470 return false;
471 }
472 inline static int IsUTF8Continuation( const char p ) {
473 return p & 0x80;
474 }
475 inline static int IsAlphaNum( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200476 return ( anyByte < 128 ) ? std::isalnum( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700477 }
478 inline static int IsAlpha( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200479 return ( anyByte < 128 ) ? std::isalpha( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800481
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700482 static const char* ReadBOM( const char* p, bool* hasBOM );
483 // p is the starting location,
484 // the UTF-8 value of the entity will be placed in value, and length filled in.
485 static const char* GetCharacterRef( const char* p, char* value, int* length );
486 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700487
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700488 // converts primitive types to strings
489 static void ToStr( int v, char* buffer, int bufferSize );
490 static void ToStr( unsigned v, char* buffer, int bufferSize );
491 static void ToStr( bool v, char* buffer, int bufferSize );
492 static void ToStr( float v, char* buffer, int bufferSize );
493 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700494
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700495 // converts strings to primitive types
496 static bool ToInt( const char* str, int* value );
497 static bool ToUnsigned( const char* str, unsigned* value );
498 static bool ToBool( const char* str, bool* value );
499 static bool ToFloat( const char* str, float* value );
500 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800501};
502
Lee Thomason5cae8972012-01-24 18:03:07 -0800503
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800504/** XMLNode is a base class for every object that is in the
505 XML Document Object Model (DOM), except XMLAttributes.
506 Nodes have siblings, a parent, and children which can
507 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700508 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800509 be cast to its more defined type.
510
Thomas Roß08bdf502012-05-12 14:21:23 +0200511 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800512 When the XMLDocument gets deleted, all its Nodes
513 will also be deleted.
514
515 @verbatim
516 A Document can contain: Element (container or leaf)
517 Comment (leaf)
518 Unknown (leaf)
519 Declaration( leaf )
520
521 An Element can contain: Element (container or leaf)
522 Text (leaf)
523 Attributes (not on tree)
524 Comment (leaf)
525 Unknown (leaf)
526
527 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800528*/
Lee Thomasond1983222012-02-06 08:41:24 -0800529class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800530{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 friend class XMLDocument;
532 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800533public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800534
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700535 /// Get the XMLDocument that owns this XMLNode.
536 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700537 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700538 }
539 /// Get the XMLDocument that owns this XMLNode.
540 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700541 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700542 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800543
Lee Thomason2fa81722012-11-09 12:37:46 -0800544 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700545 virtual XMLElement* ToElement() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800546 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700547 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800548 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700549 virtual XMLText* ToText() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800550 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700551 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800552 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700553 virtual XMLComment* ToComment() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800554 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700555 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800556 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700557 virtual XMLDocument* ToDocument() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800558 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700559 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800560 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700561 virtual XMLDeclaration* ToDeclaration() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800562 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700563 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800564 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700565 virtual XMLUnknown* ToUnknown() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800566 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700567 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800568
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700569 virtual const XMLElement* ToElement() const {
570 return 0;
571 }
572 virtual const XMLText* ToText() const {
573 return 0;
574 }
575 virtual const XMLComment* ToComment() const {
576 return 0;
577 }
578 virtual const XMLDocument* ToDocument() const {
579 return 0;
580 }
581 virtual const XMLDeclaration* ToDeclaration() const {
582 return 0;
583 }
584 virtual const XMLUnknown* ToUnknown() const {
585 return 0;
586 }
Lee Thomason751da522012-02-10 08:50:51 -0800587
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 /** The meaning of 'value' changes for the specific type.
589 @verbatim
590 Document: empty
591 Element: name of the element
592 Comment: the comment text
593 Unknown: the tag contents
594 Text: the text string
595 @endverbatim
596 */
597 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700598 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700599 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700600
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 /** Set the Value of an XML node.
602 @sa Value()
603 */
604 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800605
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 /// Get the parent of this node on the DOM.
607 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700608 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700609 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700610
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700612 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700613 }
Lee Thomason751da522012-02-10 08:50:51 -0800614
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700615 /// Returns true if this node has no children.
616 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700617 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 }
Lee Thomason751da522012-02-10 08:50:51 -0800619
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700620 /// Get the first child node, or null if none exists.
621 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700622 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700623 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700624
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700625 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700626 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700627 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700628
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 /** Get the first child element, or optionally the first child
630 element with the specified name.
631 */
632 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700633
634 XMLElement* FirstChildElement( const char* value=0 ) {
635 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700636 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800637
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700638 /// Get the last child node, or null if none exists.
639 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700640 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700642
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 XMLNode* LastChild() {
644 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
645 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800646
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 /** Get the last child element or optionally the last child
648 element with the specified name.
649 */
650 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700651
652 XMLElement* LastChildElement( const char* value=0 ) {
653 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700655
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 /// Get the previous (left) sibling node of this node.
657 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700658 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700660
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700662 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800664
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
666 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700667
668 XMLElement* PreviousSiblingElement( const char* value=0 ) {
669 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700671
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 /// Get the next (right) sibling node of this node.
673 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700674 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700676
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700677 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700678 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700679 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700680
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
682 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700683
684 XMLElement* NextSiblingElement( const char* value=0 ) {
685 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800687
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 /**
689 Add a child node as the last (right) child.
690 */
691 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800692
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700693 XMLNode* LinkEndChild( XMLNode* addThis ) {
694 return InsertEndChild( addThis );
695 }
696 /**
697 Add a child node as the first (left) child.
698 */
699 XMLNode* InsertFirstChild( XMLNode* addThis );
700 /**
701 Add a node after the specified child node.
702 */
703 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 /**
706 Delete all the children of this node.
707 */
708 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800709
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 /**
711 Delete a child of this node.
712 */
713 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 /**
716 Make a copy of this node, but not its children.
717 You may pass in a Document pointer that will be
718 the owner of the new Node. If the 'document' is
719 null, then the node returned will be allocated
720 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800721
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700722 Note: if called on a XMLDocument, this will return null.
723 */
724 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 /**
727 Test if 2 nodes are the same, but don't test children.
728 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800729
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700730 Note: if called on a XMLDocument, this will return false.
731 */
732 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
735 XML tree will be conditionally visited and the host will be called back
736 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
739 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
740 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800741
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800743
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700744 - http://www.saxproject.org/
745 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800746
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700747 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800748
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 An example of using Accept():
750 @verbatim
751 TiXmlPrinter printer;
752 tinyxmlDoc.Accept( &printer );
753 const char* xmlcstr = printer.CStr();
754 @endverbatim
755 */
756 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800757
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700758 // internal
759 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800760
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800761protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 XMLNode( XMLDocument* );
763 virtual ~XMLNode();
764 XMLNode( const XMLNode& ); // not supported
765 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700766
Lee Thomason624d43f2012-10-12 10:58:48 -0700767 XMLDocument* _document;
768 XMLNode* _parent;
769 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800770
Lee Thomason624d43f2012-10-12 10:58:48 -0700771 XMLNode* _firstChild;
772 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800773
Lee Thomason624d43f2012-10-12 10:58:48 -0700774 XMLNode* _prev;
775 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800776
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800777private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700778 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700779 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800780};
781
782
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800783/** XML text.
784
785 Note that a text node can have child element nodes, for example:
786 @verbatim
787 <root>This is <b>bold</b></root>
788 @endverbatim
789
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700790 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800791 and CDATA. It will default to the mode it was parsed from the XML file and
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700792 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800793 SetCDATA() and query it with CDATA().
794*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800795class XMLText : public XMLNode
796{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700797 friend class XMLBase;
798 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800799public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800801
Lee Thomason624d43f2012-10-12 10:58:48 -0700802 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 return this;
804 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700805 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 return this;
807 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800808
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700810 void SetCData( bool isCData ) {
811 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 }
813 /// Returns true if this is a CDATA text element.
814 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700815 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700816 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800817
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700818 char* ParseDeep( char*, StrPair* endTag );
819 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
820 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800821
Lee Thomason5492a1c2012-01-23 15:32:10 -0800822protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700823 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700824 virtual ~XMLText() {}
825 XMLText( const XMLText& ); // not supported
826 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800827
828private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700829 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800830};
831
832
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800833/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800834class XMLComment : public XMLNode
835{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700836 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800837public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700838 virtual XMLComment* ToComment() {
839 return this;
840 }
841 virtual const XMLComment* ToComment() const {
842 return this;
843 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800844
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700845 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800846
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 char* ParseDeep( char*, StrPair* endTag );
848 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
849 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800850
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800851protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 XMLComment( XMLDocument* doc );
853 virtual ~XMLComment();
854 XMLComment( const XMLComment& ); // not supported
855 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800856
Lee Thomason3f57d272012-01-11 15:30:03 -0800857private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800858};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800859
860
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800861/** In correct XML the declaration is the first entry in the file.
862 @verbatim
863 <?xml version="1.0" standalone="yes"?>
864 @endverbatim
865
866 TinyXML2 will happily read or write files without a declaration,
867 however.
868
869 The text of the declaration isn't interpreted. It is parsed
870 and written as a string.
871*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800872class XMLDeclaration : public XMLNode
873{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700874 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800875public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 virtual XMLDeclaration* ToDeclaration() {
877 return this;
878 }
879 virtual const XMLDeclaration* ToDeclaration() const {
880 return this;
881 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800882
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800884
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 char* ParseDeep( char*, StrPair* endTag );
886 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
887 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800888
889protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700890 XMLDeclaration( XMLDocument* doc );
891 virtual ~XMLDeclaration();
892 XMLDeclaration( const XMLDeclaration& ); // not supported
893 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800894};
895
896
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800897/** Any tag that tinyXml doesn't recognize is saved as an
898 unknown. It is a tag of text, but should not be modified.
899 It will be written back to the XML, unchanged, when the file
900 is saved.
901
902 DTD tags get thrown into TiXmlUnknowns.
903*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800904class XMLUnknown : public XMLNode
905{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700906 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800907public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700908 virtual XMLUnknown* ToUnknown() {
909 return this;
910 }
911 virtual const XMLUnknown* ToUnknown() const {
912 return this;
913 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800914
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800916
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700917 char* ParseDeep( char*, StrPair* endTag );
918 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
919 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800920
921protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 XMLUnknown( XMLDocument* doc );
923 virtual ~XMLUnknown();
924 XMLUnknown( const XMLUnknown& ); // not supported
925 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800926};
927
928
Lee Thomason2fa81722012-11-09 12:37:46 -0800929enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700930 XML_NO_ERROR = 0,
931 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800932
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700933 XML_NO_ATTRIBUTE,
934 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800935
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 XML_ERROR_FILE_NOT_FOUND,
937 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
938 XML_ERROR_FILE_READ_ERROR,
939 XML_ERROR_ELEMENT_MISMATCH,
940 XML_ERROR_PARSING_ELEMENT,
941 XML_ERROR_PARSING_ATTRIBUTE,
942 XML_ERROR_IDENTIFYING_TAG,
943 XML_ERROR_PARSING_TEXT,
944 XML_ERROR_PARSING_CDATA,
945 XML_ERROR_PARSING_COMMENT,
946 XML_ERROR_PARSING_DECLARATION,
947 XML_ERROR_PARSING_UNKNOWN,
948 XML_ERROR_EMPTY_DOCUMENT,
949 XML_ERROR_MISMATCHED_ELEMENT,
950 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700951
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700952 XML_CAN_NOT_CONVERT_TEXT,
953 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800954};
955
956
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800957/** An attribute is a name-value pair. Elements have an arbitrary
958 number of attributes, each with a unique name.
959
960 @note The attributes are not XMLNodes. You may only query the
961 Next() attribute in a list.
962*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800963class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800964{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700965 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800966public:
Lee Thomason2fa81722012-11-09 12:37:46 -0800967 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700968 const char* Name() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800969 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700970 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800971 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700972 const char* Value() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800973 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700974 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800975 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 const XMLAttribute* Next() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800977 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700978 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800979
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700980 /** IntAttribute interprets the attribute as an integer, and returns the value.
981 If the value isn't an integer, 0 will be returned. There is no error checking;
982 use QueryIntAttribute() if you need error checking.
983 */
984 int IntValue() const {
985 int i=0;
986 QueryIntValue( &i );
987 return i;
988 }
989 /// Query as an unsigned integer. See IntAttribute()
990 unsigned UnsignedValue() const {
991 unsigned i=0;
992 QueryUnsignedValue( &i );
993 return i;
994 }
995 /// Query as a boolean. See IntAttribute()
996 bool BoolValue() const {
997 bool b=false;
998 QueryBoolValue( &b );
999 return b;
1000 }
1001 /// Query as a double. See IntAttribute()
1002 double DoubleValue() const {
1003 double d=0;
1004 QueryDoubleValue( &d );
1005 return d;
1006 }
1007 /// Query as a float. See IntAttribute()
1008 float FloatValue() const {
1009 float f=0;
1010 QueryFloatValue( &f );
1011 return f;
1012 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001013
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
1015 in the provided paremeter. The function will return XML_NO_ERROR on success,
1016 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1017 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001018 XMLError QueryIntValue( int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001020 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001021 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001022 XMLError QueryBoolValue( bool* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001023 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001024 XMLError QueryDoubleValue( double* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001026 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001027
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001028 /// Set the attribute to a string value.
1029 void SetAttribute( const char* value );
1030 /// Set the attribute to value.
1031 void SetAttribute( int value );
1032 /// Set the attribute to value.
1033 void SetAttribute( unsigned value );
1034 /// Set the attribute to value.
1035 void SetAttribute( bool value );
1036 /// Set the attribute to value.
1037 void SetAttribute( double value );
1038 /// Set the attribute to value.
1039 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001040
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001041private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001043
Lee Thomason624d43f2012-10-12 10:58:48 -07001044 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001045 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001046
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 XMLAttribute( const XMLAttribute& ); // not supported
1048 void operator=( const XMLAttribute& ); // not supported
1049 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001050
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001052
Lee Thomason624d43f2012-10-12 10:58:48 -07001053 mutable StrPair _name;
1054 mutable StrPair _value;
1055 XMLAttribute* _next;
1056 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001057};
1058
1059
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001060/** The element is a container class. It has a value, the element name,
1061 and can contain other elements, text, comments, and unknowns.
1062 Elements also contain an arbitrary number of attributes.
1063*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001064class XMLElement : public XMLNode
1065{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001066 friend class XMLBase;
1067 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001068public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001069 /// Get the name of an element (which is the Value() of the node.)
1070 const char* Name() const {
1071 return Value();
1072 }
1073 /// Set the name of the element.
1074 void SetName( const char* str, bool staticMem=false ) {
1075 SetValue( str, staticMem );
1076 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001077
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001078 virtual XMLElement* ToElement() {
1079 return this;
1080 }
1081 virtual const XMLElement* ToElement() const {
1082 return this;
1083 }
1084 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001085
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001086 /** Given an attribute name, Attribute() returns the value
1087 for the attribute of that name, or null if none
1088 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001089
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001090 @verbatim
1091 const char* value = ele->Attribute( "foo" );
1092 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001093
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001094 The 'value' parameter is normally null. However, if specified,
1095 the attribute will only be returned if the 'name' and 'value'
1096 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001097
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001098 @verbatim
1099 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1100 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001101
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001102 rather than:
1103 @verbatim
1104 if ( ele->Attribute( "foo" ) ) {
1105 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1106 }
1107 @endverbatim
1108 */
1109 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001110
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001111 /** Given an attribute name, IntAttribute() returns the value
1112 of the attribute interpreted as an integer. 0 will be
1113 returned if there is an error. For a method with error
1114 checking, see QueryIntAttribute()
1115 */
1116 int IntAttribute( const char* name ) const {
1117 int i=0;
1118 QueryIntAttribute( name, &i );
1119 return i;
1120 }
1121 /// See IntAttribute()
1122 unsigned UnsignedAttribute( const char* name ) const {
1123 unsigned i=0;
1124 QueryUnsignedAttribute( name, &i );
1125 return i;
1126 }
1127 /// See IntAttribute()
1128 bool BoolAttribute( const char* name ) const {
1129 bool b=false;
1130 QueryBoolAttribute( name, &b );
1131 return b;
1132 }
1133 /// See IntAttribute()
1134 double DoubleAttribute( const char* name ) const {
1135 double d=0;
1136 QueryDoubleAttribute( name, &d );
1137 return d;
1138 }
1139 /// See IntAttribute()
1140 float FloatAttribute( const char* name ) const {
1141 float f=0;
1142 QueryFloatAttribute( name, &f );
1143 return f;
1144 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001145
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 /** Given an attribute name, QueryIntAttribute() returns
1147 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1148 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1149 doesn't exist. If successful, the result of the conversion
1150 will be written to 'value'. If not successful, nothing will
1151 be written to 'value'. This allows you to provide default
1152 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001153
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001154 @verbatim
1155 int value = 10;
1156 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1157 @endverbatim
1158 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001159 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001160 const XMLAttribute* a = FindAttribute( name );
1161 if ( !a ) {
1162 return XML_NO_ATTRIBUTE;
1163 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001164 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001165 }
1166 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001167 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001168 const XMLAttribute* a = FindAttribute( name );
1169 if ( !a ) {
1170 return XML_NO_ATTRIBUTE;
1171 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001172 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001173 }
1174 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001175 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001176 const XMLAttribute* a = FindAttribute( name );
1177 if ( !a ) {
1178 return XML_NO_ATTRIBUTE;
1179 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001180 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001181 }
1182 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001183 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001184 const XMLAttribute* a = FindAttribute( name );
1185 if ( !a ) {
1186 return XML_NO_ATTRIBUTE;
1187 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001188 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001189 }
1190 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001191 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 const XMLAttribute* a = FindAttribute( name );
1193 if ( !a ) {
1194 return XML_NO_ATTRIBUTE;
1195 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001196 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001197 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001198
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001199 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001200 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001201 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001202 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001203 }
1204 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001205 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001206 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001207 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 }
1209 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001210 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001211 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001212 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001213 }
1214 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001215 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001217 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 }
1219 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001220 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001222 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001224
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 /**
1226 Delete an attribute.
1227 */
1228 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001229
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 /// Return the first attribute in the list.
1231 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001232 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 }
1234 /// Query a specific attribute in the list.
1235 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001236
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 /** Convenience function for easy access to the text inside an element. Although easy
1238 and concise, GetText() is limited compared to getting the TiXmlText child
1239 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001240
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 If the first child of 'this' is a TiXmlText, the GetText()
1242 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001243
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 This is a convenient method for getting the text of simple contained text:
1245 @verbatim
1246 <foo>This is text</foo>
1247 const char* str = fooElement->GetText();
1248 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001249
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001250 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001251
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 Note that this function can be misleading. If the element foo was created from
1253 this XML:
1254 @verbatim
1255 <foo><b>This is text</b></foo>
1256 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001257
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001258 then the value of str would be null. The first child node isn't a text node, it is
1259 another element. From this XML:
1260 @verbatim
1261 <foo>This is <b>text</b></foo>
1262 @endverbatim
1263 GetText() will return "This is ".
1264 */
1265 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001266
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001267 /**
1268 Convenience method to query the value of a child text node. This is probably best
1269 shown by example. Given you have a document is this form:
1270 @verbatim
1271 <point>
1272 <x>1</x>
1273 <y>1.4</y>
1274 </point>
1275 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001276
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001277 The QueryIntText() and similar functions provide a safe and easier way to get to the
1278 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001279
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001280 @verbatim
1281 int x = 0;
1282 float y = 0; // types of x and y are contrived for example
1283 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1284 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1285 xElement->QueryIntText( &x );
1286 yElement->QueryFloatText( &y );
1287 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001288
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001289 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1290 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001291
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001293 XMLError QueryIntText( int* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001294 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001295 XMLError QueryUnsignedText( unsigned* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001297 XMLError QueryBoolText( bool* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001298 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001299 XMLError QueryDoubleText( double* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001301 XMLError QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001302
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 // internal:
1304 enum {
1305 OPEN, // <foo>
1306 CLOSED, // <foo/>
1307 CLOSING // </foo>
1308 };
1309 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001310 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 }
1312 char* ParseDeep( char* p, StrPair* endTag );
1313 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1314 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001315
Lee Thomason50adb4c2012-02-13 15:07:09 -08001316private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 XMLElement( XMLDocument* doc );
1318 virtual ~XMLElement();
1319 XMLElement( const XMLElement& ); // not supported
1320 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001321
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 XMLAttribute* FindAttribute( const char* name );
1323 XMLAttribute* FindOrCreateAttribute( const char* name );
1324 //void LinkAttribute( XMLAttribute* attrib );
1325 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001326
Lee Thomason624d43f2012-10-12 10:58:48 -07001327 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001328 // The attribute list is ordered; there is no 'lastAttribute'
1329 // because the list needs to be scanned for dupes before adding
1330 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001331 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001332};
1333
1334
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001335enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001336 PRESERVE_WHITESPACE,
1337 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001338};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001339
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001340
1341/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001342 It can be saved, loaded, and printed to the screen.
1343 All Nodes are connected and allocated to a Document.
1344 If the Document is deleted, all its Nodes are also deleted.
1345*/
Lee Thomason67d61312012-01-24 16:01:51 -08001346class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001347{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001348 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001349public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001350 /// constructor
1351 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1352 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001353
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001354 virtual XMLDocument* ToDocument() {
1355 return this;
1356 }
1357 virtual const XMLDocument* ToDocument() const {
1358 return this;
1359 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001360
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 /**
1362 Parse an XML file from a character string.
1363 Returns XML_NO_ERROR (0) on success, or
1364 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001365
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001366 You may optionally pass in the 'nBytes', which is
1367 the number of bytes which will be parsed. If not
1368 specified, TinyXML will assume 'xml' points to a
1369 null terminated string.
1370 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001371 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001372
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 /**
1374 Load an XML file from disk.
1375 Returns XML_NO_ERROR (0) on success, or
1376 an errorID.
1377 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001378 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001379
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /**
1381 Load an XML file from disk. You are responsible
1382 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001383
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 Returns XML_NO_ERROR (0) on success, or
1385 an errorID.
1386 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001387 XMLError LoadFile( std::FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001388
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001389 /**
1390 Save the XML file to disk.
1391 Returns XML_NO_ERROR (0) on success, or
1392 an errorID.
1393 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001394 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001395
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 /**
1397 Save the XML file to disk. You are responsible
1398 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001399
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001400 Returns XML_NO_ERROR (0) on success, or
1401 an errorID.
1402 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001403 XMLError SaveFile( std::FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001404
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001406 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 }
1408 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001409 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001410 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001411
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001412 /**
1413 Returns true if this document has a leading Byte Order Mark of UTF8.
1414 */
1415 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001416 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001417 }
1418 /** Sets whether to write the BOM when writing the file.
1419 */
1420 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001421 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001422 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001423
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 /** Return the root element of DOM. Equivalent to FirstChildElement().
1425 To get the first node, use FirstChild().
1426 */
1427 XMLElement* RootElement() {
1428 return FirstChildElement();
1429 }
1430 const XMLElement* RootElement() const {
1431 return FirstChildElement();
1432 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001433
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 /** Print the Document. If the Printer is not provided, it will
1435 print to stdout. If you provide Printer, this can print to a file:
1436 @verbatim
1437 XMLPrinter printer( fp );
1438 doc.Print( &printer );
1439 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001440
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 Or you can use a printer to print to memory:
1442 @verbatim
1443 XMLPrinter printer;
1444 doc->Print( &printer );
1445 // printer.CStr() has a const char* to the XML
1446 @endverbatim
1447 */
1448 void Print( XMLPrinter* streamer=0 );
1449 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001450
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001451 /**
1452 Create a new Element associated with
1453 this Document. The memory for the Element
1454 is managed by the Document.
1455 */
1456 XMLElement* NewElement( const char* name );
1457 /**
1458 Create a new Comment associated with
1459 this Document. The memory for the Comment
1460 is managed by the Document.
1461 */
1462 XMLComment* NewComment( const char* comment );
1463 /**
1464 Create a new Text associated with
1465 this Document. The memory for the Text
1466 is managed by the Document.
1467 */
1468 XMLText* NewText( const char* text );
1469 /**
1470 Create a new Declaration associated with
1471 this Document. The memory for the object
1472 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001473
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001474 If the 'text' param is null, the standard
1475 declaration is used.:
1476 @verbatim
1477 <?xml version="1.0" encoding="UTF-8"?>
1478 @endverbatim
1479 */
1480 XMLDeclaration* NewDeclaration( const char* text=0 );
1481 /**
1482 Create a new Unknown associated with
Lee Thomason624d43f2012-10-12 10:58:48 -07001483 this Document. The memory forthe object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001484 is managed by the Document.
1485 */
1486 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001487
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 /**
1489 Delete a node associated with this document.
1490 It will be unlinked from the DOM.
1491 */
1492 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001493 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001494 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001495
Lee Thomason2fa81722012-11-09 12:37:46 -08001496 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001497
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001498 /// Return true if there was an error parsing the document.
1499 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001500 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001501 }
1502 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001503 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001504 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 }
1506 /// Return a possibly helpful diagnostic location or string.
1507 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001508 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001509 }
1510 /// Return a possibly helpful secondary diagnostic location or string.
1511 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001512 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 }
1514 /// If there is an error, print it to stdout.
1515 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 // internal
1518 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1521 return 0;
1522 }
1523 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1524 return false;
1525 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001526
Lee Thomason3f57d272012-01-11 15:30:03 -08001527private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 XMLDocument( const XMLDocument& ); // not supported
1529 void operator=( const XMLDocument& ); // not supported
1530 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001531
Lee Thomason2fa81722012-11-09 12:37:46 -08001532 bool _writeBOM;
1533 bool _processEntities;
1534 XMLError _errorID;
1535 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001536 const char* _errorStr1;
1537 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001538 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001539
Lee Thomason624d43f2012-10-12 10:58:48 -07001540 MemPoolT< sizeof(XMLElement) > _elementPool;
1541 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1542 MemPoolT< sizeof(XMLText) > _textPool;
1543 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001544};
1545
Lee Thomason7c913cd2012-01-26 18:32:34 -08001546
Lee Thomason3ffdd392012-03-28 17:27:55 -07001547/**
1548 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001549 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001550 DOM structure. It is a separate utility class.
1551
1552 Take an example:
1553 @verbatim
1554 <Document>
1555 <Element attributeA = "valueA">
1556 <Child attributeB = "value1" />
1557 <Child attributeB = "value2" />
1558 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001559 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001560 @endverbatim
1561
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001562 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001563 easy to write a *lot* of code that looks like:
1564
1565 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001566 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001567 if ( root )
1568 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001569 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001570 if ( element )
1571 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001572 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001573 if ( child )
1574 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001575 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001576 if ( child2 )
1577 {
1578 // Finally do something useful.
1579 @endverbatim
1580
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001581 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001582 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001583 and correct to use:
1584
1585 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001586 XMLHandle docHandle( &document );
1587 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001588 if ( child2 )
1589 {
1590 // do something useful
1591 @endverbatim
1592
1593 Which is MUCH more concise and useful.
1594
1595 It is also safe to copy handles - internally they are nothing more than node pointers.
1596 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001597 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001598 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001599
1600 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001601*/
1602class XMLHandle
1603{
1604public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001605 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Lee Thomason624d43f2012-10-12 10:58:48 -07001606 XMLHandle( XMLNode* node ) {
1607 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001608 }
1609 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001610 XMLHandle( XMLNode& node ) {
1611 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001612 }
1613 /// Copy constructor
1614 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001615 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 }
1617 /// Assignment
1618 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001619 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001620 return *this;
1621 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001622
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001623 /// Get the first child of this handle.
1624 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001625 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 }
1627 /// Get the first child element of this handle.
1628 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001629 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001630 }
1631 /// Get the last child of this handle.
1632 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001633 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001634 }
1635 /// Get the last child element of this handle.
1636 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001637 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001638 }
1639 /// Get the previous sibling of this handle.
1640 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001641 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001642 }
1643 /// Get the previous sibling element of this handle.
1644 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001645 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 }
1647 /// Get the next sibling of this handle.
1648 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001649 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 }
1651 /// Get the next sibling element of this handle.
1652 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001653 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001655
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001656 /// Safe cast to XMLNode. This can return null.
1657 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001658 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 }
1660 /// Safe cast to XMLElement. This can return null.
1661 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001662 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001663 }
1664 /// Safe cast to XMLText. This can return null.
1665 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001666 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 }
1668 /// Safe cast to XMLUnknown. This can return null.
1669 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001670 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 }
1672 /// Safe cast to XMLDeclaration. This can return null.
1673 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001674 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001675 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001676
1677private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001678 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001679};
1680
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001681
1682/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001683 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1684 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001685*/
1686class XMLConstHandle
1687{
1688public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001689 XMLConstHandle( const XMLNode* node ) {
1690 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001692 XMLConstHandle( const XMLNode& node ) {
1693 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001694 }
1695 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001696 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
Lee Thomason8b899812012-04-04 15:58:16 -07001698
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001699 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 return *this;
1702 }
Lee Thomason8b899812012-04-04 15:58:16 -07001703
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001704 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001705 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 }
1707 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001708 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 }
1710 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001711 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 }
1713 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
1719 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001720 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001721 }
1722 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001723 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 }
1725 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
Lee Thomason8b899812012-04-04 15:58:16 -07001728
1729
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001730 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001731 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 }
1733 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001737 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001738 }
1739 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001740 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 }
1742 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001743 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001745
Lee Thomason5cae8972012-01-24 18:03:07 -08001746private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001748};
Lee Thomason6f381b72012-03-02 12:59:39 -08001749
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001750
1751/**
1752 Printing functionality. The XMLPrinter gives you more
1753 options than the XMLDocument::Print() method.
1754
1755 It can:
1756 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001757 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001758 -# Print XML without a XMLDocument.
1759
1760 Print to Memory
1761
1762 @verbatim
1763 XMLPrinter printer;
1764 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001765 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001766 @endverbatim
1767
1768 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001769
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001770 You provide the file pointer.
1771 @verbatim
1772 XMLPrinter printer( fp );
1773 doc.Print( &printer );
1774 @endverbatim
1775
1776 Print without a XMLDocument
1777
1778 When loading, an XML parser is very useful. However, sometimes
1779 when saving, it just gets in the way. The code is often set up
1780 for streaming, and constructing the DOM is just overhead.
1781
1782 The Printer supports the streaming case. The following code
1783 prints out a trivially simple XML file without ever creating
1784 an XML document.
1785
1786 @verbatim
1787 XMLPrinter printer( fp );
1788 printer.OpenElement( "foo" );
1789 printer.PushAttribute( "foo", "bar" );
1790 printer.CloseElement();
1791 @endverbatim
1792*/
1793class XMLPrinter : public XMLVisitor
1794{
1795public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 /** Construct the printer. If the FILE* is specified,
1797 this will print to the FILE. Else it will print
1798 to memory, and the result is available in CStr().
1799 If 'compact' is set to true, then output is created
1800 with only required whitespace and newlines.
1801 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001802 XMLPrinter( std::FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001804
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001805 /** If streaming, write the BOM and declaration. */
1806 void PushHeader( bool writeBOM, bool writeDeclaration );
1807 /** If streaming, start writing an element.
1808 The element must be closed with CloseElement()
1809 */
1810 void OpenElement( const char* name );
1811 /// If streaming, add an attribute to an open element.
1812 void PushAttribute( const char* name, const char* value );
1813 void PushAttribute( const char* name, int value );
1814 void PushAttribute( const char* name, unsigned value );
1815 void PushAttribute( const char* name, bool value );
1816 void PushAttribute( const char* name, double value );
1817 /// If streaming, close the Element.
1818 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001819
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001820 /// Add a text node.
1821 void PushText( const char* text, bool cdata=false );
1822 /// Add a text node from an integer.
1823 void PushText( int value );
1824 /// Add a text node from an unsigned.
1825 void PushText( unsigned value );
1826 /// Add a text node from a bool.
1827 void PushText( bool value );
1828 /// Add a text node from a float.
1829 void PushText( float value );
1830 /// Add a text node from a double.
1831 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001832
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001833 /// Add a comment
1834 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001835
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001836 void PushDeclaration( const char* value );
1837 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001838
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001839 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1840 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1841 return true;
1842 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001843
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001844 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1845 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001846
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001847 virtual bool Visit( const XMLText& text );
1848 virtual bool Visit( const XMLComment& comment );
1849 virtual bool Visit( const XMLDeclaration& declaration );
1850 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001851
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001852 /**
1853 If in print to memory mode, return a pointer to
1854 the XML file in memory.
1855 */
1856 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001857 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001858 }
1859 /**
1860 If in print to memory mode, return the size
1861 of the XML file in memory. (Note the size returned
1862 includes the terminating null.)
1863 */
1864 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001867
1868private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001869 void SealElement();
1870 void PrintSpace( int depth );
1871 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1872 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001873
Lee Thomason624d43f2012-10-12 10:58:48 -07001874 bool _elementJustOpened;
1875 bool _firstElement;
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001876 std::FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 int _depth;
1878 int _textDepth;
1879 bool _processEntities;
1880 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001881
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 enum {
1883 ENTITY_RANGE = 64,
1884 BUF_SIZE = 200
1885 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001886 bool _entityFlag[ENTITY_RANGE];
1887 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001888
Lee Thomason624d43f2012-10-12 10:58:48 -07001889 DynArray< const char*, 10 > _stack;
1890 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001891#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001892 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001893#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001894};
1895
1896
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001897} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001898
1899
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001900#endif // TINYXML2_INCLUDED