blob: cf60a582f742fe4df3f81a561c50cc7ecf04a088 [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
MortenMacFly4ee49f12013-01-14 20:03:14 +010049
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 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 Thomason86ca9dc2013-01-28 07:31:59 -0800101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
103static const int TIXML2_PATCH_VERSION = 10;
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 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200467
468 inline static bool IsNameStartChar( unsigned char ch ) {
469 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
470 || ch == ':'
471 || ch == '_';
472 }
473
474 inline static bool IsNameChar( unsigned char ch ) {
475 return IsNameStartChar( ch )
476 || isdigit( ch )
477 || ch == '.'
478 || ch == '-';
479 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800480
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700481 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
482 int n = 0;
483 if ( p == q ) {
484 return true;
485 }
486 while( *p && *q && *p == *q && n<nChar ) {
487 ++p;
488 ++q;
489 ++n;
490 }
491 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
492 return true;
493 }
494 return false;
495 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200496
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700497 inline static int IsUTF8Continuation( const char p ) {
498 return p & 0x80;
499 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800500
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700501 static const char* ReadBOM( const char* p, bool* hasBOM );
502 // p is the starting location,
503 // the UTF-8 value of the entity will be placed in value, and length filled in.
504 static const char* GetCharacterRef( const char* p, char* value, int* length );
505 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700506
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700507 // converts primitive types to strings
508 static void ToStr( int v, char* buffer, int bufferSize );
509 static void ToStr( unsigned v, char* buffer, int bufferSize );
510 static void ToStr( bool v, char* buffer, int bufferSize );
511 static void ToStr( float v, char* buffer, int bufferSize );
512 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700513
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700514 // converts strings to primitive types
515 static bool ToInt( const char* str, int* value );
516 static bool ToUnsigned( const char* str, unsigned* value );
517 static bool ToBool( const char* str, bool* value );
518 static bool ToFloat( const char* str, float* value );
519 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800520};
521
Lee Thomason5cae8972012-01-24 18:03:07 -0800522
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800523/** XMLNode is a base class for every object that is in the
524 XML Document Object Model (DOM), except XMLAttributes.
525 Nodes have siblings, a parent, and children which can
526 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700527 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800528 be cast to its more defined type.
529
Thomas Roß08bdf502012-05-12 14:21:23 +0200530 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800531 When the XMLDocument gets deleted, all its Nodes
532 will also be deleted.
533
534 @verbatim
535 A Document can contain: Element (container or leaf)
536 Comment (leaf)
537 Unknown (leaf)
538 Declaration( leaf )
539
540 An Element can contain: Element (container or leaf)
541 Text (leaf)
542 Attributes (not on tree)
543 Comment (leaf)
544 Unknown (leaf)
545
546 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800547*/
Lee Thomasond1983222012-02-06 08:41:24 -0800548class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800549{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700550 friend class XMLDocument;
551 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800552public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800553
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700554 /// Get the XMLDocument that owns this XMLNode.
555 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700556 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700557 }
558 /// Get the XMLDocument that owns this XMLNode.
559 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700560 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700561 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800562
Lee Thomason2fa81722012-11-09 12:37:46 -0800563 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700564 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100565 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700566 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800567 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700568 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100569 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800571 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100573 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700574 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800575 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100577 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700578 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800579 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100581 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700582 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800583 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100585 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700586 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800587
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 virtual const XMLElement* ToElement() const {
589 return 0;
590 }
591 virtual const XMLText* ToText() const {
592 return 0;
593 }
594 virtual const XMLComment* ToComment() const {
595 return 0;
596 }
597 virtual const XMLDocument* ToDocument() const {
598 return 0;
599 }
600 virtual const XMLDeclaration* ToDeclaration() const {
601 return 0;
602 }
603 virtual const XMLUnknown* ToUnknown() const {
604 return 0;
605 }
Lee Thomason751da522012-02-10 08:50:51 -0800606
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700607 /** The meaning of 'value' changes for the specific type.
608 @verbatim
609 Document: empty
610 Element: name of the element
611 Comment: the comment text
612 Unknown: the tag contents
613 Text: the text string
614 @endverbatim
615 */
616 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700617 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100619
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700620 /** Set the Value of an XML node.
621 @sa Value()
622 */
623 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800624
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700625 /// Get the parent of this node on the DOM.
626 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700627 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700628 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100629
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700630 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700631 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700632 }
Lee Thomason751da522012-02-10 08:50:51 -0800633
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 /// Returns true if this node has no children.
635 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700636 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 }
Lee Thomason751da522012-02-10 08:50:51 -0800638
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700639 /// Get the first child node, or null if none exists.
640 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700641 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700642 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100643
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700644 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700645 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700646 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100647
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 /** Get the first child element, or optionally the first child
649 element with the specified name.
650 */
651 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700652
653 XMLElement* FirstChildElement( const char* value=0 ) {
654 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800656
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 /// Get the last child node, or null if none exists.
658 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700659 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700661
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700662 XMLNode* LastChild() {
663 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
664 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800665
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 /** Get the last child element or optionally the last child
667 element with the specified name.
668 */
669 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700670
671 XMLElement* LastChildElement( const char* value=0 ) {
672 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700673 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700674
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 /// Get the previous (left) sibling node of this node.
676 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700677 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700678 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700679
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700681 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
685 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700686
687 XMLElement* PreviousSiblingElement( const char* value=0 ) {
688 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700689 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700690
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 /// Get the next (right) sibling node of this node.
692 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700693 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700695
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700697 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700698 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700699
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
701 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700702
703 XMLElement* NextSiblingElement( const char* value=0 ) {
704 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800706
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 /**
708 Add a child node as the last (right) child.
709 */
710 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800711
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 XMLNode* LinkEndChild( XMLNode* addThis ) {
713 return InsertEndChild( addThis );
714 }
715 /**
716 Add a child node as the first (left) child.
717 */
718 XMLNode* InsertFirstChild( XMLNode* addThis );
719 /**
720 Add a node after the specified child node.
721 */
722 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 /**
725 Delete all the children of this node.
726 */
727 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 /**
730 Delete a child of this node.
731 */
732 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 /**
735 Make a copy of this node, but not its children.
736 You may pass in a Document pointer that will be
737 the owner of the new Node. If the 'document' is
738 null, then the node returned will be allocated
739 from the current Document. (this->GetDocument())
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 null.
742 */
743 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800744
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 /**
746 Test if 2 nodes are the same, but don't test children.
747 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800748
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 Note: if called on a XMLDocument, this will return false.
750 */
751 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800752
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
754 XML tree will be conditionally visited and the host will be called back
755 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800756
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
758 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
759 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800760
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700761 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800762
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700763 - http://www.saxproject.org/
764 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800765
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800767
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 An example of using Accept():
769 @verbatim
770 TiXmlPrinter printer;
771 tinyxmlDoc.Accept( &printer );
772 const char* xmlcstr = printer.CStr();
773 @endverbatim
774 */
775 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800776
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 // internal
778 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800779
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800780protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700781 XMLNode( XMLDocument* );
782 virtual ~XMLNode();
783 XMLNode( const XMLNode& ); // not supported
784 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700785
Lee Thomason624d43f2012-10-12 10:58:48 -0700786 XMLDocument* _document;
787 XMLNode* _parent;
788 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800789
Lee Thomason624d43f2012-10-12 10:58:48 -0700790 XMLNode* _firstChild;
791 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800792
Lee Thomason624d43f2012-10-12 10:58:48 -0700793 XMLNode* _prev;
794 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800795
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800796private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700797 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700798 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800799};
800
801
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800802/** XML text.
803
804 Note that a text node can have child element nodes, for example:
805 @verbatim
806 <root>This is <b>bold</b></root>
807 @endverbatim
808
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700809 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800810 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 -0700811 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800812 SetCDATA() and query it with CDATA().
813*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800814class XMLText : public XMLNode
815{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700816 friend class XMLBase;
817 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800818public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800820
Lee Thomason624d43f2012-10-12 10:58:48 -0700821 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 return this;
823 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700824 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 return this;
826 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800827
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700828 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700829 void SetCData( bool isCData ) {
830 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 }
832 /// Returns true if this is a CDATA text element.
833 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700834 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700835 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800836
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700837 char* ParseDeep( char*, StrPair* endTag );
838 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
839 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800840
Lee Thomason5492a1c2012-01-23 15:32:10 -0800841protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700842 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700843 virtual ~XMLText() {}
844 XMLText( const XMLText& ); // not supported
845 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800846
847private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700848 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800849};
850
851
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800852/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800853class XMLComment : public XMLNode
854{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800856public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 virtual XMLComment* ToComment() {
858 return this;
859 }
860 virtual const XMLComment* ToComment() const {
861 return this;
862 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800863
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700864 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800865
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700866 char* ParseDeep( char*, StrPair* endTag );
867 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
868 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800869
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800870protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700871 XMLComment( XMLDocument* doc );
872 virtual ~XMLComment();
873 XMLComment( const XMLComment& ); // not supported
874 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800875
Lee Thomason3f57d272012-01-11 15:30:03 -0800876private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800877};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800878
879
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800880/** In correct XML the declaration is the first entry in the file.
881 @verbatim
882 <?xml version="1.0" standalone="yes"?>
883 @endverbatim
884
885 TinyXML2 will happily read or write files without a declaration,
886 however.
887
888 The text of the declaration isn't interpreted. It is parsed
889 and written as a string.
890*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800891class XMLDeclaration : public XMLNode
892{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700893 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800894public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700895 virtual XMLDeclaration* ToDeclaration() {
896 return this;
897 }
898 virtual const XMLDeclaration* ToDeclaration() const {
899 return this;
900 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800901
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700902 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800903
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700904 char* ParseDeep( char*, StrPair* endTag );
905 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
906 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800907
908protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700909 XMLDeclaration( XMLDocument* doc );
910 virtual ~XMLDeclaration();
911 XMLDeclaration( const XMLDeclaration& ); // not supported
912 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800913};
914
915
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800916/** Any tag that tinyXml doesn't recognize is saved as an
917 unknown. It is a tag of text, but should not be modified.
918 It will be written back to the XML, unchanged, when the file
919 is saved.
920
921 DTD tags get thrown into TiXmlUnknowns.
922*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800923class XMLUnknown : public XMLNode
924{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700925 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800926public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700927 virtual XMLUnknown* ToUnknown() {
928 return this;
929 }
930 virtual const XMLUnknown* ToUnknown() const {
931 return this;
932 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800933
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800935
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 char* ParseDeep( char*, StrPair* endTag );
937 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
938 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800939
940protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700941 XMLUnknown( XMLDocument* doc );
942 virtual ~XMLUnknown();
943 XMLUnknown( const XMLUnknown& ); // not supported
944 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800945};
946
947
Lee Thomason2fa81722012-11-09 12:37:46 -0800948enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700949 XML_NO_ERROR = 0,
950 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800951
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700952 XML_NO_ATTRIBUTE,
953 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800954
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700955 XML_ERROR_FILE_NOT_FOUND,
956 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
957 XML_ERROR_FILE_READ_ERROR,
958 XML_ERROR_ELEMENT_MISMATCH,
959 XML_ERROR_PARSING_ELEMENT,
960 XML_ERROR_PARSING_ATTRIBUTE,
961 XML_ERROR_IDENTIFYING_TAG,
962 XML_ERROR_PARSING_TEXT,
963 XML_ERROR_PARSING_CDATA,
964 XML_ERROR_PARSING_COMMENT,
965 XML_ERROR_PARSING_DECLARATION,
966 XML_ERROR_PARSING_UNKNOWN,
967 XML_ERROR_EMPTY_DOCUMENT,
968 XML_ERROR_MISMATCHED_ELEMENT,
969 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700970
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700971 XML_CAN_NOT_CONVERT_TEXT,
972 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800973};
974
975
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800976/** An attribute is a name-value pair. Elements have an arbitrary
977 number of attributes, each with a unique name.
978
979 @note The attributes are not XMLNodes. You may only query the
980 Next() attribute in a list.
981*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800982class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800983{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700984 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800985public:
Lee Thomason2fa81722012-11-09 12:37:46 -0800986 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700987 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100988 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700989 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800990 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700991 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100992 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700993 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800994 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700995 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100996 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700997 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800998
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700999 /** IntAttribute interprets the attribute as an integer, and returns the value.
1000 If the value isn't an integer, 0 will be returned. There is no error checking;
1001 use QueryIntAttribute() if you need error checking.
1002 */
1003 int IntValue() const {
1004 int i=0;
1005 QueryIntValue( &i );
1006 return i;
1007 }
1008 /// Query as an unsigned integer. See IntAttribute()
1009 unsigned UnsignedValue() const {
1010 unsigned i=0;
1011 QueryUnsignedValue( &i );
1012 return i;
1013 }
1014 /// Query as a boolean. See IntAttribute()
1015 bool BoolValue() const {
1016 bool b=false;
1017 QueryBoolValue( &b );
1018 return b;
1019 }
1020 /// Query as a double. See IntAttribute()
1021 double DoubleValue() const {
1022 double d=0;
1023 QueryDoubleValue( &d );
1024 return d;
1025 }
1026 /// Query as a float. See IntAttribute()
1027 float FloatValue() const {
1028 float f=0;
1029 QueryFloatValue( &f );
1030 return f;
1031 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001032
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001033 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
1034 in the provided paremeter. The function will return XML_NO_ERROR on success,
1035 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1036 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001037 XMLError QueryIntValue( int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001038 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001039 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001040 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001041 XMLError QueryBoolValue( bool* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001043 XMLError QueryDoubleValue( double* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001044 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001045 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001046
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 /// Set the attribute to a string value.
1048 void SetAttribute( const char* value );
1049 /// Set the attribute to value.
1050 void SetAttribute( int value );
1051 /// Set the attribute to value.
1052 void SetAttribute( unsigned value );
1053 /// Set the attribute to value.
1054 void SetAttribute( bool value );
1055 /// Set the attribute to value.
1056 void SetAttribute( double value );
1057 /// Set the attribute to value.
1058 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001059
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001060private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001061 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001062
Lee Thomason624d43f2012-10-12 10:58:48 -07001063 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001064 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001065
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001066 XMLAttribute( const XMLAttribute& ); // not supported
1067 void operator=( const XMLAttribute& ); // not supported
1068 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001069
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001070 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001071
Lee Thomason624d43f2012-10-12 10:58:48 -07001072 mutable StrPair _name;
1073 mutable StrPair _value;
1074 XMLAttribute* _next;
1075 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001076};
1077
1078
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001079/** The element is a container class. It has a value, the element name,
1080 and can contain other elements, text, comments, and unknowns.
1081 Elements also contain an arbitrary number of attributes.
1082*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001083class XMLElement : public XMLNode
1084{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001085 friend class XMLBase;
1086 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001087public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 /// Get the name of an element (which is the Value() of the node.)
1089 const char* Name() const {
1090 return Value();
1091 }
1092 /// Set the name of the element.
1093 void SetName( const char* str, bool staticMem=false ) {
1094 SetValue( str, staticMem );
1095 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001096
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001097 virtual XMLElement* ToElement() {
1098 return this;
1099 }
1100 virtual const XMLElement* ToElement() const {
1101 return this;
1102 }
1103 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001104
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 /** Given an attribute name, Attribute() returns the value
1106 for the attribute of that name, or null if none
1107 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001108
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001109 @verbatim
1110 const char* value = ele->Attribute( "foo" );
1111 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001112
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001113 The 'value' parameter is normally null. However, if specified,
1114 the attribute will only be returned if the 'name' and 'value'
1115 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001116
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001117 @verbatim
1118 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1119 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001120
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001121 rather than:
1122 @verbatim
1123 if ( ele->Attribute( "foo" ) ) {
1124 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1125 }
1126 @endverbatim
1127 */
1128 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001129
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001130 /** Given an attribute name, IntAttribute() returns the value
1131 of the attribute interpreted as an integer. 0 will be
1132 returned if there is an error. For a method with error
1133 checking, see QueryIntAttribute()
1134 */
1135 int IntAttribute( const char* name ) const {
1136 int i=0;
1137 QueryIntAttribute( name, &i );
1138 return i;
1139 }
1140 /// See IntAttribute()
1141 unsigned UnsignedAttribute( const char* name ) const {
1142 unsigned i=0;
1143 QueryUnsignedAttribute( name, &i );
1144 return i;
1145 }
1146 /// See IntAttribute()
1147 bool BoolAttribute( const char* name ) const {
1148 bool b=false;
1149 QueryBoolAttribute( name, &b );
1150 return b;
1151 }
1152 /// See IntAttribute()
1153 double DoubleAttribute( const char* name ) const {
1154 double d=0;
1155 QueryDoubleAttribute( name, &d );
1156 return d;
1157 }
1158 /// See IntAttribute()
1159 float FloatAttribute( const char* name ) const {
1160 float f=0;
1161 QueryFloatAttribute( name, &f );
1162 return f;
1163 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001164
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001165 /** Given an attribute name, QueryIntAttribute() returns
1166 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1167 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1168 doesn't exist. If successful, the result of the conversion
1169 will be written to 'value'. If not successful, nothing will
1170 be written to 'value'. This allows you to provide default
1171 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001172
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001173 @verbatim
1174 int value = 10;
1175 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1176 @endverbatim
1177 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001178 XMLError QueryIntAttribute( const char* name, 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->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001184 }
1185 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001186 XMLError QueryUnsignedAttribute( const char* name, unsigned int* 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->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 }
1193 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001194 XMLError QueryBoolAttribute( const char* name, bool* 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->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001200 }
1201 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001202 XMLError QueryDoubleAttribute( const char* name, double* 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->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 }
1209 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001210 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001211 const XMLAttribute* a = FindAttribute( name );
1212 if ( !a ) {
1213 return XML_NO_ATTRIBUTE;
1214 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001215 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001217
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001219 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001221 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 }
1223 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001224 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001226 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001227 }
1228 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001229 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001231 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 }
1233 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001234 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001236 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 }
1238 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001239 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001240 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001241 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001242 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001243
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 /**
1245 Delete an attribute.
1246 */
1247 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001248
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 /// Return the first attribute in the list.
1250 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001251 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 }
1253 /// Query a specific attribute in the list.
1254 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001255
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001256 /** Convenience function for easy access to the text inside an element. Although easy
1257 and concise, GetText() is limited compared to getting the TiXmlText child
1258 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001259
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 If the first child of 'this' is a TiXmlText, the GetText()
1261 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001262
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001263 This is a convenient method for getting the text of simple contained text:
1264 @verbatim
1265 <foo>This is text</foo>
1266 const char* str = fooElement->GetText();
1267 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001268
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001270
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 Note that this function can be misleading. If the element foo was created from
1272 this XML:
1273 @verbatim
1274 <foo><b>This is text</b></foo>
1275 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001276
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001277 then the value of str would be null. The first child node isn't a text node, it is
1278 another element. From this XML:
1279 @verbatim
1280 <foo>This is <b>text</b></foo>
1281 @endverbatim
1282 GetText() will return "This is ".
1283 */
1284 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001285
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001286 /**
1287 Convenience method to query the value of a child text node. This is probably best
1288 shown by example. Given you have a document is this form:
1289 @verbatim
1290 <point>
1291 <x>1</x>
1292 <y>1.4</y>
1293 </point>
1294 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001295
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 The QueryIntText() and similar functions provide a safe and easier way to get to the
1297 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001298
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 @verbatim
1300 int x = 0;
1301 float y = 0; // types of x and y are contrived for example
1302 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1303 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1304 xElement->QueryIntText( &x );
1305 yElement->QueryFloatText( &y );
1306 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001307
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1309 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 -07001310
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001312 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001313 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001314 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001316 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001318 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001320 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001321
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 // internal:
1323 enum {
1324 OPEN, // <foo>
1325 CLOSED, // <foo/>
1326 CLOSING // </foo>
1327 };
1328 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001329 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001330 }
1331 char* ParseDeep( char* p, StrPair* endTag );
1332 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1333 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001334
Lee Thomason50adb4c2012-02-13 15:07:09 -08001335private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001336 XMLElement( XMLDocument* doc );
1337 virtual ~XMLElement();
1338 XMLElement( const XMLElement& ); // not supported
1339 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001340
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 XMLAttribute* FindAttribute( const char* name );
1342 XMLAttribute* FindOrCreateAttribute( const char* name );
1343 //void LinkAttribute( XMLAttribute* attrib );
1344 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001345
Lee Thomason624d43f2012-10-12 10:58:48 -07001346 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001347 // The attribute list is ordered; there is no 'lastAttribute'
1348 // because the list needs to be scanned for dupes before adding
1349 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001350 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001351};
1352
1353
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001354enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001355 PRESERVE_WHITESPACE,
1356 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001357};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001358
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001359
1360/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001361 It can be saved, loaded, and printed to the screen.
1362 All Nodes are connected and allocated to a Document.
1363 If the Document is deleted, all its Nodes are also deleted.
1364*/
Lee Thomason67d61312012-01-24 16:01:51 -08001365class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001366{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001367 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001368public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001369 /// constructor
1370 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1371 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001372
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 virtual XMLDocument* ToDocument() {
1374 return this;
1375 }
1376 virtual const XMLDocument* ToDocument() const {
1377 return this;
1378 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001379
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /**
1381 Parse an XML file from a character string.
1382 Returns XML_NO_ERROR (0) on success, or
1383 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001384
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001385 You may optionally pass in the 'nBytes', which is
1386 the number of bytes which will be parsed. If not
1387 specified, TinyXML will assume 'xml' points to a
1388 null terminated string.
1389 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001390 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001391
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001392 /**
1393 Load an XML file from disk.
1394 Returns XML_NO_ERROR (0) on success, or
1395 an errorID.
1396 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001397 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001398
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001399 /**
1400 Load an XML file from disk. You are responsible
1401 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001402
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 Returns XML_NO_ERROR (0) on success, or
1404 an errorID.
1405 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001406 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001407
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 /**
1409 Save the XML file to disk.
1410 Returns XML_NO_ERROR (0) on success, or
1411 an errorID.
1412 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001413 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001414
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 /**
1416 Save the XML file to disk. You are responsible
1417 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001418
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001419 Returns XML_NO_ERROR (0) on success, or
1420 an errorID.
1421 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001422 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001423
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001425 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001426 }
1427 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001428 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001430
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 /**
1432 Returns true if this document has a leading Byte Order Mark of UTF8.
1433 */
1434 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001435 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001436 }
1437 /** Sets whether to write the BOM when writing the file.
1438 */
1439 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001440 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001442
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001443 /** Return the root element of DOM. Equivalent to FirstChildElement().
1444 To get the first node, use FirstChild().
1445 */
1446 XMLElement* RootElement() {
1447 return FirstChildElement();
1448 }
1449 const XMLElement* RootElement() const {
1450 return FirstChildElement();
1451 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001452
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 /** Print the Document. If the Printer is not provided, it will
1454 print to stdout. If you provide Printer, this can print to a file:
1455 @verbatim
1456 XMLPrinter printer( fp );
1457 doc.Print( &printer );
1458 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001459
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001460 Or you can use a printer to print to memory:
1461 @verbatim
1462 XMLPrinter printer;
1463 doc->Print( &printer );
1464 // printer.CStr() has a const char* to the XML
1465 @endverbatim
1466 */
1467 void Print( XMLPrinter* streamer=0 );
1468 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001469
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001470 /**
1471 Create a new Element associated with
1472 this Document. The memory for the Element
1473 is managed by the Document.
1474 */
1475 XMLElement* NewElement( const char* name );
1476 /**
1477 Create a new Comment associated with
1478 this Document. The memory for the Comment
1479 is managed by the Document.
1480 */
1481 XMLComment* NewComment( const char* comment );
1482 /**
1483 Create a new Text associated with
1484 this Document. The memory for the Text
1485 is managed by the Document.
1486 */
1487 XMLText* NewText( const char* text );
1488 /**
1489 Create a new Declaration associated with
1490 this Document. The memory for the object
1491 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001492
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001493 If the 'text' param is null, the standard
1494 declaration is used.:
1495 @verbatim
1496 <?xml version="1.0" encoding="UTF-8"?>
1497 @endverbatim
1498 */
1499 XMLDeclaration* NewDeclaration( const char* text=0 );
1500 /**
1501 Create a new Unknown associated with
Lee Thomason624d43f2012-10-12 10:58:48 -07001502 this Document. The memory forthe object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 is managed by the Document.
1504 */
1505 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /**
1508 Delete a node associated with this document.
1509 It will be unlinked from the DOM.
1510 */
1511 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001512 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001514
Lee Thomason2fa81722012-11-09 12:37:46 -08001515 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 /// Return true if there was an error parsing the document.
1518 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001519 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 }
1521 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001522 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001523 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 }
1525 /// Return a possibly helpful diagnostic location or string.
1526 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001527 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 }
1529 /// Return a possibly helpful secondary diagnostic location or string.
1530 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001531 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 }
1533 /// If there is an error, print it to stdout.
1534 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001535
1536 /// Clear the document, resetting it to the initial state.
1537 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001538
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 // internal
1540 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001541
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1543 return 0;
1544 }
1545 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1546 return false;
1547 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001548
Lee Thomason3f57d272012-01-11 15:30:03 -08001549private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001550 XMLDocument( const XMLDocument& ); // not supported
1551 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001552
Lee Thomason2fa81722012-11-09 12:37:46 -08001553 bool _writeBOM;
1554 bool _processEntities;
1555 XMLError _errorID;
1556 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001557 const char* _errorStr1;
1558 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001559 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001560
Lee Thomason624d43f2012-10-12 10:58:48 -07001561 MemPoolT< sizeof(XMLElement) > _elementPool;
1562 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1563 MemPoolT< sizeof(XMLText) > _textPool;
1564 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001565};
1566
Lee Thomason7c913cd2012-01-26 18:32:34 -08001567
Lee Thomason3ffdd392012-03-28 17:27:55 -07001568/**
1569 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001570 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001571 DOM structure. It is a separate utility class.
1572
1573 Take an example:
1574 @verbatim
1575 <Document>
1576 <Element attributeA = "valueA">
1577 <Child attributeB = "value1" />
1578 <Child attributeB = "value2" />
1579 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001580 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001581 @endverbatim
1582
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001583 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001584 easy to write a *lot* of code that looks like:
1585
1586 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001587 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001588 if ( root )
1589 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001590 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001591 if ( element )
1592 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001593 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001594 if ( child )
1595 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001596 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001597 if ( child2 )
1598 {
1599 // Finally do something useful.
1600 @endverbatim
1601
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001602 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001603 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001604 and correct to use:
1605
1606 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001607 XMLHandle docHandle( &document );
1608 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001609 if ( child2 )
1610 {
1611 // do something useful
1612 @endverbatim
1613
1614 Which is MUCH more concise and useful.
1615
1616 It is also safe to copy handles - internally they are nothing more than node pointers.
1617 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001618 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001619 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001620
1621 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001622*/
1623class XMLHandle
1624{
1625public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 /// 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 -07001627 XMLHandle( XMLNode* node ) {
1628 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001629 }
1630 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001631 XMLHandle( XMLNode& node ) {
1632 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001633 }
1634 /// Copy constructor
1635 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001636 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001637 }
1638 /// Assignment
1639 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001640 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001641 return *this;
1642 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001643
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001644 /// Get the first child of this handle.
1645 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001646 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 }
1648 /// Get the first child element of this handle.
1649 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001650 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001651 }
1652 /// Get the last child of this handle.
1653 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001654 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001655 }
1656 /// Get the last child element of this handle.
1657 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001658 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 }
1660 /// Get the previous sibling of this handle.
1661 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001662 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001663 }
1664 /// Get the previous sibling element of this handle.
1665 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001666 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 }
1668 /// Get the next sibling of this handle.
1669 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001670 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 }
1672 /// Get the next sibling element of this handle.
1673 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001674 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001675 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001676
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001677 /// Safe cast to XMLNode. This can return null.
1678 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001679 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001680 }
1681 /// Safe cast to XMLElement. This can return null.
1682 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001683 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001684 }
1685 /// Safe cast to XMLText. This can return null.
1686 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001687 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001688 }
1689 /// Safe cast to XMLUnknown. This can return null.
1690 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001691 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001692 }
1693 /// Safe cast to XMLDeclaration. This can return null.
1694 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001695 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001696 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001697
1698private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001699 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001700};
1701
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001702
1703/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001704 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1705 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001706*/
1707class XMLConstHandle
1708{
1709public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001710 XMLConstHandle( const XMLNode* node ) {
1711 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001713 XMLConstHandle( const XMLNode& node ) {
1714 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
Lee Thomason8b899812012-04-04 15:58:16 -07001719
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001720 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001721 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001722 return *this;
1723 }
Lee Thomason8b899812012-04-04 15:58:16 -07001724
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001725 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001729 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001730 }
1731 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001732 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001733 }
1734 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001735 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 }
1737 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
1740 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001741 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001742 }
1743 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001744 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001745 }
1746 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
Lee Thomason8b899812012-04-04 15:58:16 -07001749
1750
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001751 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001752 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 }
1754 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001755 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 }
1757 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001758 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001759 }
1760 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001761 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001762 }
1763 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001764 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001766
Lee Thomason5cae8972012-01-24 18:03:07 -08001767private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001768 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001769};
Lee Thomason6f381b72012-03-02 12:59:39 -08001770
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001771
1772/**
1773 Printing functionality. The XMLPrinter gives you more
1774 options than the XMLDocument::Print() method.
1775
1776 It can:
1777 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001778 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001779 -# Print XML without a XMLDocument.
1780
1781 Print to Memory
1782
1783 @verbatim
1784 XMLPrinter printer;
1785 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001786 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001787 @endverbatim
1788
1789 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001790
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001791 You provide the file pointer.
1792 @verbatim
1793 XMLPrinter printer( fp );
1794 doc.Print( &printer );
1795 @endverbatim
1796
1797 Print without a XMLDocument
1798
1799 When loading, an XML parser is very useful. However, sometimes
1800 when saving, it just gets in the way. The code is often set up
1801 for streaming, and constructing the DOM is just overhead.
1802
1803 The Printer supports the streaming case. The following code
1804 prints out a trivially simple XML file without ever creating
1805 an XML document.
1806
1807 @verbatim
1808 XMLPrinter printer( fp );
1809 printer.OpenElement( "foo" );
1810 printer.PushAttribute( "foo", "bar" );
1811 printer.CloseElement();
1812 @endverbatim
1813*/
1814class XMLPrinter : public XMLVisitor
1815{
1816public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001817 /** Construct the printer. If the FILE* is specified,
1818 this will print to the FILE. Else it will print
1819 to memory, and the result is available in CStr().
1820 If 'compact' is set to true, then output is created
1821 with only required whitespace and newlines.
1822 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001823 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001824 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001825
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001826 /** If streaming, write the BOM and declaration. */
1827 void PushHeader( bool writeBOM, bool writeDeclaration );
1828 /** If streaming, start writing an element.
1829 The element must be closed with CloseElement()
1830 */
1831 void OpenElement( const char* name );
1832 /// If streaming, add an attribute to an open element.
1833 void PushAttribute( const char* name, const char* value );
1834 void PushAttribute( const char* name, int value );
1835 void PushAttribute( const char* name, unsigned value );
1836 void PushAttribute( const char* name, bool value );
1837 void PushAttribute( const char* name, double value );
1838 /// If streaming, close the Element.
1839 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001840
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001841 /// Add a text node.
1842 void PushText( const char* text, bool cdata=false );
1843 /// Add a text node from an integer.
1844 void PushText( int value );
1845 /// Add a text node from an unsigned.
1846 void PushText( unsigned value );
1847 /// Add a text node from a bool.
1848 void PushText( bool value );
1849 /// Add a text node from a float.
1850 void PushText( float value );
1851 /// Add a text node from a double.
1852 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001853
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001854 /// Add a comment
1855 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001856
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001857 void PushDeclaration( const char* value );
1858 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001859
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001860 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1861 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1862 return true;
1863 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001864
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001865 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1866 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001867
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001868 virtual bool Visit( const XMLText& text );
1869 virtual bool Visit( const XMLComment& comment );
1870 virtual bool Visit( const XMLDeclaration& declaration );
1871 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001872
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001873 /**
1874 If in print to memory mode, return a pointer to
1875 the XML file in memory.
1876 */
1877 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001878 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001879 }
1880 /**
1881 If in print to memory mode, return the size
1882 of the XML file in memory. (Note the size returned
1883 includes the terminating null.)
1884 */
1885 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001886 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001887 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001888
1889private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 void SealElement();
1891 void PrintSpace( int depth );
1892 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1893 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001894
Lee Thomason624d43f2012-10-12 10:58:48 -07001895 bool _elementJustOpened;
1896 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001897 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001898 int _depth;
1899 int _textDepth;
1900 bool _processEntities;
1901 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001902
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001903 enum {
1904 ENTITY_RANGE = 64,
1905 BUF_SIZE = 200
1906 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001907 bool _entityFlag[ENTITY_RANGE];
1908 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001909
Lee Thomason624d43f2012-10-12 10:58:48 -07001910 DynArray< const char*, 10 > _stack;
1911 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001912#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001913 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001914#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001915};
1916
1917
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001918} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001919
1920
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001921#endif // TINYXML2_INCLUDED