blob: 55f57a31a743c3219b003181f7429338b7f986dd [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
Jerome Martinez242c3ea2013-01-06 12:20:04 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__)
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:
Lee Thomason5b0a6772012-11-19 13:54:42 -080048 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
Lee Thomasona9cf3f92012-10-11 16:56:51 -070049
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 Thomason5b0a6772012-11-19 13:54:42 -0800101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
103static const int TIXML2_PATCH_VERSION = 9;
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 Thomason5b0a6772012-11-19 13:54:42 -0800288 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800289};
290
Lee Thomason50adb4c2012-02-13 15:07:09 -0800291
U-Stream\Leeae25a442012-02-17 17:48:16 -0800292/*
293 Template child class to create pools of the correct type.
294*/
Lee Thomasond1983222012-02-06 08:41:24 -0800295template< int SIZE >
296class MemPoolT : public MemPool
297{
298public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800299 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700300 ~MemPoolT() {
301 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700302 for( int i=0; i<_blockPtrs.Size(); ++i ) {
303 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700304 }
305 }
Lee Thomasond1983222012-02-06 08:41:24 -0800306
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700307 virtual int ItemSize() const {
308 return SIZE;
309 }
310 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700311 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700312 }
Lee Thomasond1983222012-02-06 08:41:24 -0800313
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700314 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700315 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700316 // Need a new block.
317 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700318 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800319
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700320 for( int i=0; i<COUNT-1; ++i ) {
321 block->chunk[i].next = &block->chunk[i+1];
322 }
323 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700324 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700326 void* result = _root;
327 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800328
Lee Thomason624d43f2012-10-12 10:58:48 -0700329 ++_currentAllocs;
330 if ( _currentAllocs > _maxAllocs ) {
331 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700333 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800334 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 return result;
336 }
337 virtual void Free( void* mem ) {
338 if ( !mem ) {
339 return;
340 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700341 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700345#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 chunk->next = _root;
347 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 }
349 void Trace( const char* name ) {
350 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700351 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700352 }
Lee Thomasond1983222012-02-06 08:41:24 -0800353
Lee Thomason5b0a6772012-11-19 13:54:42 -0800354 void SetTracked() {
355 _nUntracked--;
356 }
357
358 int Untracked() const {
359 return _nUntracked;
360 }
361
Jerome Martinez7921df12012-10-24 11:45:44 +0200362 enum { COUNT = 1024/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
363
Lee Thomasond1983222012-02-06 08:41:24 -0800364private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700366 Chunk* next;
367 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700368 };
369 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700370 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700371 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 DynArray< Block*, 10 > _blockPtrs;
373 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800374
Lee Thomason624d43f2012-10-12 10:58:48 -0700375 int _currentAllocs;
376 int _nAllocs;
377 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800378 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800379};
380
Lee Thomason2c85a712012-01-31 08:24:24 -0800381
Lee Thomason56bdd022012-02-09 18:16:58 -0800382
383/**
384 Implements the interface to the "Visitor pattern" (see the Accept() method.)
385 If you call the Accept() method, it requires being passed a XMLVisitor
386 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200387 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800388 are simply called with Visit().
389
390 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200391 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800392
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700393 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800394 visiting). You need to only override methods that are interesting to you.
395
Thomas Roß08bdf502012-05-12 14:21:23 +0200396 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800397
398 You should never change the document from a callback.
399
400 @sa XMLNode::Accept()
401*/
402class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800403{
404public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700405 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800406
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700407 /// Visit a document.
408 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
409 return true;
410 }
411 /// Visit a document.
412 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
413 return true;
414 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800415
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700416 /// Visit an element.
417 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
418 return true;
419 }
420 /// Visit an element.
421 virtual bool VisitExit( const XMLElement& /*element*/ ) {
422 return true;
423 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800424
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700425 /// Visit a declaration.
426 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
427 return true;
428 }
429 /// Visit a text node.
430 virtual bool Visit( const XMLText& /*text*/ ) {
431 return true;
432 }
433 /// Visit a comment node.
434 virtual bool Visit( const XMLComment& /*comment*/ ) {
435 return true;
436 }
437 /// Visit an unknown node.
438 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
439 return true;
440 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800441};
442
443
U-Stream\Leeae25a442012-02-17 17:48:16 -0800444/*
445 Utility functionality.
446*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800447class XMLUtil
448{
Lee Thomasond1983222012-02-06 08:41:24 -0800449public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700450 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
451 // correct, but simple, and usually works.
452 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100453 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700454 ++p;
455 }
456 return p;
457 }
458 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100459 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700460 ++p;
461 }
462 return p;
463 }
464 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100465 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700466 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800467
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700468 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
469 int n = 0;
470 if ( p == q ) {
471 return true;
472 }
473 while( *p && *q && *p == *q && n<nChar ) {
474 ++p;
475 ++q;
476 ++n;
477 }
478 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
479 return true;
480 }
481 return false;
482 }
483 inline static int IsUTF8Continuation( const char p ) {
484 return p & 0x80;
485 }
486 inline static int IsAlphaNum( unsigned char anyByte ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100487 return ( anyByte < 128 ) ? isalnum( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700488 }
489 inline static int IsAlpha( unsigned char anyByte ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100490 return ( anyByte < 128 ) ? isalpha( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700491 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800492
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700493 static const char* ReadBOM( const char* p, bool* hasBOM );
494 // p is the starting location,
495 // the UTF-8 value of the entity will be placed in value, and length filled in.
496 static const char* GetCharacterRef( const char* p, char* value, int* length );
497 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700498
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700499 // converts primitive types to strings
500 static void ToStr( int v, char* buffer, int bufferSize );
501 static void ToStr( unsigned v, char* buffer, int bufferSize );
502 static void ToStr( bool v, char* buffer, int bufferSize );
503 static void ToStr( float v, char* buffer, int bufferSize );
504 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700505
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700506 // converts strings to primitive types
507 static bool ToInt( const char* str, int* value );
508 static bool ToUnsigned( const char* str, unsigned* value );
509 static bool ToBool( const char* str, bool* value );
510 static bool ToFloat( const char* str, float* value );
511 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800512};
513
Lee Thomason5cae8972012-01-24 18:03:07 -0800514
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800515/** XMLNode is a base class for every object that is in the
516 XML Document Object Model (DOM), except XMLAttributes.
517 Nodes have siblings, a parent, and children which can
518 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700519 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800520 be cast to its more defined type.
521
Thomas Roß08bdf502012-05-12 14:21:23 +0200522 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800523 When the XMLDocument gets deleted, all its Nodes
524 will also be deleted.
525
526 @verbatim
527 A Document can contain: Element (container or leaf)
528 Comment (leaf)
529 Unknown (leaf)
530 Declaration( leaf )
531
532 An Element can contain: Element (container or leaf)
533 Text (leaf)
534 Attributes (not on tree)
535 Comment (leaf)
536 Unknown (leaf)
537
538 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800539*/
Lee Thomasond1983222012-02-06 08:41:24 -0800540class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800541{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700542 friend class XMLDocument;
543 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800544public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800545
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700546 /// Get the XMLDocument that owns this XMLNode.
547 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700548 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700549 }
550 /// Get the XMLDocument that owns this XMLNode.
551 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700552 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700553 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800554
Lee Thomason2fa81722012-11-09 12:37:46 -0800555 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700556 virtual XMLElement* ToElement() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800557 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700558 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800559 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700560 virtual XMLText* ToText() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800561 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700562 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800563 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700564 virtual XMLComment* ToComment() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800565 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700566 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800567 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700568 virtual XMLDocument* ToDocument() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800569 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800571 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 virtual XMLDeclaration* ToDeclaration() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800573 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700574 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800575 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 virtual XMLUnknown* ToUnknown() {
Lee Thomason2fa81722012-11-09 12:37:46 -0800577 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700578 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 virtual const XMLElement* ToElement() const {
581 return 0;
582 }
583 virtual const XMLText* ToText() const {
584 return 0;
585 }
586 virtual const XMLComment* ToComment() const {
587 return 0;
588 }
589 virtual const XMLDocument* ToDocument() const {
590 return 0;
591 }
592 virtual const XMLDeclaration* ToDeclaration() const {
593 return 0;
594 }
595 virtual const XMLUnknown* ToUnknown() const {
596 return 0;
597 }
Lee Thomason751da522012-02-10 08:50:51 -0800598
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700599 /** The meaning of 'value' changes for the specific type.
600 @verbatim
601 Document: empty
602 Element: name of the element
603 Comment: the comment text
604 Unknown: the tag contents
605 Text: the text string
606 @endverbatim
607 */
608 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700609 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700611
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 /** Set the Value of an XML node.
613 @sa Value()
614 */
615 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800616
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700617 /// Get the parent of this node on the DOM.
618 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700619 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700620 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700621
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700622 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700623 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700624 }
Lee Thomason751da522012-02-10 08:50:51 -0800625
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700626 /// Returns true if this node has no children.
627 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700628 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 }
Lee Thomason751da522012-02-10 08:50:51 -0800630
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700631 /// Get the first child node, or null if none exists.
632 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700633 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700635
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700636 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700637 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700638 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700639
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700640 /** Get the first child element, or optionally the first child
641 element with the specified name.
642 */
643 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700644
645 XMLElement* FirstChildElement( const char* value=0 ) {
646 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800648
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 /// Get the last child node, or null if none exists.
650 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700651 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700652 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700653
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 XMLNode* LastChild() {
655 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
656 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800657
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 /** Get the last child element or optionally the last child
659 element with the specified name.
660 */
661 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700662
663 XMLElement* LastChildElement( const char* value=0 ) {
664 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700666
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 /// Get the previous (left) sibling node of this node.
668 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700669 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700671
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700673 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800675
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
677 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700678
679 XMLElement* PreviousSiblingElement( const char* value=0 ) {
680 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700682
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 /// Get the next (right) sibling node of this node.
684 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700685 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700687
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700689 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700691
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
693 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700694
695 XMLElement* NextSiblingElement( const char* value=0 ) {
696 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800698
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 /**
700 Add a child node as the last (right) child.
701 */
702 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800703
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 XMLNode* LinkEndChild( XMLNode* addThis ) {
705 return InsertEndChild( addThis );
706 }
707 /**
708 Add a child node as the first (left) child.
709 */
710 XMLNode* InsertFirstChild( XMLNode* addThis );
711 /**
712 Add a node after the specified child node.
713 */
714 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 /**
717 Delete all the children of this node.
718 */
719 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 /**
722 Delete a child of this node.
723 */
724 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 /**
727 Make a copy of this node, but not its children.
728 You may pass in a Document pointer that will be
729 the owner of the new Node. If the 'document' is
730 null, then the node returned will be allocated
731 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800732
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 Note: if called on a XMLDocument, this will return null.
734 */
735 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 /**
738 Test if 2 nodes are the same, but don't test children.
739 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800740
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 Note: if called on a XMLDocument, this will return false.
742 */
743 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800744
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
746 XML tree will be conditionally visited and the host will be called back
747 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800748
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
750 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
751 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800752
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800754
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 - http://www.saxproject.org/
756 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800757
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700758 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800759
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 An example of using Accept():
761 @verbatim
762 TiXmlPrinter printer;
763 tinyxmlDoc.Accept( &printer );
764 const char* xmlcstr = printer.CStr();
765 @endverbatim
766 */
767 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800768
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 // internal
770 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800771
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800772protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 XMLNode( XMLDocument* );
774 virtual ~XMLNode();
775 XMLNode( const XMLNode& ); // not supported
776 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700777
Lee Thomason624d43f2012-10-12 10:58:48 -0700778 XMLDocument* _document;
779 XMLNode* _parent;
780 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800781
Lee Thomason624d43f2012-10-12 10:58:48 -0700782 XMLNode* _firstChild;
783 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800784
Lee Thomason624d43f2012-10-12 10:58:48 -0700785 XMLNode* _prev;
786 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800787
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800788private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700789 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800791};
792
793
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800794/** XML text.
795
796 Note that a text node can have child element nodes, for example:
797 @verbatim
798 <root>This is <b>bold</b></root>
799 @endverbatim
800
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700801 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800802 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 -0700803 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800804 SetCDATA() and query it with CDATA().
805*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800806class XMLText : public XMLNode
807{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700808 friend class XMLBase;
809 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800810public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800812
Lee Thomason624d43f2012-10-12 10:58:48 -0700813 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700814 return this;
815 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700816 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 return this;
818 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800819
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700820 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700821 void SetCData( bool isCData ) {
822 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700823 }
824 /// Returns true if this is a CDATA text element.
825 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700826 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700827 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800828
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700829 char* ParseDeep( char*, StrPair* endTag );
830 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
831 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800832
Lee Thomason5492a1c2012-01-23 15:32:10 -0800833protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700834 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700835 virtual ~XMLText() {}
836 XMLText( const XMLText& ); // not supported
837 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800838
839private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700840 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800841};
842
843
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800844/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800845class XMLComment : public XMLNode
846{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800848public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 virtual XMLComment* ToComment() {
850 return this;
851 }
852 virtual const XMLComment* ToComment() const {
853 return this;
854 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800855
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800857
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700858 char* ParseDeep( char*, StrPair* endTag );
859 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
860 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800861
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800862protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 XMLComment( XMLDocument* doc );
864 virtual ~XMLComment();
865 XMLComment( const XMLComment& ); // not supported
866 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800867
Lee Thomason3f57d272012-01-11 15:30:03 -0800868private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800869};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800870
871
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800872/** In correct XML the declaration is the first entry in the file.
873 @verbatim
874 <?xml version="1.0" standalone="yes"?>
875 @endverbatim
876
877 TinyXML2 will happily read or write files without a declaration,
878 however.
879
880 The text of the declaration isn't interpreted. It is parsed
881 and written as a string.
882*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800883class XMLDeclaration : public XMLNode
884{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800886public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700887 virtual XMLDeclaration* ToDeclaration() {
888 return this;
889 }
890 virtual const XMLDeclaration* ToDeclaration() const {
891 return this;
892 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800893
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700894 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800895
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700896 char* ParseDeep( char*, StrPair* endTag );
897 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
898 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800899
900protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700901 XMLDeclaration( XMLDocument* doc );
902 virtual ~XMLDeclaration();
903 XMLDeclaration( const XMLDeclaration& ); // not supported
904 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800905};
906
907
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800908/** Any tag that tinyXml doesn't recognize is saved as an
909 unknown. It is a tag of text, but should not be modified.
910 It will be written back to the XML, unchanged, when the file
911 is saved.
912
913 DTD tags get thrown into TiXmlUnknowns.
914*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800915class XMLUnknown : public XMLNode
916{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700917 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800918public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700919 virtual XMLUnknown* ToUnknown() {
920 return this;
921 }
922 virtual const XMLUnknown* ToUnknown() const {
923 return this;
924 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800925
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700926 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800927
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700928 char* ParseDeep( char*, StrPair* endTag );
929 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
930 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800931
932protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700933 XMLUnknown( XMLDocument* doc );
934 virtual ~XMLUnknown();
935 XMLUnknown( const XMLUnknown& ); // not supported
936 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800937};
938
939
Lee Thomason2fa81722012-11-09 12:37:46 -0800940enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700941 XML_NO_ERROR = 0,
942 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800943
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 XML_NO_ATTRIBUTE,
945 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800946
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700947 XML_ERROR_FILE_NOT_FOUND,
948 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
949 XML_ERROR_FILE_READ_ERROR,
950 XML_ERROR_ELEMENT_MISMATCH,
951 XML_ERROR_PARSING_ELEMENT,
952 XML_ERROR_PARSING_ATTRIBUTE,
953 XML_ERROR_IDENTIFYING_TAG,
954 XML_ERROR_PARSING_TEXT,
955 XML_ERROR_PARSING_CDATA,
956 XML_ERROR_PARSING_COMMENT,
957 XML_ERROR_PARSING_DECLARATION,
958 XML_ERROR_PARSING_UNKNOWN,
959 XML_ERROR_EMPTY_DOCUMENT,
960 XML_ERROR_MISMATCHED_ELEMENT,
961 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700962
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700963 XML_CAN_NOT_CONVERT_TEXT,
964 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800965};
966
967
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800968/** An attribute is a name-value pair. Elements have an arbitrary
969 number of attributes, each with a unique name.
970
971 @note The attributes are not XMLNodes. You may only query the
972 Next() attribute in a list.
973*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800974class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800975{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800977public:
Lee Thomason2fa81722012-11-09 12:37:46 -0800978 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700979 const char* Name() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800980 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700981 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800982 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 const char* Value() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800984 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700985 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800986 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700987 const XMLAttribute* Next() const {
Lee Thomason2fa81722012-11-09 12:37:46 -0800988 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700989 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800990
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700991 /** IntAttribute interprets the attribute as an integer, and returns the value.
992 If the value isn't an integer, 0 will be returned. There is no error checking;
993 use QueryIntAttribute() if you need error checking.
994 */
995 int IntValue() const {
996 int i=0;
997 QueryIntValue( &i );
998 return i;
999 }
1000 /// Query as an unsigned integer. See IntAttribute()
1001 unsigned UnsignedValue() const {
1002 unsigned i=0;
1003 QueryUnsignedValue( &i );
1004 return i;
1005 }
1006 /// Query as a boolean. See IntAttribute()
1007 bool BoolValue() const {
1008 bool b=false;
1009 QueryBoolValue( &b );
1010 return b;
1011 }
1012 /// Query as a double. See IntAttribute()
1013 double DoubleValue() const {
1014 double d=0;
1015 QueryDoubleValue( &d );
1016 return d;
1017 }
1018 /// Query as a float. See IntAttribute()
1019 float FloatValue() const {
1020 float f=0;
1021 QueryFloatValue( &f );
1022 return f;
1023 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001024
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
1026 in the provided paremeter. The function will return XML_NO_ERROR on success,
1027 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1028 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001029 XMLError QueryIntValue( int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001030 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001031 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001032 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001033 XMLError QueryBoolValue( bool* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001034 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001035 XMLError QueryDoubleValue( double* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001036 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001037 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001038
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 /// Set the attribute to a string value.
1040 void SetAttribute( const char* value );
1041 /// Set the attribute to value.
1042 void SetAttribute( int value );
1043 /// Set the attribute to value.
1044 void SetAttribute( unsigned value );
1045 /// Set the attribute to value.
1046 void SetAttribute( bool value );
1047 /// Set the attribute to value.
1048 void SetAttribute( double value );
1049 /// Set the attribute to value.
1050 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001051
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001052private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001054
Lee Thomason624d43f2012-10-12 10:58:48 -07001055 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001056 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001057
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001058 XMLAttribute( const XMLAttribute& ); // not supported
1059 void operator=( const XMLAttribute& ); // not supported
1060 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001061
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001062 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001063
Lee Thomason624d43f2012-10-12 10:58:48 -07001064 mutable StrPair _name;
1065 mutable StrPair _value;
1066 XMLAttribute* _next;
1067 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001068};
1069
1070
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001071/** The element is a container class. It has a value, the element name,
1072 and can contain other elements, text, comments, and unknowns.
1073 Elements also contain an arbitrary number of attributes.
1074*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001075class XMLElement : public XMLNode
1076{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001077 friend class XMLBase;
1078 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001079public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001080 /// Get the name of an element (which is the Value() of the node.)
1081 const char* Name() const {
1082 return Value();
1083 }
1084 /// Set the name of the element.
1085 void SetName( const char* str, bool staticMem=false ) {
1086 SetValue( str, staticMem );
1087 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001088
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001089 virtual XMLElement* ToElement() {
1090 return this;
1091 }
1092 virtual const XMLElement* ToElement() const {
1093 return this;
1094 }
1095 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001096
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001097 /** Given an attribute name, Attribute() returns the value
1098 for the attribute of that name, or null if none
1099 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001100
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001101 @verbatim
1102 const char* value = ele->Attribute( "foo" );
1103 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001104
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 The 'value' parameter is normally null. However, if specified,
1106 the attribute will only be returned if the 'name' and 'value'
1107 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001108
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001109 @verbatim
1110 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1111 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001112
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001113 rather than:
1114 @verbatim
1115 if ( ele->Attribute( "foo" ) ) {
1116 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1117 }
1118 @endverbatim
1119 */
1120 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001121
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001122 /** Given an attribute name, IntAttribute() returns the value
1123 of the attribute interpreted as an integer. 0 will be
1124 returned if there is an error. For a method with error
1125 checking, see QueryIntAttribute()
1126 */
1127 int IntAttribute( const char* name ) const {
1128 int i=0;
1129 QueryIntAttribute( name, &i );
1130 return i;
1131 }
1132 /// See IntAttribute()
1133 unsigned UnsignedAttribute( const char* name ) const {
1134 unsigned i=0;
1135 QueryUnsignedAttribute( name, &i );
1136 return i;
1137 }
1138 /// See IntAttribute()
1139 bool BoolAttribute( const char* name ) const {
1140 bool b=false;
1141 QueryBoolAttribute( name, &b );
1142 return b;
1143 }
1144 /// See IntAttribute()
1145 double DoubleAttribute( const char* name ) const {
1146 double d=0;
1147 QueryDoubleAttribute( name, &d );
1148 return d;
1149 }
1150 /// See IntAttribute()
1151 float FloatAttribute( const char* name ) const {
1152 float f=0;
1153 QueryFloatAttribute( name, &f );
1154 return f;
1155 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001156
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001157 /** Given an attribute name, QueryIntAttribute() returns
1158 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1159 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1160 doesn't exist. If successful, the result of the conversion
1161 will be written to 'value'. If not successful, nothing will
1162 be written to 'value'. This allows you to provide default
1163 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001164
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001165 @verbatim
1166 int value = 10;
1167 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1168 @endverbatim
1169 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001170 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001171 const XMLAttribute* a = FindAttribute( name );
1172 if ( !a ) {
1173 return XML_NO_ATTRIBUTE;
1174 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001175 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001176 }
1177 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001178 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001179 const XMLAttribute* a = FindAttribute( name );
1180 if ( !a ) {
1181 return XML_NO_ATTRIBUTE;
1182 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001183 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001184 }
1185 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001186 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001187 const XMLAttribute* a = FindAttribute( name );
1188 if ( !a ) {
1189 return XML_NO_ATTRIBUTE;
1190 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001191 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 }
1193 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001194 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001195 const XMLAttribute* a = FindAttribute( name );
1196 if ( !a ) {
1197 return XML_NO_ATTRIBUTE;
1198 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001199 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001200 }
1201 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001202 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001203 const XMLAttribute* a = FindAttribute( name );
1204 if ( !a ) {
1205 return XML_NO_ATTRIBUTE;
1206 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001207 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001209
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001210 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001211 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001213 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 }
1215 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001216 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001217 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001218 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001219 }
1220 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001221 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001223 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001224 }
1225 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001226 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001227 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001228 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 }
1230 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001231 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001233 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001234 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001235
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001236 /**
1237 Delete an attribute.
1238 */
1239 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001240
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 /// Return the first attribute in the list.
1242 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001243 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 }
1245 /// Query a specific attribute in the list.
1246 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001247
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001248 /** Convenience function for easy access to the text inside an element. Although easy
1249 and concise, GetText() is limited compared to getting the TiXmlText child
1250 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001251
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 If the first child of 'this' is a TiXmlText, the GetText()
1253 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001254
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001255 This is a convenient method for getting the text of simple contained text:
1256 @verbatim
1257 <foo>This is text</foo>
1258 const char* str = fooElement->GetText();
1259 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001260
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001261 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001262
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001263 Note that this function can be misleading. If the element foo was created from
1264 this XML:
1265 @verbatim
1266 <foo><b>This is text</b></foo>
1267 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001268
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 then the value of str would be null. The first child node isn't a text node, it is
1270 another element. From this XML:
1271 @verbatim
1272 <foo>This is <b>text</b></foo>
1273 @endverbatim
1274 GetText() will return "This is ".
1275 */
1276 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001277
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001278 /**
1279 Convenience method to query the value of a child text node. This is probably best
1280 shown by example. Given you have a document is this form:
1281 @verbatim
1282 <point>
1283 <x>1</x>
1284 <y>1.4</y>
1285 </point>
1286 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001287
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001288 The QueryIntText() and similar functions provide a safe and easier way to get to the
1289 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001290
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001291 @verbatim
1292 int x = 0;
1293 float y = 0; // types of x and y are contrived for example
1294 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1295 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1296 xElement->QueryIntText( &x );
1297 yElement->QueryFloatText( &y );
1298 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001299
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1301 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 -07001302
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001304 XMLError QueryIntText( int* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001305 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001306 XMLError QueryUnsignedText( unsigned* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001308 XMLError QueryBoolText( bool* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001310 XMLError QueryDoubleText( double* _value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 /// See QueryIntText()
Lee Thomason2fa81722012-11-09 12:37:46 -08001312 XMLError QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001313
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 // internal:
1315 enum {
1316 OPEN, // <foo>
1317 CLOSED, // <foo/>
1318 CLOSING // </foo>
1319 };
1320 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001321 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 }
1323 char* ParseDeep( char* p, StrPair* endTag );
1324 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1325 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001326
Lee Thomason50adb4c2012-02-13 15:07:09 -08001327private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001328 XMLElement( XMLDocument* doc );
1329 virtual ~XMLElement();
1330 XMLElement( const XMLElement& ); // not supported
1331 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 XMLAttribute* FindAttribute( const char* name );
1334 XMLAttribute* FindOrCreateAttribute( const char* name );
1335 //void LinkAttribute( XMLAttribute* attrib );
1336 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001337
Lee Thomason624d43f2012-10-12 10:58:48 -07001338 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001339 // The attribute list is ordered; there is no 'lastAttribute'
1340 // because the list needs to be scanned for dupes before adding
1341 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001342 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001343};
1344
1345
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001346enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001347 PRESERVE_WHITESPACE,
1348 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001349};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001350
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001351
1352/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001353 It can be saved, loaded, and printed to the screen.
1354 All Nodes are connected and allocated to a Document.
1355 If the Document is deleted, all its Nodes are also deleted.
1356*/
Lee Thomason67d61312012-01-24 16:01:51 -08001357class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001358{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001360public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 /// constructor
1362 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1363 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001364
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001365 virtual XMLDocument* ToDocument() {
1366 return this;
1367 }
1368 virtual const XMLDocument* ToDocument() const {
1369 return this;
1370 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001371
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001372 /**
1373 Parse an XML file from a character string.
1374 Returns XML_NO_ERROR (0) on success, or
1375 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001376
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 You may optionally pass in the 'nBytes', which is
1378 the number of bytes which will be parsed. If not
1379 specified, TinyXML will assume 'xml' points to a
1380 null terminated string.
1381 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001382 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001383
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 /**
1385 Load an XML file from disk.
1386 Returns XML_NO_ERROR (0) on success, or
1387 an errorID.
1388 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001389 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001390
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 /**
1392 Load an XML file from disk. You are responsible
1393 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001394
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001395 Returns XML_NO_ERROR (0) on success, or
1396 an errorID.
1397 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001398 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001399
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001400 /**
1401 Save the XML file to disk.
1402 Returns XML_NO_ERROR (0) on success, or
1403 an errorID.
1404 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001405 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001406
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 /**
1408 Save the XML file to disk. You are responsible
1409 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001410
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001411 Returns XML_NO_ERROR (0) on success, or
1412 an errorID.
1413 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001414 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001415
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001416 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001417 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 }
1419 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001420 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001421 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001422
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001423 /**
1424 Returns true if this document has a leading Byte Order Mark of UTF8.
1425 */
1426 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001427 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001428 }
1429 /** Sets whether to write the BOM when writing the file.
1430 */
1431 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001432 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001433 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001434
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001435 /** Return the root element of DOM. Equivalent to FirstChildElement().
1436 To get the first node, use FirstChild().
1437 */
1438 XMLElement* RootElement() {
1439 return FirstChildElement();
1440 }
1441 const XMLElement* RootElement() const {
1442 return FirstChildElement();
1443 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001444
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001445 /** Print the Document. If the Printer is not provided, it will
1446 print to stdout. If you provide Printer, this can print to a file:
1447 @verbatim
1448 XMLPrinter printer( fp );
1449 doc.Print( &printer );
1450 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001451
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 Or you can use a printer to print to memory:
1453 @verbatim
1454 XMLPrinter printer;
1455 doc->Print( &printer );
1456 // printer.CStr() has a const char* to the XML
1457 @endverbatim
1458 */
1459 void Print( XMLPrinter* streamer=0 );
1460 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001461
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001462 /**
1463 Create a new Element associated with
1464 this Document. The memory for the Element
1465 is managed by the Document.
1466 */
1467 XMLElement* NewElement( const char* name );
1468 /**
1469 Create a new Comment associated with
1470 this Document. The memory for the Comment
1471 is managed by the Document.
1472 */
1473 XMLComment* NewComment( const char* comment );
1474 /**
1475 Create a new Text associated with
1476 this Document. The memory for the Text
1477 is managed by the Document.
1478 */
1479 XMLText* NewText( const char* text );
1480 /**
1481 Create a new Declaration associated with
1482 this Document. The memory for the object
1483 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001484
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001485 If the 'text' param is null, the standard
1486 declaration is used.:
1487 @verbatim
1488 <?xml version="1.0" encoding="UTF-8"?>
1489 @endverbatim
1490 */
1491 XMLDeclaration* NewDeclaration( const char* text=0 );
1492 /**
1493 Create a new Unknown associated with
Lee Thomason624d43f2012-10-12 10:58:48 -07001494 this Document. The memory forthe object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001495 is managed by the Document.
1496 */
1497 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001498
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 /**
1500 Delete a node associated with this document.
1501 It will be unlinked from the DOM.
1502 */
1503 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001504 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001506
Lee Thomason2fa81722012-11-09 12:37:46 -08001507 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001508
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001509 /// Return true if there was an error parsing the document.
1510 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001511 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001512 }
1513 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001514 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001515 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001516 }
1517 /// Return a possibly helpful diagnostic location or string.
1518 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001519 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 }
1521 /// Return a possibly helpful secondary diagnostic location or string.
1522 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001523 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 }
1525 /// If there is an error, print it to stdout.
1526 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001527
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 // internal
1529 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001530
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1532 return 0;
1533 }
1534 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1535 return false;
1536 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001537
Lee Thomason3f57d272012-01-11 15:30:03 -08001538private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 XMLDocument( const XMLDocument& ); // not supported
1540 void operator=( const XMLDocument& ); // not supported
1541 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001542
Lee Thomason2fa81722012-11-09 12:37:46 -08001543 bool _writeBOM;
1544 bool _processEntities;
1545 XMLError _errorID;
1546 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001547 const char* _errorStr1;
1548 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001549 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001550
Lee Thomason624d43f2012-10-12 10:58:48 -07001551 MemPoolT< sizeof(XMLElement) > _elementPool;
1552 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1553 MemPoolT< sizeof(XMLText) > _textPool;
1554 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001555};
1556
Lee Thomason7c913cd2012-01-26 18:32:34 -08001557
Lee Thomason3ffdd392012-03-28 17:27:55 -07001558/**
1559 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001560 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001561 DOM structure. It is a separate utility class.
1562
1563 Take an example:
1564 @verbatim
1565 <Document>
1566 <Element attributeA = "valueA">
1567 <Child attributeB = "value1" />
1568 <Child attributeB = "value2" />
1569 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001570 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001571 @endverbatim
1572
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001573 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001574 easy to write a *lot* of code that looks like:
1575
1576 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001577 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001578 if ( root )
1579 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001580 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001581 if ( element )
1582 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001583 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001584 if ( child )
1585 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001586 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001587 if ( child2 )
1588 {
1589 // Finally do something useful.
1590 @endverbatim
1591
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001592 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001593 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001594 and correct to use:
1595
1596 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001597 XMLHandle docHandle( &document );
1598 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001599 if ( child2 )
1600 {
1601 // do something useful
1602 @endverbatim
1603
1604 Which is MUCH more concise and useful.
1605
1606 It is also safe to copy handles - internally they are nothing more than node pointers.
1607 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001608 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001609 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001610
1611 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001612*/
1613class XMLHandle
1614{
1615public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 /// 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 -07001617 XMLHandle( XMLNode* node ) {
1618 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 }
1620 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001621 XMLHandle( XMLNode& node ) {
1622 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001623 }
1624 /// Copy constructor
1625 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001626 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001627 }
1628 /// Assignment
1629 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001630 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001631 return *this;
1632 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001633
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001634 /// Get the first child of this handle.
1635 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001636 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001637 }
1638 /// Get the first child element of this handle.
1639 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001640 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001641 }
1642 /// Get the last child of this handle.
1643 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001644 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001645 }
1646 /// Get the last child element of this handle.
1647 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001648 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001649 }
1650 /// Get the previous sibling of this handle.
1651 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001652 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001653 }
1654 /// Get the previous sibling element of this handle.
1655 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001656 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 }
1658 /// Get the next sibling of this handle.
1659 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001660 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001661 }
1662 /// Get the next sibling element of this handle.
1663 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001664 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001665 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001666
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 /// Safe cast to XMLNode. This can return null.
1668 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001669 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001670 }
1671 /// Safe cast to XMLElement. This can return null.
1672 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001673 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001674 }
1675 /// Safe cast to XMLText. This can return null.
1676 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001677 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001678 }
1679 /// Safe cast to XMLUnknown. This can return null.
1680 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001681 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001682 }
1683 /// Safe cast to XMLDeclaration. This can return null.
1684 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001685 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001687
1688private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001689 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001690};
1691
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001692
1693/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001694 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1695 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001696*/
1697class XMLConstHandle
1698{
1699public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 XMLConstHandle( const XMLNode* node ) {
1701 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001702 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001703 XMLConstHandle( const XMLNode& node ) {
1704 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 }
1706 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001707 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 }
Lee Thomason8b899812012-04-04 15:58:16 -07001709
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001710 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001711 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 return *this;
1713 }
Lee Thomason8b899812012-04-04 15:58:16 -07001714
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001716 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001717 }
1718 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001719 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001720 }
1721 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001725 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 }
1727 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001728 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001729 }
1730 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001731 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 }
1733 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001737 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001738 }
Lee Thomason8b899812012-04-04 15:58:16 -07001739
1740
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
1744 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001745 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001746 }
1747 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001748 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001749 }
1750 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
1753 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001754 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001755 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001756
Lee Thomason5cae8972012-01-24 18:03:07 -08001757private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001758 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001759};
Lee Thomason6f381b72012-03-02 12:59:39 -08001760
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001761
1762/**
1763 Printing functionality. The XMLPrinter gives you more
1764 options than the XMLDocument::Print() method.
1765
1766 It can:
1767 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001768 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001769 -# Print XML without a XMLDocument.
1770
1771 Print to Memory
1772
1773 @verbatim
1774 XMLPrinter printer;
1775 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001776 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001777 @endverbatim
1778
1779 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001780
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001781 You provide the file pointer.
1782 @verbatim
1783 XMLPrinter printer( fp );
1784 doc.Print( &printer );
1785 @endverbatim
1786
1787 Print without a XMLDocument
1788
1789 When loading, an XML parser is very useful. However, sometimes
1790 when saving, it just gets in the way. The code is often set up
1791 for streaming, and constructing the DOM is just overhead.
1792
1793 The Printer supports the streaming case. The following code
1794 prints out a trivially simple XML file without ever creating
1795 an XML document.
1796
1797 @verbatim
1798 XMLPrinter printer( fp );
1799 printer.OpenElement( "foo" );
1800 printer.PushAttribute( "foo", "bar" );
1801 printer.CloseElement();
1802 @endverbatim
1803*/
1804class XMLPrinter : public XMLVisitor
1805{
1806public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 /** Construct the printer. If the FILE* is specified,
1808 this will print to the FILE. Else it will print
1809 to memory, and the result is available in CStr().
1810 If 'compact' is set to true, then output is created
1811 with only required whitespace and newlines.
1812 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001813 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001814 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001815
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 /** If streaming, write the BOM and declaration. */
1817 void PushHeader( bool writeBOM, bool writeDeclaration );
1818 /** If streaming, start writing an element.
1819 The element must be closed with CloseElement()
1820 */
1821 void OpenElement( const char* name );
1822 /// If streaming, add an attribute to an open element.
1823 void PushAttribute( const char* name, const char* value );
1824 void PushAttribute( const char* name, int value );
1825 void PushAttribute( const char* name, unsigned value );
1826 void PushAttribute( const char* name, bool value );
1827 void PushAttribute( const char* name, double value );
1828 /// If streaming, close the Element.
1829 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001830
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001831 /// Add a text node.
1832 void PushText( const char* text, bool cdata=false );
1833 /// Add a text node from an integer.
1834 void PushText( int value );
1835 /// Add a text node from an unsigned.
1836 void PushText( unsigned value );
1837 /// Add a text node from a bool.
1838 void PushText( bool value );
1839 /// Add a text node from a float.
1840 void PushText( float value );
1841 /// Add a text node from a double.
1842 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001843
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001844 /// Add a comment
1845 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001846
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001847 void PushDeclaration( const char* value );
1848 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001849
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001850 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1851 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1852 return true;
1853 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001854
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001855 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1856 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001857
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001858 virtual bool Visit( const XMLText& text );
1859 virtual bool Visit( const XMLComment& comment );
1860 virtual bool Visit( const XMLDeclaration& declaration );
1861 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001862
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001863 /**
1864 If in print to memory mode, return a pointer to
1865 the XML file in memory.
1866 */
1867 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001868 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001869 }
1870 /**
1871 If in print to memory mode, return the size
1872 of the XML file in memory. (Note the size returned
1873 includes the terminating null.)
1874 */
1875 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001876 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001877 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001878
1879private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 void SealElement();
1881 void PrintSpace( int depth );
1882 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1883 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001884
Lee Thomason624d43f2012-10-12 10:58:48 -07001885 bool _elementJustOpened;
1886 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001887 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001888 int _depth;
1889 int _textDepth;
1890 bool _processEntities;
1891 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001892
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001893 enum {
1894 ENTITY_RANGE = 64,
1895 BUF_SIZE = 200
1896 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001897 bool _entityFlag[ENTITY_RANGE];
1898 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001899
Lee Thomason624d43f2012-10-12 10:58:48 -07001900 DynArray< const char*, 10 > _stack;
1901 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001902#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001903 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001904#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001905};
1906
1907
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001908} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001909
1910
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001911#endif // TINYXML2_INCLUDED