blob: b75471ff633f10ccd8fc8105051504c404f113cf [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Jerome Martinez242c3ea2013-01-06 12:20:04 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080048 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010049
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# if defined(_MSC_VER)
63# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64# elif defined (ANDROID_NDK)
65# include <android/log.h>
66# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67# else
68# include <assert.h>
69# define TIXMLASSERT assert
70# endif
71# else
72# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// Microsoft visual studio, version 2005 and higher.
78/*int _snprintf_s(
79 char *buffer,
80 size_t sizeOfBuffer,
81 size_t count,
82 const char *format [,
83 argument] ...
84);*/
85inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86{
87 va_list va;
88 va_start( va, format );
89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90 va_end( va );
91 return result;
92}
93#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
selfpoisede77e1952013-03-13 14:08:29 +0800101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
103static const int TIXML2_PATCH_VERSION = 11;
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,
selfpoisede77e1952013-03-13 14:08:29 +0800130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
selfpoisede77e1952013-03-13 14:08:29 +0800132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800134 ATTRIBUTE_NAME = 0,
135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700138 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 // After parsing, if *end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 int _flags;
177 char* _start;
178 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800187template <class T, int INIT>
188class DynArray
189{
190public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700192 _mem = _pool;
193 _allocated = INIT;
194 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700204 EnsureCapacity( _size+1 );
205 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700206 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 EnsureCapacity( _size+count );
210 T* ret = &_mem[_size];
211 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 return ret;
213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 TIXMLASSERT( _size >= count );
221 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700230 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700235 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800253
Lee Thomason2c85a712012-01-31 08:24:24 -0800254private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int newAllocated = cap * 2;
258 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
260 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700261 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
266 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800267
Lee Thomason624d43f2012-10-12 10:58:48 -0700268 T* _mem;
269 T _pool[INIT];
270 int _allocated; // objects allocated
271 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800272};
273
Lee Thomason50adb4c2012-02-13 15:07:09 -0800274
U-Stream\Leeae25a442012-02-17 17:48:16 -0800275/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200276 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800277 and deallocation of objects.
278*/
Lee Thomasond1983222012-02-06 08:41:24 -0800279class MemPool
280{
281public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 MemPool() {}
283 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800284
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 virtual int ItemSize() const = 0;
286 virtual void* Alloc() = 0;
287 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800288 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800289};
290
Lee Thomason50adb4c2012-02-13 15:07:09 -0800291
U-Stream\Leeae25a442012-02-17 17:48:16 -0800292/*
293 Template child class to create pools of the correct type.
294*/
Lee Thomasond1983222012-02-06 08:41:24 -0800295template< int SIZE >
296class MemPoolT : public MemPool
297{
298public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800299 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700300 ~MemPoolT() {
301 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700302 for( int i=0; i<_blockPtrs.Size(); ++i ) {
303 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700304 }
305 }
Lee Thomasond1983222012-02-06 08:41:24 -0800306
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700307 virtual int ItemSize() const {
308 return SIZE;
309 }
310 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700311 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700312 }
Lee Thomasond1983222012-02-06 08:41:24 -0800313
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700314 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700315 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700316 // Need a new block.
317 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700318 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800319
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700320 for( int i=0; i<COUNT-1; ++i ) {
321 block->chunk[i].next = &block->chunk[i+1];
322 }
323 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700324 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700326 void* result = _root;
327 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800328
Lee Thomason624d43f2012-10-12 10:58:48 -0700329 ++_currentAllocs;
330 if ( _currentAllocs > _maxAllocs ) {
331 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700333 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800334 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 return result;
336 }
337 virtual void Free( void* mem ) {
338 if ( !mem ) {
339 return;
340 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700341 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700345#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 chunk->next = _root;
347 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 }
349 void Trace( const char* name ) {
350 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700351 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700352 }
Lee Thomasond1983222012-02-06 08:41:24 -0800353
Lee Thomason5b0a6772012-11-19 13:54:42 -0800354 void SetTracked() {
355 _nUntracked--;
356 }
357
358 int Untracked() const {
359 return _nUntracked;
360 }
361
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800362 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
363 // The test file is large, 170k.
364 // Release: VS2010 gcc(no opt)
365 // 1k: 4000
366 // 2k: 4000
367 // 4k: 3900 21000
368 // 16k: 5200
369 // 32k: 4300
370 // 64k: 4000 21000
371 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
Jerome Martinez7921df12012-10-24 11:45:44 +0200372
Lee Thomasond1983222012-02-06 08:41:24 -0800373private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700374 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700375 Chunk* next;
376 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700377 };
378 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700379 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700380 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700381 DynArray< Block*, 10 > _blockPtrs;
382 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800383
Lee Thomason624d43f2012-10-12 10:58:48 -0700384 int _currentAllocs;
385 int _nAllocs;
386 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800387 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800388};
389
Lee Thomason2c85a712012-01-31 08:24:24 -0800390
Lee Thomason56bdd022012-02-09 18:16:58 -0800391
392/**
393 Implements the interface to the "Visitor pattern" (see the Accept() method.)
394 If you call the Accept() method, it requires being passed a XMLVisitor
395 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200396 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800397 are simply called with Visit().
398
399 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700400 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800401
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700402 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800403 visiting). You need to only override methods that are interesting to you.
404
Thomas Roß08bdf502012-05-12 14:21:23 +0200405 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800406
407 You should never change the document from a callback.
408
409 @sa XMLNode::Accept()
410*/
411class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800412{
413public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700414 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800415
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700416 /// Visit a document.
417 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
418 return true;
419 }
420 /// Visit a document.
421 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
422 return true;
423 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800424
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700425 /// Visit an element.
426 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
427 return true;
428 }
429 /// Visit an element.
430 virtual bool VisitExit( const XMLElement& /*element*/ ) {
431 return true;
432 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800433
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700434 /// Visit a declaration.
435 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
436 return true;
437 }
438 /// Visit a text node.
439 virtual bool Visit( const XMLText& /*text*/ ) {
440 return true;
441 }
442 /// Visit a comment node.
443 virtual bool Visit( const XMLComment& /*comment*/ ) {
444 return true;
445 }
446 /// Visit an unknown node.
447 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
448 return true;
449 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800450};
451
452
U-Stream\Leeae25a442012-02-17 17:48:16 -0800453/*
454 Utility functionality.
455*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800456class XMLUtil
457{
Lee Thomasond1983222012-02-06 08:41:24 -0800458public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700459 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
460 // correct, but simple, and usually works.
461 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100462 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700463 ++p;
464 }
465 return p;
466 }
467 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100468 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700469 ++p;
470 }
471 return p;
472 }
473 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100474 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700475 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200476
477 inline static bool IsNameStartChar( unsigned char ch ) {
478 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
479 || ch == ':'
480 || ch == '_';
481 }
482
483 inline static bool IsNameChar( unsigned char ch ) {
484 return IsNameStartChar( ch )
485 || isdigit( ch )
486 || ch == '.'
487 || ch == '-';
488 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800489
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700490 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
491 int n = 0;
492 if ( p == q ) {
493 return true;
494 }
495 while( *p && *q && *p == *q && n<nChar ) {
496 ++p;
497 ++q;
498 ++n;
499 }
500 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
501 return true;
502 }
503 return false;
504 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200505
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700506 inline static int IsUTF8Continuation( const char p ) {
507 return p & 0x80;
508 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800509
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700510 static const char* ReadBOM( const char* p, bool* hasBOM );
511 // p is the starting location,
512 // the UTF-8 value of the entity will be placed in value, and length filled in.
513 static const char* GetCharacterRef( const char* p, char* value, int* length );
514 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700515
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700516 // converts primitive types to strings
517 static void ToStr( int v, char* buffer, int bufferSize );
518 static void ToStr( unsigned v, char* buffer, int bufferSize );
519 static void ToStr( bool v, char* buffer, int bufferSize );
520 static void ToStr( float v, char* buffer, int bufferSize );
521 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700522
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700523 // converts strings to primitive types
524 static bool ToInt( const char* str, int* value );
525 static bool ToUnsigned( const char* str, unsigned* value );
526 static bool ToBool( const char* str, bool* value );
527 static bool ToFloat( const char* str, float* value );
528 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800529};
530
Lee Thomason5cae8972012-01-24 18:03:07 -0800531
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800532/** XMLNode is a base class for every object that is in the
533 XML Document Object Model (DOM), except XMLAttributes.
534 Nodes have siblings, a parent, and children which can
535 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700536 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800537 be cast to its more defined type.
538
Thomas Roß08bdf502012-05-12 14:21:23 +0200539 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800540 When the XMLDocument gets deleted, all its Nodes
541 will also be deleted.
542
543 @verbatim
544 A Document can contain: Element (container or leaf)
545 Comment (leaf)
546 Unknown (leaf)
547 Declaration( leaf )
548
549 An Element can contain: Element (container or leaf)
550 Text (leaf)
551 Attributes (not on tree)
552 Comment (leaf)
553 Unknown (leaf)
554
555 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800556*/
Lee Thomasond1983222012-02-06 08:41:24 -0800557class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800558{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700559 friend class XMLDocument;
560 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800561public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800562
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700563 /// Get the XMLDocument that owns this XMLNode.
564 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700565 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700566 }
567 /// Get the XMLDocument that owns this XMLNode.
568 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700569 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800571
Lee Thomason2fa81722012-11-09 12:37:46 -0800572 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700573 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100574 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700575 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800576 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700577 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100578 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700579 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800580 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700581 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100582 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700583 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800584 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700585 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100586 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800588 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700589 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100590 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800592 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700593 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100594 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800596
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700597 virtual const XMLElement* ToElement() const {
598 return 0;
599 }
600 virtual const XMLText* ToText() const {
601 return 0;
602 }
603 virtual const XMLComment* ToComment() const {
604 return 0;
605 }
606 virtual const XMLDocument* ToDocument() const {
607 return 0;
608 }
609 virtual const XMLDeclaration* ToDeclaration() const {
610 return 0;
611 }
612 virtual const XMLUnknown* ToUnknown() const {
613 return 0;
614 }
Lee Thomason751da522012-02-10 08:50:51 -0800615
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 /** The meaning of 'value' changes for the specific type.
617 @verbatim
618 Document: empty
619 Element: name of the element
620 Comment: the comment text
621 Unknown: the tag contents
622 Text: the text string
623 @endverbatim
624 */
625 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700626 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700627 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100628
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 /** Set the Value of an XML node.
630 @sa Value()
631 */
632 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800633
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 /// Get the parent of this node on the DOM.
635 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700636 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100638
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700639 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700640 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 }
Lee Thomason751da522012-02-10 08:50:51 -0800642
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 /// Returns true if this node has no children.
644 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700645 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700646 }
Lee Thomason751da522012-02-10 08:50:51 -0800647
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 /// Get the first child node, or null if none exists.
649 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700650 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100652
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700654 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100656
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 /** Get the first child element, or optionally the first child
658 element with the specified name.
659 */
660 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700661
662 XMLElement* FirstChildElement( const char* value=0 ) {
663 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800665
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 /// Get the last child node, or null if none exists.
667 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700668 return _lastChild;
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* LastChild() {
672 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
673 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800674
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 /** Get the last child element or optionally the last child
676 element with the specified name.
677 */
678 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700679
680 XMLElement* LastChildElement( const char* value=0 ) {
681 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 /// Get the previous (left) sibling node of this node.
685 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700686 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700688
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700689 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700690 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800692
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700693 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700695
696 XMLElement* PreviousSiblingElement( const char* value=0 ) {
697 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700698 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700699
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 /// Get the next (right) sibling node of this node.
701 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700702 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700706 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700708
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700709 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700711
712 XMLElement* NextSiblingElement( const char* value=0 ) {
713 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700714 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 /**
717 Add a child node as the last (right) child.
718 */
719 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 XMLNode* LinkEndChild( XMLNode* addThis ) {
722 return InsertEndChild( addThis );
723 }
724 /**
725 Add a child node as the first (left) child.
726 */
727 XMLNode* InsertFirstChild( XMLNode* addThis );
728 /**
729 Add a node after the specified child node.
730 */
731 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700732
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 /**
734 Delete all the children of this node.
735 */
736 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 /**
739 Delete a child of this node.
740 */
741 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800742
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 /**
744 Make a copy of this node, but not its children.
745 You may pass in a Document pointer that will be
746 the owner of the new Node. If the 'document' is
747 null, then the node returned will be allocated
748 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800749
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700750 Note: if called on a XMLDocument, this will return null.
751 */
752 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800753
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 /**
755 Test if 2 nodes are the same, but don't test children.
756 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800757
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700758 Note: if called on a XMLDocument, this will return false.
759 */
760 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800761
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
763 XML tree will be conditionally visited and the host will be called back
764 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800765
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
767 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
768 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800769
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700770 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800771
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 - http://www.saxproject.org/
773 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800776
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 An example of using Accept():
778 @verbatim
779 TiXmlPrinter printer;
780 tinyxmlDoc.Accept( &printer );
781 const char* xmlcstr = printer.CStr();
782 @endverbatim
783 */
784 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800785
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 // internal
787 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800788
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800789protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 XMLNode( XMLDocument* );
791 virtual ~XMLNode();
792 XMLNode( const XMLNode& ); // not supported
793 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700794
Lee Thomason624d43f2012-10-12 10:58:48 -0700795 XMLDocument* _document;
796 XMLNode* _parent;
797 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800798
Lee Thomason624d43f2012-10-12 10:58:48 -0700799 XMLNode* _firstChild;
800 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800801
Lee Thomason624d43f2012-10-12 10:58:48 -0700802 XMLNode* _prev;
803 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800804
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800805private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700806 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800808};
809
810
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800811/** XML text.
812
813 Note that a text node can have child element nodes, for example:
814 @verbatim
815 <root>This is <b>bold</b></root>
816 @endverbatim
817
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700818 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800819 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 -0700820 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800821 SetCDATA() and query it with CDATA().
822*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800823class XMLText : public XMLNode
824{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 friend class XMLBase;
826 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800827public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700828 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800829
Lee Thomason624d43f2012-10-12 10:58:48 -0700830 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 return this;
832 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700833 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700834 return this;
835 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800836
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700837 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700838 void SetCData( bool isCData ) {
839 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700840 }
841 /// Returns true if this is a CDATA text element.
842 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700843 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800845
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 char* ParseDeep( char*, StrPair* endTag );
847 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
848 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800849
Lee Thomason5492a1c2012-01-23 15:32:10 -0800850protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700851 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 virtual ~XMLText() {}
853 XMLText( const XMLText& ); // not supported
854 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800855
856private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700857 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800858};
859
860
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800861/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800862class XMLComment : public XMLNode
863{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700864 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800865public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700866 virtual XMLComment* ToComment() {
867 return this;
868 }
869 virtual const XMLComment* ToComment() const {
870 return this;
871 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800872
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700873 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800874
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700875 char* ParseDeep( char*, StrPair* endTag );
876 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
877 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800878
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800879protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700880 XMLComment( XMLDocument* doc );
881 virtual ~XMLComment();
882 XMLComment( const XMLComment& ); // not supported
883 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800884
Lee Thomason3f57d272012-01-11 15:30:03 -0800885private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800886};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800887
888
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800889/** In correct XML the declaration is the first entry in the file.
890 @verbatim
891 <?xml version="1.0" standalone="yes"?>
892 @endverbatim
893
894 TinyXML2 will happily read or write files without a declaration,
895 however.
896
897 The text of the declaration isn't interpreted. It is parsed
898 and written as a string.
899*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800900class XMLDeclaration : public XMLNode
901{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700902 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800903public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700904 virtual XMLDeclaration* ToDeclaration() {
905 return this;
906 }
907 virtual const XMLDeclaration* ToDeclaration() const {
908 return this;
909 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800910
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700911 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800912
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700913 char* ParseDeep( char*, StrPair* endTag );
914 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
915 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800916
917protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700918 XMLDeclaration( XMLDocument* doc );
919 virtual ~XMLDeclaration();
920 XMLDeclaration( const XMLDeclaration& ); // not supported
921 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800922};
923
924
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800925/** Any tag that tinyXml doesn't recognize is saved as an
926 unknown. It is a tag of text, but should not be modified.
927 It will be written back to the XML, unchanged, when the file
928 is saved.
929
930 DTD tags get thrown into TiXmlUnknowns.
931*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800932class XMLUnknown : public XMLNode
933{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800935public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 virtual XMLUnknown* ToUnknown() {
937 return this;
938 }
939 virtual const XMLUnknown* ToUnknown() const {
940 return this;
941 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800942
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700943 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800944
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700945 char* ParseDeep( char*, StrPair* endTag );
946 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800948
949protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 XMLUnknown( XMLDocument* doc );
951 virtual ~XMLUnknown();
952 XMLUnknown( const XMLUnknown& ); // not supported
953 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800954};
955
956
Lee Thomason2fa81722012-11-09 12:37:46 -0800957enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700958 XML_NO_ERROR = 0,
959 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800960
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700961 XML_NO_ATTRIBUTE,
962 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800963
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 XML_ERROR_FILE_NOT_FOUND,
965 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
966 XML_ERROR_FILE_READ_ERROR,
967 XML_ERROR_ELEMENT_MISMATCH,
968 XML_ERROR_PARSING_ELEMENT,
969 XML_ERROR_PARSING_ATTRIBUTE,
970 XML_ERROR_IDENTIFYING_TAG,
971 XML_ERROR_PARSING_TEXT,
972 XML_ERROR_PARSING_CDATA,
973 XML_ERROR_PARSING_COMMENT,
974 XML_ERROR_PARSING_DECLARATION,
975 XML_ERROR_PARSING_UNKNOWN,
976 XML_ERROR_EMPTY_DOCUMENT,
977 XML_ERROR_MISMATCHED_ELEMENT,
978 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700979
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700980 XML_CAN_NOT_CONVERT_TEXT,
981 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800982};
983
984
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800985/** An attribute is a name-value pair. Elements have an arbitrary
986 number of attributes, each with a unique name.
987
988 @note The attributes are not XMLNodes. You may only query the
989 Next() attribute in a list.
990*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800991class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800992{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700993 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800994public:
Lee Thomason2fa81722012-11-09 12:37:46 -0800995 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700996 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100997 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700998 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800999 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001000 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001001 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001002 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001003 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001004 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001005 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001006 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001007
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001008 /** IntAttribute interprets the attribute as an integer, and returns the value.
1009 If the value isn't an integer, 0 will be returned. There is no error checking;
1010 use QueryIntAttribute() if you need error checking.
1011 */
1012 int IntValue() const {
1013 int i=0;
1014 QueryIntValue( &i );
1015 return i;
1016 }
1017 /// Query as an unsigned integer. See IntAttribute()
1018 unsigned UnsignedValue() const {
1019 unsigned i=0;
1020 QueryUnsignedValue( &i );
1021 return i;
1022 }
1023 /// Query as a boolean. See IntAttribute()
1024 bool BoolValue() const {
1025 bool b=false;
1026 QueryBoolValue( &b );
1027 return b;
1028 }
1029 /// Query as a double. See IntAttribute()
1030 double DoubleValue() const {
1031 double d=0;
1032 QueryDoubleValue( &d );
1033 return d;
1034 }
1035 /// Query as a float. See IntAttribute()
1036 float FloatValue() const {
1037 float f=0;
1038 QueryFloatValue( &f );
1039 return f;
1040 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001041
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001043 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001044 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1045 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001046 XMLError QueryIntValue( int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001048 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001049 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001050 XMLError QueryBoolValue( bool* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001052 XMLError QueryDoubleValue( double* value ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 /// See QueryIntAttribute
Lee Thomason2fa81722012-11-09 12:37:46 -08001054 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001055
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001056 /// Set the attribute to a string value.
1057 void SetAttribute( const char* value );
1058 /// Set the attribute to value.
1059 void SetAttribute( int value );
1060 /// Set the attribute to value.
1061 void SetAttribute( unsigned value );
1062 /// Set the attribute to value.
1063 void SetAttribute( bool value );
1064 /// Set the attribute to value.
1065 void SetAttribute( double value );
1066 /// Set the attribute to value.
1067 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001068
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001069private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001070 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001071
Lee Thomason624d43f2012-10-12 10:58:48 -07001072 XMLAttribute() : _next( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001074
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001075 XMLAttribute( const XMLAttribute& ); // not supported
1076 void operator=( const XMLAttribute& ); // not supported
1077 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001078
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001079 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001080
Lee Thomason624d43f2012-10-12 10:58:48 -07001081 mutable StrPair _name;
1082 mutable StrPair _value;
1083 XMLAttribute* _next;
1084 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001085};
1086
1087
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001088/** The element is a container class. It has a value, the element name,
1089 and can contain other elements, text, comments, and unknowns.
1090 Elements also contain an arbitrary number of attributes.
1091*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001092class XMLElement : public XMLNode
1093{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001094 friend class XMLBase;
1095 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001096public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001097 /// Get the name of an element (which is the Value() of the node.)
1098 const char* Name() const {
1099 return Value();
1100 }
1101 /// Set the name of the element.
1102 void SetName( const char* str, bool staticMem=false ) {
1103 SetValue( str, staticMem );
1104 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001105
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001106 virtual XMLElement* ToElement() {
1107 return this;
1108 }
1109 virtual const XMLElement* ToElement() const {
1110 return this;
1111 }
1112 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001113
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001114 /** Given an attribute name, Attribute() returns the value
1115 for the attribute of that name, or null if none
1116 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001117
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001118 @verbatim
1119 const char* value = ele->Attribute( "foo" );
1120 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001121
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001122 The 'value' parameter is normally null. However, if specified,
1123 the attribute will only be returned if the 'name' and 'value'
1124 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001125
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001126 @verbatim
1127 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1128 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001129
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001130 rather than:
1131 @verbatim
1132 if ( ele->Attribute( "foo" ) ) {
1133 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1134 }
1135 @endverbatim
1136 */
1137 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001138
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 /** Given an attribute name, IntAttribute() returns the value
1140 of the attribute interpreted as an integer. 0 will be
1141 returned if there is an error. For a method with error
1142 checking, see QueryIntAttribute()
1143 */
1144 int IntAttribute( const char* name ) const {
1145 int i=0;
1146 QueryIntAttribute( name, &i );
1147 return i;
1148 }
1149 /// See IntAttribute()
1150 unsigned UnsignedAttribute( const char* name ) const {
1151 unsigned i=0;
1152 QueryUnsignedAttribute( name, &i );
1153 return i;
1154 }
1155 /// See IntAttribute()
1156 bool BoolAttribute( const char* name ) const {
1157 bool b=false;
1158 QueryBoolAttribute( name, &b );
1159 return b;
1160 }
1161 /// See IntAttribute()
1162 double DoubleAttribute( const char* name ) const {
1163 double d=0;
1164 QueryDoubleAttribute( name, &d );
1165 return d;
1166 }
1167 /// See IntAttribute()
1168 float FloatAttribute( const char* name ) const {
1169 float f=0;
1170 QueryFloatAttribute( name, &f );
1171 return f;
1172 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001173
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001174 /** Given an attribute name, QueryIntAttribute() returns
1175 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1176 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1177 doesn't exist. If successful, the result of the conversion
1178 will be written to 'value'. If not successful, nothing will
1179 be written to 'value'. This allows you to provide default
1180 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001181
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001182 @verbatim
1183 int value = 10;
1184 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1185 @endverbatim
1186 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001187 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001188 const XMLAttribute* a = FindAttribute( name );
1189 if ( !a ) {
1190 return XML_NO_ATTRIBUTE;
1191 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001192 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001193 }
1194 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001195 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001196 const XMLAttribute* a = FindAttribute( name );
1197 if ( !a ) {
1198 return XML_NO_ATTRIBUTE;
1199 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001200 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001201 }
1202 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001203 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 const XMLAttribute* a = FindAttribute( name );
1205 if ( !a ) {
1206 return XML_NO_ATTRIBUTE;
1207 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001208 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 }
1210 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001211 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 const XMLAttribute* a = FindAttribute( name );
1213 if ( !a ) {
1214 return XML_NO_ATTRIBUTE;
1215 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001216 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001217 }
1218 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001219 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 const XMLAttribute* a = FindAttribute( name );
1221 if ( !a ) {
1222 return XML_NO_ATTRIBUTE;
1223 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001224 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001226
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001227
1228 /** Given an attribute name, QueryAttribute() returns
1229 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1230 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1231 doesn't exist. It is overloaded for the primitive types,
1232 and is a generally more convenient replacement of
1233 QueryIntAttribute() and related functions.
1234
1235 If successful, the result of the conversion
1236 will be written to 'value'. If not successful, nothing will
1237 be written to 'value'. This allows you to provide default
1238 value:
1239
1240 @verbatim
1241 int value = 10;
1242 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1243 @endverbatim
1244 */
1245 int QueryAttribute( const char* name, int* value ) const {
1246 return QueryIntAttribute( name, value );
1247 }
1248
1249 int QueryAttribute( const char* name, unsigned int* value ) const {
1250 return QueryUnsignedAttribute( name, value );
1251 }
1252
1253 int QueryAttribute( const char* name, bool* value ) const {
1254 return QueryBoolAttribute( name, value );
1255 }
1256
1257 int QueryAttribute( const char* name, double* value ) const {
1258 return QueryDoubleAttribute( name, value );
1259 }
1260
1261 int QueryAttribute( const char* name, float* value ) const {
1262 return QueryFloatAttribute( name, value );
1263 }
1264
1265 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001266 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001267 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001268 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 }
1270 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001271 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001272 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001273 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001274 }
1275 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001276 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001277 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001278 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001279 }
1280 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001281 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001282 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001283 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001284 }
1285 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001286 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001288 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001289 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001290
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001291 /**
1292 Delete an attribute.
1293 */
1294 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001295
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 /// Return the first attribute in the list.
1297 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001298 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 }
1300 /// Query a specific attribute in the list.
1301 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001302
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 /** Convenience function for easy access to the text inside an element. Although easy
1304 and concise, GetText() is limited compared to getting the TiXmlText child
1305 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001306
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 If the first child of 'this' is a TiXmlText, the GetText()
1308 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001309
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001310 This is a convenient method for getting the text of simple contained text:
1311 @verbatim
1312 <foo>This is text</foo>
1313 const char* str = fooElement->GetText();
1314 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001315
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001317
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 Note that this function can be misleading. If the element foo was created from
1319 this XML:
1320 @verbatim
1321 <foo><b>This is text</b></foo>
1322 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001323
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 then the value of str would be null. The first child node isn't a text node, it is
1325 another element. From this XML:
1326 @verbatim
1327 <foo>This is <b>text</b></foo>
1328 @endverbatim
1329 GetText() will return "This is ".
1330 */
1331 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 /**
1334 Convenience method to query the value of a child text node. This is probably best
1335 shown by example. Given you have a document is this form:
1336 @verbatim
1337 <point>
1338 <x>1</x>
1339 <y>1.4</y>
1340 </point>
1341 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001342
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001343 The QueryIntText() and similar functions provide a safe and easier way to get to the
1344 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001345
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001346 @verbatim
1347 int x = 0;
1348 float y = 0; // types of x and y are contrived for example
1349 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1350 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1351 xElement->QueryIntText( &x );
1352 yElement->QueryFloatText( &y );
1353 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001354
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001355 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1356 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 -07001357
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001358 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001359 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001360 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001361 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001362 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001363 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001365 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001366 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001367 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001368
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001369 // internal:
1370 enum {
1371 OPEN, // <foo>
1372 CLOSED, // <foo/>
1373 CLOSING // </foo>
1374 };
1375 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001376 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 }
1378 char* ParseDeep( char* p, StrPair* endTag );
1379 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1380 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001381
Lee Thomason50adb4c2012-02-13 15:07:09 -08001382private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 XMLElement( XMLDocument* doc );
1384 virtual ~XMLElement();
1385 XMLElement( const XMLElement& ); // not supported
1386 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001387
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001388 XMLAttribute* FindAttribute( const char* name );
1389 XMLAttribute* FindOrCreateAttribute( const char* name );
1390 //void LinkAttribute( XMLAttribute* attrib );
1391 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001392
Lee Thomason624d43f2012-10-12 10:58:48 -07001393 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001394 // The attribute list is ordered; there is no 'lastAttribute'
1395 // because the list needs to be scanned for dupes before adding
1396 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001397 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001398};
1399
1400
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001401enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001402 PRESERVE_WHITESPACE,
1403 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001404};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001405
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001406
1407/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001408 It can be saved, loaded, and printed to the screen.
1409 All Nodes are connected and allocated to a Document.
1410 If the Document is deleted, all its Nodes are also deleted.
1411*/
Lee Thomason67d61312012-01-24 16:01:51 -08001412class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001413{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001414 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001415public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001416 /// constructor
1417 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1418 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001419
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 virtual XMLDocument* ToDocument() {
1421 return this;
1422 }
1423 virtual const XMLDocument* ToDocument() const {
1424 return this;
1425 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001426
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 /**
1428 Parse an XML file from a character string.
1429 Returns XML_NO_ERROR (0) on success, or
1430 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001431
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 You may optionally pass in the 'nBytes', which is
1433 the number of bytes which will be parsed. If not
1434 specified, TinyXML will assume 'xml' points to a
1435 null terminated string.
1436 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001437 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001438
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001439 /**
1440 Load an XML file from disk.
1441 Returns XML_NO_ERROR (0) on success, or
1442 an errorID.
1443 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001444 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001445
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 /**
1447 Load an XML file from disk. You are responsible
1448 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001449
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 Returns XML_NO_ERROR (0) on success, or
1451 an errorID.
1452 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001453 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001454
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001455 /**
1456 Save the XML file to disk.
1457 Returns XML_NO_ERROR (0) on success, or
1458 an errorID.
1459 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001460 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001461
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001462 /**
1463 Save the XML file to disk. You are responsible
1464 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001465
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001466 Returns XML_NO_ERROR (0) on success, or
1467 an errorID.
1468 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001469 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001470
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001471 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001472 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001473 }
1474 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001475 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001477
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001478 /**
1479 Returns true if this document has a leading Byte Order Mark of UTF8.
1480 */
1481 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001482 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 }
1484 /** Sets whether to write the BOM when writing the file.
1485 */
1486 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001487 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001489
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001490 /** Return the root element of DOM. Equivalent to FirstChildElement().
1491 To get the first node, use FirstChild().
1492 */
1493 XMLElement* RootElement() {
1494 return FirstChildElement();
1495 }
1496 const XMLElement* RootElement() const {
1497 return FirstChildElement();
1498 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001499
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001500 /** Print the Document. If the Printer is not provided, it will
1501 print to stdout. If you provide Printer, this can print to a file:
1502 @verbatim
1503 XMLPrinter printer( fp );
1504 doc.Print( &printer );
1505 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 Or you can use a printer to print to memory:
1508 @verbatim
1509 XMLPrinter printer;
1510 doc->Print( &printer );
1511 // printer.CStr() has a const char* to the XML
1512 @endverbatim
1513 */
1514 void Print( XMLPrinter* streamer=0 );
1515 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 /**
1518 Create a new Element associated with
1519 this Document. The memory for the Element
1520 is managed by the Document.
1521 */
1522 XMLElement* NewElement( const char* name );
1523 /**
1524 Create a new Comment associated with
1525 this Document. The memory for the Comment
1526 is managed by the Document.
1527 */
1528 XMLComment* NewComment( const char* comment );
1529 /**
1530 Create a new Text associated with
1531 this Document. The memory for the Text
1532 is managed by the Document.
1533 */
1534 XMLText* NewText( const char* text );
1535 /**
1536 Create a new Declaration associated with
1537 this Document. The memory for the object
1538 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001539
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001540 If the 'text' param is null, the standard
1541 declaration is used.:
1542 @verbatim
1543 <?xml version="1.0" encoding="UTF-8"?>
1544 @endverbatim
1545 */
1546 XMLDeclaration* NewDeclaration( const char* text=0 );
1547 /**
1548 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001549 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001550 is managed by the Document.
1551 */
1552 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001553
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001554 /**
1555 Delete a node associated with this document.
1556 It will be unlinked from the DOM.
1557 */
1558 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001559 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001560 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001561
Lee Thomason2fa81722012-11-09 12:37:46 -08001562 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001563
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001564 /// Return true if there was an error parsing the document.
1565 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001566 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 }
1568 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001569 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001570 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001571 }
1572 /// Return a possibly helpful diagnostic location or string.
1573 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001574 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001575 }
1576 /// Return a possibly helpful secondary diagnostic location or string.
1577 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001578 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001579 }
1580 /// If there is an error, print it to stdout.
1581 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001582
1583 /// Clear the document, resetting it to the initial state.
1584 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001585
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001586 // internal
1587 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001588
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001589 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1590 return 0;
1591 }
1592 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1593 return false;
1594 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001595
Lee Thomason3f57d272012-01-11 15:30:03 -08001596private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001597 XMLDocument( const XMLDocument& ); // not supported
1598 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001599
Lee Thomason2fa81722012-11-09 12:37:46 -08001600 bool _writeBOM;
1601 bool _processEntities;
1602 XMLError _errorID;
1603 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001604 const char* _errorStr1;
1605 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001606 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001607
Lee Thomason624d43f2012-10-12 10:58:48 -07001608 MemPoolT< sizeof(XMLElement) > _elementPool;
1609 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1610 MemPoolT< sizeof(XMLText) > _textPool;
1611 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001612};
1613
Lee Thomason7c913cd2012-01-26 18:32:34 -08001614
Lee Thomason3ffdd392012-03-28 17:27:55 -07001615/**
1616 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001617 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001618 DOM structure. It is a separate utility class.
1619
1620 Take an example:
1621 @verbatim
1622 <Document>
1623 <Element attributeA = "valueA">
1624 <Child attributeB = "value1" />
1625 <Child attributeB = "value2" />
1626 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001627 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001628 @endverbatim
1629
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001630 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001631 easy to write a *lot* of code that looks like:
1632
1633 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001634 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001635 if ( root )
1636 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001637 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001638 if ( element )
1639 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001640 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001641 if ( child )
1642 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001643 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001644 if ( child2 )
1645 {
1646 // Finally do something useful.
1647 @endverbatim
1648
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001649 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001650 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001651 and correct to use:
1652
1653 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001654 XMLHandle docHandle( &document );
1655 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001656 if ( child2 )
1657 {
1658 // do something useful
1659 @endverbatim
1660
1661 Which is MUCH more concise and useful.
1662
1663 It is also safe to copy handles - internally they are nothing more than node pointers.
1664 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001665 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001666 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001667
1668 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001669*/
1670class XMLHandle
1671{
1672public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001673 /// 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 -07001674 XMLHandle( XMLNode* node ) {
1675 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001676 }
1677 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001678 XMLHandle( XMLNode& node ) {
1679 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001680 }
1681 /// Copy constructor
1682 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001683 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001684 }
1685 /// Assignment
1686 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001687 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001688 return *this;
1689 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001690
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 /// Get the first child of this handle.
1692 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001693 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001694 }
1695 /// Get the first child element of this handle.
1696 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001697 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001698 }
1699 /// Get the last child of this handle.
1700 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001701 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001702 }
1703 /// Get the last child element of this handle.
1704 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001705 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 }
1707 /// Get the previous sibling of this handle.
1708 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001709 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001710 }
1711 /// Get the previous sibling element of this handle.
1712 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001713 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 }
1715 /// Get the next sibling of this handle.
1716 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
1719 /// Get the next sibling element of this handle.
1720 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001721 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001722 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001723
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 /// Safe cast to XMLNode. This can return null.
1725 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 /// Safe cast to XMLElement. This can return null.
1729 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 /// Safe cast to XMLText. This can return null.
1733 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 /// Safe cast to XMLUnknown. This can return null.
1737 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
1740 /// Safe cast to XMLDeclaration. This can return null.
1741 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001744
1745private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001746 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001747};
1748
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001749
1750/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001751 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1752 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001753*/
1754class XMLConstHandle
1755{
1756public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001757 XMLConstHandle( const XMLNode* node ) {
1758 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001759 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001760 XMLConstHandle( const XMLNode& node ) {
1761 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001762 }
1763 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001764 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
Lee Thomason8b899812012-04-04 15:58:16 -07001766
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001767 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001768 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001769 return *this;
1770 }
Lee Thomason8b899812012-04-04 15:58:16 -07001771
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001772 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001773 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001774 }
1775 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001776 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 }
1778 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001779 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 }
1781 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001782 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 }
1784 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001785 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 }
1787 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001788 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 }
1790 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001791 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 }
1793 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
Lee Thomason8b899812012-04-04 15:58:16 -07001796
1797
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001798 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001799 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001800 }
1801 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001802 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 }
1804 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001805 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001806 }
1807 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 }
1810 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001811 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001812 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001813
Lee Thomason5cae8972012-01-24 18:03:07 -08001814private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001816};
Lee Thomason6f381b72012-03-02 12:59:39 -08001817
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001818
1819/**
1820 Printing functionality. The XMLPrinter gives you more
1821 options than the XMLDocument::Print() method.
1822
1823 It can:
1824 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001825 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001826 -# Print XML without a XMLDocument.
1827
1828 Print to Memory
1829
1830 @verbatim
1831 XMLPrinter printer;
1832 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001833 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001834 @endverbatim
1835
1836 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001837
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001838 You provide the file pointer.
1839 @verbatim
1840 XMLPrinter printer( fp );
1841 doc.Print( &printer );
1842 @endverbatim
1843
1844 Print without a XMLDocument
1845
1846 When loading, an XML parser is very useful. However, sometimes
1847 when saving, it just gets in the way. The code is often set up
1848 for streaming, and constructing the DOM is just overhead.
1849
1850 The Printer supports the streaming case. The following code
1851 prints out a trivially simple XML file without ever creating
1852 an XML document.
1853
1854 @verbatim
1855 XMLPrinter printer( fp );
1856 printer.OpenElement( "foo" );
1857 printer.PushAttribute( "foo", "bar" );
1858 printer.CloseElement();
1859 @endverbatim
1860*/
1861class XMLPrinter : public XMLVisitor
1862{
1863public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001864 /** Construct the printer. If the FILE* is specified,
1865 this will print to the FILE. Else it will print
1866 to memory, and the result is available in CStr().
1867 If 'compact' is set to true, then output is created
1868 with only required whitespace and newlines.
1869 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001870 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001871 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001872
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001873 /** If streaming, write the BOM and declaration. */
1874 void PushHeader( bool writeBOM, bool writeDeclaration );
1875 /** If streaming, start writing an element.
1876 The element must be closed with CloseElement()
1877 */
1878 void OpenElement( const char* name );
1879 /// If streaming, add an attribute to an open element.
1880 void PushAttribute( const char* name, const char* value );
1881 void PushAttribute( const char* name, int value );
1882 void PushAttribute( const char* name, unsigned value );
1883 void PushAttribute( const char* name, bool value );
1884 void PushAttribute( const char* name, double value );
1885 /// If streaming, close the Element.
1886 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001887
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001888 /// Add a text node.
1889 void PushText( const char* text, bool cdata=false );
1890 /// Add a text node from an integer.
1891 void PushText( int value );
1892 /// Add a text node from an unsigned.
1893 void PushText( unsigned value );
1894 /// Add a text node from a bool.
1895 void PushText( bool value );
1896 /// Add a text node from a float.
1897 void PushText( float value );
1898 /// Add a text node from a double.
1899 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001900
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001901 /// Add a comment
1902 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001903
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001904 void PushDeclaration( const char* value );
1905 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001906
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001907 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1908 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1909 return true;
1910 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001911
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001912 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1913 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001914
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001915 virtual bool Visit( const XMLText& text );
1916 virtual bool Visit( const XMLComment& comment );
1917 virtual bool Visit( const XMLDeclaration& declaration );
1918 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001919
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001920 /**
1921 If in print to memory mode, return a pointer to
1922 the XML file in memory.
1923 */
1924 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001925 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001926 }
1927 /**
1928 If in print to memory mode, return the size
1929 of the XML file in memory. (Note the size returned
1930 includes the terminating null.)
1931 */
1932 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001933 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001934 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001935
1936private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 void SealElement();
1938 void PrintSpace( int depth );
1939 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1940 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001941
Lee Thomason624d43f2012-10-12 10:58:48 -07001942 bool _elementJustOpened;
1943 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001944 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001945 int _depth;
1946 int _textDepth;
1947 bool _processEntities;
1948 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001949
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 enum {
1951 ENTITY_RANGE = 64,
1952 BUF_SIZE = 200
1953 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001954 bool _entityFlag[ENTITY_RANGE];
1955 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001956
Lee Thomason624d43f2012-10-12 10:58:48 -07001957 DynArray< const char*, 10 > _stack;
1958 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001959#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001960 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001961#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001962};
1963
1964
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001965} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001966
1967
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001968#endif // TINYXML2_INCLUDED