blob: 071dbbe3ce75c15da5853f2fc5890b272bdd98ed [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070027#ifdef ANDROID_NDK
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
48 g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
49
50 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# if defined(_MSC_VER)
63# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64# elif defined (ANDROID_NDK)
65# include <android/log.h>
66# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67# else
68# include <assert.h>
69# define TIXMLASSERT assert
70# endif
71# else
72# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// Microsoft visual studio, version 2005 and higher.
78/*int _snprintf_s(
79 char *buffer,
80 size_t sizeOfBuffer,
81 size_t count,
82 const char *format [,
83 argument] ...
84);*/
85inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86{
87 va_list va;
88 va_start( va, format );
89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90 va_end( va );
91 return result;
92}
93#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700103static const int TIXML2_PATCH_VERSION = 8;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
111class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800112class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800113class XMLDeclaration;
114class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800115
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118/*
119 A class that wraps strings. Normally stores the start and end
120 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800121 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800122 manage) a traditional char[]
123*/
Lee Thomason39ede242012-01-20 11:27:56 -0800124class StrPair
125{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700127 enum {
128 NEEDS_ENTITY_PROCESSING = 0x01,
129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
Lee Thomason624d43f2012-10-12 10:58:48 -0700132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason624d43f2012-10-12 10:58:48 -0700134 ATTRIBUTE_NAME = 0,
135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700138 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 // After parsing, if *end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 int _flags;
177 char* _start;
178 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800187template <class T, int INIT>
188class DynArray
189{
190public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700192 _mem = _pool;
193 _allocated = INIT;
194 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700204 EnsureCapacity( _size+1 );
205 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700206 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 EnsureCapacity( _size+count );
210 T* ret = &_mem[_size];
211 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 return ret;
213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 TIXMLASSERT( _size >= count );
221 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700230 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700235 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800253
Lee Thomason2c85a712012-01-31 08:24:24 -0800254private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int newAllocated = cap * 2;
258 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
260 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700261 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
266 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800267
Lee Thomason624d43f2012-10-12 10:58:48 -0700268 T* _mem;
269 T _pool[INIT];
270 int _allocated; // objects allocated
271 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800272};
273
Lee Thomason50adb4c2012-02-13 15:07:09 -0800274
U-Stream\Leeae25a442012-02-17 17:48:16 -0800275/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200276 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800277 and deallocation of objects.
278*/
Lee Thomasond1983222012-02-06 08:41:24 -0800279class MemPool
280{
281public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 MemPool() {}
283 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800284
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 virtual int ItemSize() const = 0;
286 virtual void* Alloc() = 0;
287 virtual void Free( void* ) = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800288};
289
Lee Thomason50adb4c2012-02-13 15:07:09 -0800290
U-Stream\Leeae25a442012-02-17 17:48:16 -0800291/*
292 Template child class to create pools of the correct type.
293*/
Lee Thomasond1983222012-02-06 08:41:24 -0800294template< int SIZE >
295class MemPoolT : public MemPool
296{
297public:
Lee Thomason624d43f2012-10-12 10:58:48 -0700298 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700299 ~MemPoolT() {
300 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700301 for( int i=0; i<_blockPtrs.Size(); ++i ) {
302 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 }
304 }
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const {
307 return SIZE;
308 }
309 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700310 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700311 }
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700314 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700315 // Need a new block.
316 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700317 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800318
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700319 for( int i=0; i<COUNT-1; ++i ) {
320 block->chunk[i].next = &block->chunk[i+1];
321 }
322 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700325 void* result = _root;
326 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800327
Lee Thomason624d43f2012-10-12 10:58:48 -0700328 ++_currentAllocs;
329 if ( _currentAllocs > _maxAllocs ) {
330 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 _nAllocs++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 return result;
334 }
335 virtual void Free( void* mem ) {
336 if ( !mem ) {
337 return;
338 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700341#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 chunk->next = _root;
345 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
347 void Trace( const char* name ) {
348 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700350 }
Lee Thomasond1983222012-02-06 08:41:24 -0800351
Jerome Martinez7921df12012-10-24 11:45:44 +0200352 enum { COUNT = 1024/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
353
Lee Thomasond1983222012-02-06 08:41:24 -0800354private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700355 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700356 Chunk* next;
357 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700358 };
359 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700360 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 DynArray< Block*, 10 > _blockPtrs;
363 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800364
Lee Thomason624d43f2012-10-12 10:58:48 -0700365 int _currentAllocs;
366 int _nAllocs;
367 int _maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800368};
369
Lee Thomason2c85a712012-01-31 08:24:24 -0800370
Lee Thomason56bdd022012-02-09 18:16:58 -0800371
372/**
373 Implements the interface to the "Visitor pattern" (see the Accept() method.)
374 If you call the Accept() method, it requires being passed a XMLVisitor
375 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200376 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800377 are simply called with Visit().
378
379 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200380 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800381
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700382 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800383 visiting). You need to only override methods that are interesting to you.
384
Thomas Roß08bdf502012-05-12 14:21:23 +0200385 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800386
387 You should never change the document from a callback.
388
389 @sa XMLNode::Accept()
390*/
391class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800392{
393public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700394 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800395
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700396 /// Visit a document.
397 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
398 return true;
399 }
400 /// Visit a document.
401 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
402 return true;
403 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800404
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700405 /// Visit an element.
406 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
407 return true;
408 }
409 /// Visit an element.
410 virtual bool VisitExit( const XMLElement& /*element*/ ) {
411 return true;
412 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800413
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700414 /// Visit a declaration.
415 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
416 return true;
417 }
418 /// Visit a text node.
419 virtual bool Visit( const XMLText& /*text*/ ) {
420 return true;
421 }
422 /// Visit a comment node.
423 virtual bool Visit( const XMLComment& /*comment*/ ) {
424 return true;
425 }
426 /// Visit an unknown node.
427 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
428 return true;
429 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800430};
431
432
U-Stream\Leeae25a442012-02-17 17:48:16 -0800433/*
434 Utility functionality.
435*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800436class XMLUtil
437{
Lee Thomasond1983222012-02-06 08:41:24 -0800438public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700439 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
440 // correct, but simple, and usually works.
441 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200442 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700443 ++p;
444 }
445 return p;
446 }
447 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200448 while( !IsUTF8Continuation(*p) && std::isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700449 ++p;
450 }
451 return p;
452 }
453 static bool IsWhiteSpace( char p ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200454 return !IsUTF8Continuation(p) && std::isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700455 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800456
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700457 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
458 int n = 0;
459 if ( p == q ) {
460 return true;
461 }
462 while( *p && *q && *p == *q && n<nChar ) {
463 ++p;
464 ++q;
465 ++n;
466 }
467 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
468 return true;
469 }
470 return false;
471 }
472 inline static int IsUTF8Continuation( const char p ) {
473 return p & 0x80;
474 }
475 inline static int IsAlphaNum( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200476 return ( anyByte < 128 ) ? std::isalnum( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700477 }
478 inline static int IsAlpha( unsigned char anyByte ) {
Jerome Martinez7fbefab2012-10-19 11:30:33 +0200479 return ( anyByte < 128 ) ? std::isalpha( anyByte ) : 1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800481
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700482 static const char* ReadBOM( const char* p, bool* hasBOM );
483 // p is the starting location,
484 // the UTF-8 value of the entity will be placed in value, and length filled in.
485 static const char* GetCharacterRef( const char* p, char* value, int* length );
486 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700487
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700488 // converts primitive types to strings
489 static void ToStr( int v, char* buffer, int bufferSize );
490 static void ToStr( unsigned v, char* buffer, int bufferSize );
491 static void ToStr( bool v, char* buffer, int bufferSize );
492 static void ToStr( float v, char* buffer, int bufferSize );
493 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700494
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700495 // converts strings to primitive types
496 static bool ToInt( const char* str, int* value );
497 static bool ToUnsigned( const char* str, unsigned* value );
498 static bool ToBool( const char* str, bool* value );
499 static bool ToFloat( const char* str, float* value );
500 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800501};
502
Lee Thomason5cae8972012-01-24 18:03:07 -0800503
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800504/** XMLNode is a base class for every object that is in the
505 XML Document Object Model (DOM), except XMLAttributes.
506 Nodes have siblings, a parent, and children which can
507 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700508 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800509 be cast to its more defined type.
510
Thomas Roß08bdf502012-05-12 14:21:23 +0200511 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800512 When the XMLDocument gets deleted, all its Nodes
513 will also be deleted.
514
515 @verbatim
516 A Document can contain: Element (container or leaf)
517 Comment (leaf)
518 Unknown (leaf)
519 Declaration( leaf )
520
521 An Element can contain: Element (container or leaf)
522 Text (leaf)
523 Attributes (not on tree)
524 Comment (leaf)
525 Unknown (leaf)
526
527 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800528*/
Lee Thomasond1983222012-02-06 08:41:24 -0800529class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800530{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 friend class XMLDocument;
532 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800533public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800534
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700535 /// Get the XMLDocument that owns this XMLNode.
536 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700537 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700538 }
539 /// Get the XMLDocument that owns this XMLNode.
540 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700541 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700542 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800543
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700544 virtual XMLElement* ToElement() {
545 return 0; ///< Safely cast to an Element, or null.
546 }
547 virtual XMLText* ToText() {
548 return 0; ///< Safely cast to Text, or null.
549 }
550 virtual XMLComment* ToComment() {
551 return 0; ///< Safely cast to a Comment, or null.
552 }
553 virtual XMLDocument* ToDocument() {
554 return 0; ///< Safely cast to a Document, or null.
555 }
556 virtual XMLDeclaration* ToDeclaration() {
557 return 0; ///< Safely cast to a Declaration, or null.
558 }
559 virtual XMLUnknown* ToUnknown() {
560 return 0; ///< Safely cast to an Unknown, or null.
561 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800562
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700563 virtual const XMLElement* ToElement() const {
564 return 0;
565 }
566 virtual const XMLText* ToText() const {
567 return 0;
568 }
569 virtual const XMLComment* ToComment() const {
570 return 0;
571 }
572 virtual const XMLDocument* ToDocument() const {
573 return 0;
574 }
575 virtual const XMLDeclaration* ToDeclaration() const {
576 return 0;
577 }
578 virtual const XMLUnknown* ToUnknown() const {
579 return 0;
580 }
Lee Thomason751da522012-02-10 08:50:51 -0800581
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700582 /** The meaning of 'value' changes for the specific type.
583 @verbatim
584 Document: empty
585 Element: name of the element
586 Comment: the comment text
587 Unknown: the tag contents
588 Text: the text string
589 @endverbatim
590 */
591 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700592 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700593 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700594
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 /** Set the Value of an XML node.
596 @sa Value()
597 */
598 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800599
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 /// Get the parent of this node on the DOM.
601 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700602 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700603 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700604
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700605 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700606 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700607 }
Lee Thomason751da522012-02-10 08:50:51 -0800608
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700609 /// Returns true if this node has no children.
610 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700611 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 }
Lee Thomason751da522012-02-10 08:50:51 -0800613
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 /// Get the first child node, or null if none exists.
615 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700616 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700617 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700618
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700619 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700620 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700621 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700622
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700623 /** Get the first child element, or optionally the first child
624 element with the specified name.
625 */
626 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700627
628 XMLElement* FirstChildElement( const char* value=0 ) {
629 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700630 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800631
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700632 /// Get the last child node, or null if none exists.
633 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700634 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700635 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700636
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 XMLNode* LastChild() {
638 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
639 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800640
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 /** Get the last child element or optionally the last child
642 element with the specified name.
643 */
644 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700645
646 XMLElement* LastChildElement( const char* value=0 ) {
647 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700649
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 /// Get the previous (left) sibling node of this node.
651 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700652 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700654
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700656 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800658
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
660 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700661
662 XMLElement* PreviousSiblingElement( const char* value=0 ) {
663 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700665
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 /// Get the next (right) sibling node of this node.
667 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700668 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700670
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700671 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700672 return _next;
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 next (right) sibling element of this node, with an opitionally supplied name.
676 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700677
678 XMLElement* NextSiblingElement( const char* value=0 ) {
679 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800681
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 /**
683 Add a child node as the last (right) child.
684 */
685 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800686
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 XMLNode* LinkEndChild( XMLNode* addThis ) {
688 return InsertEndChild( addThis );
689 }
690 /**
691 Add a child node as the first (left) child.
692 */
693 XMLNode* InsertFirstChild( XMLNode* addThis );
694 /**
695 Add a node after the specified child node.
696 */
697 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700698
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 /**
700 Delete all the children of this node.
701 */
702 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800703
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 /**
705 Delete a child of this node.
706 */
707 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800708
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 /**
710 Make a copy of this node, but not its children.
711 You may pass in a Document pointer that will be
712 the owner of the new Node. If the 'document' is
713 null, then the node returned will be allocated
714 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 Note: if called on a XMLDocument, this will return null.
717 */
718 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800719
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 /**
721 Test if 2 nodes are the same, but don't test children.
722 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 Note: if called on a XMLDocument, this will return false.
725 */
726 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800727
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700728 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
729 XML tree will be conditionally visited and the host will be called back
730 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800731
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
733 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
734 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800735
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700736 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 - http://www.saxproject.org/
739 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800740
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800742
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 An example of using Accept():
744 @verbatim
745 TiXmlPrinter printer;
746 tinyxmlDoc.Accept( &printer );
747 const char* xmlcstr = printer.CStr();
748 @endverbatim
749 */
750 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800751
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 // internal
753 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800754
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800755protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700756 XMLNode( XMLDocument* );
757 virtual ~XMLNode();
758 XMLNode( const XMLNode& ); // not supported
759 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700760
Lee Thomason624d43f2012-10-12 10:58:48 -0700761 XMLDocument* _document;
762 XMLNode* _parent;
763 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800764
Lee Thomason624d43f2012-10-12 10:58:48 -0700765 XMLNode* _firstChild;
766 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800767
Lee Thomason624d43f2012-10-12 10:58:48 -0700768 XMLNode* _prev;
769 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800770
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800771private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700772 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800774};
775
776
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800777/** XML text.
778
779 Note that a text node can have child element nodes, for example:
780 @verbatim
781 <root>This is <b>bold</b></root>
782 @endverbatim
783
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700784 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800785 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 -0700786 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800787 SetCDATA() and query it with CDATA().
788*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800789class XMLText : public XMLNode
790{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 friend class XMLBase;
792 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800793public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700794 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800795
Lee Thomason624d43f2012-10-12 10:58:48 -0700796 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700797 return this;
798 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700799 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 return this;
801 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800802
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700804 void SetCData( bool isCData ) {
805 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 }
807 /// Returns true if this is a CDATA text element.
808 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700809 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700810 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800811
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 char* ParseDeep( char*, StrPair* endTag );
813 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
814 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800815
Lee Thomason5492a1c2012-01-23 15:32:10 -0800816protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700817 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700818 virtual ~XMLText() {}
819 XMLText( const XMLText& ); // not supported
820 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800821
822private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700823 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800824};
825
826
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800827/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800828class XMLComment : public XMLNode
829{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700830 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800831public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700832 virtual XMLComment* ToComment() {
833 return this;
834 }
835 virtual const XMLComment* ToComment() const {
836 return this;
837 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800838
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700839 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800840
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700841 char* ParseDeep( char*, StrPair* endTag );
842 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
843 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800844
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800845protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 XMLComment( XMLDocument* doc );
847 virtual ~XMLComment();
848 XMLComment( const XMLComment& ); // not supported
849 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800850
Lee Thomason3f57d272012-01-11 15:30:03 -0800851private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800852};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800853
854
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800855/** In correct XML the declaration is the first entry in the file.
856 @verbatim
857 <?xml version="1.0" standalone="yes"?>
858 @endverbatim
859
860 TinyXML2 will happily read or write files without a declaration,
861 however.
862
863 The text of the declaration isn't interpreted. It is parsed
864 and written as a string.
865*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800866class XMLDeclaration : public XMLNode
867{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700868 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800869public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700870 virtual XMLDeclaration* ToDeclaration() {
871 return this;
872 }
873 virtual const XMLDeclaration* ToDeclaration() const {
874 return this;
875 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800876
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700877 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800878
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700879 char* ParseDeep( char*, StrPair* endTag );
880 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
881 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800882
883protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700884 XMLDeclaration( XMLDocument* doc );
885 virtual ~XMLDeclaration();
886 XMLDeclaration( const XMLDeclaration& ); // not supported
887 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800888};
889
890
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800891/** Any tag that tinyXml doesn't recognize is saved as an
892 unknown. It is a tag of text, but should not be modified.
893 It will be written back to the XML, unchanged, when the file
894 is saved.
895
896 DTD tags get thrown into TiXmlUnknowns.
897*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800898class XMLUnknown : public XMLNode
899{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700900 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800901public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700902 virtual XMLUnknown* ToUnknown() {
903 return this;
904 }
905 virtual const XMLUnknown* ToUnknown() const {
906 return this;
907 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800908
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700909 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800910
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700911 char* ParseDeep( char*, StrPair* endTag );
912 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
913 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800914
915protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700916 XMLUnknown( XMLDocument* doc );
917 virtual ~XMLUnknown();
918 XMLUnknown( const XMLUnknown& ); // not supported
919 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800920};
921
922
Lee Thomason1ff38e02012-02-14 18:18:16 -0800923enum {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700924 XML_NO_ERROR = 0,
925 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800926
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700927 XML_NO_ATTRIBUTE,
928 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800929
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700930 XML_ERROR_FILE_NOT_FOUND,
931 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
932 XML_ERROR_FILE_READ_ERROR,
933 XML_ERROR_ELEMENT_MISMATCH,
934 XML_ERROR_PARSING_ELEMENT,
935 XML_ERROR_PARSING_ATTRIBUTE,
936 XML_ERROR_IDENTIFYING_TAG,
937 XML_ERROR_PARSING_TEXT,
938 XML_ERROR_PARSING_CDATA,
939 XML_ERROR_PARSING_COMMENT,
940 XML_ERROR_PARSING_DECLARATION,
941 XML_ERROR_PARSING_UNKNOWN,
942 XML_ERROR_EMPTY_DOCUMENT,
943 XML_ERROR_MISMATCHED_ELEMENT,
944 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700945
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700946 XML_CAN_NOT_CONVERT_TEXT,
947 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800948};
949
950
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800951/** An attribute is a name-value pair. Elements have an arbitrary
952 number of attributes, each with a unique name.
953
954 @note The attributes are not XMLNodes. You may only query the
955 Next() attribute in a list.
956*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800957class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800958{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700959 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800960public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700961 const char* Name() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700962 return _name.GetStr(); ///< The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700963 }
964 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700965 return _value.GetStr(); ///< The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 }
967 const XMLAttribute* Next() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700968 return _next; ///< The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700969 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800970
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700971 /** IntAttribute interprets the attribute as an integer, and returns the value.
972 If the value isn't an integer, 0 will be returned. There is no error checking;
973 use QueryIntAttribute() if you need error checking.
974 */
975 int IntValue() const {
976 int i=0;
977 QueryIntValue( &i );
978 return i;
979 }
980 /// Query as an unsigned integer. See IntAttribute()
981 unsigned UnsignedValue() const {
982 unsigned i=0;
983 QueryUnsignedValue( &i );
984 return i;
985 }
986 /// Query as a boolean. See IntAttribute()
987 bool BoolValue() const {
988 bool b=false;
989 QueryBoolValue( &b );
990 return b;
991 }
992 /// Query as a double. See IntAttribute()
993 double DoubleValue() const {
994 double d=0;
995 QueryDoubleValue( &d );
996 return d;
997 }
998 /// Query as a float. See IntAttribute()
999 float FloatValue() const {
1000 float f=0;
1001 QueryFloatValue( &f );
1002 return f;
1003 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001004
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001005 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
1006 in the provided paremeter. The function will return XML_NO_ERROR on success,
1007 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1008 */
1009 int QueryIntValue( int* value ) const;
1010 /// See QueryIntAttribute
1011 int QueryUnsignedValue( unsigned int* value ) const;
1012 /// See QueryIntAttribute
1013 int QueryBoolValue( bool* value ) const;
1014 /// See QueryIntAttribute
1015 int QueryDoubleValue( double* value ) const;
1016 /// See QueryIntAttribute
1017 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001018
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 /// Set the attribute to a string value.
1020 void SetAttribute( const char* value );
1021 /// Set the attribute to value.
1022 void SetAttribute( int value );
1023 /// Set the attribute to value.
1024 void SetAttribute( unsigned value );
1025 /// Set the attribute to value.
1026 void SetAttribute( bool value );
1027 /// Set the attribute to value.
1028 void SetAttribute( double value );
1029 /// Set the attribute to value.
1030 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001031
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001032private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001033 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001034
Lee Thomason624d43f2012-10-12 10:58:48 -07001035 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001036 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001037
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001038 XMLAttribute( const XMLAttribute& ); // not supported
1039 void operator=( const XMLAttribute& ); // not supported
1040 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001041
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001043
Lee Thomason624d43f2012-10-12 10:58:48 -07001044 mutable StrPair _name;
1045 mutable StrPair _value;
1046 XMLAttribute* _next;
1047 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001048};
1049
1050
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001051/** The element is a container class. It has a value, the element name,
1052 and can contain other elements, text, comments, and unknowns.
1053 Elements also contain an arbitrary number of attributes.
1054*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001055class XMLElement : public XMLNode
1056{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 friend class XMLBase;
1058 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001059public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001060 /// Get the name of an element (which is the Value() of the node.)
1061 const char* Name() const {
1062 return Value();
1063 }
1064 /// Set the name of the element.
1065 void SetName( const char* str, bool staticMem=false ) {
1066 SetValue( str, staticMem );
1067 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001068
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001069 virtual XMLElement* ToElement() {
1070 return this;
1071 }
1072 virtual const XMLElement* ToElement() const {
1073 return this;
1074 }
1075 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001076
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001077 /** Given an attribute name, Attribute() returns the value
1078 for the attribute of that name, or null if none
1079 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001080
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001081 @verbatim
1082 const char* value = ele->Attribute( "foo" );
1083 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001084
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001085 The 'value' parameter is normally null. However, if specified,
1086 the attribute will only be returned if the 'name' and 'value'
1087 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001088
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001089 @verbatim
1090 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1091 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001092
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 rather than:
1094 @verbatim
1095 if ( ele->Attribute( "foo" ) ) {
1096 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1097 }
1098 @endverbatim
1099 */
1100 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001101
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001102 /** Given an attribute name, IntAttribute() returns the value
1103 of the attribute interpreted as an integer. 0 will be
1104 returned if there is an error. For a method with error
1105 checking, see QueryIntAttribute()
1106 */
1107 int IntAttribute( const char* name ) const {
1108 int i=0;
1109 QueryIntAttribute( name, &i );
1110 return i;
1111 }
1112 /// See IntAttribute()
1113 unsigned UnsignedAttribute( const char* name ) const {
1114 unsigned i=0;
1115 QueryUnsignedAttribute( name, &i );
1116 return i;
1117 }
1118 /// See IntAttribute()
1119 bool BoolAttribute( const char* name ) const {
1120 bool b=false;
1121 QueryBoolAttribute( name, &b );
1122 return b;
1123 }
1124 /// See IntAttribute()
1125 double DoubleAttribute( const char* name ) const {
1126 double d=0;
1127 QueryDoubleAttribute( name, &d );
1128 return d;
1129 }
1130 /// See IntAttribute()
1131 float FloatAttribute( const char* name ) const {
1132 float f=0;
1133 QueryFloatAttribute( name, &f );
1134 return f;
1135 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001136
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001137 /** Given an attribute name, QueryIntAttribute() returns
1138 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1139 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1140 doesn't exist. If successful, the result of the conversion
1141 will be written to 'value'. If not successful, nothing will
1142 be written to 'value'. This allows you to provide default
1143 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001144
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001145 @verbatim
1146 int value = 10;
1147 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1148 @endverbatim
1149 */
Lee Thomason624d43f2012-10-12 10:58:48 -07001150 int QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001151 const XMLAttribute* a = FindAttribute( name );
1152 if ( !a ) {
1153 return XML_NO_ATTRIBUTE;
1154 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001155 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001156 }
1157 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001158 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001159 const XMLAttribute* a = FindAttribute( name );
1160 if ( !a ) {
1161 return XML_NO_ATTRIBUTE;
1162 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001163 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001164 }
1165 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001166 int QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001167 const XMLAttribute* a = FindAttribute( name );
1168 if ( !a ) {
1169 return XML_NO_ATTRIBUTE;
1170 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001171 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001172 }
1173 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001174 int QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001175 const XMLAttribute* a = FindAttribute( name );
1176 if ( !a ) {
1177 return XML_NO_ATTRIBUTE;
1178 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001179 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001180 }
1181 /// See QueryIntAttribute()
Lee Thomason624d43f2012-10-12 10:58:48 -07001182 int QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001183 const XMLAttribute* a = FindAttribute( name );
1184 if ( !a ) {
1185 return XML_NO_ATTRIBUTE;
1186 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001187 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001188 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001189
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001190 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001191 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001193 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001194 }
1195 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001196 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001197 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001198 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001199 }
1200 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001201 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001202 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001203 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 }
1205 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001206 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001207 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001208 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 }
1210 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001211 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001213 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001215
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 /**
1217 Delete an attribute.
1218 */
1219 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001220
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 /// Return the first attribute in the list.
1222 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001223 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001224 }
1225 /// Query a specific attribute in the list.
1226 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001227
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001228 /** Convenience function for easy access to the text inside an element. Although easy
1229 and concise, GetText() is limited compared to getting the TiXmlText child
1230 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001231
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 If the first child of 'this' is a TiXmlText, the GetText()
1233 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001234
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 This is a convenient method for getting the text of simple contained text:
1236 @verbatim
1237 <foo>This is text</foo>
1238 const char* str = fooElement->GetText();
1239 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001240
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001242
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001243 Note that this function can be misleading. If the element foo was created from
1244 this XML:
1245 @verbatim
1246 <foo><b>This is text</b></foo>
1247 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001248
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 then the value of str would be null. The first child node isn't a text node, it is
1250 another element. From this XML:
1251 @verbatim
1252 <foo>This is <b>text</b></foo>
1253 @endverbatim
1254 GetText() will return "This is ".
1255 */
1256 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001257
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001258 /**
1259 Convenience method to query the value of a child text node. This is probably best
1260 shown by example. Given you have a document is this form:
1261 @verbatim
1262 <point>
1263 <x>1</x>
1264 <y>1.4</y>
1265 </point>
1266 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001267
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001268 The QueryIntText() and similar functions provide a safe and easier way to get to the
1269 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001270
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 @verbatim
1272 int x = 0;
1273 float y = 0; // types of x and y are contrived for example
1274 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1275 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1276 xElement->QueryIntText( &x );
1277 yElement->QueryFloatText( &y );
1278 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001279
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001280 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1281 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 -07001282
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001283 */
1284 int QueryIntText( int* _value ) const;
1285 /// See QueryIntText()
1286 int QueryUnsignedText( unsigned* _value ) const;
1287 /// See QueryIntText()
1288 int QueryBoolText( bool* _value ) const;
1289 /// See QueryIntText()
1290 int QueryDoubleText( double* _value ) const;
1291 /// See QueryIntText()
1292 int QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001293
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001294 // internal:
1295 enum {
1296 OPEN, // <foo>
1297 CLOSED, // <foo/>
1298 CLOSING // </foo>
1299 };
1300 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001301 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001302 }
1303 char* ParseDeep( char* p, StrPair* endTag );
1304 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1305 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001306
Lee Thomason50adb4c2012-02-13 15:07:09 -08001307private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 XMLElement( XMLDocument* doc );
1309 virtual ~XMLElement();
1310 XMLElement( const XMLElement& ); // not supported
1311 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001312
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001313 XMLAttribute* FindAttribute( const char* name );
1314 XMLAttribute* FindOrCreateAttribute( const char* name );
1315 //void LinkAttribute( XMLAttribute* attrib );
1316 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001317
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 // The attribute list is ordered; there is no 'lastAttribute'
1320 // because the list needs to be scanned for dupes before adding
1321 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001322 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001323};
1324
1325
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001326enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 PRESERVE_WHITESPACE,
1328 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001329};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001330
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001331
1332/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001333 It can be saved, loaded, and printed to the screen.
1334 All Nodes are connected and allocated to a Document.
1335 If the Document is deleted, all its Nodes are also deleted.
1336*/
Lee Thomason67d61312012-01-24 16:01:51 -08001337class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001338{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001339 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001340public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 /// constructor
1342 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1343 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001344
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001345 virtual XMLDocument* ToDocument() {
1346 return this;
1347 }
1348 virtual const XMLDocument* ToDocument() const {
1349 return this;
1350 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001351
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 /**
1353 Parse an XML file from a character string.
1354 Returns XML_NO_ERROR (0) on success, or
1355 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001356
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001357 You may optionally pass in the 'nBytes', which is
1358 the number of bytes which will be parsed. If not
1359 specified, TinyXML will assume 'xml' points to a
1360 null terminated string.
1361 */
1362 int Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001363
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 /**
1365 Load an XML file from disk.
1366 Returns XML_NO_ERROR (0) on success, or
1367 an errorID.
1368 */
1369 int LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001370
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001371 /**
1372 Load an XML file from disk. You are responsible
1373 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001374
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001375 Returns XML_NO_ERROR (0) on success, or
1376 an errorID.
1377 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001378 int LoadFile( std::FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001379
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /**
1381 Save the XML file to disk.
1382 Returns XML_NO_ERROR (0) on success, or
1383 an errorID.
1384 */
1385 int SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001386
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001387 /**
1388 Save the XML file to disk. You are responsible
1389 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001390
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 Returns XML_NO_ERROR (0) on success, or
1392 an errorID.
1393 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001394 int SaveFile( std::FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001395
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001397 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001398 }
1399 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001402
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 /**
1404 Returns true if this document has a leading Byte Order Mark of UTF8.
1405 */
1406 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001407 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 }
1409 /** Sets whether to write the BOM when writing the file.
1410 */
1411 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001412 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001414
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 /** Return the root element of DOM. Equivalent to FirstChildElement().
1416 To get the first node, use FirstChild().
1417 */
1418 XMLElement* RootElement() {
1419 return FirstChildElement();
1420 }
1421 const XMLElement* RootElement() const {
1422 return FirstChildElement();
1423 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001424
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001425 /** Print the Document. If the Printer is not provided, it will
1426 print to stdout. If you provide Printer, this can print to a file:
1427 @verbatim
1428 XMLPrinter printer( fp );
1429 doc.Print( &printer );
1430 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001431
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 Or you can use a printer to print to memory:
1433 @verbatim
1434 XMLPrinter printer;
1435 doc->Print( &printer );
1436 // printer.CStr() has a const char* to the XML
1437 @endverbatim
1438 */
1439 void Print( XMLPrinter* streamer=0 );
1440 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 /**
1443 Create a new Element associated with
1444 this Document. The memory for the Element
1445 is managed by the Document.
1446 */
1447 XMLElement* NewElement( const char* name );
1448 /**
1449 Create a new Comment associated with
1450 this Document. The memory for the Comment
1451 is managed by the Document.
1452 */
1453 XMLComment* NewComment( const char* comment );
1454 /**
1455 Create a new Text associated with
1456 this Document. The memory for the Text
1457 is managed by the Document.
1458 */
1459 XMLText* NewText( const char* text );
1460 /**
1461 Create a new Declaration associated with
1462 this Document. The memory for the object
1463 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001464
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001465 If the 'text' param is null, the standard
1466 declaration is used.:
1467 @verbatim
1468 <?xml version="1.0" encoding="UTF-8"?>
1469 @endverbatim
1470 */
1471 XMLDeclaration* NewDeclaration( const char* text=0 );
1472 /**
1473 Create a new Unknown associated with
Lee Thomason624d43f2012-10-12 10:58:48 -07001474 this Document. The memory forthe object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001475 is managed by the Document.
1476 */
1477 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001478
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001479 /**
1480 Delete a node associated with this document.
1481 It will be unlinked from the DOM.
1482 */
1483 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001484 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001485 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001486
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001487 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001488
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001489 /// Return true if there was an error parsing the document.
1490 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001491 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001492 }
1493 /// Return the errorID.
1494 int ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001495 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 }
1497 /// Return a possibly helpful diagnostic location or string.
1498 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001499 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001500 }
1501 /// Return a possibly helpful secondary diagnostic location or string.
1502 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001503 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001504 }
1505 /// If there is an error, print it to stdout.
1506 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 // internal
1509 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001510
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001511 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1512 return 0;
1513 }
1514 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1515 return false;
1516 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001517
Lee Thomason3f57d272012-01-11 15:30:03 -08001518private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001519 XMLDocument( const XMLDocument& ); // not supported
1520 void operator=( const XMLDocument& ); // not supported
1521 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001522
Lee Thomason624d43f2012-10-12 10:58:48 -07001523 bool _writeBOM;
1524 bool _processEntities;
1525 int _errorID;
1526 Whitespace _whitespace;
1527 const char* _errorStr1;
1528 const char* _errorStr2;
1529 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001530
Lee Thomason624d43f2012-10-12 10:58:48 -07001531 MemPoolT< sizeof(XMLElement) > _elementPool;
1532 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1533 MemPoolT< sizeof(XMLText) > _textPool;
1534 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001535};
1536
Lee Thomason7c913cd2012-01-26 18:32:34 -08001537
Lee Thomason3ffdd392012-03-28 17:27:55 -07001538/**
1539 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001540 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001541 DOM structure. It is a separate utility class.
1542
1543 Take an example:
1544 @verbatim
1545 <Document>
1546 <Element attributeA = "valueA">
1547 <Child attributeB = "value1" />
1548 <Child attributeB = "value2" />
1549 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001550 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001551 @endverbatim
1552
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001553 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001554 easy to write a *lot* of code that looks like:
1555
1556 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001557 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001558 if ( root )
1559 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001560 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001561 if ( element )
1562 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001563 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001564 if ( child )
1565 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001566 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001567 if ( child2 )
1568 {
1569 // Finally do something useful.
1570 @endverbatim
1571
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001572 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001573 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001574 and correct to use:
1575
1576 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001577 XMLHandle docHandle( &document );
1578 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001579 if ( child2 )
1580 {
1581 // do something useful
1582 @endverbatim
1583
1584 Which is MUCH more concise and useful.
1585
1586 It is also safe to copy handles - internally they are nothing more than node pointers.
1587 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001588 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001589 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001590
1591 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001592*/
1593class XMLHandle
1594{
1595public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 /// 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 -07001597 XMLHandle( XMLNode* node ) {
1598 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001599 }
1600 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001601 XMLHandle( XMLNode& node ) {
1602 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 }
1604 /// Copy constructor
1605 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001606 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 }
1608 /// Assignment
1609 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001610 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001611 return *this;
1612 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001613
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 /// Get the first child of this handle.
1615 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001616 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001617 }
1618 /// Get the first child element of this handle.
1619 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001620 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001621 }
1622 /// Get the last child of this handle.
1623 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001624 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001625 }
1626 /// Get the last child element of this handle.
1627 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001628 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001629 }
1630 /// Get the previous sibling of this handle.
1631 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001632 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001633 }
1634 /// Get the previous sibling element of this handle.
1635 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001636 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001637 }
1638 /// Get the next sibling of this handle.
1639 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001640 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001641 }
1642 /// Get the next sibling element of this handle.
1643 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001644 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001645 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001646
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 /// Safe cast to XMLNode. This can return null.
1648 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001649 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 }
1651 /// Safe cast to XMLElement. This can return null.
1652 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001653 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 }
1655 /// Safe cast to XMLText. This can return null.
1656 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001657 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001658 }
1659 /// Safe cast to XMLUnknown. This can return null.
1660 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001661 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001662 }
1663 /// Safe cast to XMLDeclaration. This can return null.
1664 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001665 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001666 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001667
1668private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001669 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001670};
1671
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001672
1673/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001674 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1675 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001676*/
1677class XMLConstHandle
1678{
1679public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001680 XMLConstHandle( const XMLNode* node ) {
1681 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001682 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001683 XMLConstHandle( const XMLNode& node ) {
1684 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001685 }
1686 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001687 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001688 }
Lee Thomason8b899812012-04-04 15:58:16 -07001689
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001690 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001691 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001692 return *this;
1693 }
Lee Thomason8b899812012-04-04 15:58:16 -07001694
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001695 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001696 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
1698 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001699 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001700 }
1701 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001702 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 }
1704 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001705 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 }
1707 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001708 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 }
1710 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001711 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 }
1713 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
Lee Thomason8b899812012-04-04 15:58:16 -07001719
1720
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001721 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001725 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 }
1727 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001728 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001729 }
1730 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001731 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 }
1733 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001736
Lee Thomason5cae8972012-01-24 18:03:07 -08001737private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001739};
Lee Thomason6f381b72012-03-02 12:59:39 -08001740
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001741
1742/**
1743 Printing functionality. The XMLPrinter gives you more
1744 options than the XMLDocument::Print() method.
1745
1746 It can:
1747 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001748 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001749 -# Print XML without a XMLDocument.
1750
1751 Print to Memory
1752
1753 @verbatim
1754 XMLPrinter printer;
1755 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001756 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001757 @endverbatim
1758
1759 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001760
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001761 You provide the file pointer.
1762 @verbatim
1763 XMLPrinter printer( fp );
1764 doc.Print( &printer );
1765 @endverbatim
1766
1767 Print without a XMLDocument
1768
1769 When loading, an XML parser is very useful. However, sometimes
1770 when saving, it just gets in the way. The code is often set up
1771 for streaming, and constructing the DOM is just overhead.
1772
1773 The Printer supports the streaming case. The following code
1774 prints out a trivially simple XML file without ever creating
1775 an XML document.
1776
1777 @verbatim
1778 XMLPrinter printer( fp );
1779 printer.OpenElement( "foo" );
1780 printer.PushAttribute( "foo", "bar" );
1781 printer.CloseElement();
1782 @endverbatim
1783*/
1784class XMLPrinter : public XMLVisitor
1785{
1786public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 /** Construct the printer. If the FILE* is specified,
1788 this will print to the FILE. Else it will print
1789 to memory, and the result is available in CStr().
1790 If 'compact' is set to true, then output is created
1791 with only required whitespace and newlines.
1792 */
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001793 XMLPrinter( std::FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001794 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001795
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 /** If streaming, write the BOM and declaration. */
1797 void PushHeader( bool writeBOM, bool writeDeclaration );
1798 /** If streaming, start writing an element.
1799 The element must be closed with CloseElement()
1800 */
1801 void OpenElement( const char* name );
1802 /// If streaming, add an attribute to an open element.
1803 void PushAttribute( const char* name, const char* value );
1804 void PushAttribute( const char* name, int value );
1805 void PushAttribute( const char* name, unsigned value );
1806 void PushAttribute( const char* name, bool value );
1807 void PushAttribute( const char* name, double value );
1808 /// If streaming, close the Element.
1809 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001810
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001811 /// Add a text node.
1812 void PushText( const char* text, bool cdata=false );
1813 /// Add a text node from an integer.
1814 void PushText( int value );
1815 /// Add a text node from an unsigned.
1816 void PushText( unsigned value );
1817 /// Add a text node from a bool.
1818 void PushText( bool value );
1819 /// Add a text node from a float.
1820 void PushText( float value );
1821 /// Add a text node from a double.
1822 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001823
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001824 /// Add a comment
1825 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001826
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001827 void PushDeclaration( const char* value );
1828 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001829
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001830 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1831 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1832 return true;
1833 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001834
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001835 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1836 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001837
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001838 virtual bool Visit( const XMLText& text );
1839 virtual bool Visit( const XMLComment& comment );
1840 virtual bool Visit( const XMLDeclaration& declaration );
1841 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001842
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001843 /**
1844 If in print to memory mode, return a pointer to
1845 the XML file in memory.
1846 */
1847 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001848 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001849 }
1850 /**
1851 If in print to memory mode, return the size
1852 of the XML file in memory. (Note the size returned
1853 includes the terminating null.)
1854 */
1855 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001856 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001857 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001858
1859private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001860 void SealElement();
1861 void PrintSpace( int depth );
1862 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1863 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001864
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 bool _elementJustOpened;
1866 bool _firstElement;
Jerome Martinez7fbefab2012-10-19 11:30:33 +02001867 std::FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001868 int _depth;
1869 int _textDepth;
1870 bool _processEntities;
1871 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001872
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001873 enum {
1874 ENTITY_RANGE = 64,
1875 BUF_SIZE = 200
1876 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 bool _entityFlag[ENTITY_RANGE];
1878 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001879
Lee Thomason624d43f2012-10-12 10:58:48 -07001880 DynArray< const char*, 10 > _stack;
1881 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001882#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001883 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001884#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001885};
1886
1887
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001888} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001889
1890
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001891#endif // TINYXML2_INCLUDED