blob: c6a1f87aab12b4b4add4d4488c4bb23dfe68042b [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 Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070033#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070034# include <cctype>
35# include <climits>
36# include <cstdio>
37# include <cstdlib>
38# include <cstring>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070039#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070040
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070041/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080042 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080043*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080044/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070045 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080046 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010047
Lee Thomasona9cf3f92012-10-11 16:56:51 -070048 Formatting, Artistic Style:
49 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080050*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080051
U-Lama\Lee4cee6112011-12-31 14:58:18 -080052#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070053# ifndef DEBUG
54# define DEBUG
55# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080056#endif
57
PKEuS95060352013-07-26 10:42:44 +020058#ifdef _MSC_VER
59# pragma warning(push)
60# pragma warning(disable: 4251)
61#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080062
PKEuS16ed47d2013-07-06 12:02:43 +020063#ifdef _WIN32
64# ifdef TINYXML2_EXPORT
65# define TINYXML2_LIB __declspec(dllexport)
66# elif defined(TINYXML2_IMPORT)
67# define TINYXML2_LIB __declspec(dllimport)
68# else
69# define TINYXML2_LIB
70# endif
71#else
72# define TINYXML2_LIB
73#endif
74
75
U-Lama\Lee4cee6112011-12-31 14:58:18 -080076#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030078# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070079# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070080# elif defined (ANDROID_NDK)
81# include <android/log.h>
82# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
83# else
84# include <assert.h>
85# define TIXMLASSERT assert
86# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070087#else
88# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080089#endif
90
U-Lama\Leee13c3e62011-12-28 14:36:55 -080091
Lee Thomasonc18eb232014-02-21 17:31:17 -080092/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080093 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -080094*/
Sarat Addepalli9afd1d02015-05-19 12:56:27 +053095static const int TIXML2_MAJOR_VERSION = 3;
96static const int TIXML2_MINOR_VERSION = 0;
97static const int TIXML2_PATCH_VERSION = 0;
Lee Thomason1ff38e02012-02-14 18:18:16 -080098
U-Lama\Leee13c3e62011-12-28 14:36:55 -080099namespace tinyxml2
100{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800101class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800102class XMLElement;
103class XMLAttribute;
104class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800105class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800106class XMLDeclaration;
107class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800108class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800109
U-Stream\Leeae25a442012-02-17 17:48:16 -0800110/*
111 A class that wraps strings. Normally stores the start and end
112 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800113 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800114 manage) a traditional char[]
115*/
PKEuS95060352013-07-26 10:42:44 +0200116class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800117{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800118public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700119 enum {
120 NEEDS_ENTITY_PROCESSING = 0x01,
121 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300122 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800123
selfpoisede77e1952013-03-13 14:08:29 +0800124 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700125 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800126 ATTRIBUTE_NAME = 0,
127 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
128 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
129 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700130 };
Lee Thomason39ede242012-01-20 11:27:56 -0800131
Lee Thomason120b3a62012-10-12 10:06:59 -0700132 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700133 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800134
Lee Thomason120b3a62012-10-12 10:06:59 -0700135 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700136 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700137 _start = start;
138 _end = end;
139 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700140 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700141
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700142 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700143
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700146 }
Lee Thomason39ede242012-01-20 11:27:56 -0800147
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 void SetInternedStr( const char* str ) {
149 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700150 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700151 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700152
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700153 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800154
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700155 char* ParseText( char* in, const char* endTag, int strFlags );
156 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800157
Lee Thomason29658802014-11-27 22:31:11 -0800158 void TransferTo( StrPair* other );
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300159
Lee Thomason39ede242012-01-20 11:27:56 -0800160private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void Reset();
162 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800163
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 enum {
165 NEEDS_FLUSH = 0x100,
166 NEEDS_DELETE = 0x200
167 };
Lee Thomasone4422302012-01-20 17:59:50 -0800168
Lee Thomason120b3a62012-10-12 10:06:59 -0700169 int _flags;
170 char* _start;
171 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300172
173 StrPair( const StrPair& other ); // not supported
174 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800175};
176
U-Lama\Lee560bd472011-12-28 19:42:49 -0800177
U-Stream\Leeae25a442012-02-17 17:48:16 -0800178/*
179 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
180 Has a small initial memory pool, so that low or no usage will not
181 cause a call to new/delete
182*/
Dmitry-Me04009222015-04-06 18:07:18 +0300183template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200184class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800185{
186public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300187 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700188 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300189 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700190 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700192
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700193 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700194 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700195 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700196 }
197 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700198
Lee Thomasonce0510b2013-11-26 21:29:37 -0800199 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100200 _size = 0;
201 }
202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300204 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700205 EnsureCapacity( _size+1 );
206 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800208
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700209 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300210 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300211 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700212 EnsureCapacity( _size+count );
213 T* ret = &_mem[_size];
214 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 return ret;
216 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700217
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700218 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300219 TIXMLASSERT( _size > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700221 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700222
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700223 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700224 TIXMLASSERT( _size >= count );
225 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700230 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700231
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700233 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700234 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700236
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700237 const T& operator[](int i) const {
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 Thomasonf07b9522014-10-30 13:25:12 -0700242 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500243 TIXMLASSERT( _size > 0 );
244 return _mem[ _size - 1];
245 }
246
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300248 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700249 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700251
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300253 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700254 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700256
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300258 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700259 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700261
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 T* Mem() {
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 Thomason2c85a712012-01-31 08:24:24 -0800266
Lee Thomason2c85a712012-01-31 08:24:24 -0800267private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300268 DynArray( const DynArray& ); // not supported
269 void operator=( const DynArray& ); // not supported
270
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300272 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700273 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300274 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 int newAllocated = cap * 2;
276 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
278 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700279 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700280 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700281 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700282 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
284 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800285
Lee Thomason624d43f2012-10-12 10:58:48 -0700286 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300287 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700288 int _allocated; // objects allocated
289 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800290};
291
Lee Thomason50adb4c2012-02-13 15:07:09 -0800292
U-Stream\Leeae25a442012-02-17 17:48:16 -0800293/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200294 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800295 and deallocation of objects.
296*/
PKEuS95060352013-07-26 10:42:44 +0200297class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800298{
299public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700300 MemPool() {}
301 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800302
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 virtual int ItemSize() const = 0;
304 virtual void* Alloc() = 0;
305 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800306 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700307 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800308};
309
Lee Thomason50adb4c2012-02-13 15:07:09 -0800310
U-Stream\Leeae25a442012-02-17 17:48:16 -0800311/*
312 Template child class to create pools of the correct type.
313*/
Lee Thomasond1983222012-02-06 08:41:24 -0800314template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200315class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800316{
317public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800318 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700319 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700320 Clear();
321 }
322
323 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700325 while( !_blockPtrs.Empty()) {
326 Block* b = _blockPtrs.Pop();
327 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700329 _root = 0;
330 _currentAllocs = 0;
331 _nAllocs = 0;
332 _maxAllocs = 0;
333 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700334 }
Lee Thomasond1983222012-02-06 08:41:24 -0800335
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700336 virtual int ItemSize() const {
337 return SIZE;
338 }
339 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700340 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 }
Lee Thomasond1983222012-02-06 08:41:24 -0800342
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700343 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700345 // Need a new block.
346 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700347 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800348
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 for( int i=0; i<COUNT-1; ++i ) {
350 block->chunk[i].next = &block->chunk[i+1];
351 }
352 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700353 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700354 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700355 void* result = _root;
356 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800357
Lee Thomason624d43f2012-10-12 10:58:48 -0700358 ++_currentAllocs;
359 if ( _currentAllocs > _maxAllocs ) {
360 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800363 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700364 return result;
365 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700366
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700367 virtual void Free( void* mem ) {
368 if ( !mem ) {
369 return;
370 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700371 --_currentAllocs;
Dmitry-Me56571762014-08-15 11:03:47 +0400372 Chunk* chunk = static_cast<Chunk*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700373#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700374 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700375#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700376 chunk->next = _root;
377 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700378 }
379 void Trace( const char* name ) {
380 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700381 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700382 }
Lee Thomasond1983222012-02-06 08:41:24 -0800383
Lee Thomason5b0a6772012-11-19 13:54:42 -0800384 void SetTracked() {
385 _nUntracked--;
386 }
387
388 int Untracked() const {
389 return _nUntracked;
390 }
391
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800392 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
393 // The test file is large, 170k.
394 // Release: VS2010 gcc(no opt)
395 // 1k: 4000
396 // 2k: 4000
397 // 4k: 3900 21000
398 // 16k: 5200
399 // 32k: 4300
400 // 64k: 4000 21000
401 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 +0200402
Lee Thomasond1983222012-02-06 08:41:24 -0800403private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300404 MemPoolT( const MemPoolT& ); // not supported
405 void operator=( const MemPoolT& ); // not supported
406
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700407 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700408 Chunk* next;
409 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700410 };
411 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700412 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700413 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700414 DynArray< Block*, 10 > _blockPtrs;
415 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800416
Lee Thomason624d43f2012-10-12 10:58:48 -0700417 int _currentAllocs;
418 int _nAllocs;
419 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800420 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800421};
422
Lee Thomason2c85a712012-01-31 08:24:24 -0800423
Lee Thomason56bdd022012-02-09 18:16:58 -0800424
425/**
426 Implements the interface to the "Visitor pattern" (see the Accept() method.)
427 If you call the Accept() method, it requires being passed a XMLVisitor
428 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200429 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800430 are simply called with Visit().
431
432 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700433 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800434
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700435 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800436 visiting). You need to only override methods that are interesting to you.
437
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600438 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800439
440 You should never change the document from a callback.
441
442 @sa XMLNode::Accept()
443*/
PKEuS16ed47d2013-07-06 12:02:43 +0200444class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800445{
446public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700447 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800448
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700449 /// Visit a document.
450 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
451 return true;
452 }
453 /// Visit a document.
454 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
455 return true;
456 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800457
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700458 /// Visit an element.
459 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
460 return true;
461 }
462 /// Visit an element.
463 virtual bool VisitExit( const XMLElement& /*element*/ ) {
464 return true;
465 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800466
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700467 /// Visit a declaration.
468 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
469 return true;
470 }
471 /// Visit a text node.
472 virtual bool Visit( const XMLText& /*text*/ ) {
473 return true;
474 }
475 /// Visit a comment node.
476 virtual bool Visit( const XMLComment& /*comment*/ ) {
477 return true;
478 }
479 /// Visit an unknown node.
480 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
481 return true;
482 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800483};
484
Dmitry-Me66d2a842014-11-08 15:24:52 +0300485// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900486enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900487 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900488 XML_NO_ATTRIBUTE,
489 XML_WRONG_ATTRIBUTE_TYPE,
490 XML_ERROR_FILE_NOT_FOUND,
491 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
492 XML_ERROR_FILE_READ_ERROR,
493 XML_ERROR_ELEMENT_MISMATCH,
494 XML_ERROR_PARSING_ELEMENT,
495 XML_ERROR_PARSING_ATTRIBUTE,
496 XML_ERROR_IDENTIFYING_TAG,
497 XML_ERROR_PARSING_TEXT,
498 XML_ERROR_PARSING_CDATA,
499 XML_ERROR_PARSING_COMMENT,
500 XML_ERROR_PARSING_DECLARATION,
501 XML_ERROR_PARSING_UNKNOWN,
502 XML_ERROR_EMPTY_DOCUMENT,
503 XML_ERROR_MISMATCHED_ELEMENT,
504 XML_ERROR_PARSING,
505 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700506 XML_NO_TEXT_NODE,
507
508 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900509};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900510
numatrumpetcd8550c2014-09-08 16:59:39 +0900511
U-Stream\Leeae25a442012-02-17 17:48:16 -0800512/*
513 Utility functionality.
514*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800515class XMLUtil
516{
Lee Thomasond1983222012-02-06 08:41:24 -0800517public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700518 static const char* SkipWhiteSpace( const char* p ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300519 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300520 while( IsWhiteSpace(*p) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700521 ++p;
522 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300523 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700524 return p;
525 }
526 static char* SkipWhiteSpace( char* p ) {
Dmitry-Me9de541f2014-09-24 14:21:36 +0400527 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700528 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300529
530 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
531 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700532 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100533 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200535
536 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300537 if ( ch >= 128 ) {
538 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
539 return true;
540 }
541 if ( isalpha( ch ) ) {
542 return true;
543 }
544 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200545 }
546
547 inline static bool IsNameChar( unsigned char ch ) {
548 return IsNameStartChar( ch )
549 || isdigit( ch )
550 || ch == '.'
551 || ch == '-';
552 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800553
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700554 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700555 if ( p == q ) {
556 return true;
557 }
Lee Thomason598a88d2015-10-09 14:42:12 -0700558 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700559 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200560
Dmitry-Me7865aad2015-06-19 16:23:35 +0300561 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400562 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700563 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800564
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700565 static const char* ReadBOM( const char* p, bool* hasBOM );
566 // p is the starting location,
567 // the UTF-8 value of the entity will be placed in value, and length filled in.
568 static const char* GetCharacterRef( const char* p, char* value, int* length );
569 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700570
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700571 // converts primitive types to strings
572 static void ToStr( int v, char* buffer, int bufferSize );
573 static void ToStr( unsigned v, char* buffer, int bufferSize );
574 static void ToStr( bool v, char* buffer, int bufferSize );
575 static void ToStr( float v, char* buffer, int bufferSize );
576 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700577
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700578 // converts strings to primitive types
579 static bool ToInt( const char* str, int* value );
580 static bool ToUnsigned( const char* str, unsigned* value );
581 static bool ToBool( const char* str, bool* value );
582 static bool ToFloat( const char* str, float* value );
583 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800584};
585
Lee Thomason5cae8972012-01-24 18:03:07 -0800586
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800587/** XMLNode is a base class for every object that is in the
588 XML Document Object Model (DOM), except XMLAttributes.
589 Nodes have siblings, a parent, and children which can
590 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700591 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800592 be cast to its more defined type.
593
Thomas Roß08bdf502012-05-12 14:21:23 +0200594 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800595 When the XMLDocument gets deleted, all its Nodes
596 will also be deleted.
597
598 @verbatim
599 A Document can contain: Element (container or leaf)
600 Comment (leaf)
601 Unknown (leaf)
602 Declaration( leaf )
603
604 An Element can contain: Element (container or leaf)
605 Text (leaf)
606 Attributes (not on tree)
607 Comment (leaf)
608 Unknown (leaf)
609
610 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800611*/
PKEuS16ed47d2013-07-06 12:02:43 +0200612class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800613{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 friend class XMLDocument;
615 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800616public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800617
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 /// Get the XMLDocument that owns this XMLNode.
619 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300620 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700621 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700622 }
623 /// Get the XMLDocument that owns this XMLNode.
624 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300625 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700626 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700627 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800628
Lee Thomason2fa81722012-11-09 12:37:46 -0800629 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700630 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100631 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700632 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800633 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100635 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700636 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800637 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700638 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100639 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700640 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800641 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700642 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100643 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700644 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800645 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700646 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100647 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800649 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100651 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700652 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800653
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 virtual const XMLElement* ToElement() const {
655 return 0;
656 }
657 virtual const XMLText* ToText() const {
658 return 0;
659 }
660 virtual const XMLComment* ToComment() const {
661 return 0;
662 }
663 virtual const XMLDocument* ToDocument() const {
664 return 0;
665 }
666 virtual const XMLDeclaration* ToDeclaration() const {
667 return 0;
668 }
669 virtual const XMLUnknown* ToUnknown() const {
670 return 0;
671 }
Lee Thomason751da522012-02-10 08:50:51 -0800672
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700673 /** The meaning of 'value' changes for the specific type.
674 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530675 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 Element: name of the element
677 Comment: the comment text
678 Unknown: the tag contents
679 Text: the text string
680 @endverbatim
681 */
Michael Daumling21626882013-10-22 17:03:37 +0200682 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 /** Set the Value of an XML node.
685 @sa Value()
686 */
687 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800688
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700689 /// Get the parent of this node on the DOM.
690 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700691 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100693
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700695 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 }
Lee Thomason751da522012-02-10 08:50:51 -0800697
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700698 /// Returns true if this node has no children.
699 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700700 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 }
Lee Thomason751da522012-02-10 08:50:51 -0800702
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 /// Get the first child node, or null if none exists.
704 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700705 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700706 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100707
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700709 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100711
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 /** Get the first child element, or optionally the first child
713 element with the specified name.
714 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300715 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700716
Dmitry-Me886ad972015-07-22 11:00:51 +0300717 XMLElement* FirstChildElement( const char* name = 0 ) {
718 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 /// Get the last child node, or null if none exists.
722 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700723 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300727 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700728 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800729
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700730 /** Get the last child element or optionally the last child
731 element with the specified name.
732 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300733 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700734
Dmitry-Me886ad972015-07-22 11:00:51 +0300735 XMLElement* LastChildElement( const char* name = 0 ) {
736 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700738
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 /// Get the previous (left) sibling node of this node.
740 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700741 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700743
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700744 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700745 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700746 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800747
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700748 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300749 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700750
Dmitry-Me886ad972015-07-22 11:00:51 +0300751 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
752 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700754
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 /// Get the next (right) sibling node of this node.
756 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700757 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700758 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700759
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700761 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700763
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700764 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300765 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700766
Dmitry-Me886ad972015-07-22 11:00:51 +0300767 XMLElement* NextSiblingElement( const char* name = 0 ) {
768 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800770
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 /**
772 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200773 If the child node is already part of the document,
774 it is moved from its old location to the new location.
775 Returns the addThis argument or 0 if the node does not
776 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 */
778 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800779
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700780 XMLNode* LinkEndChild( XMLNode* addThis ) {
781 return InsertEndChild( addThis );
782 }
783 /**
784 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200785 If the child node is already part of the document,
786 it is moved from its old location to the new location.
787 Returns the addThis argument or 0 if the node does not
788 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 */
790 XMLNode* InsertFirstChild( XMLNode* addThis );
791 /**
792 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200793 If the child node is already part of the document,
794 it is moved from its old location to the new location.
795 Returns the addThis argument or 0 if the afterThis node
796 is not a child of this node, or if the node does not
797 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700798 */
799 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700800
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700801 /**
802 Delete all the children of this node.
803 */
804 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800805
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 /**
807 Delete a child of this node.
808 */
809 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800810
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 /**
812 Make a copy of this node, but not its children.
813 You may pass in a Document pointer that will be
814 the owner of the new Node. If the 'document' is
815 null, then the node returned will be allocated
816 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800817
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700818 Note: if called on a XMLDocument, this will return null.
819 */
820 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800821
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 /**
823 Test if 2 nodes are the same, but don't test children.
824 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800825
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700826 Note: if called on a XMLDocument, this will return false.
827 */
828 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800829
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600830 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600832 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800833
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600834 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
835 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700836 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800837
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700838 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800839
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700840 - http://www.saxproject.org/
841 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800842
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700843 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800844
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700845 An example of using Accept():
846 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600847 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700848 tinyxmlDoc.Accept( &printer );
849 const char* xmlcstr = printer.CStr();
850 @endverbatim
851 */
852 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800853
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800854protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 XMLNode( XMLDocument* );
856 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700857
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300858 virtual char* ParseDeep( char*, StrPair* );
859
Lee Thomason624d43f2012-10-12 10:58:48 -0700860 XMLDocument* _document;
861 XMLNode* _parent;
862 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800863
Lee Thomason624d43f2012-10-12 10:58:48 -0700864 XMLNode* _firstChild;
865 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800866
Lee Thomason624d43f2012-10-12 10:58:48 -0700867 XMLNode* _prev;
868 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800869
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800870private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700871 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700872 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400873 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800874 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300875
876 XMLNode( const XMLNode& ); // not supported
877 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800878};
879
880
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800881/** XML text.
882
883 Note that a text node can have child element nodes, for example:
884 @verbatim
885 <root>This is <b>bold</b></root>
886 @endverbatim
887
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700888 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800889 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 -0700890 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600891 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800892*/
PKEuS16ed47d2013-07-06 12:02:43 +0200893class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800894{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700895 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800896public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700897 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800898
Lee Thomason624d43f2012-10-12 10:58:48 -0700899 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700900 return this;
901 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700902 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700903 return this;
904 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800905
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700906 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700907 void SetCData( bool isCData ) {
908 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700909 }
910 /// Returns true if this is a CDATA text element.
911 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700912 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700913 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800914
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
916 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800917
Lee Thomason5492a1c2012-01-23 15:32:10 -0800918protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700919 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700920 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800921
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300922 char* ParseDeep( char*, StrPair* endTag );
923
Lee Thomason5492a1c2012-01-23 15:32:10 -0800924private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700925 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300926
927 XMLText( const XMLText& ); // not supported
928 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800929};
930
931
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800932/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200933class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800934{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700935 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800936public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700937 virtual XMLComment* ToComment() {
938 return this;
939 }
940 virtual const XMLComment* ToComment() const {
941 return this;
942 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800943
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800945
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700946 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800948
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800949protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 XMLComment( XMLDocument* doc );
951 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800952
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300953 char* ParseDeep( char*, StrPair* endTag );
954
Lee Thomason3f57d272012-01-11 15:30:03 -0800955private:
Dmitry-Mef547a992015-01-09 15:17:09 +0300956 XMLComment( const XMLComment& ); // not supported
957 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800958};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800959
960
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800961/** In correct XML the declaration is the first entry in the file.
962 @verbatim
963 <?xml version="1.0" standalone="yes"?>
964 @endverbatim
965
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600966 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800967 however.
968
969 The text of the declaration isn't interpreted. It is parsed
970 and written as a string.
971*/
PKEuS16ed47d2013-07-06 12:02:43 +0200972class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800973{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700974 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800975public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 virtual XMLDeclaration* ToDeclaration() {
977 return this;
978 }
979 virtual const XMLDeclaration* ToDeclaration() const {
980 return this;
981 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800982
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800984
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700985 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
986 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800987
988protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700989 XMLDeclaration( XMLDocument* doc );
990 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +0300991
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300992 char* ParseDeep( char*, StrPair* endTag );
993
Dmitry-Mef547a992015-01-09 15:17:09 +0300994private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700995 XMLDeclaration( const XMLDeclaration& ); // not supported
996 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800997};
998
999
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001000/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001001 unknown. It is a tag of text, but should not be modified.
1002 It will be written back to the XML, unchanged, when the file
1003 is saved.
1004
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001005 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001006*/
PKEuS16ed47d2013-07-06 12:02:43 +02001007class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001008{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001009 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001010public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001011 virtual XMLUnknown* ToUnknown() {
1012 return this;
1013 }
1014 virtual const XMLUnknown* ToUnknown() const {
1015 return this;
1016 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001017
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001019
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001020 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1021 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001022
1023protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001024 XMLUnknown( XMLDocument* doc );
1025 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001026
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001027 char* ParseDeep( char*, StrPair* endTag );
1028
Dmitry-Mef547a992015-01-09 15:17:09 +03001029private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001030 XMLUnknown( const XMLUnknown& ); // not supported
1031 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001032};
1033
1034
Lee Thomason1ff38e02012-02-14 18:18:16 -08001035
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001036/** An attribute is a name-value pair. Elements have an arbitrary
1037 number of attributes, each with a unique name.
1038
1039 @note The attributes are not XMLNodes. You may only query the
1040 Next() attribute in a list.
1041*/
PKEuS16ed47d2013-07-06 12:02:43 +02001042class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001043{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001044 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001045public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001046 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001047 const char* Name() const;
1048
Lee Thomason2fa81722012-11-09 12:37:46 -08001049 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001050 const char* Value() const;
1051
Lee Thomason2fa81722012-11-09 12:37:46 -08001052 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001054 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001055 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001056
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001057 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001058 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001059 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001060 */
1061 int IntValue() const {
1062 int i=0;
1063 QueryIntValue( &i );
1064 return i;
1065 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001067 unsigned UnsignedValue() const {
1068 unsigned i=0;
1069 QueryUnsignedValue( &i );
1070 return i;
1071 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001072 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 bool BoolValue() const {
1074 bool b=false;
1075 QueryBoolValue( &b );
1076 return b;
1077 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001078 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001079 double DoubleValue() const {
1080 double d=0;
1081 QueryDoubleValue( &d );
1082 return d;
1083 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001084 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001085 float FloatValue() const {
1086 float f=0;
1087 QueryFloatValue( &f );
1088 return f;
1089 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001090
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001091 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001092 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1094 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001095 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001096 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001097 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001098 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001099 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001100 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001101 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001102 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001103 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001104
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 /// Set the attribute to a string value.
1106 void SetAttribute( const char* value );
1107 /// Set the attribute to value.
1108 void SetAttribute( int value );
1109 /// Set the attribute to value.
1110 void SetAttribute( unsigned value );
1111 /// Set the attribute to value.
1112 void SetAttribute( bool value );
1113 /// Set the attribute to value.
1114 void SetAttribute( double value );
1115 /// Set the attribute to value.
1116 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001117
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001118private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001119 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001120
Thomas Roß61892312013-05-12 14:07:38 +02001121 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001122 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001123
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001124 XMLAttribute( const XMLAttribute& ); // not supported
1125 void operator=( const XMLAttribute& ); // not supported
1126 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001127
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001128 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001129
Lee Thomason624d43f2012-10-12 10:58:48 -07001130 mutable StrPair _name;
1131 mutable StrPair _value;
1132 XMLAttribute* _next;
1133 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001134};
1135
1136
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001137/** The element is a container class. It has a value, the element name,
1138 and can contain other elements, text, comments, and unknowns.
1139 Elements also contain an arbitrary number of attributes.
1140*/
PKEuS16ed47d2013-07-06 12:02:43 +02001141class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001142{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001144public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001145 /// Get the name of an element (which is the Value() of the node.)
1146 const char* Name() const {
1147 return Value();
1148 }
1149 /// Set the name of the element.
1150 void SetName( const char* str, bool staticMem=false ) {
1151 SetValue( str, staticMem );
1152 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001153
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001154 virtual XMLElement* ToElement() {
1155 return this;
1156 }
1157 virtual const XMLElement* ToElement() const {
1158 return this;
1159 }
1160 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001161
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001162 /** Given an attribute name, Attribute() returns the value
1163 for the attribute of that name, or null if none
1164 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001165
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 @verbatim
1167 const char* value = ele->Attribute( "foo" );
1168 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001169
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001170 The 'value' parameter is normally null. However, if specified,
1171 the attribute will only be returned if the 'name' and 'value'
1172 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001173
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001174 @verbatim
1175 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1176 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001177
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001178 rather than:
1179 @verbatim
1180 if ( ele->Attribute( "foo" ) ) {
1181 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1182 }
1183 @endverbatim
1184 */
1185 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001186
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001187 /** Given an attribute name, IntAttribute() returns the value
1188 of the attribute interpreted as an integer. 0 will be
1189 returned if there is an error. For a method with error
1190 checking, see QueryIntAttribute()
1191 */
1192 int IntAttribute( const char* name ) const {
1193 int i=0;
1194 QueryIntAttribute( name, &i );
1195 return i;
1196 }
1197 /// See IntAttribute()
1198 unsigned UnsignedAttribute( const char* name ) const {
1199 unsigned i=0;
1200 QueryUnsignedAttribute( name, &i );
1201 return i;
1202 }
1203 /// See IntAttribute()
1204 bool BoolAttribute( const char* name ) const {
1205 bool b=false;
1206 QueryBoolAttribute( name, &b );
1207 return b;
1208 }
1209 /// See IntAttribute()
1210 double DoubleAttribute( const char* name ) const {
1211 double d=0;
1212 QueryDoubleAttribute( name, &d );
1213 return d;
1214 }
1215 /// See IntAttribute()
1216 float FloatAttribute( const char* name ) const {
1217 float f=0;
1218 QueryFloatAttribute( name, &f );
1219 return f;
1220 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001221
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 /** Given an attribute name, QueryIntAttribute() returns
1223 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1224 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1225 doesn't exist. If successful, the result of the conversion
1226 will be written to 'value'. If not successful, nothing will
1227 be written to 'value'. This allows you to provide default
1228 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001229
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 @verbatim
1231 int value = 10;
1232 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1233 @endverbatim
1234 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001235 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001236 const XMLAttribute* a = FindAttribute( name );
1237 if ( !a ) {
1238 return XML_NO_ATTRIBUTE;
1239 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001240 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 }
1242 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001243 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 const XMLAttribute* a = FindAttribute( name );
1245 if ( !a ) {
1246 return XML_NO_ATTRIBUTE;
1247 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001248 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 }
1250 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001251 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 const XMLAttribute* a = FindAttribute( name );
1253 if ( !a ) {
1254 return XML_NO_ATTRIBUTE;
1255 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001256 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 }
1258 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001259 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 const XMLAttribute* a = FindAttribute( name );
1261 if ( !a ) {
1262 return XML_NO_ATTRIBUTE;
1263 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001264 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001265 }
1266 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001267 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001268 const XMLAttribute* a = FindAttribute( name );
1269 if ( !a ) {
1270 return XML_NO_ATTRIBUTE;
1271 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001272 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001273 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001274
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001275
1276 /** Given an attribute name, QueryAttribute() returns
1277 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1278 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1279 doesn't exist. It is overloaded for the primitive types,
1280 and is a generally more convenient replacement of
1281 QueryIntAttribute() and related functions.
1282
1283 If successful, the result of the conversion
1284 will be written to 'value'. If not successful, nothing will
1285 be written to 'value'. This allows you to provide default
1286 value:
1287
1288 @verbatim
1289 int value = 10;
1290 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1291 @endverbatim
1292 */
1293 int QueryAttribute( const char* name, int* value ) const {
1294 return QueryIntAttribute( name, value );
1295 }
1296
1297 int QueryAttribute( const char* name, unsigned int* value ) const {
1298 return QueryUnsignedAttribute( name, value );
1299 }
1300
1301 int QueryAttribute( const char* name, bool* value ) const {
1302 return QueryBoolAttribute( name, value );
1303 }
1304
1305 int QueryAttribute( const char* name, double* value ) const {
1306 return QueryDoubleAttribute( name, value );
1307 }
1308
1309 int QueryAttribute( const char* name, float* value ) const {
1310 return QueryFloatAttribute( name, value );
1311 }
1312
1313 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001314 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001316 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 }
1318 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001319 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001320 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001321 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 }
1323 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001324 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001325 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001326 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 }
1328 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001329 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001330 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001331 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001332 }
1333 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001334 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001336 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001337 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001338 /// Sets the named attribute to value.
1339 void SetAttribute( const char* name, float value ) {
1340 XMLAttribute* a = FindOrCreateAttribute( name );
1341 a->SetAttribute( value );
1342 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001343
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001344 /**
1345 Delete an attribute.
1346 */
1347 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001348
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001349 /// Return the first attribute in the list.
1350 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001351 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 }
1353 /// Query a specific attribute in the list.
1354 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001355
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001356 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001357 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001358 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001359
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001360 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 This is a convenient method for getting the text of simple contained text:
1364 @verbatim
1365 <foo>This is text</foo>
1366 const char* str = fooElement->GetText();
1367 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001368
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001369 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001370
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001371 Note that this function can be misleading. If the element foo was created from
1372 this XML:
1373 @verbatim
1374 <foo><b>This is text</b></foo>
1375 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001376
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 then the value of str would be null. The first child node isn't a text node, it is
1378 another element. From this XML:
1379 @verbatim
1380 <foo>This is <b>text</b></foo>
1381 @endverbatim
1382 GetText() will return "This is ".
1383 */
1384 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001385
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001386 /** Convenience function for easy access to the text inside an element. Although easy
1387 and concise, SetText() is limited compared to creating an XMLText child
1388 and mutating it directly.
1389
1390 If the first child of 'this' is a XMLText, SetText() sets its value to
1391 the given string, otherwise it will create a first child that is an XMLText.
1392
1393 This is a convenient method for setting the text of simple contained text:
1394 @verbatim
1395 <foo>This is text</foo>
1396 fooElement->SetText( "Hullaballoo!" );
1397 <foo>Hullaballoo!</foo>
1398 @endverbatim
1399
1400 Note that this function can be misleading. If the element foo was created from
1401 this XML:
1402 @verbatim
1403 <foo><b>This is text</b></foo>
1404 @endverbatim
1405
1406 then it will not change "This is text", but rather prefix it with a text element:
1407 @verbatim
1408 <foo>Hullaballoo!<b>This is text</b></foo>
1409 @endverbatim
1410
1411 For this XML:
1412 @verbatim
1413 <foo />
1414 @endverbatim
1415 SetText() will generate
1416 @verbatim
1417 <foo>Hullaballoo!</foo>
1418 @endverbatim
1419 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001420 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001421 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001422 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001423 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001424 void SetText( unsigned value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001425 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001426 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001427 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001428 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001429 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001430 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001431
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 /**
1433 Convenience method to query the value of a child text node. This is probably best
1434 shown by example. Given you have a document is this form:
1435 @verbatim
1436 <point>
1437 <x>1</x>
1438 <y>1.4</y>
1439 </point>
1440 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 The QueryIntText() and similar functions provide a safe and easier way to get to the
1443 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001444
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001445 @verbatim
1446 int x = 0;
1447 float y = 0; // types of x and y are contrived for example
1448 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1449 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1450 xElement->QueryIntText( &x );
1451 yElement->QueryFloatText( &y );
1452 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001453
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001454 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1455 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 -07001456
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001457 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001458 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001459 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001460 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001461 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001462 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001463 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001464 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001465 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001466 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001467
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001468 // internal:
1469 enum {
1470 OPEN, // <foo>
1471 CLOSED, // <foo/>
1472 CLOSING // </foo>
1473 };
1474 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001475 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001477 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1478 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001479
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001480protected:
1481 char* ParseDeep( char* p, StrPair* endTag );
1482
Lee Thomason50adb4c2012-02-13 15:07:09 -08001483private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001484 XMLElement( XMLDocument* doc );
1485 virtual ~XMLElement();
1486 XMLElement( const XMLElement& ); // not supported
1487 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001488
Dmitry-Me1227d512014-12-05 13:41:45 +03001489 XMLAttribute* FindAttribute( const char* name ) {
1490 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1491 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001492 XMLAttribute* FindOrCreateAttribute( const char* name );
1493 //void LinkAttribute( XMLAttribute* attrib );
1494 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001495 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001496
Lee Thomason5bb2d802014-01-24 10:42:57 -08001497 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001498 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 // The attribute list is ordered; there is no 'lastAttribute'
1500 // because the list needs to be scanned for dupes before adding
1501 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001502 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001503};
1504
1505
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001506enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 PRESERVE_WHITESPACE,
1508 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001509};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001510
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001511
1512/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001513 It can be saved, loaded, and printed to the screen.
1514 All Nodes are connected and allocated to a Document.
1515 If the Document is deleted, all its Nodes are also deleted.
1516*/
PKEuS16ed47d2013-07-06 12:02:43 +02001517class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001518{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001519 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001520public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001521 /// constructor
1522 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1523 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001524
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001525 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001526 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001527 return this;
1528 }
1529 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001530 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 return this;
1532 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001533
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001534 /**
1535 Parse an XML file from a character string.
1536 Returns XML_NO_ERROR (0) on success, or
1537 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001538
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 You may optionally pass in the 'nBytes', which is
1540 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001541 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 null terminated string.
1543 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001544 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001545
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001546 /**
1547 Load an XML file from disk.
1548 Returns XML_NO_ERROR (0) on success, or
1549 an errorID.
1550 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001551 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001552
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001553 /**
1554 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001555 for providing and closing the FILE*.
1556
1557 NOTE: The file should be opened as binary ("rb")
1558 not text in order for TinyXML-2 to correctly
1559 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001560
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001561 Returns XML_NO_ERROR (0) on success, or
1562 an errorID.
1563 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001564 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001565
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001566 /**
1567 Save the XML file to disk.
1568 Returns XML_NO_ERROR (0) on success, or
1569 an errorID.
1570 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001571 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001572
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001573 /**
1574 Save the XML file to disk. You are responsible
1575 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001576
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 Returns XML_NO_ERROR (0) on success, or
1578 an errorID.
1579 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001580 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001581
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001582 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001583 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 }
1585 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001586 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001587 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001588
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001589 /**
1590 Returns true if this document has a leading Byte Order Mark of UTF8.
1591 */
1592 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001593 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001594 }
1595 /** Sets whether to write the BOM when writing the file.
1596 */
1597 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001598 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001599 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001600
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001601 /** Return the root element of DOM. Equivalent to FirstChildElement().
1602 To get the first node, use FirstChild().
1603 */
1604 XMLElement* RootElement() {
1605 return FirstChildElement();
1606 }
1607 const XMLElement* RootElement() const {
1608 return FirstChildElement();
1609 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001610
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001611 /** Print the Document. If the Printer is not provided, it will
1612 print to stdout. If you provide Printer, this can print to a file:
1613 @verbatim
1614 XMLPrinter printer( fp );
1615 doc.Print( &printer );
1616 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001617
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001618 Or you can use a printer to print to memory:
1619 @verbatim
1620 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001621 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001622 // printer.CStr() has a const char* to the XML
1623 @endverbatim
1624 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001625 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001627
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 /**
1629 Create a new Element associated with
1630 this Document. The memory for the Element
1631 is managed by the Document.
1632 */
1633 XMLElement* NewElement( const char* name );
1634 /**
1635 Create a new Comment associated with
1636 this Document. The memory for the Comment
1637 is managed by the Document.
1638 */
1639 XMLComment* NewComment( const char* comment );
1640 /**
1641 Create a new Text associated with
1642 this Document. The memory for the Text
1643 is managed by the Document.
1644 */
1645 XMLText* NewText( const char* text );
1646 /**
1647 Create a new Declaration associated with
1648 this Document. The memory for the object
1649 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001650
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001651 If the 'text' param is null, the standard
1652 declaration is used.:
1653 @verbatim
1654 <?xml version="1.0" encoding="UTF-8"?>
1655 @endverbatim
1656 */
1657 XMLDeclaration* NewDeclaration( const char* text=0 );
1658 /**
1659 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001660 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001661 is managed by the Document.
1662 */
1663 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001664
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001665 /**
1666 Delete a node associated with this document.
1667 It will be unlinked from the DOM.
1668 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001669 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001670
Lee Thomason2fa81722012-11-09 12:37:46 -08001671 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001672
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001673 /// Return true if there was an error parsing the document.
1674 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001675 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001676 }
1677 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001678 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001679 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001680 }
Lee Thomason331596e2014-09-11 14:56:43 -07001681 const char* ErrorName() const;
1682
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001683 /// Return a possibly helpful diagnostic location or string.
1684 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001685 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 }
1687 /// Return a possibly helpful secondary diagnostic location or string.
1688 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001689 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001690 }
1691 /// If there is an error, print it to stdout.
1692 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001693
1694 /// Clear the document, resetting it to the initial state.
1695 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001696
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 // internal
1698 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001699
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001700 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1701 return 0;
1702 }
1703 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1704 return false;
1705 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001706
Lee Thomason3f57d272012-01-11 15:30:03 -08001707private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 XMLDocument( const XMLDocument& ); // not supported
1709 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001710
Lee Thomason2fa81722012-11-09 12:37:46 -08001711 bool _writeBOM;
1712 bool _processEntities;
1713 XMLError _errorID;
1714 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001715 const char* _errorStr1;
1716 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001717 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001718
Lee Thomason624d43f2012-10-12 10:58:48 -07001719 MemPoolT< sizeof(XMLElement) > _elementPool;
1720 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1721 MemPoolT< sizeof(XMLText) > _textPool;
1722 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001723
1724 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001725
1726 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001727};
1728
Lee Thomason7c913cd2012-01-26 18:32:34 -08001729
Lee Thomason3ffdd392012-03-28 17:27:55 -07001730/**
1731 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001732 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001733 DOM structure. It is a separate utility class.
1734
1735 Take an example:
1736 @verbatim
1737 <Document>
1738 <Element attributeA = "valueA">
1739 <Child attributeB = "value1" />
1740 <Child attributeB = "value2" />
1741 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001742 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001743 @endverbatim
1744
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001745 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001746 easy to write a *lot* of code that looks like:
1747
1748 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001749 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001750 if ( root )
1751 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001752 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001753 if ( element )
1754 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001755 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001756 if ( child )
1757 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001758 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001759 if ( child2 )
1760 {
1761 // Finally do something useful.
1762 @endverbatim
1763
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001764 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001765 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001766 and correct to use:
1767
1768 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001769 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001770 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001771 if ( child2 )
1772 {
1773 // do something useful
1774 @endverbatim
1775
1776 Which is MUCH more concise and useful.
1777
1778 It is also safe to copy handles - internally they are nothing more than node pointers.
1779 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001780 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001781 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001782
1783 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001784*/
PKEuS16ed47d2013-07-06 12:02:43 +02001785class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001786{
1787public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001788 /// 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 -07001789 XMLHandle( XMLNode* node ) {
1790 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001791 }
1792 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001793 XMLHandle( XMLNode& node ) {
1794 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
1796 /// Copy constructor
1797 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 }
1800 /// Assignment
1801 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001802 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 return *this;
1804 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001805
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001806 /// Get the first child of this handle.
1807 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 }
1810 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001811 XMLHandle FirstChildElement( const char* name = 0 ) {
1812 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 }
1814 /// Get the last child of this handle.
1815 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001816 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001817 }
1818 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001819 XMLHandle LastChildElement( const char* name = 0 ) {
1820 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001821 }
1822 /// Get the previous sibling of this handle.
1823 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001824 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001825 }
1826 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001827 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1828 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001829 }
1830 /// Get the next sibling of this handle.
1831 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001832 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001833 }
1834 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001835 XMLHandle NextSiblingElement( const char* name = 0 ) {
1836 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001837 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001838
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001839 /// Safe cast to XMLNode. This can return null.
1840 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001841 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001842 }
1843 /// Safe cast to XMLElement. This can return null.
1844 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001845 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001846 }
1847 /// Safe cast to XMLText. This can return null.
1848 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001849 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001850 }
1851 /// Safe cast to XMLUnknown. This can return null.
1852 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001853 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001854 }
1855 /// Safe cast to XMLDeclaration. This can return null.
1856 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001857 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001858 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001859
1860private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001861 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001862};
1863
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001864
1865/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001866 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1867 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001868*/
PKEuS16ed47d2013-07-06 12:02:43 +02001869class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001870{
1871public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001872 XMLConstHandle( const XMLNode* node ) {
1873 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001874 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001875 XMLConstHandle( const XMLNode& node ) {
1876 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001877 }
1878 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001879 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 }
Lee Thomason8b899812012-04-04 15:58:16 -07001881
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001883 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 return *this;
1885 }
Lee Thomason8b899812012-04-04 15:58:16 -07001886
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001887 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001888 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001889 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001890 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1891 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 }
1893 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001894 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001895 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001896 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1897 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001900 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001901 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001902 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1903 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001904 }
1905 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001906 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001907 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001908 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1909 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001910 }
Lee Thomason8b899812012-04-04 15:58:16 -07001911
1912
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001913 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001914 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001915 }
1916 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001917 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 }
1919 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001920 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001921 }
1922 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001923 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001924 }
1925 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001926 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001927 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001928
Lee Thomason5cae8972012-01-24 18:03:07 -08001929private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001930 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001931};
Lee Thomason6f381b72012-03-02 12:59:39 -08001932
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001933
1934/**
1935 Printing functionality. The XMLPrinter gives you more
1936 options than the XMLDocument::Print() method.
1937
1938 It can:
1939 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001940 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001941 -# Print XML without a XMLDocument.
1942
1943 Print to Memory
1944
1945 @verbatim
1946 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001947 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001948 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001949 @endverbatim
1950
1951 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001952
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001953 You provide the file pointer.
1954 @verbatim
1955 XMLPrinter printer( fp );
1956 doc.Print( &printer );
1957 @endverbatim
1958
1959 Print without a XMLDocument
1960
1961 When loading, an XML parser is very useful. However, sometimes
1962 when saving, it just gets in the way. The code is often set up
1963 for streaming, and constructing the DOM is just overhead.
1964
1965 The Printer supports the streaming case. The following code
1966 prints out a trivially simple XML file without ever creating
1967 an XML document.
1968
1969 @verbatim
1970 XMLPrinter printer( fp );
1971 printer.OpenElement( "foo" );
1972 printer.PushAttribute( "foo", "bar" );
1973 printer.CloseElement();
1974 @endverbatim
1975*/
PKEuS16ed47d2013-07-06 12:02:43 +02001976class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001977{
1978public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001979 /** Construct the printer. If the FILE* is specified,
1980 this will print to the FILE. Else it will print
1981 to memory, and the result is available in CStr().
1982 If 'compact' is set to true, then output is created
1983 with only required whitespace and newlines.
1984 */
PKEuS1bfb9542013-08-04 13:51:17 +02001985 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001986 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001987
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001988 /** If streaming, write the BOM and declaration. */
1989 void PushHeader( bool writeBOM, bool writeDeclaration );
1990 /** If streaming, start writing an element.
1991 The element must be closed with CloseElement()
1992 */
Lee Thomason256adb62014-04-06 14:41:46 -07001993 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001994 /// If streaming, add an attribute to an open element.
1995 void PushAttribute( const char* name, const char* value );
1996 void PushAttribute( const char* name, int value );
1997 void PushAttribute( const char* name, unsigned value );
1998 void PushAttribute( const char* name, bool value );
1999 void PushAttribute( const char* name, double value );
2000 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002001 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002002
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002003 /// Add a text node.
2004 void PushText( const char* text, bool cdata=false );
2005 /// Add a text node from an integer.
2006 void PushText( int value );
2007 /// Add a text node from an unsigned.
2008 void PushText( unsigned value );
2009 /// Add a text node from a bool.
2010 void PushText( bool value );
2011 /// Add a text node from a float.
2012 void PushText( float value );
2013 /// Add a text node from a double.
2014 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002015
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002016 /// Add a comment
2017 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002018
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002019 void PushDeclaration( const char* value );
2020 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002021
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002022 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2023 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2024 return true;
2025 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002026
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002027 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2028 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002029
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002030 virtual bool Visit( const XMLText& text );
2031 virtual bool Visit( const XMLComment& comment );
2032 virtual bool Visit( const XMLDeclaration& declaration );
2033 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002034
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002035 /**
2036 If in print to memory mode, return a pointer to
2037 the XML file in memory.
2038 */
2039 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002040 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002041 }
2042 /**
2043 If in print to memory mode, return the size
2044 of the XML file in memory. (Note the size returned
2045 includes the terminating null.)
2046 */
2047 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002048 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002049 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002050 /**
2051 If in print to memory mode, reset the buffer to the
2052 beginning.
2053 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002054 void ClearBuffer() {
2055 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002056 _buffer.Push(0);
2057 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002058
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002059protected:
Alexander Maid740b642014-05-20 22:04:42 +02002060 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002061
Lee Thomasonc18eb232014-02-21 17:31:17 -08002062 /** Prints out the space before an element. You may override to change
2063 the space and tabs used. A PrintSpace() override should call Print().
2064 */
2065 virtual void PrintSpace( int depth );
2066 void Print( const char* format, ... );
2067
Dmitry-Mea092bc12014-12-23 17:57:05 +03002068 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002069 bool _elementJustOpened;
2070 DynArray< const char*, 10 > _stack;
2071
2072private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002073 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002074
Lee Thomason624d43f2012-10-12 10:58:48 -07002075 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002076 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002077 int _depth;
2078 int _textDepth;
2079 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002080 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002081
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002082 enum {
2083 ENTITY_RANGE = 64,
2084 BUF_SIZE = 200
2085 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002086 bool _entityFlag[ENTITY_RANGE];
2087 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002088
Lee Thomason624d43f2012-10-12 10:58:48 -07002089 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002090};
2091
2092
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002093} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002094
PKEuS95060352013-07-26 10:42:44 +02002095#if defined(_MSC_VER)
2096# pragma warning(pop)
2097#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002098
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002099#endif // TINYXML2_INCLUDED