blob: adda85a141ca8e080a9ab50c54cadec4427c690b [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
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -070017
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -0800182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080024
Lee Thomason7d00b9a2012-02-27 17:54:22 -080025#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080026#define TINYXML2_INCLUDED
27
Jerome Martinez242c3ea2013-01-06 12:20:04 +010028#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070029# include <ctype.h>
30# include <limits.h>
31# include <stdio.h>
32# include <stdlib.h>
33# include <string.h>
34# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070035#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070036# include <cctype>
37# include <climits>
38# include <cstdio>
39# include <cstdlib>
40# include <cstring>
41# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070043
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070044/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080045 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080046*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080047/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070048 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080049 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010050
Lee Thomasona9cf3f92012-10-11 16:56:51 -070051 Formatting, Artistic Style:
52 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080053*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080054
U-Lama\Lee4cee6112011-12-31 14:58:18 -080055#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070056# ifndef DEBUG
57# define DEBUG
58# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080059#endif
60
PKEuS95060352013-07-26 10:42:44 +020061#ifdef _MSC_VER
62# pragma warning(push)
63# pragma warning(disable: 4251)
64#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080065
PKEuS16ed47d2013-07-06 12:02:43 +020066#ifdef _WIN32
67# ifdef TINYXML2_EXPORT
68# define TINYXML2_LIB __declspec(dllexport)
69# elif defined(TINYXML2_IMPORT)
70# define TINYXML2_LIB __declspec(dllimport)
71# else
72# define TINYXML2_LIB
73# endif
74#else
75# define TINYXML2_LIB
76#endif
77
78
U-Lama\Lee4cee6112011-12-31 14:58:18 -080079#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070080# if defined(_MSC_VER)
81# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
82# elif defined (ANDROID_NDK)
83# include <android/log.h>
84# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85# else
86# include <assert.h>
87# define TIXMLASSERT assert
88# endif
89# else
90# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080091#endif
92
U-Lama\Leee13c3e62011-12-28 14:36:55 -080093
Lee Thomason1a1d4a72012-02-15 09:09:25 -080094#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// Microsoft visual studio, version 2005 and higher.
96/*int _snprintf_s(
97 char *buffer,
98 size_t sizeOfBuffer,
99 size_t count,
100 const char *format [,
101 argument] ...
102);*/
103inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
104{
105 va_list va;
106 va_start( va, format );
107 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
108 va_end( va );
109 return result;
110}
111#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700112#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700113// GCC version 3 and higher
114//#warning( "Using sn* functions." )
115#define TIXML_SNPRINTF snprintf
116#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800117#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800118
selfpoisede77e1952013-03-13 14:08:29 +0800119static const int TIXML2_MAJOR_VERSION = 1;
120static const int TIXML2_MINOR_VERSION = 0;
121static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800122
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800123namespace tinyxml2
124{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800125class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800126class XMLElement;
127class XMLAttribute;
128class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800129class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800130class XMLDeclaration;
131class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800132class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800133
U-Stream\Leeae25a442012-02-17 17:48:16 -0800134/*
135 A class that wraps strings. Normally stores the start and end
136 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800137 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800138 manage) a traditional char[]
139*/
PKEuS95060352013-07-26 10:42:44 +0200140class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800141{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800142public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 enum {
144 NEEDS_ENTITY_PROCESSING = 0x01,
145 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800146 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800147
selfpoisede77e1952013-03-13 14:08:29 +0800148 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800150 ATTRIBUTE_NAME = 0,
151 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
152 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
153 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 };
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800158
Lee Thomason120b3a62012-10-12 10:06:59 -0700159 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700161 _start = start;
162 _end = end;
163 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700165
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700169 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 }
Lee Thomason39ede242012-01-20 11:27:56 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 void SetInternedStr( const char* str ) {
173 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700174 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700176
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700177 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800178
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700179 char* ParseText( char* in, const char* endTag, int strFlags );
180 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800181
Lee Thomason39ede242012-01-20 11:27:56 -0800182private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 void Reset();
184 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800185
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700186 enum {
187 NEEDS_FLUSH = 0x100,
188 NEEDS_DELETE = 0x200
189 };
Lee Thomasone4422302012-01-20 17:59:50 -0800190
selfpoised4dd59bc2013-03-13 16:54:15 +0800191 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700192 int _flags;
193 char* _start;
194 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800195};
196
U-Lama\Lee560bd472011-12-28 19:42:49 -0800197
U-Stream\Leeae25a442012-02-17 17:48:16 -0800198/*
199 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
200 Has a small initial memory pool, so that low or no usage will not
201 cause a call to new/delete
202*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800203template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200204class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800205{
206public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700208 _mem = _pool;
209 _allocated = INIT;
210 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700212
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700214 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700215 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 EnsureCapacity( _size+1 );
221 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 EnsureCapacity( _size+count );
226 T* ret = &_mem[_size];
227 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 return ret;
229 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700234
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700236 TIXMLASSERT( _size >= count );
237 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800239
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700241 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700243
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700245 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700246 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700248
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700250 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700253
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700254 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700255 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700256 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700257
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700258 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700261
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700264 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700265
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700266 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700267 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800269
Lee Thomason2c85a712012-01-31 08:24:24 -0800270private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700272 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 int newAllocated = cap * 2;
274 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700275 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
276 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700277 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700279 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700280 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700281 }
282 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800283
Lee Thomason624d43f2012-10-12 10:58:48 -0700284 T* _mem;
285 T _pool[INIT];
286 int _allocated; // objects allocated
287 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800288};
289
Lee Thomason50adb4c2012-02-13 15:07:09 -0800290
U-Stream\Leeae25a442012-02-17 17:48:16 -0800291/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200292 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800293 and deallocation of objects.
294*/
PKEuS95060352013-07-26 10:42:44 +0200295class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800296{
297public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700298 MemPool() {}
299 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800300
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700301 virtual int ItemSize() const = 0;
302 virtual void* Alloc() = 0;
303 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800304 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800305};
306
Lee Thomason50adb4c2012-02-13 15:07:09 -0800307
U-Stream\Leeae25a442012-02-17 17:48:16 -0800308/*
309 Template child class to create pools of the correct type.
310*/
Lee Thomasond1983222012-02-06 08:41:24 -0800311template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200312class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800313{
314public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800315 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700316 ~MemPoolT() {
317 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700318 for( int i=0; i<_blockPtrs.Size(); ++i ) {
319 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700320 }
321 }
Lee Thomasond1983222012-02-06 08:41:24 -0800322
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700323 virtual int ItemSize() const {
324 return SIZE;
325 }
326 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700327 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 }
Lee Thomasond1983222012-02-06 08:41:24 -0800329
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700330 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700331 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 // Need a new block.
333 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700334 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800335
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700336 for( int i=0; i<COUNT-1; ++i ) {
337 block->chunk[i].next = &block->chunk[i+1];
338 }
339 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700340 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700342 void* result = _root;
343 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800344
Lee Thomason624d43f2012-10-12 10:58:48 -0700345 ++_currentAllocs;
346 if ( _currentAllocs > _maxAllocs ) {
347 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800350 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700351 return result;
352 }
353 virtual void Free( void* mem ) {
354 if ( !mem ) {
355 return;
356 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700357 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700358 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700359#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700361#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 chunk->next = _root;
363 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700364 }
365 void Trace( const char* name ) {
366 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700367 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700368 }
Lee Thomasond1983222012-02-06 08:41:24 -0800369
Lee Thomason5b0a6772012-11-19 13:54:42 -0800370 void SetTracked() {
371 _nUntracked--;
372 }
373
374 int Untracked() const {
375 return _nUntracked;
376 }
377
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800378 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
379 // The test file is large, 170k.
380 // Release: VS2010 gcc(no opt)
381 // 1k: 4000
382 // 2k: 4000
383 // 4k: 3900 21000
384 // 16k: 5200
385 // 32k: 4300
386 // 64k: 4000 21000
387 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 +0200388
Lee Thomasond1983222012-02-06 08:41:24 -0800389private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700390 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700391 Chunk* next;
392 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 };
394 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700395 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700396 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700397 DynArray< Block*, 10 > _blockPtrs;
398 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800399
Lee Thomason624d43f2012-10-12 10:58:48 -0700400 int _currentAllocs;
401 int _nAllocs;
402 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800403 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800404};
405
Lee Thomason2c85a712012-01-31 08:24:24 -0800406
Lee Thomason56bdd022012-02-09 18:16:58 -0800407
408/**
409 Implements the interface to the "Visitor pattern" (see the Accept() method.)
410 If you call the Accept() method, it requires being passed a XMLVisitor
411 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200412 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800413 are simply called with Visit().
414
415 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700416 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800417
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700418 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800419 visiting). You need to only override methods that are interesting to you.
420
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600421 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800422
423 You should never change the document from a callback.
424
425 @sa XMLNode::Accept()
426*/
PKEuS16ed47d2013-07-06 12:02:43 +0200427class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800428{
429public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700430 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800431
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700432 /// Visit a document.
433 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
434 return true;
435 }
436 /// Visit a document.
437 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
438 return true;
439 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800440
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700441 /// Visit an element.
442 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
443 return true;
444 }
445 /// Visit an element.
446 virtual bool VisitExit( const XMLElement& /*element*/ ) {
447 return true;
448 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800449
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700450 /// Visit a declaration.
451 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
452 return true;
453 }
454 /// Visit a text node.
455 virtual bool Visit( const XMLText& /*text*/ ) {
456 return true;
457 }
458 /// Visit a comment node.
459 virtual bool Visit( const XMLComment& /*comment*/ ) {
460 return true;
461 }
462 /// Visit an unknown node.
463 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
464 return true;
465 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800466};
467
468
U-Stream\Leeae25a442012-02-17 17:48:16 -0800469/*
470 Utility functionality.
471*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800472class XMLUtil
473{
Lee Thomasond1983222012-02-06 08:41:24 -0800474public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700475 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
476 // correct, but simple, and usually works.
477 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100478 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700479 ++p;
480 }
481 return p;
482 }
483 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100484 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700485 ++p;
486 }
487 return p;
488 }
489 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100490 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700491 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200492
493 inline static bool IsNameStartChar( unsigned char ch ) {
494 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
495 || ch == ':'
496 || ch == '_';
497 }
498
499 inline static bool IsNameChar( unsigned char ch ) {
500 return IsNameStartChar( ch )
501 || isdigit( ch )
502 || ch == '.'
503 || ch == '-';
504 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800505
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700506 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
507 int n = 0;
508 if ( p == q ) {
509 return true;
510 }
511 while( *p && *q && *p == *q && n<nChar ) {
512 ++p;
513 ++q;
514 ++n;
515 }
516 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
517 return true;
518 }
519 return false;
520 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200521
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700522 inline static int IsUTF8Continuation( const char p ) {
523 return p & 0x80;
524 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800525
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700526 static const char* ReadBOM( const char* p, bool* hasBOM );
527 // p is the starting location,
528 // the UTF-8 value of the entity will be placed in value, and length filled in.
529 static const char* GetCharacterRef( const char* p, char* value, int* length );
530 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700531
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700532 // converts primitive types to strings
533 static void ToStr( int v, char* buffer, int bufferSize );
534 static void ToStr( unsigned v, char* buffer, int bufferSize );
535 static void ToStr( bool v, char* buffer, int bufferSize );
536 static void ToStr( float v, char* buffer, int bufferSize );
537 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700538
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700539 // converts strings to primitive types
540 static bool ToInt( const char* str, int* value );
541 static bool ToUnsigned( const char* str, unsigned* value );
542 static bool ToBool( const char* str, bool* value );
543 static bool ToFloat( const char* str, float* value );
544 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800545};
546
Lee Thomason5cae8972012-01-24 18:03:07 -0800547
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800548/** XMLNode is a base class for every object that is in the
549 XML Document Object Model (DOM), except XMLAttributes.
550 Nodes have siblings, a parent, and children which can
551 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700552 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800553 be cast to its more defined type.
554
Thomas Roß08bdf502012-05-12 14:21:23 +0200555 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800556 When the XMLDocument gets deleted, all its Nodes
557 will also be deleted.
558
559 @verbatim
560 A Document can contain: Element (container or leaf)
561 Comment (leaf)
562 Unknown (leaf)
563 Declaration( leaf )
564
565 An Element can contain: Element (container or leaf)
566 Text (leaf)
567 Attributes (not on tree)
568 Comment (leaf)
569 Unknown (leaf)
570
571 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800572*/
PKEuS16ed47d2013-07-06 12:02:43 +0200573class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800574{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700575 friend class XMLDocument;
576 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800577public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800578
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700579 /// Get the XMLDocument that owns this XMLNode.
580 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700581 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700582 }
583 /// Get the XMLDocument that owns this XMLNode.
584 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700585 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700586 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800587
Lee Thomason2fa81722012-11-09 12:37:46 -0800588 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700589 virtual XMLElement* ToElement() {
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 Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700593 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100594 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800596 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700597 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100598 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700599 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800600 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100602 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700603 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800604 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700605 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100606 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700607 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800608 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700609 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100610 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800612
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700613 virtual const XMLElement* ToElement() const {
614 return 0;
615 }
616 virtual const XMLText* ToText() const {
617 return 0;
618 }
619 virtual const XMLComment* ToComment() const {
620 return 0;
621 }
622 virtual const XMLDocument* ToDocument() const {
623 return 0;
624 }
625 virtual const XMLDeclaration* ToDeclaration() const {
626 return 0;
627 }
628 virtual const XMLUnknown* ToUnknown() const {
629 return 0;
630 }
Lee Thomason751da522012-02-10 08:50:51 -0800631
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700632 /** The meaning of 'value' changes for the specific type.
633 @verbatim
634 Document: empty
635 Element: name of the element
636 Comment: the comment text
637 Unknown: the tag contents
638 Text: the text string
639 @endverbatim
640 */
641 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700642 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100644
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 /** Set the Value of an XML node.
646 @sa Value()
647 */
648 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800649
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 /// Get the parent of this node on the DOM.
651 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700652 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700656 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 }
Lee Thomason751da522012-02-10 08:50:51 -0800658
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 /// Returns true if this node has no children.
660 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700661 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700662 }
Lee Thomason751da522012-02-10 08:50:51 -0800663
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 /// Get the first child node, or null if none exists.
665 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700666 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100668
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700670 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700671 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100672
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700673 /** Get the first child element, or optionally the first child
674 element with the specified name.
675 */
676 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700677
678 XMLElement* FirstChildElement( const char* value=0 ) {
679 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800681
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 /// Get the last child node, or null if none exists.
683 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700684 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700685 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700686
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 XMLNode* LastChild() {
688 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
689 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800690
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 /** Get the last child element or optionally the last child
692 element with the specified name.
693 */
694 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700695
696 XMLElement* LastChildElement( const char* value=0 ) {
697 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(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 previous (left) sibling node of this node.
701 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700702 return _prev;
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* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700706 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800708
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700709 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700711
712 XMLElement* PreviousSiblingElement( const char* value=0 ) {
713 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700714 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 /// Get the next (right) sibling node of this node.
717 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700718 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700722 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700724
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700725 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700727
728 XMLElement* NextSiblingElement( const char* value=0 ) {
729 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700730 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800731
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 /**
733 Add a child node as the last (right) child.
734 */
735 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 XMLNode* LinkEndChild( XMLNode* addThis ) {
738 return InsertEndChild( addThis );
739 }
740 /**
741 Add a child node as the first (left) child.
742 */
743 XMLNode* InsertFirstChild( XMLNode* addThis );
744 /**
745 Add a node after the specified child node.
746 */
747 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700748
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 /**
750 Delete all the children of this node.
751 */
752 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800753
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 /**
755 Delete a child of this node.
756 */
757 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800758
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700759 /**
760 Make a copy of this node, but not its children.
761 You may pass in a Document pointer that will be
762 the owner of the new Node. If the 'document' is
763 null, then the node returned will be allocated
764 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800765
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 Note: if called on a XMLDocument, this will return null.
767 */
768 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800769
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700770 /**
771 Test if 2 nodes are the same, but don't test children.
772 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800773
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700774 Note: if called on a XMLDocument, this will return false.
775 */
776 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800777
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600778 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700779 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600780 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800781
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600782 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
783 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800785
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800787
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700788 - http://www.saxproject.org/
789 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800790
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800792
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 An example of using Accept():
794 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600795 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 tinyxmlDoc.Accept( &printer );
797 const char* xmlcstr = printer.CStr();
798 @endverbatim
799 */
800 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800801
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700802 // internal
803 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800804
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800805protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 XMLNode( XMLDocument* );
807 virtual ~XMLNode();
808 XMLNode( const XMLNode& ); // not supported
809 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700810
Lee Thomason624d43f2012-10-12 10:58:48 -0700811 XMLDocument* _document;
812 XMLNode* _parent;
813 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800814
Lee Thomason624d43f2012-10-12 10:58:48 -0700815 XMLNode* _firstChild;
816 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800817
Lee Thomason624d43f2012-10-12 10:58:48 -0700818 XMLNode* _prev;
819 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800820
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800821private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700822 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700823 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800824};
825
826
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800827/** XML text.
828
829 Note that a text node can have child element nodes, for example:
830 @verbatim
831 <root>This is <b>bold</b></root>
832 @endverbatim
833
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700834 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800835 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 -0700836 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600837 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800838*/
PKEuS16ed47d2013-07-06 12:02:43 +0200839class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800840{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700841 friend class XMLBase;
842 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800843public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800845
Lee Thomason624d43f2012-10-12 10:58:48 -0700846 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 return this;
848 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700849 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700850 return this;
851 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800852
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700853 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700854 void SetCData( bool isCData ) {
855 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 }
857 /// Returns true if this is a CDATA text element.
858 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700859 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700860 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800861
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700862 char* ParseDeep( char*, StrPair* endTag );
863 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
864 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800865
Lee Thomason5492a1c2012-01-23 15:32:10 -0800866protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700867 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700868 virtual ~XMLText() {}
869 XMLText( const XMLText& ); // not supported
870 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800871
872private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700873 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800874};
875
876
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800877/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200878class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800879{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700880 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800881public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700882 virtual XMLComment* ToComment() {
883 return this;
884 }
885 virtual const XMLComment* ToComment() const {
886 return this;
887 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800888
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700889 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800890
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700891 char* ParseDeep( char*, StrPair* endTag );
892 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
893 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800894
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800895protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700896 XMLComment( XMLDocument* doc );
897 virtual ~XMLComment();
898 XMLComment( const XMLComment& ); // not supported
899 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800900
Lee Thomason3f57d272012-01-11 15:30:03 -0800901private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800902};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800903
904
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800905/** In correct XML the declaration is the first entry in the file.
906 @verbatim
907 <?xml version="1.0" standalone="yes"?>
908 @endverbatim
909
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600910 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800911 however.
912
913 The text of the declaration isn't interpreted. It is parsed
914 and written as a string.
915*/
PKEuS16ed47d2013-07-06 12:02:43 +0200916class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800917{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700918 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800919public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700920 virtual XMLDeclaration* ToDeclaration() {
921 return this;
922 }
923 virtual const XMLDeclaration* ToDeclaration() const {
924 return this;
925 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800926
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700927 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800928
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700929 char* ParseDeep( char*, StrPair* endTag );
930 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
931 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800932
933protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 XMLDeclaration( XMLDocument* doc );
935 virtual ~XMLDeclaration();
936 XMLDeclaration( const XMLDeclaration& ); // not supported
937 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800938};
939
940
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600941/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800942 unknown. It is a tag of text, but should not be modified.
943 It will be written back to the XML, unchanged, when the file
944 is saved.
945
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600946 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800947*/
PKEuS16ed47d2013-07-06 12:02:43 +0200948class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800949{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800951public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700952 virtual XMLUnknown* ToUnknown() {
953 return this;
954 }
955 virtual const XMLUnknown* ToUnknown() const {
956 return this;
957 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800958
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700959 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800960
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700961 char* ParseDeep( char*, StrPair* endTag );
962 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
963 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800964
965protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 XMLUnknown( XMLDocument* doc );
967 virtual ~XMLUnknown();
968 XMLUnknown( const XMLUnknown& ); // not supported
969 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800970};
971
972
Lee Thomason2fa81722012-11-09 12:37:46 -0800973enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700974 XML_NO_ERROR = 0,
975 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800976
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 XML_NO_ATTRIBUTE,
978 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800979
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700980 XML_ERROR_FILE_NOT_FOUND,
981 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
982 XML_ERROR_FILE_READ_ERROR,
983 XML_ERROR_ELEMENT_MISMATCH,
984 XML_ERROR_PARSING_ELEMENT,
985 XML_ERROR_PARSING_ATTRIBUTE,
986 XML_ERROR_IDENTIFYING_TAG,
987 XML_ERROR_PARSING_TEXT,
988 XML_ERROR_PARSING_CDATA,
989 XML_ERROR_PARSING_COMMENT,
990 XML_ERROR_PARSING_DECLARATION,
991 XML_ERROR_PARSING_UNKNOWN,
992 XML_ERROR_EMPTY_DOCUMENT,
993 XML_ERROR_MISMATCHED_ELEMENT,
994 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700995
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700996 XML_CAN_NOT_CONVERT_TEXT,
997 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800998};
999
1000
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001001/** An attribute is a name-value pair. Elements have an arbitrary
1002 number of attributes, each with a unique name.
1003
1004 @note The attributes are not XMLNodes. You may only query the
1005 Next() attribute in a list.
1006*/
PKEuS16ed47d2013-07-06 12:02:43 +02001007class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001008{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001009 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001010public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001011 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001012 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001013 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001015 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001017 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001019 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001020 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001021 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001023
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001024 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001026 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001027 */
1028 int IntValue() const {
1029 int i=0;
1030 QueryIntValue( &i );
1031 return i;
1032 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001033 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001034 unsigned UnsignedValue() const {
1035 unsigned i=0;
1036 QueryUnsignedValue( &i );
1037 return i;
1038 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001039 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001040 bool BoolValue() const {
1041 bool b=false;
1042 QueryBoolValue( &b );
1043 return b;
1044 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001045 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001046 double DoubleValue() const {
1047 double d=0;
1048 QueryDoubleValue( &d );
1049 return d;
1050 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001051 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001052 float FloatValue() const {
1053 float f=0;
1054 QueryFloatValue( &f );
1055 return f;
1056 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001057
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001058 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001059 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001060 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1061 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001062 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001063 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001064 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001065 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001066 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001067 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001068 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001069 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001070 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001071
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001072 /// Set the attribute to a string value.
1073 void SetAttribute( const char* value );
1074 /// Set the attribute to value.
1075 void SetAttribute( int value );
1076 /// Set the attribute to value.
1077 void SetAttribute( unsigned value );
1078 /// Set the attribute to value.
1079 void SetAttribute( bool value );
1080 /// Set the attribute to value.
1081 void SetAttribute( double value );
1082 /// Set the attribute to value.
1083 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001084
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001085private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001086 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001087
Thomas Roß61892312013-05-12 14:07:38 +02001088 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001089 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001090
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001091 XMLAttribute( const XMLAttribute& ); // not supported
1092 void operator=( const XMLAttribute& ); // not supported
1093 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001094
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001095 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001096
Lee Thomason624d43f2012-10-12 10:58:48 -07001097 mutable StrPair _name;
1098 mutable StrPair _value;
1099 XMLAttribute* _next;
1100 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001101};
1102
1103
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001104/** The element is a container class. It has a value, the element name,
1105 and can contain other elements, text, comments, and unknowns.
1106 Elements also contain an arbitrary number of attributes.
1107*/
PKEuS16ed47d2013-07-06 12:02:43 +02001108class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001109{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001110 friend class XMLBase;
1111 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001112public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001113 /// Get the name of an element (which is the Value() of the node.)
1114 const char* Name() const {
1115 return Value();
1116 }
1117 /// Set the name of the element.
1118 void SetName( const char* str, bool staticMem=false ) {
1119 SetValue( str, staticMem );
1120 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001121
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001122 virtual XMLElement* ToElement() {
1123 return this;
1124 }
1125 virtual const XMLElement* ToElement() const {
1126 return this;
1127 }
1128 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001129
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001130 /** Given an attribute name, Attribute() returns the value
1131 for the attribute of that name, or null if none
1132 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001133
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001134 @verbatim
1135 const char* value = ele->Attribute( "foo" );
1136 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001137
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001138 The 'value' parameter is normally null. However, if specified,
1139 the attribute will only be returned if the 'name' and 'value'
1140 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001141
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001142 @verbatim
1143 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1144 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001145
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 rather than:
1147 @verbatim
1148 if ( ele->Attribute( "foo" ) ) {
1149 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1150 }
1151 @endverbatim
1152 */
1153 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001154
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001155 /** Given an attribute name, IntAttribute() returns the value
1156 of the attribute interpreted as an integer. 0 will be
1157 returned if there is an error. For a method with error
1158 checking, see QueryIntAttribute()
1159 */
1160 int IntAttribute( const char* name ) const {
1161 int i=0;
1162 QueryIntAttribute( name, &i );
1163 return i;
1164 }
1165 /// See IntAttribute()
1166 unsigned UnsignedAttribute( const char* name ) const {
1167 unsigned i=0;
1168 QueryUnsignedAttribute( name, &i );
1169 return i;
1170 }
1171 /// See IntAttribute()
1172 bool BoolAttribute( const char* name ) const {
1173 bool b=false;
1174 QueryBoolAttribute( name, &b );
1175 return b;
1176 }
1177 /// See IntAttribute()
1178 double DoubleAttribute( const char* name ) const {
1179 double d=0;
1180 QueryDoubleAttribute( name, &d );
1181 return d;
1182 }
1183 /// See IntAttribute()
1184 float FloatAttribute( const char* name ) const {
1185 float f=0;
1186 QueryFloatAttribute( name, &f );
1187 return f;
1188 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001189
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001190 /** Given an attribute name, QueryIntAttribute() returns
1191 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1192 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1193 doesn't exist. If successful, the result of the conversion
1194 will be written to 'value'. If not successful, nothing will
1195 be written to 'value'. This allows you to provide default
1196 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001197
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001198 @verbatim
1199 int value = 10;
1200 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1201 @endverbatim
1202 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001203 XMLError QueryIntAttribute( const char* name, int* 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->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 }
1210 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001211 XMLError QueryUnsignedAttribute( const char* name, unsigned int* 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->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001217 }
1218 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001219 XMLError QueryBoolAttribute( const char* name, bool* 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->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 }
1226 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001227 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001228 const XMLAttribute* a = FindAttribute( name );
1229 if ( !a ) {
1230 return XML_NO_ATTRIBUTE;
1231 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001232 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 }
1234 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001235 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001236 const XMLAttribute* a = FindAttribute( name );
1237 if ( !a ) {
1238 return XML_NO_ATTRIBUTE;
1239 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001240 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001242
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001243
1244 /** Given an attribute name, QueryAttribute() returns
1245 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1246 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1247 doesn't exist. It is overloaded for the primitive types,
1248 and is a generally more convenient replacement of
1249 QueryIntAttribute() and related functions.
1250
1251 If successful, the result of the conversion
1252 will be written to 'value'. If not successful, nothing will
1253 be written to 'value'. This allows you to provide default
1254 value:
1255
1256 @verbatim
1257 int value = 10;
1258 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1259 @endverbatim
1260 */
1261 int QueryAttribute( const char* name, int* value ) const {
1262 return QueryIntAttribute( name, value );
1263 }
1264
1265 int QueryAttribute( const char* name, unsigned int* value ) const {
1266 return QueryUnsignedAttribute( name, value );
1267 }
1268
1269 int QueryAttribute( const char* name, bool* value ) const {
1270 return QueryBoolAttribute( name, value );
1271 }
1272
1273 int QueryAttribute( const char* name, double* value ) const {
1274 return QueryDoubleAttribute( name, value );
1275 }
1276
1277 int QueryAttribute( const char* name, float* value ) const {
1278 return QueryFloatAttribute( name, value );
1279 }
1280
1281 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001282 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001283 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001284 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 }
1286 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001287 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001288 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001289 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 }
1291 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001292 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001293 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001294 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 }
1296 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001297 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001298 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001299 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 }
1301 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001302 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001304 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001305 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001306
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 /**
1308 Delete an attribute.
1309 */
1310 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001311
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 /// Return the first attribute in the list.
1313 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001314 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 }
1316 /// Query a specific attribute in the list.
1317 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001318
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001320 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001322
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001323 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001325
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 This is a convenient method for getting the text of simple contained text:
1327 @verbatim
1328 <foo>This is text</foo>
1329 const char* str = fooElement->GetText();
1330 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001331
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001332 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001333
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001334 Note that this function can be misleading. If the element foo was created from
1335 this XML:
1336 @verbatim
1337 <foo><b>This is text</b></foo>
1338 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001339
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001340 then the value of str would be null. The first child node isn't a text node, it is
1341 another element. From this XML:
1342 @verbatim
1343 <foo>This is <b>text</b></foo>
1344 @endverbatim
1345 GetText() will return "This is ".
1346 */
1347 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001348
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001349 /**
1350 Convenience method to query the value of a child text node. This is probably best
1351 shown by example. Given you have a document is this form:
1352 @verbatim
1353 <point>
1354 <x>1</x>
1355 <y>1.4</y>
1356 </point>
1357 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001358
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 The QueryIntText() and similar functions provide a safe and easier way to get to the
1360 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001361
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001362 @verbatim
1363 int x = 0;
1364 float y = 0; // types of x and y are contrived for example
1365 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1366 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1367 xElement->QueryIntText( &x );
1368 yElement->QueryFloatText( &y );
1369 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001370
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001371 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1372 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 -07001373
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001374 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001375 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001376 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001377 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001378 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001379 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001381 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001382 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001383 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001384
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001385 // internal:
1386 enum {
1387 OPEN, // <foo>
1388 CLOSED, // <foo/>
1389 CLOSING // </foo>
1390 };
1391 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001392 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001393 }
1394 char* ParseDeep( char* p, StrPair* endTag );
1395 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1396 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001397
Lee Thomason50adb4c2012-02-13 15:07:09 -08001398private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001399 XMLElement( XMLDocument* doc );
1400 virtual ~XMLElement();
1401 XMLElement( const XMLElement& ); // not supported
1402 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001403
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001404 XMLAttribute* FindAttribute( const char* name );
1405 XMLAttribute* FindOrCreateAttribute( const char* name );
1406 //void LinkAttribute( XMLAttribute* attrib );
1407 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001408
Lee Thomason624d43f2012-10-12 10:58:48 -07001409 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001410 // The attribute list is ordered; there is no 'lastAttribute'
1411 // because the list needs to be scanned for dupes before adding
1412 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001413 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001414};
1415
1416
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001417enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 PRESERVE_WHITESPACE,
1419 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001420};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001421
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001422
1423/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001424 It can be saved, loaded, and printed to the screen.
1425 All Nodes are connected and allocated to a Document.
1426 If the Document is deleted, all its Nodes are also deleted.
1427*/
PKEuS16ed47d2013-07-06 12:02:43 +02001428class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001429{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001430 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001431public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 /// constructor
1433 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1434 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001435
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001436 virtual XMLDocument* ToDocument() {
1437 return this;
1438 }
1439 virtual const XMLDocument* ToDocument() const {
1440 return this;
1441 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001442
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001443 /**
1444 Parse an XML file from a character string.
1445 Returns XML_NO_ERROR (0) on success, or
1446 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001447
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001448 You may optionally pass in the 'nBytes', which is
1449 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001450 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001451 null terminated string.
1452 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001453 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001454
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001455 /**
1456 Load an XML file from disk.
1457 Returns XML_NO_ERROR (0) on success, or
1458 an errorID.
1459 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001460 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001461
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001462 /**
1463 Load an XML file from disk. You are responsible
1464 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001465
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 LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001470
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001471 /**
1472 Save the XML file to disk.
1473 Returns XML_NO_ERROR (0) on success, or
1474 an errorID.
1475 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001476 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001477
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001478 /**
1479 Save the XML file to disk. You are responsible
1480 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001481
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001482 Returns XML_NO_ERROR (0) on success, or
1483 an errorID.
1484 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001485 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001486
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001487 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001488 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001489 }
1490 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001491 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001492 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001493
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001494 /**
1495 Returns true if this document has a leading Byte Order Mark of UTF8.
1496 */
1497 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001498 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 }
1500 /** Sets whether to write the BOM when writing the file.
1501 */
1502 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001503 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001504 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001505
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001506 /** Return the root element of DOM. Equivalent to FirstChildElement().
1507 To get the first node, use FirstChild().
1508 */
1509 XMLElement* RootElement() {
1510 return FirstChildElement();
1511 }
1512 const XMLElement* RootElement() const {
1513 return FirstChildElement();
1514 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001515
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001516 /** Print the Document. If the Printer is not provided, it will
1517 print to stdout. If you provide Printer, this can print to a file:
1518 @verbatim
1519 XMLPrinter printer( fp );
1520 doc.Print( &printer );
1521 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001522
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001523 Or you can use a printer to print to memory:
1524 @verbatim
1525 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001526 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001527 // printer.CStr() has a const char* to the XML
1528 @endverbatim
1529 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001530 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001532
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001533 /**
1534 Create a new Element associated with
1535 this Document. The memory for the Element
1536 is managed by the Document.
1537 */
1538 XMLElement* NewElement( const char* name );
1539 /**
1540 Create a new Comment associated with
1541 this Document. The memory for the Comment
1542 is managed by the Document.
1543 */
1544 XMLComment* NewComment( const char* comment );
1545 /**
1546 Create a new Text associated with
1547 this Document. The memory for the Text
1548 is managed by the Document.
1549 */
1550 XMLText* NewText( const char* text );
1551 /**
1552 Create a new Declaration associated with
1553 this Document. The memory for the object
1554 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001555
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001556 If the 'text' param is null, the standard
1557 declaration is used.:
1558 @verbatim
1559 <?xml version="1.0" encoding="UTF-8"?>
1560 @endverbatim
1561 */
1562 XMLDeclaration* NewDeclaration( const char* text=0 );
1563 /**
1564 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001565 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001566 is managed by the Document.
1567 */
1568 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001569
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001570 /**
1571 Delete a node associated with this document.
1572 It will be unlinked from the DOM.
1573 */
1574 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001575 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001576 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001577
Lee Thomason2fa81722012-11-09 12:37:46 -08001578 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001579
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 /// Return true if there was an error parsing the document.
1581 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001582 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001583 }
1584 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001585 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001586 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001587 }
1588 /// Return a possibly helpful diagnostic location or string.
1589 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001590 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001591 }
1592 /// Return a possibly helpful secondary diagnostic location or string.
1593 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001594 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001595 }
1596 /// If there is an error, print it to stdout.
1597 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001598
1599 /// Clear the document, resetting it to the initial state.
1600 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001601
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 // internal
1603 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001604
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001605 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1606 return 0;
1607 }
1608 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1609 return false;
1610 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001611
Lee Thomason3f57d272012-01-11 15:30:03 -08001612private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001613 XMLDocument( const XMLDocument& ); // not supported
1614 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001615
Lee Thomason2fa81722012-11-09 12:37:46 -08001616 bool _writeBOM;
1617 bool _processEntities;
1618 XMLError _errorID;
1619 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001620 const char* _errorStr1;
1621 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001622 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001623
Lee Thomason624d43f2012-10-12 10:58:48 -07001624 MemPoolT< sizeof(XMLElement) > _elementPool;
1625 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1626 MemPoolT< sizeof(XMLText) > _textPool;
1627 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001628};
1629
Lee Thomason7c913cd2012-01-26 18:32:34 -08001630
Lee Thomason3ffdd392012-03-28 17:27:55 -07001631/**
1632 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001633 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001634 DOM structure. It is a separate utility class.
1635
1636 Take an example:
1637 @verbatim
1638 <Document>
1639 <Element attributeA = "valueA">
1640 <Child attributeB = "value1" />
1641 <Child attributeB = "value2" />
1642 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001643 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001644 @endverbatim
1645
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001646 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001647 easy to write a *lot* of code that looks like:
1648
1649 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001650 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001651 if ( root )
1652 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001653 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001654 if ( element )
1655 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001656 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001657 if ( child )
1658 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001659 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001660 if ( child2 )
1661 {
1662 // Finally do something useful.
1663 @endverbatim
1664
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001665 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001666 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001667 and correct to use:
1668
1669 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001670 XMLHandle docHandle( &document );
1671 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001672 if ( child2 )
1673 {
1674 // do something useful
1675 @endverbatim
1676
1677 Which is MUCH more concise and useful.
1678
1679 It is also safe to copy handles - internally they are nothing more than node pointers.
1680 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001681 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001682 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001683
1684 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001685*/
PKEuS16ed47d2013-07-06 12:02:43 +02001686class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001687{
1688public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001689 /// 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 -07001690 XMLHandle( XMLNode* node ) {
1691 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001692 }
1693 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001694 XMLHandle( XMLNode& node ) {
1695 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001696 }
1697 /// Copy constructor
1698 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001699 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001700 }
1701 /// Assignment
1702 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001703 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001704 return *this;
1705 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001706
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001707 /// Get the first child of this handle.
1708 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001709 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001710 }
1711 /// Get the first child element of this handle.
1712 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001713 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 }
1715 /// Get the last child of this handle.
1716 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
1719 /// Get the last child element of this handle.
1720 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001721 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001722 }
1723 /// Get the previous sibling of this handle.
1724 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001725 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 }
1727 /// Get the previous sibling element of this handle.
1728 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001729 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001730 }
1731 /// Get the next sibling of this handle.
1732 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001733 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001734 }
1735 /// Get the next sibling element of this handle.
1736 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001737 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001738 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001739
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001740 /// Safe cast to XMLNode. This can return null.
1741 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
1744 /// Safe cast to XMLElement. This can return null.
1745 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001746 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001747 }
1748 /// Safe cast to XMLText. This can return null.
1749 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001750 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001751 }
1752 /// Safe cast to XMLUnknown. This can return null.
1753 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001754 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001755 }
1756 /// Safe cast to XMLDeclaration. This can return null.
1757 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001758 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001759 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001760
1761private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001762 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001763};
1764
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001765
1766/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001767 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1768 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001769*/
PKEuS16ed47d2013-07-06 12:02:43 +02001770class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001771{
1772public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001773 XMLConstHandle( const XMLNode* node ) {
1774 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001775 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001776 XMLConstHandle( const XMLNode& node ) {
1777 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001778 }
1779 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001780 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001781 }
Lee Thomason8b899812012-04-04 15:58:16 -07001782
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001784 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001785 return *this;
1786 }
Lee Thomason8b899812012-04-04 15:58:16 -07001787
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001788 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001789 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001790 }
1791 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001792 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001793 }
1794 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001795 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 }
1797 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 }
1800 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001801 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 }
1803 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001804 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001805 }
1806 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001807 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001808 }
1809 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001810 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001811 }
Lee Thomason8b899812012-04-04 15:58:16 -07001812
1813
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001814 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 }
1817 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001818 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 }
1820 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001821 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001822 }
1823 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001824 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001825 }
1826 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001827 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001828 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001829
Lee Thomason5cae8972012-01-24 18:03:07 -08001830private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001831 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001832};
Lee Thomason6f381b72012-03-02 12:59:39 -08001833
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001834
1835/**
1836 Printing functionality. The XMLPrinter gives you more
1837 options than the XMLDocument::Print() method.
1838
1839 It can:
1840 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001841 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001842 -# Print XML without a XMLDocument.
1843
1844 Print to Memory
1845
1846 @verbatim
1847 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001848 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001849 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001850 @endverbatim
1851
1852 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001853
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001854 You provide the file pointer.
1855 @verbatim
1856 XMLPrinter printer( fp );
1857 doc.Print( &printer );
1858 @endverbatim
1859
1860 Print without a XMLDocument
1861
1862 When loading, an XML parser is very useful. However, sometimes
1863 when saving, it just gets in the way. The code is often set up
1864 for streaming, and constructing the DOM is just overhead.
1865
1866 The Printer supports the streaming case. The following code
1867 prints out a trivially simple XML file without ever creating
1868 an XML document.
1869
1870 @verbatim
1871 XMLPrinter printer( fp );
1872 printer.OpenElement( "foo" );
1873 printer.PushAttribute( "foo", "bar" );
1874 printer.CloseElement();
1875 @endverbatim
1876*/
PKEuS16ed47d2013-07-06 12:02:43 +02001877class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001878{
1879public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 /** Construct the printer. If the FILE* is specified,
1881 this will print to the FILE. Else it will print
1882 to memory, and the result is available in CStr().
1883 If 'compact' is set to true, then output is created
1884 with only required whitespace and newlines.
1885 */
PKEuS1bfb9542013-08-04 13:51:17 +02001886 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001887 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001888
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001889 /** If streaming, write the BOM and declaration. */
1890 void PushHeader( bool writeBOM, bool writeDeclaration );
1891 /** If streaming, start writing an element.
1892 The element must be closed with CloseElement()
1893 */
1894 void OpenElement( const char* name );
1895 /// If streaming, add an attribute to an open element.
1896 void PushAttribute( const char* name, const char* value );
1897 void PushAttribute( const char* name, int value );
1898 void PushAttribute( const char* name, unsigned value );
1899 void PushAttribute( const char* name, bool value );
1900 void PushAttribute( const char* name, double value );
1901 /// If streaming, close the Element.
1902 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001903
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001904 /// Add a text node.
1905 void PushText( const char* text, bool cdata=false );
1906 /// Add a text node from an integer.
1907 void PushText( int value );
1908 /// Add a text node from an unsigned.
1909 void PushText( unsigned value );
1910 /// Add a text node from a bool.
1911 void PushText( bool value );
1912 /// Add a text node from a float.
1913 void PushText( float value );
1914 /// Add a text node from a double.
1915 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001916
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001917 /// Add a comment
1918 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001919
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001920 void PushDeclaration( const char* value );
1921 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001922
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001923 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1924 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1925 return true;
1926 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001927
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001928 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1929 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001930
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 virtual bool Visit( const XMLText& text );
1932 virtual bool Visit( const XMLComment& comment );
1933 virtual bool Visit( const XMLDeclaration& declaration );
1934 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001935
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001936 /**
1937 If in print to memory mode, return a pointer to
1938 the XML file in memory.
1939 */
1940 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001941 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001942 }
1943 /**
1944 If in print to memory mode, return the size
1945 of the XML file in memory. (Note the size returned
1946 includes the terminating null.)
1947 */
1948 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001949 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001951
1952private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001953 void SealElement();
1954 void PrintSpace( int depth );
1955 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1956 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001957
Lee Thomason624d43f2012-10-12 10:58:48 -07001958 bool _elementJustOpened;
1959 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001960 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001961 int _depth;
1962 int _textDepth;
1963 bool _processEntities;
1964 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001965
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001966 enum {
1967 ENTITY_RANGE = 64,
1968 BUF_SIZE = 200
1969 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001970 bool _entityFlag[ENTITY_RANGE];
1971 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001972
Lee Thomason624d43f2012-10-12 10:58:48 -07001973 DynArray< const char*, 10 > _stack;
1974 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001975#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001976 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001977#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001978};
1979
1980
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001981} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001982
PKEuS95060352013-07-26 10:42:44 +02001983#if defined(_MSC_VER)
1984# pragma warning(pop)
1985#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001986
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001987#endif // TINYXML2_INCLUDED