blob: 796f2b0934ed4ce98a097cb0438bc0355a5998fb [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
pffang91d34a02014-07-10 10:02:35 +080094#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
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
pffang91d34a02014-07-10 10:02:35 +0800112#elif defined WINCE
113#define TIXML_SNPRINTF _snprintf
114#define TIXML_SSCANF sscanf
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700115#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700116// GCC version 3 and higher
117//#warning( "Using sn* functions." )
118#define TIXML_SNPRINTF snprintf
119#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800120#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800121
Lee Thomasonc18eb232014-02-21 17:31:17 -0800122/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -0800123 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800124*/
Lee Thomason85afe9c2014-02-23 21:42:16 -0800125static const int TIXML2_MAJOR_VERSION = 2;
Lee Thomason6ee53e72014-04-06 14:43:37 -0700126static const int TIXML2_MINOR_VERSION = 1;
127static const int TIXML2_PATCH_VERSION = 0;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800128
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800129namespace tinyxml2
130{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800131class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800132class XMLElement;
133class XMLAttribute;
134class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800135class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800136class XMLDeclaration;
137class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800138class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800139
U-Stream\Leeae25a442012-02-17 17:48:16 -0800140/*
141 A class that wraps strings. Normally stores the start and end
142 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800143 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800144 manage) a traditional char[]
145*/
PKEuS95060352013-07-26 10:42:44 +0200146class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800147{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800148public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 enum {
150 NEEDS_ENTITY_PROCESSING = 0x01,
151 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800152 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800153
selfpoisede77e1952013-03-13 14:08:29 +0800154 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700155 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800156 ATTRIBUTE_NAME = 0,
157 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
158 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
159 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 };
Lee Thomason39ede242012-01-20 11:27:56 -0800161
Lee Thomason120b3a62012-10-12 10:06:59 -0700162 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800164
Lee Thomason120b3a62012-10-12 10:06:59 -0700165 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700167 _start = start;
168 _end = end;
169 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700173
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700174 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700175 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700176 }
Lee Thomason39ede242012-01-20 11:27:56 -0800177
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700178 void SetInternedStr( const char* str ) {
179 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700180 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700181 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700182
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800184
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700185 char* ParseText( char* in, const char* endTag, int strFlags );
186 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800187
Lee Thomason39ede242012-01-20 11:27:56 -0800188private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700189 void Reset();
190 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800191
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700192 enum {
193 NEEDS_FLUSH = 0x100,
194 NEEDS_DELETE = 0x200
195 };
Lee Thomasone4422302012-01-20 17:59:50 -0800196
selfpoised4dd59bc2013-03-13 16:54:15 +0800197 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700198 int _flags;
199 char* _start;
200 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800201};
202
U-Lama\Lee560bd472011-12-28 19:42:49 -0800203
U-Stream\Leeae25a442012-02-17 17:48:16 -0800204/*
205 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
206 Has a small initial memory pool, so that low or no usage will not
207 cause a call to new/delete
208*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800209template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200210class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800211{
212public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700214 _mem = _pool;
215 _allocated = INIT;
216 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700221 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
223 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700224
Lee Thomasonce0510b2013-11-26 21:29:37 -0800225 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100226 _size = 0;
227 }
228
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700229 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700230 EnsureCapacity( _size+1 );
231 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800233
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700234 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700235 EnsureCapacity( _size+count );
236 T* ret = &_mem[_size];
237 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 return ret;
239 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700240
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700241 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700242 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700243 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700244
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700246 TIXMLASSERT( _size >= count );
247 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700251 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700253
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700254 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700255 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700256 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700261 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700263
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500264 const T& PeekTop() const {
265 TIXMLASSERT( _size > 0 );
266 return _mem[ _size - 1];
267 }
268
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700270 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700272
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700274 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700276
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700277 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700278 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700279 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700280
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700281 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700282 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800284
Lee Thomason2c85a712012-01-31 08:24:24 -0800285private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700286 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700287 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700288 int newAllocated = cap * 2;
289 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700290 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
291 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700292 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700293 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700294 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700295 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700296 }
297 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800298
Lee Thomason624d43f2012-10-12 10:58:48 -0700299 T* _mem;
300 T _pool[INIT];
301 int _allocated; // objects allocated
302 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800303};
304
Lee Thomason50adb4c2012-02-13 15:07:09 -0800305
U-Stream\Leeae25a442012-02-17 17:48:16 -0800306/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200307 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800308 and deallocation of objects.
309*/
PKEuS95060352013-07-26 10:42:44 +0200310class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800311{
312public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 MemPool() {}
314 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800315
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700316 virtual int ItemSize() const = 0;
317 virtual void* Alloc() = 0;
318 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800319 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800320};
321
Lee Thomason50adb4c2012-02-13 15:07:09 -0800322
U-Stream\Leeae25a442012-02-17 17:48:16 -0800323/*
324 Template child class to create pools of the correct type.
325*/
Lee Thomasond1983222012-02-06 08:41:24 -0800326template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200327class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800328{
329public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800330 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 ~MemPoolT() {
332 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700333 for( int i=0; i<_blockPtrs.Size(); ++i ) {
334 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 }
336 }
Lee Thomasond1983222012-02-06 08:41:24 -0800337
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700338 virtual int ItemSize() const {
339 return SIZE;
340 }
341 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700342 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700343 }
Lee Thomasond1983222012-02-06 08:41:24 -0800344
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700345 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700347 // Need a new block.
348 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800350
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700351 for( int i=0; i<COUNT-1; ++i ) {
352 block->chunk[i].next = &block->chunk[i+1];
353 }
354 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700355 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700357 void* result = _root;
358 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800359
Lee Thomason624d43f2012-10-12 10:58:48 -0700360 ++_currentAllocs;
361 if ( _currentAllocs > _maxAllocs ) {
362 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800365 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700366 return result;
367 }
368 virtual void Free( void* mem ) {
369 if ( !mem ) {
370 return;
371 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700374#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700375 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700376#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700377 chunk->next = _root;
378 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700379 }
380 void Trace( const char* name ) {
381 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700382 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700383 }
Lee Thomasond1983222012-02-06 08:41:24 -0800384
Lee Thomason5b0a6772012-11-19 13:54:42 -0800385 void SetTracked() {
386 _nUntracked--;
387 }
388
389 int Untracked() const {
390 return _nUntracked;
391 }
392
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800393 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
394 // The test file is large, 170k.
395 // Release: VS2010 gcc(no opt)
396 // 1k: 4000
397 // 2k: 4000
398 // 4k: 3900 21000
399 // 16k: 5200
400 // 32k: 4300
401 // 64k: 4000 21000
402 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 +0200403
Lee Thomasond1983222012-02-06 08:41:24 -0800404private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700405 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700406 Chunk* next;
407 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700408 };
409 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700410 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700411 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700412 DynArray< Block*, 10 > _blockPtrs;
413 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800414
Lee Thomason624d43f2012-10-12 10:58:48 -0700415 int _currentAllocs;
416 int _nAllocs;
417 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800418 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800419};
420
Lee Thomason2c85a712012-01-31 08:24:24 -0800421
Lee Thomason56bdd022012-02-09 18:16:58 -0800422
423/**
424 Implements the interface to the "Visitor pattern" (see the Accept() method.)
425 If you call the Accept() method, it requires being passed a XMLVisitor
426 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200427 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800428 are simply called with Visit().
429
430 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700431 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800432
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700433 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800434 visiting). You need to only override methods that are interesting to you.
435
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600436 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800437
438 You should never change the document from a callback.
439
440 @sa XMLNode::Accept()
441*/
PKEuS16ed47d2013-07-06 12:02:43 +0200442class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800443{
444public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700445 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800446
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700447 /// Visit a document.
448 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
449 return true;
450 }
451 /// Visit a document.
452 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
453 return true;
454 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800455
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700456 /// Visit an element.
457 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
458 return true;
459 }
460 /// Visit an element.
461 virtual bool VisitExit( const XMLElement& /*element*/ ) {
462 return true;
463 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800464
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700465 /// Visit a declaration.
466 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
467 return true;
468 }
469 /// Visit a text node.
470 virtual bool Visit( const XMLText& /*text*/ ) {
471 return true;
472 }
473 /// Visit a comment node.
474 virtual bool Visit( const XMLComment& /*comment*/ ) {
475 return true;
476 }
477 /// Visit an unknown node.
478 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
479 return true;
480 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800481};
482
483
U-Stream\Leeae25a442012-02-17 17:48:16 -0800484/*
485 Utility functionality.
486*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800487class XMLUtil
488{
Lee Thomasond1983222012-02-06 08:41:24 -0800489public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700490 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
491 // correct, but simple, and usually works.
492 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100493 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700494 ++p;
495 }
496 return p;
497 }
498 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100499 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700500 ++p;
501 }
502 return p;
503 }
504 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100505 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700506 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200507
508 inline static bool IsNameStartChar( unsigned char ch ) {
509 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
510 || ch == ':'
511 || ch == '_';
512 }
513
514 inline static bool IsNameChar( unsigned char ch ) {
515 return IsNameStartChar( ch )
516 || isdigit( ch )
517 || ch == '.'
518 || ch == '-';
519 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800520
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700521 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
522 int n = 0;
523 if ( p == q ) {
524 return true;
525 }
526 while( *p && *q && *p == *q && n<nChar ) {
527 ++p;
528 ++q;
529 ++n;
530 }
531 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
532 return true;
533 }
534 return false;
535 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200536
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 inline static int IsUTF8Continuation( const char p ) {
538 return p & 0x80;
539 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800540
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 static const char* ReadBOM( const char* p, bool* hasBOM );
542 // p is the starting location,
543 // the UTF-8 value of the entity will be placed in value, and length filled in.
544 static const char* GetCharacterRef( const char* p, char* value, int* length );
545 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700546
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700547 // converts primitive types to strings
548 static void ToStr( int v, char* buffer, int bufferSize );
549 static void ToStr( unsigned v, char* buffer, int bufferSize );
550 static void ToStr( bool v, char* buffer, int bufferSize );
551 static void ToStr( float v, char* buffer, int bufferSize );
552 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700553
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700554 // converts strings to primitive types
555 static bool ToInt( const char* str, int* value );
556 static bool ToUnsigned( const char* str, unsigned* value );
557 static bool ToBool( const char* str, bool* value );
558 static bool ToFloat( const char* str, float* value );
559 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800560};
561
Lee Thomason5cae8972012-01-24 18:03:07 -0800562
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800563/** XMLNode is a base class for every object that is in the
564 XML Document Object Model (DOM), except XMLAttributes.
565 Nodes have siblings, a parent, and children which can
566 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700567 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800568 be cast to its more defined type.
569
Thomas Roß08bdf502012-05-12 14:21:23 +0200570 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800571 When the XMLDocument gets deleted, all its Nodes
572 will also be deleted.
573
574 @verbatim
575 A Document can contain: Element (container or leaf)
576 Comment (leaf)
577 Unknown (leaf)
578 Declaration( leaf )
579
580 An Element can contain: Element (container or leaf)
581 Text (leaf)
582 Attributes (not on tree)
583 Comment (leaf)
584 Unknown (leaf)
585
586 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800587*/
PKEuS16ed47d2013-07-06 12:02:43 +0200588class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800589{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700590 friend class XMLDocument;
591 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800593
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 /// Get the XMLDocument that owns this XMLNode.
595 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700596 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700597 }
598 /// Get the XMLDocument that owns this XMLNode.
599 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700600 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800602
Lee Thomason2fa81722012-11-09 12:37:46 -0800603 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100605 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800607 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100609 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800611 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100613 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800615 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100617 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800619 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700620 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100621 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700622 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800623 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700624 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100625 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700626 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800627
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700628 virtual const XMLElement* ToElement() const {
629 return 0;
630 }
631 virtual const XMLText* ToText() const {
632 return 0;
633 }
634 virtual const XMLComment* ToComment() const {
635 return 0;
636 }
637 virtual const XMLDocument* ToDocument() const {
638 return 0;
639 }
640 virtual const XMLDeclaration* ToDeclaration() const {
641 return 0;
642 }
643 virtual const XMLUnknown* ToUnknown() const {
644 return 0;
645 }
Lee Thomason751da522012-02-10 08:50:51 -0800646
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 /** The meaning of 'value' changes for the specific type.
648 @verbatim
649 Document: empty
650 Element: name of the element
651 Comment: the comment text
652 Unknown: the tag contents
653 Text: the text string
654 @endverbatim
655 */
Michael Daumling21626882013-10-22 17:03:37 +0200656 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100657
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 /** Set the Value of an XML node.
659 @sa Value()
660 */
661 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800662
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 /// Get the parent of this node on the DOM.
664 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700665 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100667
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700668 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700669 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 }
Lee Thomason751da522012-02-10 08:50:51 -0800671
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 /// Returns true if this node has no children.
673 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700674 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 }
Lee Thomason751da522012-02-10 08:50:51 -0800676
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700677 /// Get the first child node, or null if none exists.
678 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700679 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100681
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700683 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100685
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 /** Get the first child element, or optionally the first child
687 element with the specified name.
688 */
689 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700690
691 XMLElement* FirstChildElement( const char* value=0 ) {
692 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700693 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800694
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700695 /// Get the last child node, or null if none exists.
696 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700697 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700698 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700699
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 XMLNode* LastChild() {
701 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
702 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800703
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 /** Get the last child element or optionally the last child
705 element with the specified name.
706 */
707 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700708
709 XMLElement* LastChildElement( const char* value=0 ) {
710 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700711 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700712
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 /// Get the previous (left) sibling node of this node.
714 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700715 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700717
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700719 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800721
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700722 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700724
725 XMLElement* PreviousSiblingElement( const char* value=0 ) {
726 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 /// Get the next (right) sibling node of this node.
730 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700731 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700735 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700736 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700737
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700738 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700740
741 XMLElement* NextSiblingElement( const char* value=0 ) {
742 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800744
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 /**
746 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200747 If the child node is already part of the document,
748 it is moved from its old location to the new location.
749 Returns the addThis argument or 0 if the node does not
750 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 */
752 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800753
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 XMLNode* LinkEndChild( XMLNode* addThis ) {
755 return InsertEndChild( addThis );
756 }
757 /**
758 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200759 If the child node is already part of the document,
760 it is moved from its old location to the new location.
761 Returns the addThis argument or 0 if the node does not
762 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700763 */
764 XMLNode* InsertFirstChild( XMLNode* addThis );
765 /**
766 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200767 If the child node is already part of the document,
768 it is moved from its old location to the new location.
769 Returns the addThis argument or 0 if the afterThis node
770 is not a child of this node, or if the node does not
771 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 */
773 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 /**
776 Delete all the children of this node.
777 */
778 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800779
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700780 /**
781 Delete a child of this node.
782 */
783 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800784
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700785 /**
786 Make a copy of this node, but not its children.
787 You may pass in a Document pointer that will be
788 the owner of the new Node. If the 'document' is
789 null, then the node returned will be allocated
790 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800791
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700792 Note: if called on a XMLDocument, this will return null.
793 */
794 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800795
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 /**
797 Test if 2 nodes are the same, but don't test children.
798 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800799
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 Note: if called on a XMLDocument, this will return false.
801 */
802 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800803
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600804 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700805 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600806 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800807
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600808 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
809 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700810 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800811
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800813
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700814 - http://www.saxproject.org/
815 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800816
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800818
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 An example of using Accept():
820 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600821 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 tinyxmlDoc.Accept( &printer );
823 const char* xmlcstr = printer.CStr();
824 @endverbatim
825 */
826 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800827
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700828 // internal
829 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800830
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800831protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700832 XMLNode( XMLDocument* );
833 virtual ~XMLNode();
834 XMLNode( const XMLNode& ); // not supported
835 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700836
Lee Thomason624d43f2012-10-12 10:58:48 -0700837 XMLDocument* _document;
838 XMLNode* _parent;
839 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800840
Lee Thomason624d43f2012-10-12 10:58:48 -0700841 XMLNode* _firstChild;
842 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800843
Lee Thomason624d43f2012-10-12 10:58:48 -0700844 XMLNode* _prev;
845 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800846
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800847private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700848 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800850};
851
852
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800853/** XML text.
854
855 Note that a text node can have child element nodes, for example:
856 @verbatim
857 <root>This is <b>bold</b></root>
858 @endverbatim
859
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700860 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800861 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 -0700862 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600863 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800864*/
PKEuS16ed47d2013-07-06 12:02:43 +0200865class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800866{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700867 friend class XMLBase;
868 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800869public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700870 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800871
Lee Thomason624d43f2012-10-12 10:58:48 -0700872 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700873 return this;
874 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700875 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 return this;
877 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800878
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700879 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700880 void SetCData( bool isCData ) {
881 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700882 }
883 /// Returns true if this is a CDATA text element.
884 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700885 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700886 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800887
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700888 char* ParseDeep( char*, StrPair* endTag );
889 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
890 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800891
Lee Thomason5492a1c2012-01-23 15:32:10 -0800892protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700893 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700894 virtual ~XMLText() {}
895 XMLText( const XMLText& ); // not supported
896 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800897
898private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700899 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800900};
901
902
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800903/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200904class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800905{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700906 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800907public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700908 virtual XMLComment* ToComment() {
909 return this;
910 }
911 virtual const XMLComment* ToComment() const {
912 return this;
913 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800914
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800916
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700917 char* ParseDeep( char*, StrPair* endTag );
918 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
919 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800920
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800921protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 XMLComment( XMLDocument* doc );
923 virtual ~XMLComment();
924 XMLComment( const XMLComment& ); // not supported
925 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800926
Lee Thomason3f57d272012-01-11 15:30:03 -0800927private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800928};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800929
930
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800931/** In correct XML the declaration is the first entry in the file.
932 @verbatim
933 <?xml version="1.0" standalone="yes"?>
934 @endverbatim
935
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600936 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800937 however.
938
939 The text of the declaration isn't interpreted. It is parsed
940 and written as a string.
941*/
PKEuS16ed47d2013-07-06 12:02:43 +0200942class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800943{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800945public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700946 virtual XMLDeclaration* ToDeclaration() {
947 return this;
948 }
949 virtual const XMLDeclaration* ToDeclaration() const {
950 return this;
951 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800952
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700953 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800954
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700955 char* ParseDeep( char*, StrPair* endTag );
956 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
957 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800958
959protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700960 XMLDeclaration( XMLDocument* doc );
961 virtual ~XMLDeclaration();
962 XMLDeclaration( const XMLDeclaration& ); // not supported
963 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800964};
965
966
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600967/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800968 unknown. It is a tag of text, but should not be modified.
969 It will be written back to the XML, unchanged, when the file
970 is saved.
971
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600972 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800973*/
PKEuS16ed47d2013-07-06 12:02:43 +0200974class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800975{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800977public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700978 virtual XMLUnknown* ToUnknown() {
979 return this;
980 }
981 virtual const XMLUnknown* ToUnknown() const {
982 return this;
983 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800984
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700985 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800986
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700987 char* ParseDeep( char*, StrPair* endTag );
988 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
989 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800990
991protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700992 XMLUnknown( XMLDocument* doc );
993 virtual ~XMLUnknown();
994 XMLUnknown( const XMLUnknown& ); // not supported
995 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800996};
997
998
Lee Thomason2fa81722012-11-09 12:37:46 -0800999enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001000 XML_NO_ERROR = 0,
1001 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001002
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001003 XML_NO_ATTRIBUTE,
1004 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001005
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001006 XML_ERROR_FILE_NOT_FOUND,
1007 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
1008 XML_ERROR_FILE_READ_ERROR,
1009 XML_ERROR_ELEMENT_MISMATCH,
1010 XML_ERROR_PARSING_ELEMENT,
1011 XML_ERROR_PARSING_ATTRIBUTE,
1012 XML_ERROR_IDENTIFYING_TAG,
1013 XML_ERROR_PARSING_TEXT,
1014 XML_ERROR_PARSING_CDATA,
1015 XML_ERROR_PARSING_COMMENT,
1016 XML_ERROR_PARSING_DECLARATION,
1017 XML_ERROR_PARSING_UNKNOWN,
1018 XML_ERROR_EMPTY_DOCUMENT,
1019 XML_ERROR_MISMATCHED_ELEMENT,
1020 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -07001021
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 XML_CAN_NOT_CONVERT_TEXT,
1023 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001024};
1025
1026
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001027/** An attribute is a name-value pair. Elements have an arbitrary
1028 number of attributes, each with a unique name.
1029
1030 @note The attributes are not XMLNodes. You may only query the
1031 Next() attribute in a list.
1032*/
PKEuS16ed47d2013-07-06 12:02:43 +02001033class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001034{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001035 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001036public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001037 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001038 const char* Name() const;
1039
Lee Thomason2fa81722012-11-09 12:37:46 -08001040 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001041 const char* Value() const;
1042
Lee Thomason2fa81722012-11-09 12:37:46 -08001043 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001044 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001045 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001046 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001047
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001048 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001049 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001050 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 */
1052 int IntValue() const {
1053 int i=0;
1054 QueryIntValue( &i );
1055 return i;
1056 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001057 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001058 unsigned UnsignedValue() const {
1059 unsigned i=0;
1060 QueryUnsignedValue( &i );
1061 return i;
1062 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001063 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001064 bool BoolValue() const {
1065 bool b=false;
1066 QueryBoolValue( &b );
1067 return b;
1068 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001069 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001070 double DoubleValue() const {
1071 double d=0;
1072 QueryDoubleValue( &d );
1073 return d;
1074 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001075 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001076 float FloatValue() const {
1077 float f=0;
1078 QueryFloatValue( &f );
1079 return f;
1080 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001081
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001082 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001083 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001084 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1085 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001086 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001087 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001088 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001089 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001090 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001091 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001092 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001093 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001094 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001096 /// Set the attribute to a string value.
1097 void SetAttribute( const char* value );
1098 /// Set the attribute to value.
1099 void SetAttribute( int value );
1100 /// Set the attribute to value.
1101 void SetAttribute( unsigned value );
1102 /// Set the attribute to value.
1103 void SetAttribute( bool value );
1104 /// Set the attribute to value.
1105 void SetAttribute( double value );
1106 /// Set the attribute to value.
1107 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001108
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001109private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001110 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001111
Thomas Roß61892312013-05-12 14:07:38 +02001112 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001113 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001114
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001115 XMLAttribute( const XMLAttribute& ); // not supported
1116 void operator=( const XMLAttribute& ); // not supported
1117 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001118
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001119 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001120
Lee Thomason624d43f2012-10-12 10:58:48 -07001121 mutable StrPair _name;
1122 mutable StrPair _value;
1123 XMLAttribute* _next;
1124 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001125};
1126
1127
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001128/** The element is a container class. It has a value, the element name,
1129 and can contain other elements, text, comments, and unknowns.
1130 Elements also contain an arbitrary number of attributes.
1131*/
PKEuS16ed47d2013-07-06 12:02:43 +02001132class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001133{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001134 friend class XMLBase;
1135 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001136public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001137 /// Get the name of an element (which is the Value() of the node.)
1138 const char* Name() const {
1139 return Value();
1140 }
1141 /// Set the name of the element.
1142 void SetName( const char* str, bool staticMem=false ) {
1143 SetValue( str, staticMem );
1144 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001145
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 virtual XMLElement* ToElement() {
1147 return this;
1148 }
1149 virtual const XMLElement* ToElement() const {
1150 return this;
1151 }
1152 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001153
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001154 /** Given an attribute name, Attribute() returns the value
1155 for the attribute of that name, or null if none
1156 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001157
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001158 @verbatim
1159 const char* value = ele->Attribute( "foo" );
1160 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001161
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001162 The 'value' parameter is normally null. However, if specified,
1163 the attribute will only be returned if the 'name' and 'value'
1164 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001165
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 @verbatim
1167 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1168 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001169
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001170 rather than:
1171 @verbatim
1172 if ( ele->Attribute( "foo" ) ) {
1173 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1174 }
1175 @endverbatim
1176 */
1177 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001178
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001179 /** Given an attribute name, IntAttribute() returns the value
1180 of the attribute interpreted as an integer. 0 will be
1181 returned if there is an error. For a method with error
1182 checking, see QueryIntAttribute()
1183 */
1184 int IntAttribute( const char* name ) const {
1185 int i=0;
1186 QueryIntAttribute( name, &i );
1187 return i;
1188 }
1189 /// See IntAttribute()
1190 unsigned UnsignedAttribute( const char* name ) const {
1191 unsigned i=0;
1192 QueryUnsignedAttribute( name, &i );
1193 return i;
1194 }
1195 /// See IntAttribute()
1196 bool BoolAttribute( const char* name ) const {
1197 bool b=false;
1198 QueryBoolAttribute( name, &b );
1199 return b;
1200 }
1201 /// See IntAttribute()
1202 double DoubleAttribute( const char* name ) const {
1203 double d=0;
1204 QueryDoubleAttribute( name, &d );
1205 return d;
1206 }
1207 /// See IntAttribute()
1208 float FloatAttribute( const char* name ) const {
1209 float f=0;
1210 QueryFloatAttribute( name, &f );
1211 return f;
1212 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001213
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 /** Given an attribute name, QueryIntAttribute() returns
1215 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1216 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1217 doesn't exist. If successful, the result of the conversion
1218 will be written to 'value'. If not successful, nothing will
1219 be written to 'value'. This allows you to provide default
1220 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001221
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 @verbatim
1223 int value = 10;
1224 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1225 @endverbatim
1226 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001227 XMLError QueryIntAttribute( const char* name, int* 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->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 }
1234 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001235 XMLError QueryUnsignedAttribute( const char* name, unsigned int* 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->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 }
1242 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001243 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 const XMLAttribute* a = FindAttribute( name );
1245 if ( !a ) {
1246 return XML_NO_ATTRIBUTE;
1247 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001248 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 }
1250 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001251 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 const XMLAttribute* a = FindAttribute( name );
1253 if ( !a ) {
1254 return XML_NO_ATTRIBUTE;
1255 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001256 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 }
1258 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001259 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 const XMLAttribute* a = FindAttribute( name );
1261 if ( !a ) {
1262 return XML_NO_ATTRIBUTE;
1263 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001264 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001265 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001266
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001267
1268 /** Given an attribute name, QueryAttribute() returns
1269 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1270 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1271 doesn't exist. It is overloaded for the primitive types,
1272 and is a generally more convenient replacement of
1273 QueryIntAttribute() and related functions.
1274
1275 If successful, the result of the conversion
1276 will be written to 'value'. If not successful, nothing will
1277 be written to 'value'. This allows you to provide default
1278 value:
1279
1280 @verbatim
1281 int value = 10;
1282 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1283 @endverbatim
1284 */
1285 int QueryAttribute( const char* name, int* value ) const {
1286 return QueryIntAttribute( name, value );
1287 }
1288
1289 int QueryAttribute( const char* name, unsigned int* value ) const {
1290 return QueryUnsignedAttribute( name, value );
1291 }
1292
1293 int QueryAttribute( const char* name, bool* value ) const {
1294 return QueryBoolAttribute( name, value );
1295 }
1296
1297 int QueryAttribute( const char* name, double* value ) const {
1298 return QueryDoubleAttribute( name, value );
1299 }
1300
1301 int QueryAttribute( const char* name, float* value ) const {
1302 return QueryFloatAttribute( name, value );
1303 }
1304
1305 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001306 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001308 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 }
1310 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001311 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001313 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 }
1315 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001316 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 }
1320 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001321 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001323 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 }
1325 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001326 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001328 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001330 /// Sets the named attribute to value.
1331 void SetAttribute( const char* name, float value ) {
1332 XMLAttribute* a = FindOrCreateAttribute( name );
1333 a->SetAttribute( value );
1334 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001335
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001336 /**
1337 Delete an attribute.
1338 */
1339 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001340
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 /// Return the first attribute in the list.
1342 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001343 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001344 }
1345 /// Query a specific attribute in the list.
1346 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001347
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001348 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001349 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001350 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001351
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001352 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001353 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001354
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001355 This is a convenient method for getting the text of simple contained text:
1356 @verbatim
1357 <foo>This is text</foo>
1358 const char* str = fooElement->GetText();
1359 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001360
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 Note that this function can be misleading. If the element foo was created from
1364 this XML:
1365 @verbatim
1366 <foo><b>This is text</b></foo>
1367 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001368
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001369 then the value of str would be null. The first child node isn't a text node, it is
1370 another element. From this XML:
1371 @verbatim
1372 <foo>This is <b>text</b></foo>
1373 @endverbatim
1374 GetText() will return "This is ".
1375 */
1376 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001377
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001378 /** Convenience function for easy access to the text inside an element. Although easy
1379 and concise, SetText() is limited compared to creating an XMLText child
1380 and mutating it directly.
1381
1382 If the first child of 'this' is a XMLText, SetText() sets its value to
1383 the given string, otherwise it will create a first child that is an XMLText.
1384
1385 This is a convenient method for setting the text of simple contained text:
1386 @verbatim
1387 <foo>This is text</foo>
1388 fooElement->SetText( "Hullaballoo!" );
1389 <foo>Hullaballoo!</foo>
1390 @endverbatim
1391
1392 Note that this function can be misleading. If the element foo was created from
1393 this XML:
1394 @verbatim
1395 <foo><b>This is text</b></foo>
1396 @endverbatim
1397
1398 then it will not change "This is text", but rather prefix it with a text element:
1399 @verbatim
1400 <foo>Hullaballoo!<b>This is text</b></foo>
1401 @endverbatim
1402
1403 For this XML:
1404 @verbatim
1405 <foo />
1406 @endverbatim
1407 SetText() will generate
1408 @verbatim
1409 <foo>Hullaballoo!</foo>
1410 @endverbatim
1411 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001412 void SetText( const char* inText );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001413 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001414 void SetText( int value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001415 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001416 void SetText( unsigned value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001417 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001418 void SetText( bool value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001419 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001420 void SetText( double value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001421 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001422 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001423
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 /**
1425 Convenience method to query the value of a child text node. This is probably best
1426 shown by example. Given you have a document is this form:
1427 @verbatim
1428 <point>
1429 <x>1</x>
1430 <y>1.4</y>
1431 </point>
1432 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001433
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 The QueryIntText() and similar functions provide a safe and easier way to get to the
1435 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001436
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001437 @verbatim
1438 int x = 0;
1439 float y = 0; // types of x and y are contrived for example
1440 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1441 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1442 xElement->QueryIntText( &x );
1443 yElement->QueryFloatText( &y );
1444 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001445
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1447 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 -07001448
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001449 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001450 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001451 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001452 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001454 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001455 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001456 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001457 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001458 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001459
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001460 // internal:
1461 enum {
1462 OPEN, // <foo>
1463 CLOSED, // <foo/>
1464 CLOSING // </foo>
1465 };
1466 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001467 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001468 }
1469 char* ParseDeep( char* p, StrPair* endTag );
1470 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1471 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001472
Lee Thomason50adb4c2012-02-13 15:07:09 -08001473private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001474 XMLElement( XMLDocument* doc );
1475 virtual ~XMLElement();
1476 XMLElement( const XMLElement& ); // not supported
1477 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001478
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001479 XMLAttribute* FindAttribute( const char* name );
1480 XMLAttribute* FindOrCreateAttribute( const char* name );
1481 //void LinkAttribute( XMLAttribute* attrib );
1482 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001483
Lee Thomason5bb2d802014-01-24 10:42:57 -08001484 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001485 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001486 // The attribute list is ordered; there is no 'lastAttribute'
1487 // because the list needs to be scanned for dupes before adding
1488 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001489 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001490};
1491
1492
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001493enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001494 PRESERVE_WHITESPACE,
1495 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001496};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001497
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001498
1499/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001500 It can be saved, loaded, and printed to the screen.
1501 All Nodes are connected and allocated to a Document.
1502 If the Document is deleted, all its Nodes are also deleted.
1503*/
PKEuS16ed47d2013-07-06 12:02:43 +02001504class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001505{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001506 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001507public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 /// constructor
1509 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1510 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001511
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001512 virtual XMLDocument* ToDocument() {
1513 return this;
1514 }
1515 virtual const XMLDocument* ToDocument() const {
1516 return this;
1517 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001518
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001519 /**
1520 Parse an XML file from a character string.
1521 Returns XML_NO_ERROR (0) on success, or
1522 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001523
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 You may optionally pass in the 'nBytes', which is
1525 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001526 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001527 null terminated string.
1528 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001529 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001530
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 /**
1532 Load an XML file from disk.
1533 Returns XML_NO_ERROR (0) on success, or
1534 an errorID.
1535 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001536 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001537
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001538 /**
1539 Load an XML file from disk. You are responsible
1540 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001541
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 Returns XML_NO_ERROR (0) on success, or
1543 an errorID.
1544 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001545 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001546
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001547 /**
1548 Save the XML file to disk.
1549 Returns XML_NO_ERROR (0) on success, or
1550 an errorID.
1551 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001552 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001553
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001554 /**
1555 Save the XML file to disk. You are responsible
1556 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001557
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001558 Returns XML_NO_ERROR (0) on success, or
1559 an errorID.
1560 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001561 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001562
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001563 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001564 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001565 }
1566 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001567 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001568 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001569
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001570 /**
1571 Returns true if this document has a leading Byte Order Mark of UTF8.
1572 */
1573 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001574 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001575 }
1576 /** Sets whether to write the BOM when writing the file.
1577 */
1578 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001579 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001581
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001582 /** Return the root element of DOM. Equivalent to FirstChildElement().
1583 To get the first node, use FirstChild().
1584 */
1585 XMLElement* RootElement() {
1586 return FirstChildElement();
1587 }
1588 const XMLElement* RootElement() const {
1589 return FirstChildElement();
1590 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001591
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 /** Print the Document. If the Printer is not provided, it will
1593 print to stdout. If you provide Printer, this can print to a file:
1594 @verbatim
1595 XMLPrinter printer( fp );
1596 doc.Print( &printer );
1597 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001598
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001599 Or you can use a printer to print to memory:
1600 @verbatim
1601 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001602 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 // printer.CStr() has a const char* to the XML
1604 @endverbatim
1605 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001606 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001608
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001609 /**
1610 Create a new Element associated with
1611 this Document. The memory for the Element
1612 is managed by the Document.
1613 */
1614 XMLElement* NewElement( const char* name );
1615 /**
1616 Create a new Comment associated with
1617 this Document. The memory for the Comment
1618 is managed by the Document.
1619 */
1620 XMLComment* NewComment( const char* comment );
1621 /**
1622 Create a new Text associated with
1623 this Document. The memory for the Text
1624 is managed by the Document.
1625 */
1626 XMLText* NewText( const char* text );
1627 /**
1628 Create a new Declaration associated with
1629 this Document. The memory for the object
1630 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001631
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001632 If the 'text' param is null, the standard
1633 declaration is used.:
1634 @verbatim
1635 <?xml version="1.0" encoding="UTF-8"?>
1636 @endverbatim
1637 */
1638 XMLDeclaration* NewDeclaration( const char* text=0 );
1639 /**
1640 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001641 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001642 is managed by the Document.
1643 */
1644 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001645
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 /**
1647 Delete a node associated with this document.
1648 It will be unlinked from the DOM.
1649 */
1650 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001651 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001652 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001653
Lee Thomason2fa81722012-11-09 12:37:46 -08001654 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001655
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001656 /// Return true if there was an error parsing the document.
1657 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001658 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 }
1660 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001661 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001662 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001663 }
1664 /// Return a possibly helpful diagnostic location or string.
1665 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001666 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 }
1668 /// Return a possibly helpful secondary diagnostic location or string.
1669 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001670 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 }
1672 /// If there is an error, print it to stdout.
1673 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001674
1675 /// Clear the document, resetting it to the initial state.
1676 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001677
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001678 // internal
1679 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001680
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1682 return 0;
1683 }
1684 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1685 return false;
1686 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001687
Lee Thomason3f57d272012-01-11 15:30:03 -08001688private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001689 XMLDocument( const XMLDocument& ); // not supported
1690 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001691
Lee Thomason2fa81722012-11-09 12:37:46 -08001692 bool _writeBOM;
1693 bool _processEntities;
1694 XMLError _errorID;
1695 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001696 const char* _errorStr1;
1697 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001698 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001699
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 MemPoolT< sizeof(XMLElement) > _elementPool;
1701 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1702 MemPoolT< sizeof(XMLText) > _textPool;
1703 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001704};
1705
Lee Thomason7c913cd2012-01-26 18:32:34 -08001706
Lee Thomason3ffdd392012-03-28 17:27:55 -07001707/**
1708 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001709 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001710 DOM structure. It is a separate utility class.
1711
1712 Take an example:
1713 @verbatim
1714 <Document>
1715 <Element attributeA = "valueA">
1716 <Child attributeB = "value1" />
1717 <Child attributeB = "value2" />
1718 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001719 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001720 @endverbatim
1721
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001722 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001723 easy to write a *lot* of code that looks like:
1724
1725 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001726 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001727 if ( root )
1728 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001729 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001730 if ( element )
1731 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001732 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001733 if ( child )
1734 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001735 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001736 if ( child2 )
1737 {
1738 // Finally do something useful.
1739 @endverbatim
1740
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001741 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001742 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001743 and correct to use:
1744
1745 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001746 XMLHandle docHandle( &document );
1747 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001748 if ( child2 )
1749 {
1750 // do something useful
1751 @endverbatim
1752
1753 Which is MUCH more concise and useful.
1754
1755 It is also safe to copy handles - internally they are nothing more than node pointers.
1756 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001757 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001758 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001759
1760 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001761*/
PKEuS16ed47d2013-07-06 12:02:43 +02001762class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001763{
1764public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 /// 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 -07001766 XMLHandle( XMLNode* node ) {
1767 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001768 }
1769 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001770 XMLHandle( XMLNode& node ) {
1771 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001772 }
1773 /// Copy constructor
1774 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001775 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001776 }
1777 /// Assignment
1778 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001779 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 return *this;
1781 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001782
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 /// Get the first child of this handle.
1784 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001785 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 }
1787 /// Get the first child element of this handle.
1788 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001789 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001790 }
1791 /// Get the last child of this handle.
1792 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001793 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001794 }
1795 /// Get the last child element of this handle.
1796 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001797 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001798 }
1799 /// Get the previous sibling of this handle.
1800 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001801 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 }
1803 /// Get the previous sibling element of this handle.
1804 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001805 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001806 }
1807 /// Get the next sibling of this handle.
1808 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001809 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001810 }
1811 /// Get the next sibling element of this handle.
1812 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001813 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001814 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001815
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 /// Safe cast to XMLNode. This can return null.
1817 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001818 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 }
1820 /// Safe cast to XMLElement. This can return null.
1821 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001822 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001823 }
1824 /// Safe cast to XMLText. This can return null.
1825 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001826 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001827 }
1828 /// Safe cast to XMLUnknown. This can return null.
1829 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001830 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001831 }
1832 /// Safe cast to XMLDeclaration. This can return null.
1833 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001834 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001835 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001836
1837private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001838 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001839};
1840
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001841
1842/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001843 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1844 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001845*/
PKEuS16ed47d2013-07-06 12:02:43 +02001846class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001847{
1848public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001849 XMLConstHandle( const XMLNode* node ) {
1850 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001851 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001852 XMLConstHandle( const XMLNode& node ) {
1853 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001854 }
1855 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001856 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001857 }
Lee Thomason8b899812012-04-04 15:58:16 -07001858
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001859 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001860 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001861 return *this;
1862 }
Lee Thomason8b899812012-04-04 15:58:16 -07001863
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001864 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 }
1867 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001868 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001869 }
1870 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001871 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 }
1873 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001874 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001875 }
1876 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001878 }
1879 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001880 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001881 }
1882 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001883 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 }
1885 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001886 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001887 }
Lee Thomason8b899812012-04-04 15:58:16 -07001888
1889
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001891 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 }
1893 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001894 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001895 }
1896 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001897 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001900 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001901 }
1902 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001903 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001904 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001905
Lee Thomason5cae8972012-01-24 18:03:07 -08001906private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001907 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001908};
Lee Thomason6f381b72012-03-02 12:59:39 -08001909
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001910
1911/**
1912 Printing functionality. The XMLPrinter gives you more
1913 options than the XMLDocument::Print() method.
1914
1915 It can:
1916 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001917 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001918 -# Print XML without a XMLDocument.
1919
1920 Print to Memory
1921
1922 @verbatim
1923 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001924 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001925 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001926 @endverbatim
1927
1928 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001929
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001930 You provide the file pointer.
1931 @verbatim
1932 XMLPrinter printer( fp );
1933 doc.Print( &printer );
1934 @endverbatim
1935
1936 Print without a XMLDocument
1937
1938 When loading, an XML parser is very useful. However, sometimes
1939 when saving, it just gets in the way. The code is often set up
1940 for streaming, and constructing the DOM is just overhead.
1941
1942 The Printer supports the streaming case. The following code
1943 prints out a trivially simple XML file without ever creating
1944 an XML document.
1945
1946 @verbatim
1947 XMLPrinter printer( fp );
1948 printer.OpenElement( "foo" );
1949 printer.PushAttribute( "foo", "bar" );
1950 printer.CloseElement();
1951 @endverbatim
1952*/
PKEuS16ed47d2013-07-06 12:02:43 +02001953class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001954{
1955public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001956 /** Construct the printer. If the FILE* is specified,
1957 this will print to the FILE. Else it will print
1958 to memory, and the result is available in CStr().
1959 If 'compact' is set to true, then output is created
1960 with only required whitespace and newlines.
1961 */
PKEuS1bfb9542013-08-04 13:51:17 +02001962 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001963 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001964
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001965 /** If streaming, write the BOM and declaration. */
1966 void PushHeader( bool writeBOM, bool writeDeclaration );
1967 /** If streaming, start writing an element.
1968 The element must be closed with CloseElement()
1969 */
Lee Thomason256adb62014-04-06 14:41:46 -07001970 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 /// If streaming, add an attribute to an open element.
1972 void PushAttribute( const char* name, const char* value );
1973 void PushAttribute( const char* name, int value );
1974 void PushAttribute( const char* name, unsigned value );
1975 void PushAttribute( const char* name, bool value );
1976 void PushAttribute( const char* name, double value );
1977 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07001978 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001979
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001980 /// Add a text node.
1981 void PushText( const char* text, bool cdata=false );
1982 /// Add a text node from an integer.
1983 void PushText( int value );
1984 /// Add a text node from an unsigned.
1985 void PushText( unsigned value );
1986 /// Add a text node from a bool.
1987 void PushText( bool value );
1988 /// Add a text node from a float.
1989 void PushText( float value );
1990 /// Add a text node from a double.
1991 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001992
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001993 /// Add a comment
1994 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001995
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 void PushDeclaration( const char* value );
1997 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001998
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001999 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2000 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2001 return true;
2002 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002003
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002004 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2005 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002006
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002007 virtual bool Visit( const XMLText& text );
2008 virtual bool Visit( const XMLComment& comment );
2009 virtual bool Visit( const XMLDeclaration& declaration );
2010 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002011
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002012 /**
2013 If in print to memory mode, return a pointer to
2014 the XML file in memory.
2015 */
2016 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002017 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002018 }
2019 /**
2020 If in print to memory mode, return the size
2021 of the XML file in memory. (Note the size returned
2022 includes the terminating null.)
2023 */
2024 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002025 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002026 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002027 /**
2028 If in print to memory mode, reset the buffer to the
2029 beginning.
2030 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002031 void ClearBuffer() {
2032 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002033 _buffer.Push(0);
2034 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002035
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002036protected:
Alexander Maid740b642014-05-20 22:04:42 +02002037 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002038
Lee Thomasonc18eb232014-02-21 17:31:17 -08002039 /** Prints out the space before an element. You may override to change
2040 the space and tabs used. A PrintSpace() override should call Print().
2041 */
2042 virtual void PrintSpace( int depth );
2043 void Print( const char* format, ... );
2044
2045 void SealElement();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002046 bool _elementJustOpened;
2047 DynArray< const char*, 10 > _stack;
2048
2049private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002050 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002051
Lee Thomason624d43f2012-10-12 10:58:48 -07002052 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002053 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002054 int _depth;
2055 int _textDepth;
2056 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002057 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002058
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002059 enum {
2060 ENTITY_RANGE = 64,
2061 BUF_SIZE = 200
2062 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002063 bool _entityFlag[ENTITY_RANGE];
2064 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002065
Lee Thomason624d43f2012-10-12 10:58:48 -07002066 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07002067#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07002068 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07002069#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002070};
2071
2072
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002073} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002074
PKEuS95060352013-07-26 10:42:44 +02002075#if defined(_MSC_VER)
2076# pragma warning(pop)
2077#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002078
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002079#endif // TINYXML2_INCLUDED