blob: 0c15ee8c6aabf54ba7b528ca8c3ae07f7571849b [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Anton Indrawanf59e2d62014-11-18 20:50:42 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
Lee Thomason51c12712016-06-04 20:18:49 -070033# include <stdint.h>
Lee Thomasona572db12016-06-04 19:16:24 -070034# if defined(__PS3__)
35# include <stddef.h>
36# endif
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070037#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070038# include <cctype>
39# include <climits>
40# include <cstdio>
41# include <cstdlib>
42# include <cstring>
Lee Thomason51c12712016-06-04 20:18:49 -070043# include <cstdint>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070044#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070045
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070046/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080047 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080048*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080049/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080051 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010052
Lee Thomasona9cf3f92012-10-11 16:56:51 -070053 Formatting, Artistic Style:
54 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080055*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080056
U-Lama\Lee4cee6112011-12-31 14:58:18 -080057#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070058# ifndef DEBUG
59# define DEBUG
60# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080061#endif
62
PKEuS95060352013-07-26 10:42:44 +020063#ifdef _MSC_VER
64# pragma warning(push)
65# pragma warning(disable: 4251)
66#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080067
PKEuS16ed47d2013-07-06 12:02:43 +020068#ifdef _WIN32
69# ifdef TINYXML2_EXPORT
70# define TINYXML2_LIB __declspec(dllexport)
71# elif defined(TINYXML2_IMPORT)
72# define TINYXML2_LIB __declspec(dllimport)
73# else
74# define TINYXML2_LIB
75# endif
76#else
77# define TINYXML2_LIB
78#endif
79
80
U-Lama\Lee4cee6112011-12-31 14:58:18 -080081#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070082# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030083# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070084# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070085# elif defined (ANDROID_NDK)
86# include <android/log.h>
87# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
88# else
89# include <assert.h>
90# define TIXMLASSERT assert
91# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070092#else
93# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080094#endif
95
U-Lama\Leee13c3e62011-12-28 14:36:55 -080096
Lee Thomasonc18eb232014-02-21 17:31:17 -080097/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080098 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -080099*/
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530100static const int TIXML2_MAJOR_VERSION = 3;
101static const int TIXML2_MINOR_VERSION = 0;
102static const int TIXML2_PATCH_VERSION = 0;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800103
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800104namespace tinyxml2
105{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800106class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800107class XMLElement;
108class XMLAttribute;
109class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800110class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800111class XMLDeclaration;
112class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800113class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800114
U-Stream\Leeae25a442012-02-17 17:48:16 -0800115/*
116 A class that wraps strings. Normally stores the start and end
117 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800118 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800119 manage) a traditional char[]
120*/
PKEuS95060352013-07-26 10:42:44 +0200121class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800122{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800123public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700124 enum {
125 NEEDS_ENTITY_PROCESSING = 0x01,
126 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300127 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800128
selfpoisede77e1952013-03-13 14:08:29 +0800129 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700130 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800131 ATTRIBUTE_NAME = 0,
132 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
133 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
134 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700135 };
Lee Thomason39ede242012-01-20 11:27:56 -0800136
Lee Thomason120b3a62012-10-12 10:06:59 -0700137 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700138 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700142 _start = start;
143 _end = end;
144 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700145 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700146
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700147 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700148
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700150 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700151 }
Lee Thomason39ede242012-01-20 11:27:56 -0800152
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700153 void SetInternedStr( const char* str ) {
154 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700155 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700157
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700158 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800159
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 char* ParseText( char* in, const char* endTag, int strFlags );
161 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800162
Lee Thomason29658802014-11-27 22:31:11 -0800163 void TransferTo( StrPair* other );
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300164
Lee Thomason39ede242012-01-20 11:27:56 -0800165private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 void Reset();
167 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800168
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700169 enum {
170 NEEDS_FLUSH = 0x100,
171 NEEDS_DELETE = 0x200
172 };
Lee Thomasone4422302012-01-20 17:59:50 -0800173
Lee Thomason120b3a62012-10-12 10:06:59 -0700174 int _flags;
175 char* _start;
176 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300177
178 StrPair( const StrPair& other ); // not supported
179 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800180};
181
U-Lama\Lee560bd472011-12-28 19:42:49 -0800182
U-Stream\Leeae25a442012-02-17 17:48:16 -0800183/*
184 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
185 Has a small initial memory pool, so that low or no usage will not
186 cause a call to new/delete
187*/
Dmitry-Me04009222015-04-06 18:07:18 +0300188template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200189class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800190{
191public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300192 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700193 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300194 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700195 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700196 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700197
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700198 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700199 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700200 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700201 }
202 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700203
Lee Thomasonce0510b2013-11-26 21:29:37 -0800204 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100205 _size = 0;
206 }
207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300209 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700210 EnsureCapacity( _size+1 );
211 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800213
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700214 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300215 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300216 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700217 EnsureCapacity( _size+count );
218 T* ret = &_mem[_size];
219 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700220 return ret;
221 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700222
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700223 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300224 TIXMLASSERT( _size > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 TIXMLASSERT( _size >= count );
230 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700236
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700237 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700238 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700239 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700244 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700246
Lee Thomasonf07b9522014-10-30 13:25:12 -0700247 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500248 TIXMLASSERT( _size > 0 );
249 return _mem[ _size - 1];
250 }
251
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300253 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700254 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700256
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300258 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700261
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300263 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700264 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700267 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300268 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700269 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800271
Lee Thomason2c85a712012-01-31 08:24:24 -0800272private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300273 DynArray( const DynArray& ); // not supported
274 void operator=( const DynArray& ); // not supported
275
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300277 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700278 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300279 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700280 int newAllocated = cap * 2;
281 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700282 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
283 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700284 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700286 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700287 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700288 }
289 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800290
Lee Thomason624d43f2012-10-12 10:58:48 -0700291 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300292 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700293 int _allocated; // objects allocated
294 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800295};
296
Lee Thomason50adb4c2012-02-13 15:07:09 -0800297
U-Stream\Leeae25a442012-02-17 17:48:16 -0800298/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200299 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800300 and deallocation of objects.
301*/
PKEuS95060352013-07-26 10:42:44 +0200302class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800303{
304public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700305 MemPool() {}
306 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800307
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700308 virtual int ItemSize() const = 0;
309 virtual void* Alloc() = 0;
310 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800311 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700312 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800313};
314
Lee Thomason50adb4c2012-02-13 15:07:09 -0800315
U-Stream\Leeae25a442012-02-17 17:48:16 -0800316/*
317 Template child class to create pools of the correct type.
318*/
Lee Thomasond1983222012-02-06 08:41:24 -0800319template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200320class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800321{
322public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800323 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700325 Clear();
326 }
327
328 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700329 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700330 while( !_blockPtrs.Empty()) {
331 Block* b = _blockPtrs.Pop();
332 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700334 _root = 0;
335 _currentAllocs = 0;
336 _nAllocs = 0;
337 _maxAllocs = 0;
338 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700339 }
Lee Thomasond1983222012-02-06 08:41:24 -0800340
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 virtual int ItemSize() const {
342 return SIZE;
343 }
344 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700345 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
Lee Thomasond1983222012-02-06 08:41:24 -0800347
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700349 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700350 // Need a new block.
351 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700352 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800353
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700354 for( int i=0; i<COUNT-1; ++i ) {
355 block->chunk[i].next = &block->chunk[i+1];
356 }
357 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700358 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700359 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700360 void* result = _root;
361 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800362
Lee Thomason624d43f2012-10-12 10:58:48 -0700363 ++_currentAllocs;
364 if ( _currentAllocs > _maxAllocs ) {
365 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700366 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700367 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800368 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 return result;
370 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700371
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700372 virtual void Free( void* mem ) {
373 if ( !mem ) {
374 return;
375 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700376 --_currentAllocs;
Dmitry-Me56571762014-08-15 11:03:47 +0400377 Chunk* chunk = static_cast<Chunk*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700378#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700379 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700380#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700381 chunk->next = _root;
382 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700383 }
384 void Trace( const char* name ) {
385 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700386 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700387 }
Lee Thomasond1983222012-02-06 08:41:24 -0800388
Lee Thomason5b0a6772012-11-19 13:54:42 -0800389 void SetTracked() {
390 _nUntracked--;
391 }
392
393 int Untracked() const {
394 return _nUntracked;
395 }
396
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800397 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
398 // The test file is large, 170k.
399 // Release: VS2010 gcc(no opt)
400 // 1k: 4000
401 // 2k: 4000
402 // 4k: 3900 21000
403 // 16k: 5200
404 // 32k: 4300
405 // 64k: 4000 21000
406 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 +0200407
Lee Thomasond1983222012-02-06 08:41:24 -0800408private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300409 MemPoolT( const MemPoolT& ); // not supported
410 void operator=( const MemPoolT& ); // not supported
411
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700412 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700413 Chunk* next;
414 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700415 };
416 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700417 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700418 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700419 DynArray< Block*, 10 > _blockPtrs;
420 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800421
Lee Thomason624d43f2012-10-12 10:58:48 -0700422 int _currentAllocs;
423 int _nAllocs;
424 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800425 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800426};
427
Lee Thomason2c85a712012-01-31 08:24:24 -0800428
Lee Thomason56bdd022012-02-09 18:16:58 -0800429
430/**
431 Implements the interface to the "Visitor pattern" (see the Accept() method.)
432 If you call the Accept() method, it requires being passed a XMLVisitor
433 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200434 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800435 are simply called with Visit().
436
437 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700438 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800439
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700440 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800441 visiting). You need to only override methods that are interesting to you.
442
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600443 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800444
445 You should never change the document from a callback.
446
447 @sa XMLNode::Accept()
448*/
PKEuS16ed47d2013-07-06 12:02:43 +0200449class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800450{
451public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700452 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800453
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700454 /// Visit a document.
455 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
456 return true;
457 }
458 /// Visit a document.
459 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
460 return true;
461 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800462
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700463 /// Visit an element.
464 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
465 return true;
466 }
467 /// Visit an element.
468 virtual bool VisitExit( const XMLElement& /*element*/ ) {
469 return true;
470 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800471
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700472 /// Visit a declaration.
473 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
474 return true;
475 }
476 /// Visit a text node.
477 virtual bool Visit( const XMLText& /*text*/ ) {
478 return true;
479 }
480 /// Visit a comment node.
481 virtual bool Visit( const XMLComment& /*comment*/ ) {
482 return true;
483 }
484 /// Visit an unknown node.
485 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
486 return true;
487 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800488};
489
Dmitry-Me66d2a842014-11-08 15:24:52 +0300490// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900491enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900492 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900493 XML_NO_ATTRIBUTE,
494 XML_WRONG_ATTRIBUTE_TYPE,
495 XML_ERROR_FILE_NOT_FOUND,
496 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
497 XML_ERROR_FILE_READ_ERROR,
498 XML_ERROR_ELEMENT_MISMATCH,
499 XML_ERROR_PARSING_ELEMENT,
500 XML_ERROR_PARSING_ATTRIBUTE,
501 XML_ERROR_IDENTIFYING_TAG,
502 XML_ERROR_PARSING_TEXT,
503 XML_ERROR_PARSING_CDATA,
504 XML_ERROR_PARSING_COMMENT,
505 XML_ERROR_PARSING_DECLARATION,
506 XML_ERROR_PARSING_UNKNOWN,
507 XML_ERROR_EMPTY_DOCUMENT,
508 XML_ERROR_MISMATCHED_ELEMENT,
509 XML_ERROR_PARSING,
510 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700511 XML_NO_TEXT_NODE,
512
513 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900514};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900515
numatrumpetcd8550c2014-09-08 16:59:39 +0900516
U-Stream\Leeae25a442012-02-17 17:48:16 -0800517/*
518 Utility functionality.
519*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800520class XMLUtil
521{
Lee Thomasond1983222012-02-06 08:41:24 -0800522public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700523 static const char* SkipWhiteSpace( const char* p ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300524 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300525 while( IsWhiteSpace(*p) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700526 ++p;
527 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300528 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700529 return p;
530 }
531 static char* SkipWhiteSpace( char* p ) {
Dmitry-Me9de541f2014-09-24 14:21:36 +0400532 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700533 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300534
535 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
536 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100538 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700539 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200540
541 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300542 if ( ch >= 128 ) {
543 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
544 return true;
545 }
546 if ( isalpha( ch ) ) {
547 return true;
548 }
549 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200550 }
551
552 inline static bool IsNameChar( unsigned char ch ) {
553 return IsNameStartChar( ch )
554 || isdigit( ch )
555 || ch == '.'
556 || ch == '-';
557 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800558
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700559 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700560 if ( p == q ) {
561 return true;
562 }
Lee Thomason598a88d2015-10-09 14:42:12 -0700563 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700564 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200565
Dmitry-Me7865aad2015-06-19 16:23:35 +0300566 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400567 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700568 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800569
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 static const char* ReadBOM( const char* p, bool* hasBOM );
571 // p is the starting location,
572 // the UTF-8 value of the entity will be placed in value, and length filled in.
573 static const char* GetCharacterRef( const char* p, char* value, int* length );
574 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700575
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 // converts primitive types to strings
577 static void ToStr( int v, char* buffer, int bufferSize );
578 static void ToStr( unsigned v, char* buffer, int bufferSize );
579 static void ToStr( bool v, char* buffer, int bufferSize );
580 static void ToStr( float v, char* buffer, int bufferSize );
581 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700582 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700583
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 // converts strings to primitive types
585 static bool ToInt( const char* str, int* value );
586 static bool ToUnsigned( const char* str, unsigned* value );
587 static bool ToBool( const char* str, bool* value );
588 static bool ToFloat( const char* str, float* value );
589 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700590 static bool ToInt64(const char* str, int64_t* value);
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800591};
592
Lee Thomason5cae8972012-01-24 18:03:07 -0800593
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800594/** XMLNode is a base class for every object that is in the
595 XML Document Object Model (DOM), except XMLAttributes.
596 Nodes have siblings, a parent, and children which can
597 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700598 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800599 be cast to its more defined type.
600
Thomas Roß08bdf502012-05-12 14:21:23 +0200601 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800602 When the XMLDocument gets deleted, all its Nodes
603 will also be deleted.
604
605 @verbatim
606 A Document can contain: Element (container or leaf)
607 Comment (leaf)
608 Unknown (leaf)
609 Declaration( leaf )
610
611 An Element can contain: Element (container or leaf)
612 Text (leaf)
613 Attributes (not on tree)
614 Comment (leaf)
615 Unknown (leaf)
616
617 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800618*/
PKEuS16ed47d2013-07-06 12:02:43 +0200619class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800620{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700621 friend class XMLDocument;
622 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800623public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800624
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700625 /// Get the XMLDocument that owns this XMLNode.
626 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300627 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700628 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 }
630 /// Get the XMLDocument that owns this XMLNode.
631 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300632 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700633 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800635
Lee Thomason2fa81722012-11-09 12:37:46 -0800636 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100638 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700639 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800640 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100642 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800644 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100646 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800648 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100650 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800652 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800656 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100658 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800660
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 virtual const XMLElement* ToElement() const {
662 return 0;
663 }
664 virtual const XMLText* ToText() const {
665 return 0;
666 }
667 virtual const XMLComment* ToComment() const {
668 return 0;
669 }
670 virtual const XMLDocument* ToDocument() const {
671 return 0;
672 }
673 virtual const XMLDeclaration* ToDeclaration() const {
674 return 0;
675 }
676 virtual const XMLUnknown* ToUnknown() const {
677 return 0;
678 }
Lee Thomason751da522012-02-10 08:50:51 -0800679
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 /** The meaning of 'value' changes for the specific type.
681 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530682 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 Element: name of the element
684 Comment: the comment text
685 Unknown: the tag contents
686 Text: the text string
687 @endverbatim
688 */
Michael Daumling21626882013-10-22 17:03:37 +0200689 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100690
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 /** Set the Value of an XML node.
692 @sa Value()
693 */
694 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800695
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 /// Get the parent of this node on the DOM.
697 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700698 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100700
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700702 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 }
Lee Thomason751da522012-02-10 08:50:51 -0800704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 /// Returns true if this node has no children.
706 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700707 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 }
Lee Thomason751da522012-02-10 08:50:51 -0800709
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 /// Get the first child node, or null if none exists.
711 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700712 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700716 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100718
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 /** Get the first child element, or optionally the first child
720 element with the specified name.
721 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300722 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700723
Dmitry-Me886ad972015-07-22 11:00:51 +0300724 XMLElement* FirstChildElement( const char* name = 0 ) {
725 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800727
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700728 /// Get the last child node, or null if none exists.
729 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700730 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700732
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300734 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 /** Get the last child element or optionally the last child
738 element with the specified name.
739 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300740 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700741
Dmitry-Me886ad972015-07-22 11:00:51 +0300742 XMLElement* LastChildElement( const char* name = 0 ) {
743 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700744 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700745
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700746 /// Get the previous (left) sibling node of this node.
747 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700748 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700750
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700752 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800754
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700755 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300756 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700757
Dmitry-Me886ad972015-07-22 11:00:51 +0300758 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
759 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700761
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 /// Get the next (right) sibling node of this node.
763 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700764 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700765 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700766
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700767 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700768 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700770
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700771 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300772 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700773
Dmitry-Me886ad972015-07-22 11:00:51 +0300774 XMLElement* NextSiblingElement( const char* name = 0 ) {
775 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700776 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800777
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700778 /**
779 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200780 If the child node is already part of the document,
781 it is moved from its old location to the new location.
782 Returns the addThis argument or 0 if the node does not
783 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 */
785 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800786
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700787 XMLNode* LinkEndChild( XMLNode* addThis ) {
788 return InsertEndChild( addThis );
789 }
790 /**
791 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200792 If the child node is already part of the document,
793 it is moved from its old location to the new location.
794 Returns the addThis argument or 0 if the node does not
795 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 */
797 XMLNode* InsertFirstChild( XMLNode* addThis );
798 /**
799 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200800 If the child node is already part of the document,
801 it is moved from its old location to the new location.
802 Returns the addThis argument or 0 if the afterThis node
803 is not a child of this node, or if the node does not
804 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700805 */
806 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700807
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700808 /**
809 Delete all the children of this node.
810 */
811 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800812
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700813 /**
814 Delete a child of this node.
815 */
816 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800817
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700818 /**
819 Make a copy of this node, but not its children.
820 You may pass in a Document pointer that will be
821 the owner of the new Node. If the 'document' is
822 null, then the node returned will be allocated
823 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800824
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 Note: if called on a XMLDocument, this will return null.
826 */
827 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800828
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700829 /**
830 Test if 2 nodes are the same, but don't test children.
831 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800832
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700833 Note: if called on a XMLDocument, this will return false.
834 */
835 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800836
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600837 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700838 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600839 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800840
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600841 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
842 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700843 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800844
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700845 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800846
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 - http://www.saxproject.org/
848 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800849
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700850 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800851
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 An example of using Accept():
853 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600854 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 tinyxmlDoc.Accept( &printer );
856 const char* xmlcstr = printer.CStr();
857 @endverbatim
858 */
859 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800860
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800861protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700862 XMLNode( XMLDocument* );
863 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700864
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300865 virtual char* ParseDeep( char*, StrPair* );
866
Lee Thomason624d43f2012-10-12 10:58:48 -0700867 XMLDocument* _document;
868 XMLNode* _parent;
869 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800870
Lee Thomason624d43f2012-10-12 10:58:48 -0700871 XMLNode* _firstChild;
872 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800873
Lee Thomason624d43f2012-10-12 10:58:48 -0700874 XMLNode* _prev;
875 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800876
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800877private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700878 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700879 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400880 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800881 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300882
883 XMLNode( const XMLNode& ); // not supported
884 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800885};
886
887
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800888/** XML text.
889
890 Note that a text node can have child element nodes, for example:
891 @verbatim
892 <root>This is <b>bold</b></root>
893 @endverbatim
894
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700895 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800896 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 -0700897 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600898 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800899*/
PKEuS16ed47d2013-07-06 12:02:43 +0200900class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800901{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700902 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800903public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700904 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800905
Lee Thomason624d43f2012-10-12 10:58:48 -0700906 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700907 return this;
908 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700909 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700910 return this;
911 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800912
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700913 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700914 void SetCData( bool isCData ) {
915 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700916 }
917 /// Returns true if this is a CDATA text element.
918 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700919 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700920 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800921
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
923 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800924
Lee Thomason5492a1c2012-01-23 15:32:10 -0800925protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700926 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700927 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800928
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300929 char* ParseDeep( char*, StrPair* endTag );
930
Lee Thomason5492a1c2012-01-23 15:32:10 -0800931private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700932 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300933
934 XMLText( const XMLText& ); // not supported
935 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800936};
937
938
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800939/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200940class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800941{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700942 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800943public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 virtual XMLComment* ToComment() {
945 return this;
946 }
947 virtual const XMLComment* ToComment() const {
948 return this;
949 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800950
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700951 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800952
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700953 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
954 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800955
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800956protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700957 XMLComment( XMLDocument* doc );
958 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800959
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300960 char* ParseDeep( char*, StrPair* endTag );
961
Lee Thomason3f57d272012-01-11 15:30:03 -0800962private:
Dmitry-Mef547a992015-01-09 15:17:09 +0300963 XMLComment( const XMLComment& ); // not supported
964 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800965};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800966
967
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800968/** In correct XML the declaration is the first entry in the file.
969 @verbatim
970 <?xml version="1.0" standalone="yes"?>
971 @endverbatim
972
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600973 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800974 however.
975
976 The text of the declaration isn't interpreted. It is parsed
977 and written as a string.
978*/
PKEuS16ed47d2013-07-06 12:02:43 +0200979class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800980{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700981 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800982public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 virtual XMLDeclaration* ToDeclaration() {
984 return this;
985 }
986 virtual const XMLDeclaration* ToDeclaration() const {
987 return this;
988 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800989
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700990 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800991
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700992 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
993 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800994
995protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700996 XMLDeclaration( XMLDocument* doc );
997 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +0300998
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300999 char* ParseDeep( char*, StrPair* endTag );
1000
Dmitry-Mef547a992015-01-09 15:17:09 +03001001private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001002 XMLDeclaration( const XMLDeclaration& ); // not supported
1003 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001004};
1005
1006
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001007/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001008 unknown. It is a tag of text, but should not be modified.
1009 It will be written back to the XML, unchanged, when the file
1010 is saved.
1011
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001012 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001013*/
PKEuS16ed47d2013-07-06 12:02:43 +02001014class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001015{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001017public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 virtual XMLUnknown* ToUnknown() {
1019 return this;
1020 }
1021 virtual const XMLUnknown* ToUnknown() const {
1022 return this;
1023 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001024
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001026
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001027 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1028 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001029
1030protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001031 XMLUnknown( XMLDocument* doc );
1032 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001033
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001034 char* ParseDeep( char*, StrPair* endTag );
1035
Dmitry-Mef547a992015-01-09 15:17:09 +03001036private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001037 XMLUnknown( const XMLUnknown& ); // not supported
1038 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001039};
1040
1041
Lee Thomason1ff38e02012-02-14 18:18:16 -08001042
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001043/** An attribute is a name-value pair. Elements have an arbitrary
1044 number of attributes, each with a unique name.
1045
1046 @note The attributes are not XMLNodes. You may only query the
1047 Next() attribute in a list.
1048*/
PKEuS16ed47d2013-07-06 12:02:43 +02001049class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001050{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001052public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001053 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001054 const char* Name() const;
1055
Lee Thomason2fa81722012-11-09 12:37:46 -08001056 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001057 const char* Value() const;
1058
Lee Thomason2fa81722012-11-09 12:37:46 -08001059 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001060 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001061 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001062 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001063
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001064 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001065 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001067 */
Lee Thomason51c12712016-06-04 20:18:49 -07001068 int IntValue() const {
1069 int i = 0;
1070 QueryIntValue(&i);
1071 return i;
1072 }
1073
1074 int64_t Int64Value() const {
1075 int64_t i = 0;
1076 QueryInt64Value(&i);
1077 return i;
1078 }
1079
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001080 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001081 unsigned UnsignedValue() const {
1082 unsigned i=0;
1083 QueryUnsignedValue( &i );
1084 return i;
1085 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001086 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 bool BoolValue() const {
1088 bool b=false;
1089 QueryBoolValue( &b );
1090 return b;
1091 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001092 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 double DoubleValue() const {
1094 double d=0;
1095 QueryDoubleValue( &d );
1096 return d;
1097 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001098 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001099 float FloatValue() const {
1100 float f=0;
1101 QueryFloatValue( &f );
1102 return f;
1103 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001104
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001105 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001106 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1108 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001109 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001110 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001111 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001112 /// See QueryIntValue
1113 XMLError QueryInt64Value(int64_t* value) const;
1114 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001115 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001116 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001117 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001118 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001119 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001120
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001121 /// Set the attribute to a string value.
1122 void SetAttribute( const char* value );
1123 /// Set the attribute to value.
1124 void SetAttribute( int value );
1125 /// Set the attribute to value.
1126 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001127 /// Set the attribute to value.
1128 void SetAttribute(int64_t value);
1129 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001130 void SetAttribute( bool value );
1131 /// Set the attribute to value.
1132 void SetAttribute( double value );
1133 /// Set the attribute to value.
1134 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001135
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001136private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001137 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001138
Thomas Roß61892312013-05-12 14:07:38 +02001139 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001140 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001141
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001142 XMLAttribute( const XMLAttribute& ); // not supported
1143 void operator=( const XMLAttribute& ); // not supported
1144 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001145
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001147
Lee Thomason624d43f2012-10-12 10:58:48 -07001148 mutable StrPair _name;
1149 mutable StrPair _value;
1150 XMLAttribute* _next;
1151 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001152};
1153
1154
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001155/** The element is a container class. It has a value, the element name,
1156 and can contain other elements, text, comments, and unknowns.
1157 Elements also contain an arbitrary number of attributes.
1158*/
PKEuS16ed47d2013-07-06 12:02:43 +02001159class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001160{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001161 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001162public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001163 /// Get the name of an element (which is the Value() of the node.)
1164 const char* Name() const {
1165 return Value();
1166 }
1167 /// Set the name of the element.
1168 void SetName( const char* str, bool staticMem=false ) {
1169 SetValue( str, staticMem );
1170 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001171
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001172 virtual XMLElement* ToElement() {
1173 return this;
1174 }
1175 virtual const XMLElement* ToElement() const {
1176 return this;
1177 }
1178 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001179
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001180 /** Given an attribute name, Attribute() returns the value
1181 for the attribute of that name, or null if none
1182 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001183
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001184 @verbatim
1185 const char* value = ele->Attribute( "foo" );
1186 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001187
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001188 The 'value' parameter is normally null. However, if specified,
1189 the attribute will only be returned if the 'name' and 'value'
1190 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001191
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 @verbatim
1193 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1194 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001195
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001196 rather than:
1197 @verbatim
1198 if ( ele->Attribute( "foo" ) ) {
1199 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1200 }
1201 @endverbatim
1202 */
1203 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001204
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001205 /** Given an attribute name, IntAttribute() returns the value
1206 of the attribute interpreted as an integer. 0 will be
1207 returned if there is an error. For a method with error
1208 checking, see QueryIntAttribute()
1209 */
1210 int IntAttribute( const char* name ) const {
1211 int i=0;
1212 QueryIntAttribute( name, &i );
1213 return i;
1214 }
Lee Thomason51c12712016-06-04 20:18:49 -07001215
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 /// See IntAttribute()
1217 unsigned UnsignedAttribute( const char* name ) const {
1218 unsigned i=0;
1219 QueryUnsignedAttribute( name, &i );
1220 return i;
1221 }
Lee Thomason51c12712016-06-04 20:18:49 -07001222
1223 /// See IntAttribute()
1224 int64_t Int64Attribute(const char* name) const {
1225 int64_t i = 0;
1226 QueryInt64Attribute(name, &i);
1227 return i;
1228 }
1229
1230 /// See IntAttribute()
1231 bool BoolAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 bool b=false;
1233 QueryBoolAttribute( name, &b );
1234 return b;
1235 }
1236 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001237 double DoubleAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 double d=0;
1239 QueryDoubleAttribute( name, &d );
1240 return d;
1241 }
1242 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001243 float FloatAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 float f=0;
1245 QueryFloatAttribute( name, &f );
1246 return f;
1247 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001248
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 /** Given an attribute name, QueryIntAttribute() returns
1250 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1251 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1252 doesn't exist. If successful, the result of the conversion
1253 will be written to 'value'. If not successful, nothing will
1254 be written to 'value'. This allows you to provide default
1255 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001256
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 @verbatim
1258 int value = 10;
1259 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1260 @endverbatim
1261 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001262 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001263 const XMLAttribute* a = FindAttribute( name );
1264 if ( !a ) {
1265 return XML_NO_ATTRIBUTE;
1266 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001267 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001268 }
Lee Thomason51c12712016-06-04 20:18:49 -07001269
1270 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001271 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001272 const XMLAttribute* a = FindAttribute( name );
1273 if ( !a ) {
1274 return XML_NO_ATTRIBUTE;
1275 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001276 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001277 }
Lee Thomason51c12712016-06-04 20:18:49 -07001278
1279 /// See QueryIntAttribute()
1280 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1281 const XMLAttribute* a = FindAttribute(name);
1282 if (!a) {
1283 return XML_NO_ATTRIBUTE;
1284 }
1285 return a->QueryInt64Value(value);
1286 }
1287
1288 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001289 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 const XMLAttribute* a = FindAttribute( name );
1291 if ( !a ) {
1292 return XML_NO_ATTRIBUTE;
1293 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001294 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 }
1296 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001297 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001298 const XMLAttribute* a = FindAttribute( name );
1299 if ( !a ) {
1300 return XML_NO_ATTRIBUTE;
1301 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001302 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 }
1304 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001305 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 const XMLAttribute* a = FindAttribute( name );
1307 if ( !a ) {
1308 return XML_NO_ATTRIBUTE;
1309 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001310 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001312
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001313
1314 /** Given an attribute name, QueryAttribute() returns
1315 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1316 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1317 doesn't exist. It is overloaded for the primitive types,
1318 and is a generally more convenient replacement of
1319 QueryIntAttribute() and related functions.
1320
1321 If successful, the result of the conversion
1322 will be written to 'value'. If not successful, nothing will
1323 be written to 'value'. This allows you to provide default
1324 value:
1325
1326 @verbatim
1327 int value = 10;
1328 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1329 @endverbatim
1330 */
1331 int QueryAttribute( const char* name, int* value ) const {
1332 return QueryIntAttribute( name, value );
1333 }
1334
1335 int QueryAttribute( const char* name, unsigned int* value ) const {
1336 return QueryUnsignedAttribute( name, value );
1337 }
1338
Lee Thomason51c12712016-06-04 20:18:49 -07001339 int QueryAttribute(const char* name, int64_t* value) const {
1340 return QueryInt64Attribute(name, value);
1341 }
1342
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001343 int QueryAttribute( const char* name, bool* value ) const {
1344 return QueryBoolAttribute( name, value );
1345 }
1346
1347 int QueryAttribute( const char* name, double* value ) const {
1348 return QueryDoubleAttribute( name, value );
1349 }
1350
1351 int QueryAttribute( const char* name, float* value ) const {
1352 return QueryFloatAttribute( name, value );
1353 }
1354
1355 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001356 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001357 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001358 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 }
1360 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001361 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001362 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001363 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 }
1365 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001366 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001367 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001368 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001369 }
Lee Thomason51c12712016-06-04 20:18:49 -07001370
1371 /// Sets the named attribute to value.
1372 void SetAttribute(const char* name, int64_t value) {
1373 XMLAttribute* a = FindOrCreateAttribute(name);
1374 a->SetAttribute(value);
1375 }
1376
1377 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001378 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001380 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 }
1382 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001383 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001385 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001387 /// Sets the named attribute to value.
1388 void SetAttribute( const char* name, float value ) {
1389 XMLAttribute* a = FindOrCreateAttribute( name );
1390 a->SetAttribute( value );
1391 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001392
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001393 /**
1394 Delete an attribute.
1395 */
1396 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001397
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001398 /// Return the first attribute in the list.
1399 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 }
1402 /// Query a specific attribute in the list.
1403 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001404
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001406 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001408
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001409 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001410 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001411
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001412 This is a convenient method for getting the text of simple contained text:
1413 @verbatim
1414 <foo>This is text</foo>
1415 const char* str = fooElement->GetText();
1416 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001417
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001419
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 Note that this function can be misleading. If the element foo was created from
1421 this XML:
1422 @verbatim
1423 <foo><b>This is text</b></foo>
1424 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001425
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001426 then the value of str would be null. The first child node isn't a text node, it is
1427 another element. From this XML:
1428 @verbatim
1429 <foo>This is <b>text</b></foo>
1430 @endverbatim
1431 GetText() will return "This is ".
1432 */
1433 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001434
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001435 /** Convenience function for easy access to the text inside an element. Although easy
1436 and concise, SetText() is limited compared to creating an XMLText child
1437 and mutating it directly.
1438
1439 If the first child of 'this' is a XMLText, SetText() sets its value to
1440 the given string, otherwise it will create a first child that is an XMLText.
1441
1442 This is a convenient method for setting the text of simple contained text:
1443 @verbatim
1444 <foo>This is text</foo>
1445 fooElement->SetText( "Hullaballoo!" );
1446 <foo>Hullaballoo!</foo>
1447 @endverbatim
1448
1449 Note that this function can be misleading. If the element foo was created from
1450 this XML:
1451 @verbatim
1452 <foo><b>This is text</b></foo>
1453 @endverbatim
1454
1455 then it will not change "This is text", but rather prefix it with a text element:
1456 @verbatim
1457 <foo>Hullaballoo!<b>This is text</b></foo>
1458 @endverbatim
1459
1460 For this XML:
1461 @verbatim
1462 <foo />
1463 @endverbatim
1464 SetText() will generate
1465 @verbatim
1466 <foo>Hullaballoo!</foo>
1467 @endverbatim
1468 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001469 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001470 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001471 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001472 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001473 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001474 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1475 void SetText(int64_t value);
1476 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001477 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001478 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001479 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001480 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001481 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001482
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 /**
1484 Convenience method to query the value of a child text node. This is probably best
1485 shown by example. Given you have a document is this form:
1486 @verbatim
1487 <point>
1488 <x>1</x>
1489 <y>1.4</y>
1490 </point>
1491 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001492
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001493 The QueryIntText() and similar functions provide a safe and easier way to get to the
1494 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001495
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 @verbatim
1497 int x = 0;
1498 float y = 0; // types of x and y are contrived for example
1499 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1500 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1501 xElement->QueryIntText( &x );
1502 yElement->QueryFloatText( &y );
1503 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001504
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1506 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 -07001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001509 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001510 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001511 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001512 /// See QueryIntText()
1513 XMLError QueryInt64Text(int64_t* uval) const;
1514 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001515 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001516 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001517 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001518 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001519 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001520
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001521 // internal:
1522 enum {
1523 OPEN, // <foo>
1524 CLOSED, // <foo/>
1525 CLOSING // </foo>
1526 };
1527 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001528 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001529 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1531 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001532
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001533protected:
1534 char* ParseDeep( char* p, StrPair* endTag );
1535
Lee Thomason50adb4c2012-02-13 15:07:09 -08001536private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001537 XMLElement( XMLDocument* doc );
1538 virtual ~XMLElement();
1539 XMLElement( const XMLElement& ); // not supported
1540 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001541
Dmitry-Me1227d512014-12-05 13:41:45 +03001542 XMLAttribute* FindAttribute( const char* name ) {
1543 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1544 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001545 XMLAttribute* FindOrCreateAttribute( const char* name );
1546 //void LinkAttribute( XMLAttribute* attrib );
1547 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001548 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001549
Lee Thomason5bb2d802014-01-24 10:42:57 -08001550 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001551 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001552 // The attribute list is ordered; there is no 'lastAttribute'
1553 // because the list needs to be scanned for dupes before adding
1554 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001555 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001556};
1557
1558
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001559enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001560 PRESERVE_WHITESPACE,
1561 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001562};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001563
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001564
1565/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001566 It can be saved, loaded, and printed to the screen.
1567 All Nodes are connected and allocated to a Document.
1568 If the Document is deleted, all its Nodes are also deleted.
1569*/
PKEuS16ed47d2013-07-06 12:02:43 +02001570class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001571{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001572 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001573public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001574 /// constructor
1575 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1576 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001577
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001578 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001579 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 return this;
1581 }
1582 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001583 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 return this;
1585 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001586
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001587 /**
1588 Parse an XML file from a character string.
1589 Returns XML_NO_ERROR (0) on success, or
1590 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001591
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 You may optionally pass in the 'nBytes', which is
1593 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001594 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001595 null terminated string.
1596 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001597 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001598
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001599 /**
1600 Load an XML file from disk.
1601 Returns XML_NO_ERROR (0) on success, or
1602 an errorID.
1603 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001604 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001605
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 /**
1607 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001608 for providing and closing the FILE*.
1609
1610 NOTE: The file should be opened as binary ("rb")
1611 not text in order for TinyXML-2 to correctly
1612 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001613
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 Returns XML_NO_ERROR (0) on success, or
1615 an errorID.
1616 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001617 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001618
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 /**
1620 Save the XML file to disk.
1621 Returns XML_NO_ERROR (0) on success, or
1622 an errorID.
1623 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001624 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001625
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 /**
1627 Save the XML file to disk. You are responsible
1628 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001629
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001630 Returns XML_NO_ERROR (0) on success, or
1631 an errorID.
1632 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001633 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001634
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001635 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001636 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001637 }
1638 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001639 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001641
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001642 /**
1643 Returns true if this document has a leading Byte Order Mark of UTF8.
1644 */
1645 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001646 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 }
1648 /** Sets whether to write the BOM when writing the file.
1649 */
1650 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001651 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001652 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001653
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 /** Return the root element of DOM. Equivalent to FirstChildElement().
1655 To get the first node, use FirstChild().
1656 */
1657 XMLElement* RootElement() {
1658 return FirstChildElement();
1659 }
1660 const XMLElement* RootElement() const {
1661 return FirstChildElement();
1662 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001663
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 /** Print the Document. If the Printer is not provided, it will
1665 print to stdout. If you provide Printer, this can print to a file:
1666 @verbatim
1667 XMLPrinter printer( fp );
1668 doc.Print( &printer );
1669 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001670
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 Or you can use a printer to print to memory:
1672 @verbatim
1673 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001674 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001675 // printer.CStr() has a const char* to the XML
1676 @endverbatim
1677 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001678 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001679 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001680
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 /**
1682 Create a new Element associated with
1683 this Document. The memory for the Element
1684 is managed by the Document.
1685 */
1686 XMLElement* NewElement( const char* name );
1687 /**
1688 Create a new Comment associated with
1689 this Document. The memory for the Comment
1690 is managed by the Document.
1691 */
1692 XMLComment* NewComment( const char* comment );
1693 /**
1694 Create a new Text associated with
1695 this Document. The memory for the Text
1696 is managed by the Document.
1697 */
1698 XMLText* NewText( const char* text );
1699 /**
1700 Create a new Declaration associated with
1701 this Document. The memory for the object
1702 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001703
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001704 If the 'text' param is null, the standard
1705 declaration is used.:
1706 @verbatim
1707 <?xml version="1.0" encoding="UTF-8"?>
1708 @endverbatim
1709 */
1710 XMLDeclaration* NewDeclaration( const char* text=0 );
1711 /**
1712 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001713 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 is managed by the Document.
1715 */
1716 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001717
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 /**
1719 Delete a node associated with this document.
1720 It will be unlinked from the DOM.
1721 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001722 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001723
Lee Thomason2fa81722012-11-09 12:37:46 -08001724 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001725
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 /// Return true if there was an error parsing the document.
1727 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001728 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001729 }
1730 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001731 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001732 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001733 }
Lee Thomason331596e2014-09-11 14:56:43 -07001734 const char* ErrorName() const;
1735
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 /// Return a possibly helpful diagnostic location or string.
1737 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
1740 /// Return a possibly helpful secondary diagnostic location or string.
1741 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
1744 /// If there is an error, print it to stdout.
1745 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001746
1747 /// Clear the document, resetting it to the initial state.
1748 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001749
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001750 // internal
1751 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001752
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1754 return 0;
1755 }
1756 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1757 return false;
1758 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001759
Lee Thomason3f57d272012-01-11 15:30:03 -08001760private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001761 XMLDocument( const XMLDocument& ); // not supported
1762 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001763
Lee Thomason2fa81722012-11-09 12:37:46 -08001764 bool _writeBOM;
1765 bool _processEntities;
1766 XMLError _errorID;
1767 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001768 const char* _errorStr1;
1769 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001770 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001771
Lee Thomason624d43f2012-10-12 10:58:48 -07001772 MemPoolT< sizeof(XMLElement) > _elementPool;
1773 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1774 MemPoolT< sizeof(XMLText) > _textPool;
1775 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001776
1777 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001778
1779 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001780};
1781
Lee Thomason7c913cd2012-01-26 18:32:34 -08001782
Lee Thomason3ffdd392012-03-28 17:27:55 -07001783/**
1784 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001785 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001786 DOM structure. It is a separate utility class.
1787
1788 Take an example:
1789 @verbatim
1790 <Document>
1791 <Element attributeA = "valueA">
1792 <Child attributeB = "value1" />
1793 <Child attributeB = "value2" />
1794 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001795 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001796 @endverbatim
1797
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001798 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001799 easy to write a *lot* of code that looks like:
1800
1801 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001802 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001803 if ( root )
1804 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001805 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001806 if ( element )
1807 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001808 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001809 if ( child )
1810 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001811 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001812 if ( child2 )
1813 {
1814 // Finally do something useful.
1815 @endverbatim
1816
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001817 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001818 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001819 and correct to use:
1820
1821 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001822 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001823 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001824 if ( child2 )
1825 {
1826 // do something useful
1827 @endverbatim
1828
1829 Which is MUCH more concise and useful.
1830
1831 It is also safe to copy handles - internally they are nothing more than node pointers.
1832 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001833 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001834 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001835
1836 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001837*/
PKEuS16ed47d2013-07-06 12:02:43 +02001838class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001839{
1840public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001841 /// 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 -07001842 XMLHandle( XMLNode* node ) {
1843 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001844 }
1845 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001846 XMLHandle( XMLNode& node ) {
1847 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001848 }
1849 /// Copy constructor
1850 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001851 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001852 }
1853 /// Assignment
1854 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001855 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001856 return *this;
1857 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001858
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001859 /// Get the first child of this handle.
1860 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001861 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001862 }
1863 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001864 XMLHandle FirstChildElement( const char* name = 0 ) {
1865 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 }
1867 /// Get the last child of this handle.
1868 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001869 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001870 }
1871 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001872 XMLHandle LastChildElement( const char* name = 0 ) {
1873 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001874 }
1875 /// Get the previous sibling of this handle.
1876 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001878 }
1879 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001880 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1881 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 }
1883 /// Get the next sibling of this handle.
1884 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001885 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001886 }
1887 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001888 XMLHandle NextSiblingElement( const char* name = 0 ) {
1889 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001891
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 /// Safe cast to XMLNode. This can return null.
1893 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001894 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001895 }
1896 /// Safe cast to XMLElement. This can return null.
1897 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001898 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001899 }
1900 /// Safe cast to XMLText. This can return null.
1901 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001902 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001903 }
1904 /// Safe cast to XMLUnknown. This can return null.
1905 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001906 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001907 }
1908 /// Safe cast to XMLDeclaration. This can return null.
1909 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001910 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001911 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001912
1913private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001914 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001915};
1916
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001917
1918/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001919 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1920 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001921*/
PKEuS16ed47d2013-07-06 12:02:43 +02001922class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001923{
1924public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001925 XMLConstHandle( const XMLNode* node ) {
1926 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001927 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001928 XMLConstHandle( const XMLNode& node ) {
1929 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001930 }
1931 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001932 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 }
Lee Thomason8b899812012-04-04 15:58:16 -07001934
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001935 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001936 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 return *this;
1938 }
Lee Thomason8b899812012-04-04 15:58:16 -07001939
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001940 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001941 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001942 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001943 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1944 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001945 }
1946 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001947 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001948 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001949 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1950 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001951 }
1952 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001953 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001954 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001955 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1956 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001957 }
1958 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001959 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001960 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001961 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1962 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001963 }
Lee Thomason8b899812012-04-04 15:58:16 -07001964
1965
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001966 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001967 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001968 }
1969 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001970 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 }
1972 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001973 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001974 }
1975 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001976 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001977 }
1978 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001979 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001980 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001981
Lee Thomason5cae8972012-01-24 18:03:07 -08001982private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001983 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001984};
Lee Thomason6f381b72012-03-02 12:59:39 -08001985
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001986
1987/**
1988 Printing functionality. The XMLPrinter gives you more
1989 options than the XMLDocument::Print() method.
1990
1991 It can:
1992 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001993 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001994 -# Print XML without a XMLDocument.
1995
1996 Print to Memory
1997
1998 @verbatim
1999 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002000 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002001 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002002 @endverbatim
2003
2004 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002005
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002006 You provide the file pointer.
2007 @verbatim
2008 XMLPrinter printer( fp );
2009 doc.Print( &printer );
2010 @endverbatim
2011
2012 Print without a XMLDocument
2013
2014 When loading, an XML parser is very useful. However, sometimes
2015 when saving, it just gets in the way. The code is often set up
2016 for streaming, and constructing the DOM is just overhead.
2017
2018 The Printer supports the streaming case. The following code
2019 prints out a trivially simple XML file without ever creating
2020 an XML document.
2021
2022 @verbatim
2023 XMLPrinter printer( fp );
2024 printer.OpenElement( "foo" );
2025 printer.PushAttribute( "foo", "bar" );
2026 printer.CloseElement();
2027 @endverbatim
2028*/
PKEuS16ed47d2013-07-06 12:02:43 +02002029class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002030{
2031public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002032 /** Construct the printer. If the FILE* is specified,
2033 this will print to the FILE. Else it will print
2034 to memory, and the result is available in CStr().
2035 If 'compact' is set to true, then output is created
2036 with only required whitespace and newlines.
2037 */
PKEuS1bfb9542013-08-04 13:51:17 +02002038 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002039 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002040
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002041 /** If streaming, write the BOM and declaration. */
2042 void PushHeader( bool writeBOM, bool writeDeclaration );
2043 /** If streaming, start writing an element.
2044 The element must be closed with CloseElement()
2045 */
Lee Thomason256adb62014-04-06 14:41:46 -07002046 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002047 /// If streaming, add an attribute to an open element.
2048 void PushAttribute( const char* name, const char* value );
2049 void PushAttribute( const char* name, int value );
2050 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002051 void PushAttribute(const char* name, int64_t value);
2052 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002053 void PushAttribute( const char* name, double value );
2054 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002055 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002056
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002057 /// Add a text node.
2058 void PushText( const char* text, bool cdata=false );
2059 /// Add a text node from an integer.
2060 void PushText( int value );
2061 /// Add a text node from an unsigned.
2062 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002063 /// Add a text node from an unsigned.
2064 void PushText(int64_t value);
2065 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002066 void PushText( bool value );
2067 /// Add a text node from a float.
2068 void PushText( float value );
2069 /// Add a text node from a double.
2070 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002071
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002072 /// Add a comment
2073 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002074
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002075 void PushDeclaration( const char* value );
2076 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002077
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002078 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2079 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2080 return true;
2081 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002082
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002083 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2084 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002085
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002086 virtual bool Visit( const XMLText& text );
2087 virtual bool Visit( const XMLComment& comment );
2088 virtual bool Visit( const XMLDeclaration& declaration );
2089 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002090
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002091 /**
2092 If in print to memory mode, return a pointer to
2093 the XML file in memory.
2094 */
2095 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002096 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002097 }
2098 /**
2099 If in print to memory mode, return the size
2100 of the XML file in memory. (Note the size returned
2101 includes the terminating null.)
2102 */
2103 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002104 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002105 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002106 /**
2107 If in print to memory mode, reset the buffer to the
2108 beginning.
2109 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002110 void ClearBuffer() {
2111 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002112 _buffer.Push(0);
2113 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002114
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002115protected:
Alexander Maid740b642014-05-20 22:04:42 +02002116 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002117
Lee Thomasonc18eb232014-02-21 17:31:17 -08002118 /** Prints out the space before an element. You may override to change
2119 the space and tabs used. A PrintSpace() override should call Print().
2120 */
2121 virtual void PrintSpace( int depth );
2122 void Print( const char* format, ... );
2123
Dmitry-Mea092bc12014-12-23 17:57:05 +03002124 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002125 bool _elementJustOpened;
2126 DynArray< const char*, 10 > _stack;
2127
2128private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002129 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002130
Lee Thomason624d43f2012-10-12 10:58:48 -07002131 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002132 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002133 int _depth;
2134 int _textDepth;
2135 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002136 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002137
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002138 enum {
2139 ENTITY_RANGE = 64,
2140 BUF_SIZE = 200
2141 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002142 bool _entityFlag[ENTITY_RANGE];
2143 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002144
Lee Thomason624d43f2012-10-12 10:58:48 -07002145 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002146};
2147
2148
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002149} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002150
PKEuS95060352013-07-26 10:42:44 +02002151#if defined(_MSC_VER)
2152# pragma warning(pop)
2153#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002154
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002155#endif // TINYXML2_INCLUDED