blob: ffc9797803840df9e0cc53a9da53201f1ec7d371 [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 Thomasona572db12016-06-04 19:16:24 -070033# if defined(__PS3__)
34# include <stddef.h>
35# endif
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070036#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070037# include <cctype>
38# include <climits>
39# include <cstdio>
40# include <cstdlib>
41# include <cstring>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason1889c3e2016-06-04 20:22:57 -070043#include <stdint.h>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070044
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070045/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080046 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080047*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080048/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070049 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080050 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010051
Lee Thomasona9cf3f92012-10-11 16:56:51 -070052 Formatting, Artistic Style:
53 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080054*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080055
U-Lama\Lee4cee6112011-12-31 14:58:18 -080056#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070057# ifndef DEBUG
58# define DEBUG
59# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080060#endif
61
PKEuS95060352013-07-26 10:42:44 +020062#ifdef _MSC_VER
63# pragma warning(push)
64# pragma warning(disable: 4251)
65#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080066
PKEuS16ed47d2013-07-06 12:02:43 +020067#ifdef _WIN32
68# ifdef TINYXML2_EXPORT
69# define TINYXML2_LIB __declspec(dllexport)
70# elif defined(TINYXML2_IMPORT)
71# define TINYXML2_LIB __declspec(dllimport)
72# else
73# define TINYXML2_LIB
74# endif
75#else
76# define TINYXML2_LIB
77#endif
78
79
U-Lama\Lee4cee6112011-12-31 14:58:18 -080080#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070081# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030082# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070083# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070084# elif defined (ANDROID_NDK)
85# include <android/log.h>
86# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
87# else
88# include <assert.h>
89# define TIXMLASSERT assert
90# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070091#else
92# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080093#endif
94
U-Lama\Leee13c3e62011-12-28 14:36:55 -080095
Lee Thomasonc18eb232014-02-21 17:31:17 -080096/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080097 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -080098*/
Lee Thomason6ba2a072016-07-17 22:40:43 -070099static const int TIXML2_MAJOR_VERSION = 4;
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530100static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason74d44ac2016-07-17 22:57:36 -0700101static const int TIXML2_PATCH_VERSION = 1;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800102
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800103namespace tinyxml2
104{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800105class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800106class XMLElement;
107class XMLAttribute;
108class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800109class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800110class XMLDeclaration;
111class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800112class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800113
U-Stream\Leeae25a442012-02-17 17:48:16 -0800114/*
115 A class that wraps strings. Normally stores the start and end
116 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800117 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118 manage) a traditional char[]
119*/
PKEuS95060352013-07-26 10:42:44 +0200120class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800121{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800122public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700123 enum {
124 NEEDS_ENTITY_PROCESSING = 0x01,
125 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300126 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800127
selfpoisede77e1952013-03-13 14:08:29 +0800128 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700129 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800130 ATTRIBUTE_NAME = 0,
131 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
132 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
133 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700134 };
Lee Thomason39ede242012-01-20 11:27:56 -0800135
Lee Thomason120b3a62012-10-12 10:06:59 -0700136 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700137 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800138
Lee Thomason120b3a62012-10-12 10:06:59 -0700139 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700140 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700141 _start = start;
142 _end = end;
143 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700145
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700146 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700147
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700149 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 }
Lee Thomason39ede242012-01-20 11:27:56 -0800151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 void SetInternedStr( const char* str ) {
153 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700154 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700155 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700156
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800158
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 char* ParseText( char* in, const char* endTag, int strFlags );
160 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800161
Lee Thomason29658802014-11-27 22:31:11 -0800162 void TransferTo( StrPair* other );
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300163
Lee Thomason39ede242012-01-20 11:27:56 -0800164private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700165 void Reset();
166 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 enum {
169 NEEDS_FLUSH = 0x100,
170 NEEDS_DELETE = 0x200
171 };
Lee Thomasone4422302012-01-20 17:59:50 -0800172
Lee Thomason120b3a62012-10-12 10:06:59 -0700173 int _flags;
174 char* _start;
175 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300176
177 StrPair( const StrPair& other ); // not supported
178 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Dmitry-Me04009222015-04-06 18:07:18 +0300187template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200188class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800189{
190public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300191 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700192 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300193 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700194 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasonce0510b2013-11-26 21:29:37 -0800203 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100204 _size = 0;
205 }
206
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300208 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 EnsureCapacity( _size+1 );
210 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800212
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300214 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300215 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 EnsureCapacity( _size+count );
217 T* ret = &_mem[_size];
218 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 return ret;
220 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700221
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300223 TIXMLASSERT( _size > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700224 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700225 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700226
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700227 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700228 TIXMLASSERT( _size >= count );
229 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700230 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800231
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700233 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700234 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700235
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700237 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700238 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700239 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700240
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700241 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700242 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700243 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasonf07b9522014-10-30 13:25:12 -0700246 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500247 TIXMLASSERT( _size > 0 );
248 return _mem[ _size - 1];
249 }
250
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700251 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300252 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700253 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700254 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700255
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700256 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300257 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700258 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700260
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300262 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700264 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700265
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700266 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300267 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800270
Lee Thomason2c85a712012-01-31 08:24:24 -0800271private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300272 DynArray( const DynArray& ); // not supported
273 void operator=( const DynArray& ); // not supported
274
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300276 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300278 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700279 int newAllocated = cap * 2;
280 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700281 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
282 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700283 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700284 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700285 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700286 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700287 }
288 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800289
Lee Thomason624d43f2012-10-12 10:58:48 -0700290 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300291 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700292 int _allocated; // objects allocated
293 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800294};
295
Lee Thomason50adb4c2012-02-13 15:07:09 -0800296
U-Stream\Leeae25a442012-02-17 17:48:16 -0800297/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200298 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800299 and deallocation of objects.
300*/
PKEuS95060352013-07-26 10:42:44 +0200301class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800302{
303public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700304 MemPool() {}
305 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800306
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700307 virtual int ItemSize() const = 0;
308 virtual void* Alloc() = 0;
309 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800310 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700311 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800312};
313
Lee Thomason50adb4c2012-02-13 15:07:09 -0800314
U-Stream\Leeae25a442012-02-17 17:48:16 -0800315/*
316 Template child class to create pools of the correct type.
317*/
Dmitry-Me88145b82016-08-09 17:59:31 +0300318template< int ITEM_SIZE >
PKEuS95060352013-07-26 10:42:44 +0200319class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800320{
321public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800322 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700323 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700324 Clear();
325 }
326
327 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700329 while( !_blockPtrs.Empty()) {
330 Block* b = _blockPtrs.Pop();
331 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700333 _root = 0;
334 _currentAllocs = 0;
335 _nAllocs = 0;
336 _maxAllocs = 0;
337 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700338 }
Lee Thomasond1983222012-02-06 08:41:24 -0800339
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 virtual int ItemSize() const {
Dmitry-Me88145b82016-08-09 17:59:31 +0300341 return ITEM_SIZE;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 }
343 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700345 }
Lee Thomasond1983222012-02-06 08:41:24 -0800346
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700347 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700348 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 // Need a new block.
350 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700351 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800352
Dmitry-Me88145b82016-08-09 17:59:31 +0300353 Item* blockItems = block->items;
354 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
355 blockItems[i].next = &(blockItems[i + 1]);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300357 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
358 _root = blockItems;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700359 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300360 Item* const result = _root;
361 TIXMLASSERT( result != 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800363
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 ++_currentAllocs;
365 if ( _currentAllocs > _maxAllocs ) {
366 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700367 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700368 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800369 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700370 return result;
371 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700372
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 virtual void Free( void* mem ) {
374 if ( !mem ) {
375 return;
376 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700377 --_currentAllocs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300378 Item* item = static_cast<Item*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700379#ifdef DEBUG
Dmitry-Me88145b82016-08-09 17:59:31 +0300380 memset( item, 0xfe, sizeof( *item ) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700381#endif
Dmitry-Me88145b82016-08-09 17:59:31 +0300382 item->next = _root;
383 _root = item;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700384 }
385 void Trace( const char* name ) {
386 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Dmitry-Me88145b82016-08-09 17:59:31 +0300387 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
388 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700389 }
Lee Thomasond1983222012-02-06 08:41:24 -0800390
Lee Thomason5b0a6772012-11-19 13:54:42 -0800391 void SetTracked() {
392 _nUntracked--;
393 }
394
395 int Untracked() const {
396 return _nUntracked;
397 }
398
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800399 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
400 // The test file is large, 170k.
401 // Release: VS2010 gcc(no opt)
402 // 1k: 4000
403 // 2k: 4000
404 // 4k: 3900 21000
405 // 16k: 5200
406 // 32k: 4300
407 // 64k: 4000 21000
Dmitry-Me88145b82016-08-09 17:59:31 +0300408 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
409 // in private part if ITEMS_PER_BLOCK is private
410 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
Jerome Martinez7921df12012-10-24 11:45:44 +0200411
Lee Thomasond1983222012-02-06 08:41:24 -0800412private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300413 MemPoolT( const MemPoolT& ); // not supported
414 void operator=( const MemPoolT& ); // not supported
415
Dmitry-Me88145b82016-08-09 17:59:31 +0300416 union Item {
417 Item* next;
418 char itemData[ITEM_SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700419 };
420 struct Block {
Dmitry-Me88145b82016-08-09 17:59:31 +0300421 Item items[ITEMS_PER_BLOCK];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700422 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700423 DynArray< Block*, 10 > _blockPtrs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300424 Item* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800425
Lee Thomason624d43f2012-10-12 10:58:48 -0700426 int _currentAllocs;
427 int _nAllocs;
428 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800429 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800430};
431
Lee Thomason2c85a712012-01-31 08:24:24 -0800432
Lee Thomason56bdd022012-02-09 18:16:58 -0800433
434/**
435 Implements the interface to the "Visitor pattern" (see the Accept() method.)
436 If you call the Accept() method, it requires being passed a XMLVisitor
437 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200438 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800439 are simply called with Visit().
440
441 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700442 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800443
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700444 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800445 visiting). You need to only override methods that are interesting to you.
446
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600447 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800448
449 You should never change the document from a callback.
450
451 @sa XMLNode::Accept()
452*/
PKEuS16ed47d2013-07-06 12:02:43 +0200453class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800454{
455public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700456 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800457
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700458 /// Visit a document.
459 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
460 return true;
461 }
462 /// Visit a document.
463 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
464 return true;
465 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800466
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700467 /// Visit an element.
468 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
469 return true;
470 }
471 /// Visit an element.
472 virtual bool VisitExit( const XMLElement& /*element*/ ) {
473 return true;
474 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800475
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700476 /// Visit a declaration.
477 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
478 return true;
479 }
480 /// Visit a text node.
481 virtual bool Visit( const XMLText& /*text*/ ) {
482 return true;
483 }
484 /// Visit a comment node.
485 virtual bool Visit( const XMLComment& /*comment*/ ) {
486 return true;
487 }
488 /// Visit an unknown node.
489 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
490 return true;
491 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800492};
493
Dmitry-Me66d2a842014-11-08 15:24:52 +0300494// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900495enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900496 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900497 XML_NO_ATTRIBUTE,
498 XML_WRONG_ATTRIBUTE_TYPE,
499 XML_ERROR_FILE_NOT_FOUND,
500 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
501 XML_ERROR_FILE_READ_ERROR,
502 XML_ERROR_ELEMENT_MISMATCH,
503 XML_ERROR_PARSING_ELEMENT,
504 XML_ERROR_PARSING_ATTRIBUTE,
505 XML_ERROR_IDENTIFYING_TAG,
506 XML_ERROR_PARSING_TEXT,
507 XML_ERROR_PARSING_CDATA,
508 XML_ERROR_PARSING_COMMENT,
509 XML_ERROR_PARSING_DECLARATION,
510 XML_ERROR_PARSING_UNKNOWN,
511 XML_ERROR_EMPTY_DOCUMENT,
512 XML_ERROR_MISMATCHED_ELEMENT,
513 XML_ERROR_PARSING,
514 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700515 XML_NO_TEXT_NODE,
516
517 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900518};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900519
numatrumpetcd8550c2014-09-08 16:59:39 +0900520
U-Stream\Leeae25a442012-02-17 17:48:16 -0800521/*
522 Utility functionality.
523*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800524class XMLUtil
525{
Lee Thomasond1983222012-02-06 08:41:24 -0800526public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 static const char* SkipWhiteSpace( const char* p ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300528 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300529 while( IsWhiteSpace(*p) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700530 ++p;
531 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300532 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700533 return p;
534 }
535 static char* SkipWhiteSpace( char* p ) {
Dmitry-Me9de541f2014-09-24 14:21:36 +0400536 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300538
539 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
540 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100542 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700543 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200544
545 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300546 if ( ch >= 128 ) {
547 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
548 return true;
549 }
550 if ( isalpha( ch ) ) {
551 return true;
552 }
553 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200554 }
555
556 inline static bool IsNameChar( unsigned char ch ) {
557 return IsNameStartChar( ch )
558 || isdigit( ch )
559 || ch == '.'
560 || ch == '-';
561 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800562
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700563 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700564 if ( p == q ) {
565 return true;
566 }
Lee Thomason598a88d2015-10-09 14:42:12 -0700567 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700568 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200569
Dmitry-Me7865aad2015-06-19 16:23:35 +0300570 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400571 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800573
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700574 static const char* ReadBOM( const char* p, bool* hasBOM );
575 // p is the starting location,
576 // the UTF-8 value of the entity will be placed in value, and length filled in.
577 static const char* GetCharacterRef( const char* p, char* value, int* length );
578 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700579
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 // converts primitive types to strings
581 static void ToStr( int v, char* buffer, int bufferSize );
582 static void ToStr( unsigned v, char* buffer, int bufferSize );
583 static void ToStr( bool v, char* buffer, int bufferSize );
584 static void ToStr( float v, char* buffer, int bufferSize );
585 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700586 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700587
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 // converts strings to primitive types
589 static bool ToInt( const char* str, int* value );
590 static bool ToUnsigned( const char* str, unsigned* value );
591 static bool ToBool( const char* str, bool* value );
592 static bool ToFloat( const char* str, float* value );
593 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700594 static bool ToInt64(const char* str, int64_t* value);
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800595};
596
Lee Thomason5cae8972012-01-24 18:03:07 -0800597
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800598/** XMLNode is a base class for every object that is in the
599 XML Document Object Model (DOM), except XMLAttributes.
600 Nodes have siblings, a parent, and children which can
601 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700602 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800603 be cast to its more defined type.
604
Thomas Roß08bdf502012-05-12 14:21:23 +0200605 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800606 When the XMLDocument gets deleted, all its Nodes
607 will also be deleted.
608
609 @verbatim
610 A Document can contain: Element (container or leaf)
611 Comment (leaf)
612 Unknown (leaf)
613 Declaration( leaf )
614
615 An Element can contain: Element (container or leaf)
616 Text (leaf)
617 Attributes (not on tree)
618 Comment (leaf)
619 Unknown (leaf)
620
621 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800622*/
PKEuS16ed47d2013-07-06 12:02:43 +0200623class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800624{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700625 friend class XMLDocument;
626 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800627public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800628
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 /// Get the XMLDocument that owns this XMLNode.
630 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300631 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700632 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700633 }
634 /// Get the XMLDocument that owns this XMLNode.
635 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300636 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700637 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700638 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800639
Lee Thomason2fa81722012-11-09 12:37:46 -0800640 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100642 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800644 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100646 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800648 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100650 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800652 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800656 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100658 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800660 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100662 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800664
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 virtual const XMLElement* ToElement() const {
666 return 0;
667 }
668 virtual const XMLText* ToText() const {
669 return 0;
670 }
671 virtual const XMLComment* ToComment() const {
672 return 0;
673 }
674 virtual const XMLDocument* ToDocument() const {
675 return 0;
676 }
677 virtual const XMLDeclaration* ToDeclaration() const {
678 return 0;
679 }
680 virtual const XMLUnknown* ToUnknown() const {
681 return 0;
682 }
Lee Thomason751da522012-02-10 08:50:51 -0800683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 /** The meaning of 'value' changes for the specific type.
685 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530686 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 Element: name of the element
688 Comment: the comment text
689 Unknown: the tag contents
690 Text: the text string
691 @endverbatim
692 */
Michael Daumling21626882013-10-22 17:03:37 +0200693 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100694
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700695 /** Set the Value of an XML node.
696 @sa Value()
697 */
698 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800699
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 /// Get the parent of this node on the DOM.
701 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700702 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700706 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 }
Lee Thomason751da522012-02-10 08:50:51 -0800708
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 /// Returns true if this node has no children.
710 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700711 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 }
Lee Thomason751da522012-02-10 08:50:51 -0800713
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700714 /// Get the first child node, or null if none exists.
715 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700716 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100718
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700720 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100722
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 /** Get the first child element, or optionally the first child
724 element with the specified name.
725 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300726 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700727
Dmitry-Me886ad972015-07-22 11:00:51 +0300728 XMLElement* FirstChildElement( const char* name = 0 ) {
729 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700730 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800731
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 /// Get the last child node, or null if none exists.
733 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700734 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300738 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800740
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 /** Get the last child element or optionally the last child
742 element with the specified name.
743 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300744 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700745
Dmitry-Me886ad972015-07-22 11:00:51 +0300746 XMLElement* LastChildElement( const char* name = 0 ) {
747 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700748 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700749
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700750 /// Get the previous (left) sibling node of this node.
751 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700752 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700754
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700756 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800758
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700759 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300760 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700761
Dmitry-Me886ad972015-07-22 11:00:51 +0300762 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
763 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700764 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700765
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 /// Get the next (right) sibling node of this node.
767 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700768 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700770
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700772 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700774
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700775 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300776 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700777
Dmitry-Me886ad972015-07-22 11:00:51 +0300778 XMLElement* NextSiblingElement( const char* name = 0 ) {
779 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700780 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800781
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 /**
783 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200784 If the child node is already part of the document,
785 it is moved from its old location to the new location.
786 Returns the addThis argument or 0 if the node does not
787 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700788 */
789 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800790
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 XMLNode* LinkEndChild( XMLNode* addThis ) {
792 return InsertEndChild( addThis );
793 }
794 /**
795 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200796 If the child node is already part of the document,
797 it is moved from its old location to the new location.
798 Returns the addThis argument or 0 if the node does not
799 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 */
801 XMLNode* InsertFirstChild( XMLNode* addThis );
802 /**
803 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200804 If the child node is already part of the document,
805 it is moved from its old location to the new location.
806 Returns the addThis argument or 0 if the afterThis node
807 is not a child of this node, or if the node does not
808 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 */
810 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700811
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 /**
813 Delete all the children of this node.
814 */
815 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800816
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700817 /**
818 Delete a child of this node.
819 */
820 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800821
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 /**
823 Make a copy of this node, but not its children.
824 You may pass in a Document pointer that will be
825 the owner of the new Node. If the 'document' is
826 null, then the node returned will be allocated
827 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800828
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700829 Note: if called on a XMLDocument, this will return null.
830 */
831 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800832
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700833 /**
834 Test if 2 nodes are the same, but don't test children.
835 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800836
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700837 Note: if called on a XMLDocument, this will return false.
838 */
839 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800840
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600841 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700842 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600843 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800844
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600845 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
846 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800848
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800850
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700851 - http://www.saxproject.org/
852 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800853
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700854 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800855
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 An example of using Accept():
857 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600858 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700859 tinyxmlDoc.Accept( &printer );
860 const char* xmlcstr = printer.CStr();
861 @endverbatim
862 */
863 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800864
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700865 /**
866 Set user data into the XMLNode. TinyXML-2 in
867 no way processes or interprets user data.
868 It is initially 0.
869 */
870 void SetUserData(void* userData) { _userData = userData; }
871
872 /**
873 Get user data set into the XMLNode. TinyXML-2 in
874 no way processes or interprets user data.
875 It is initially 0.
876 */
877 void* GetUserData() const { return _userData; }
878
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800879protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700880 XMLNode( XMLDocument* );
881 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700882
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300883 virtual char* ParseDeep( char*, StrPair* );
884
Lee Thomason624d43f2012-10-12 10:58:48 -0700885 XMLDocument* _document;
886 XMLNode* _parent;
887 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800888
Lee Thomason624d43f2012-10-12 10:58:48 -0700889 XMLNode* _firstChild;
890 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800891
Lee Thomason624d43f2012-10-12 10:58:48 -0700892 XMLNode* _prev;
893 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800894
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700895 void* _userData;
896
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800897private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700898 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700899 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400900 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800901 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300902
903 XMLNode( const XMLNode& ); // not supported
904 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800905};
906
907
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800908/** XML text.
909
910 Note that a text node can have child element nodes, for example:
911 @verbatim
912 <root>This is <b>bold</b></root>
913 @endverbatim
914
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700915 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800916 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 -0700917 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600918 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800919*/
PKEuS16ed47d2013-07-06 12:02:43 +0200920class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800921{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800923public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700924 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800925
Lee Thomason624d43f2012-10-12 10:58:48 -0700926 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700927 return this;
928 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700929 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700930 return this;
931 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800932
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700933 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700934 void SetCData( bool isCData ) {
935 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 }
937 /// Returns true if this is a CDATA text element.
938 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700939 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700940 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800941
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700942 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
943 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800944
Lee Thomason5492a1c2012-01-23 15:32:10 -0800945protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700946 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700947 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800948
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300949 char* ParseDeep( char*, StrPair* endTag );
950
Lee Thomason5492a1c2012-01-23 15:32:10 -0800951private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700952 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300953
954 XMLText( const XMLText& ); // not supported
955 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800956};
957
958
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800959/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200960class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800961{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700962 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800963public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 virtual XMLComment* ToComment() {
965 return this;
966 }
967 virtual const XMLComment* ToComment() const {
968 return this;
969 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800970
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700971 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800972
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700973 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
974 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800975
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800976protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 XMLComment( XMLDocument* doc );
978 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800979
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300980 char* ParseDeep( char*, StrPair* endTag );
981
Lee Thomason3f57d272012-01-11 15:30:03 -0800982private:
Dmitry-Mef547a992015-01-09 15:17:09 +0300983 XMLComment( const XMLComment& ); // not supported
984 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800985};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800986
987
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800988/** In correct XML the declaration is the first entry in the file.
989 @verbatim
990 <?xml version="1.0" standalone="yes"?>
991 @endverbatim
992
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600993 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800994 however.
995
996 The text of the declaration isn't interpreted. It is parsed
997 and written as a string.
998*/
PKEuS16ed47d2013-07-06 12:02:43 +0200999class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001000{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001001 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001002public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001003 virtual XMLDeclaration* ToDeclaration() {
1004 return this;
1005 }
1006 virtual const XMLDeclaration* ToDeclaration() const {
1007 return this;
1008 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001009
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001010 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001011
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001012 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1013 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001014
1015protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 XMLDeclaration( XMLDocument* doc );
1017 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +03001018
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001019 char* ParseDeep( char*, StrPair* endTag );
1020
Dmitry-Mef547a992015-01-09 15:17:09 +03001021private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 XMLDeclaration( const XMLDeclaration& ); // not supported
1023 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001024};
1025
1026
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001027/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001028 unknown. It is a tag of text, but should not be modified.
1029 It will be written back to the XML, unchanged, when the file
1030 is saved.
1031
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001032 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001033*/
PKEuS16ed47d2013-07-06 12:02:43 +02001034class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001035{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001036 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001037public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001038 virtual XMLUnknown* ToUnknown() {
1039 return this;
1040 }
1041 virtual const XMLUnknown* ToUnknown() const {
1042 return this;
1043 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001044
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001045 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001046
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1048 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001049
1050protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 XMLUnknown( XMLDocument* doc );
1052 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001053
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001054 char* ParseDeep( char*, StrPair* endTag );
1055
Dmitry-Mef547a992015-01-09 15:17:09 +03001056private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 XMLUnknown( const XMLUnknown& ); // not supported
1058 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001059};
1060
1061
Lee Thomason1ff38e02012-02-14 18:18:16 -08001062
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001063/** An attribute is a name-value pair. Elements have an arbitrary
1064 number of attributes, each with a unique name.
1065
1066 @note The attributes are not XMLNodes. You may only query the
1067 Next() attribute in a list.
1068*/
PKEuS16ed47d2013-07-06 12:02:43 +02001069class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001070{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001071 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001072public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001073 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001074 const char* Name() const;
1075
Lee Thomason2fa81722012-11-09 12:37:46 -08001076 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001077 const char* Value() const;
1078
Lee Thomason2fa81722012-11-09 12:37:46 -08001079 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001080 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001081 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001082 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001083
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001084 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001085 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001086 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 */
Lee Thomason51c12712016-06-04 20:18:49 -07001088 int IntValue() const {
1089 int i = 0;
1090 QueryIntValue(&i);
1091 return i;
1092 }
1093
1094 int64_t Int64Value() const {
1095 int64_t i = 0;
1096 QueryInt64Value(&i);
1097 return i;
1098 }
1099
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001100 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001101 unsigned UnsignedValue() const {
1102 unsigned i=0;
1103 QueryUnsignedValue( &i );
1104 return i;
1105 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001106 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 bool BoolValue() const {
1108 bool b=false;
1109 QueryBoolValue( &b );
1110 return b;
1111 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001112 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001113 double DoubleValue() const {
1114 double d=0;
1115 QueryDoubleValue( &d );
1116 return d;
1117 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001118 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001119 float FloatValue() const {
1120 float f=0;
1121 QueryFloatValue( &f );
1122 return f;
1123 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001124
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001125 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001126 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001127 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1128 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001129 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001130 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001131 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001132 /// See QueryIntValue
1133 XMLError QueryInt64Value(int64_t* value) const;
1134 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001135 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001136 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001137 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001138 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001139 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001140
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001141 /// Set the attribute to a string value.
1142 void SetAttribute( const char* value );
1143 /// Set the attribute to value.
1144 void SetAttribute( int value );
1145 /// Set the attribute to value.
1146 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001147 /// Set the attribute to value.
1148 void SetAttribute(int64_t value);
1149 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001150 void SetAttribute( bool value );
1151 /// Set the attribute to value.
1152 void SetAttribute( double value );
1153 /// Set the attribute to value.
1154 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001155
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001156private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001157 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001158
Thomas Roß61892312013-05-12 14:07:38 +02001159 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001160 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001161
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001162 XMLAttribute( const XMLAttribute& ); // not supported
1163 void operator=( const XMLAttribute& ); // not supported
1164 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001165
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001167
Lee Thomason624d43f2012-10-12 10:58:48 -07001168 mutable StrPair _name;
1169 mutable StrPair _value;
1170 XMLAttribute* _next;
1171 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001172};
1173
1174
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001175/** The element is a container class. It has a value, the element name,
1176 and can contain other elements, text, comments, and unknowns.
1177 Elements also contain an arbitrary number of attributes.
1178*/
PKEuS16ed47d2013-07-06 12:02:43 +02001179class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001180{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001181 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001182public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001183 /// Get the name of an element (which is the Value() of the node.)
1184 const char* Name() const {
1185 return Value();
1186 }
1187 /// Set the name of the element.
1188 void SetName( const char* str, bool staticMem=false ) {
1189 SetValue( str, staticMem );
1190 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001191
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 virtual XMLElement* ToElement() {
1193 return this;
1194 }
1195 virtual const XMLElement* ToElement() const {
1196 return this;
1197 }
1198 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001199
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001200 /** Given an attribute name, Attribute() returns the value
1201 for the attribute of that name, or null if none
1202 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001203
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 @verbatim
1205 const char* value = ele->Attribute( "foo" );
1206 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001207
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 The 'value' parameter is normally null. However, if specified,
1209 the attribute will only be returned if the 'name' and 'value'
1210 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001211
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 @verbatim
1213 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1214 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001215
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 rather than:
1217 @verbatim
1218 if ( ele->Attribute( "foo" ) ) {
1219 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1220 }
1221 @endverbatim
1222 */
1223 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001224
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 /** Given an attribute name, IntAttribute() returns the value
1226 of the attribute interpreted as an integer. 0 will be
1227 returned if there is an error. For a method with error
1228 checking, see QueryIntAttribute()
1229 */
1230 int IntAttribute( const char* name ) const {
1231 int i=0;
1232 QueryIntAttribute( name, &i );
1233 return i;
1234 }
Lee Thomason51c12712016-06-04 20:18:49 -07001235
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001236 /// See IntAttribute()
1237 unsigned UnsignedAttribute( const char* name ) const {
1238 unsigned i=0;
1239 QueryUnsignedAttribute( name, &i );
1240 return i;
1241 }
Lee Thomason51c12712016-06-04 20:18:49 -07001242
1243 /// See IntAttribute()
1244 int64_t Int64Attribute(const char* name) const {
1245 int64_t i = 0;
1246 QueryInt64Attribute(name, &i);
1247 return i;
1248 }
1249
1250 /// See IntAttribute()
1251 bool BoolAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 bool b=false;
1253 QueryBoolAttribute( name, &b );
1254 return b;
1255 }
1256 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001257 double DoubleAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001258 double d=0;
1259 QueryDoubleAttribute( name, &d );
1260 return d;
1261 }
1262 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001263 float FloatAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001264 float f=0;
1265 QueryFloatAttribute( name, &f );
1266 return f;
1267 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001268
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 /** Given an attribute name, QueryIntAttribute() returns
1270 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1271 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1272 doesn't exist. If successful, the result of the conversion
1273 will be written to 'value'. If not successful, nothing will
1274 be written to 'value'. This allows you to provide default
1275 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001276
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001277 @verbatim
1278 int value = 10;
1279 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1280 @endverbatim
1281 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001282 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001283 const XMLAttribute* a = FindAttribute( name );
1284 if ( !a ) {
1285 return XML_NO_ATTRIBUTE;
1286 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001287 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001288 }
Lee Thomason51c12712016-06-04 20:18:49 -07001289
1290 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001291 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 const XMLAttribute* a = FindAttribute( name );
1293 if ( !a ) {
1294 return XML_NO_ATTRIBUTE;
1295 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001296 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001297 }
Lee Thomason51c12712016-06-04 20:18:49 -07001298
1299 /// See QueryIntAttribute()
1300 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1301 const XMLAttribute* a = FindAttribute(name);
1302 if (!a) {
1303 return XML_NO_ATTRIBUTE;
1304 }
1305 return a->QueryInt64Value(value);
1306 }
1307
1308 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001309 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001310 const XMLAttribute* a = FindAttribute( name );
1311 if ( !a ) {
1312 return XML_NO_ATTRIBUTE;
1313 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001314 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 }
1316 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001317 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 const XMLAttribute* a = FindAttribute( name );
1319 if ( !a ) {
1320 return XML_NO_ATTRIBUTE;
1321 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001322 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001323 }
1324 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001325 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 const XMLAttribute* a = FindAttribute( name );
1327 if ( !a ) {
1328 return XML_NO_ATTRIBUTE;
1329 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001330 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001331 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001332
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001333
1334 /** Given an attribute name, QueryAttribute() returns
1335 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1336 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1337 doesn't exist. It is overloaded for the primitive types,
1338 and is a generally more convenient replacement of
1339 QueryIntAttribute() and related functions.
1340
1341 If successful, the result of the conversion
1342 will be written to 'value'. If not successful, nothing will
1343 be written to 'value'. This allows you to provide default
1344 value:
1345
1346 @verbatim
1347 int value = 10;
1348 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1349 @endverbatim
1350 */
1351 int QueryAttribute( const char* name, int* value ) const {
1352 return QueryIntAttribute( name, value );
1353 }
1354
1355 int QueryAttribute( const char* name, unsigned int* value ) const {
1356 return QueryUnsignedAttribute( name, value );
1357 }
1358
Lee Thomason51c12712016-06-04 20:18:49 -07001359 int QueryAttribute(const char* name, int64_t* value) const {
1360 return QueryInt64Attribute(name, value);
1361 }
1362
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001363 int QueryAttribute( const char* name, bool* value ) const {
1364 return QueryBoolAttribute( name, value );
1365 }
1366
1367 int QueryAttribute( const char* name, double* value ) const {
1368 return QueryDoubleAttribute( name, value );
1369 }
1370
1371 int QueryAttribute( const char* name, float* value ) const {
1372 return QueryFloatAttribute( name, value );
1373 }
1374
1375 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001376 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001378 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 }
1380 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001381 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001382 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001383 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 }
1385 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001386 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001387 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001388 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001389 }
Lee Thomason51c12712016-06-04 20:18:49 -07001390
1391 /// Sets the named attribute to value.
1392 void SetAttribute(const char* name, int64_t value) {
1393 XMLAttribute* a = FindOrCreateAttribute(name);
1394 a->SetAttribute(value);
1395 }
1396
1397 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001398 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001399 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 }
1402 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001403 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001404 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001405 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001406 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001407 /// Sets the named attribute to value.
1408 void SetAttribute( const char* name, float value ) {
1409 XMLAttribute* a = FindOrCreateAttribute( name );
1410 a->SetAttribute( value );
1411 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001412
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 /**
1414 Delete an attribute.
1415 */
1416 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001417
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 /// Return the first attribute in the list.
1419 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001420 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001421 }
1422 /// Query a specific attribute in the list.
1423 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001424
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001425 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001426 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001428
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001429 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001430 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001431
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 This is a convenient method for getting the text of simple contained text:
1433 @verbatim
1434 <foo>This is text</foo>
1435 const char* str = fooElement->GetText();
1436 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001437
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001438 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001439
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001440 Note that this function can be misleading. If the element foo was created from
1441 this XML:
1442 @verbatim
1443 <foo><b>This is text</b></foo>
1444 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001445
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 then the value of str would be null. The first child node isn't a text node, it is
1447 another element. From this XML:
1448 @verbatim
1449 <foo>This is <b>text</b></foo>
1450 @endverbatim
1451 GetText() will return "This is ".
1452 */
1453 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001454
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001455 /** Convenience function for easy access to the text inside an element. Although easy
1456 and concise, SetText() is limited compared to creating an XMLText child
1457 and mutating it directly.
1458
1459 If the first child of 'this' is a XMLText, SetText() sets its value to
1460 the given string, otherwise it will create a first child that is an XMLText.
1461
1462 This is a convenient method for setting the text of simple contained text:
1463 @verbatim
1464 <foo>This is text</foo>
1465 fooElement->SetText( "Hullaballoo!" );
1466 <foo>Hullaballoo!</foo>
1467 @endverbatim
1468
1469 Note that this function can be misleading. If the element foo was created from
1470 this XML:
1471 @verbatim
1472 <foo><b>This is text</b></foo>
1473 @endverbatim
1474
1475 then it will not change "This is text", but rather prefix it with a text element:
1476 @verbatim
1477 <foo>Hullaballoo!<b>This is text</b></foo>
1478 @endverbatim
1479
1480 For this XML:
1481 @verbatim
1482 <foo />
1483 @endverbatim
1484 SetText() will generate
1485 @verbatim
1486 <foo>Hullaballoo!</foo>
1487 @endverbatim
1488 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001489 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001490 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001491 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001492 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001493 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001494 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1495 void SetText(int64_t value);
1496 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001497 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001498 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001499 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001500 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001501 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001502
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 /**
1504 Convenience method to query the value of a child text node. This is probably best
1505 shown by example. Given you have a document is this form:
1506 @verbatim
1507 <point>
1508 <x>1</x>
1509 <y>1.4</y>
1510 </point>
1511 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001512
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 The QueryIntText() and similar functions provide a safe and easier way to get to the
1514 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001515
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001516 @verbatim
1517 int x = 0;
1518 float y = 0; // types of x and y are contrived for example
1519 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1520 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1521 xElement->QueryIntText( &x );
1522 yElement->QueryFloatText( &y );
1523 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001524
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001525 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1526 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 -07001527
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001529 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001531 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001532 /// See QueryIntText()
1533 XMLError QueryInt64Text(int64_t* uval) const;
1534 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001535 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001536 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001537 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001538 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001539 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001540
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001541 // internal:
1542 enum {
1543 OPEN, // <foo>
1544 CLOSED, // <foo/>
1545 CLOSING // </foo>
1546 };
1547 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001548 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001549 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001550 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1551 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001552
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001553protected:
1554 char* ParseDeep( char* p, StrPair* endTag );
1555
Lee Thomason50adb4c2012-02-13 15:07:09 -08001556private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001557 XMLElement( XMLDocument* doc );
1558 virtual ~XMLElement();
1559 XMLElement( const XMLElement& ); // not supported
1560 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001561
Dmitry-Me1227d512014-12-05 13:41:45 +03001562 XMLAttribute* FindAttribute( const char* name ) {
1563 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1564 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001565 XMLAttribute* FindOrCreateAttribute( const char* name );
1566 //void LinkAttribute( XMLAttribute* attrib );
1567 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001568 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001569
Lee Thomason5bb2d802014-01-24 10:42:57 -08001570 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001571 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001572 // The attribute list is ordered; there is no 'lastAttribute'
1573 // because the list needs to be scanned for dupes before adding
1574 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001575 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001576};
1577
1578
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001579enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 PRESERVE_WHITESPACE,
1581 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001582};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001583
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001584
1585/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001586 It can be saved, loaded, and printed to the screen.
1587 All Nodes are connected and allocated to a Document.
1588 If the Document is deleted, all its Nodes are also deleted.
1589*/
PKEuS16ed47d2013-07-06 12:02:43 +02001590class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001591{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001593public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001594 /// constructor
1595 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1596 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001597
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001598 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001599 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 return this;
1601 }
1602 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001603 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001604 return this;
1605 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001606
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 /**
1608 Parse an XML file from a character string.
1609 Returns XML_NO_ERROR (0) on success, or
1610 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001611
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001612 You may optionally pass in the 'nBytes', which is
1613 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001614 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001615 null terminated string.
1616 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001617 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001618
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 /**
1620 Load an XML file from disk.
1621 Returns XML_NO_ERROR (0) on success, or
1622 an errorID.
1623 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001624 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001625
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 /**
1627 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001628 for providing and closing the FILE*.
1629
1630 NOTE: The file should be opened as binary ("rb")
1631 not text in order for TinyXML-2 to correctly
1632 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001633
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001634 Returns XML_NO_ERROR (0) on success, or
1635 an errorID.
1636 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001637 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001638
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001639 /**
1640 Save the XML file to disk.
1641 Returns XML_NO_ERROR (0) on success, or
1642 an errorID.
1643 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001644 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001645
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 /**
1647 Save the XML file to disk. You are responsible
1648 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001649
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 Returns XML_NO_ERROR (0) on success, or
1651 an errorID.
1652 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001653 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001654
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001655 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001656 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 }
1658 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001659 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001660 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001661
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001662 /**
1663 Returns true if this document has a leading Byte Order Mark of UTF8.
1664 */
1665 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001666 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 }
1668 /** Sets whether to write the BOM when writing the file.
1669 */
1670 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001671 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001672 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001673
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001674 /** Return the root element of DOM. Equivalent to FirstChildElement().
1675 To get the first node, use FirstChild().
1676 */
1677 XMLElement* RootElement() {
1678 return FirstChildElement();
1679 }
1680 const XMLElement* RootElement() const {
1681 return FirstChildElement();
1682 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001683
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001684 /** Print the Document. If the Printer is not provided, it will
1685 print to stdout. If you provide Printer, this can print to a file:
1686 @verbatim
1687 XMLPrinter printer( fp );
1688 doc.Print( &printer );
1689 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001690
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 Or you can use a printer to print to memory:
1692 @verbatim
1693 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001694 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001695 // printer.CStr() has a const char* to the XML
1696 @endverbatim
1697 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001698 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001699 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001700
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 /**
1702 Create a new Element associated with
1703 this Document. The memory for the Element
1704 is managed by the Document.
1705 */
1706 XMLElement* NewElement( const char* name );
1707 /**
1708 Create a new Comment associated with
1709 this Document. The memory for the Comment
1710 is managed by the Document.
1711 */
1712 XMLComment* NewComment( const char* comment );
1713 /**
1714 Create a new Text associated with
1715 this Document. The memory for the Text
1716 is managed by the Document.
1717 */
1718 XMLText* NewText( const char* text );
1719 /**
1720 Create a new Declaration associated with
1721 this Document. The memory for the object
1722 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001723
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 If the 'text' param is null, the standard
1725 declaration is used.:
1726 @verbatim
1727 <?xml version="1.0" encoding="UTF-8"?>
1728 @endverbatim
1729 */
1730 XMLDeclaration* NewDeclaration( const char* text=0 );
1731 /**
1732 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001733 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001734 is managed by the Document.
1735 */
1736 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001737
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001738 /**
1739 Delete a node associated with this document.
1740 It will be unlinked from the DOM.
1741 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001742 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001743
Lee Thomason2fa81722012-11-09 12:37:46 -08001744 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001745
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001746 /// Return true if there was an error parsing the document.
1747 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001748 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001749 }
1750 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001751 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001752 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 }
Lee Thomason331596e2014-09-11 14:56:43 -07001754 const char* ErrorName() const;
1755
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 /// Return a possibly helpful diagnostic location or string.
1757 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001758 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001759 }
1760 /// Return a possibly helpful secondary diagnostic location or string.
1761 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001762 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001763 }
1764 /// If there is an error, print it to stdout.
1765 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001766
1767 /// Clear the document, resetting it to the initial state.
1768 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001769
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001770 // internal
1771 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001772
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001773 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1774 return 0;
1775 }
1776 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1777 return false;
1778 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001779
Lee Thomason3f57d272012-01-11 15:30:03 -08001780private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001781 XMLDocument( const XMLDocument& ); // not supported
1782 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001783
Lee Thomason2fa81722012-11-09 12:37:46 -08001784 bool _writeBOM;
1785 bool _processEntities;
1786 XMLError _errorID;
1787 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001788 const char* _errorStr1;
1789 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001790 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001791
Lee Thomason624d43f2012-10-12 10:58:48 -07001792 MemPoolT< sizeof(XMLElement) > _elementPool;
1793 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1794 MemPoolT< sizeof(XMLText) > _textPool;
1795 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001796
1797 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001798
1799 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001800};
1801
Lee Thomason7c913cd2012-01-26 18:32:34 -08001802
Lee Thomason3ffdd392012-03-28 17:27:55 -07001803/**
1804 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001805 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001806 DOM structure. It is a separate utility class.
1807
1808 Take an example:
1809 @verbatim
1810 <Document>
1811 <Element attributeA = "valueA">
1812 <Child attributeB = "value1" />
1813 <Child attributeB = "value2" />
1814 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001815 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001816 @endverbatim
1817
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001818 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001819 easy to write a *lot* of code that looks like:
1820
1821 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001822 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001823 if ( root )
1824 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001825 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001826 if ( element )
1827 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001828 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001829 if ( child )
1830 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001831 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001832 if ( child2 )
1833 {
1834 // Finally do something useful.
1835 @endverbatim
1836
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001837 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001838 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001839 and correct to use:
1840
1841 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001842 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001843 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001844 if ( child2 )
1845 {
1846 // do something useful
1847 @endverbatim
1848
1849 Which is MUCH more concise and useful.
1850
1851 It is also safe to copy handles - internally they are nothing more than node pointers.
1852 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001853 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001854 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001855
1856 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001857*/
PKEuS16ed47d2013-07-06 12:02:43 +02001858class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001859{
1860public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001861 /// 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 -07001862 XMLHandle( XMLNode* node ) {
1863 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001864 }
1865 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001866 XMLHandle( XMLNode& node ) {
1867 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001868 }
1869 /// Copy constructor
1870 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001871 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 }
1873 /// Assignment
1874 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001875 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001876 return *this;
1877 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001878
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001879 /// Get the first child of this handle.
1880 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001881 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 }
1883 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001884 XMLHandle FirstChildElement( const char* name = 0 ) {
1885 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001886 }
1887 /// Get the last child of this handle.
1888 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001889 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 }
1891 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001892 XMLHandle LastChildElement( const char* name = 0 ) {
1893 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001894 }
1895 /// Get the previous sibling of this handle.
1896 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001897 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001900 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1901 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001902 }
1903 /// Get the next sibling of this handle.
1904 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001905 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001906 }
1907 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001908 XMLHandle NextSiblingElement( const char* name = 0 ) {
1909 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001910 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001911
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001912 /// Safe cast to XMLNode. This can return null.
1913 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001914 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001915 }
1916 /// Safe cast to XMLElement. This can return null.
1917 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001918 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001919 }
1920 /// Safe cast to XMLText. This can return null.
1921 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001922 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001923 }
1924 /// Safe cast to XMLUnknown. This can return null.
1925 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001926 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001927 }
1928 /// Safe cast to XMLDeclaration. This can return null.
1929 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001930 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001932
1933private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001934 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001935};
1936
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001937
1938/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001939 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1940 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001941*/
PKEuS16ed47d2013-07-06 12:02:43 +02001942class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001943{
1944public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001945 XMLConstHandle( const XMLNode* node ) {
1946 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001948 XMLConstHandle( const XMLNode& node ) {
1949 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 }
1951 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001952 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001953 }
Lee Thomason8b899812012-04-04 15:58:16 -07001954
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001956 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001957 return *this;
1958 }
Lee Thomason8b899812012-04-04 15:58:16 -07001959
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001960 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001961 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001962 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001963 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1964 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001965 }
1966 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001967 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001968 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001969 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1970 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 }
1972 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001973 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001974 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001975 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1976 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001977 }
1978 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001979 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001980 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001981 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1982 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001983 }
Lee Thomason8b899812012-04-04 15:58:16 -07001984
1985
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001986 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001987 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001988 }
1989 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001990 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001991 }
1992 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001993 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001994 }
1995 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001996 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001997 }
1998 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001999 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002000 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002001
Lee Thomason5cae8972012-01-24 18:03:07 -08002002private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002003 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002004};
Lee Thomason6f381b72012-03-02 12:59:39 -08002005
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002006
2007/**
2008 Printing functionality. The XMLPrinter gives you more
2009 options than the XMLDocument::Print() method.
2010
2011 It can:
2012 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002013 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002014 -# Print XML without a XMLDocument.
2015
2016 Print to Memory
2017
2018 @verbatim
2019 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002020 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002021 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002022 @endverbatim
2023
2024 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002025
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002026 You provide the file pointer.
2027 @verbatim
2028 XMLPrinter printer( fp );
2029 doc.Print( &printer );
2030 @endverbatim
2031
2032 Print without a XMLDocument
2033
2034 When loading, an XML parser is very useful. However, sometimes
2035 when saving, it just gets in the way. The code is often set up
2036 for streaming, and constructing the DOM is just overhead.
2037
2038 The Printer supports the streaming case. The following code
2039 prints out a trivially simple XML file without ever creating
2040 an XML document.
2041
2042 @verbatim
2043 XMLPrinter printer( fp );
2044 printer.OpenElement( "foo" );
2045 printer.PushAttribute( "foo", "bar" );
2046 printer.CloseElement();
2047 @endverbatim
2048*/
PKEuS16ed47d2013-07-06 12:02:43 +02002049class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002050{
2051public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002052 /** Construct the printer. If the FILE* is specified,
2053 this will print to the FILE. Else it will print
2054 to memory, and the result is available in CStr().
2055 If 'compact' is set to true, then output is created
2056 with only required whitespace and newlines.
2057 */
PKEuS1bfb9542013-08-04 13:51:17 +02002058 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002059 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002060
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002061 /** If streaming, write the BOM and declaration. */
2062 void PushHeader( bool writeBOM, bool writeDeclaration );
2063 /** If streaming, start writing an element.
2064 The element must be closed with CloseElement()
2065 */
Lee Thomason256adb62014-04-06 14:41:46 -07002066 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002067 /// If streaming, add an attribute to an open element.
2068 void PushAttribute( const char* name, const char* value );
2069 void PushAttribute( const char* name, int value );
2070 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002071 void PushAttribute(const char* name, int64_t value);
2072 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002073 void PushAttribute( const char* name, double value );
2074 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002075 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002076
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002077 /// Add a text node.
2078 void PushText( const char* text, bool cdata=false );
2079 /// Add a text node from an integer.
2080 void PushText( int value );
2081 /// Add a text node from an unsigned.
2082 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002083 /// Add a text node from an unsigned.
2084 void PushText(int64_t value);
2085 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002086 void PushText( bool value );
2087 /// Add a text node from a float.
2088 void PushText( float value );
2089 /// Add a text node from a double.
2090 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002091
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002092 /// Add a comment
2093 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002094
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002095 void PushDeclaration( const char* value );
2096 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002097
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002098 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2099 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2100 return true;
2101 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002102
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002103 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2104 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002105
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002106 virtual bool Visit( const XMLText& text );
2107 virtual bool Visit( const XMLComment& comment );
2108 virtual bool Visit( const XMLDeclaration& declaration );
2109 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002110
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002111 /**
2112 If in print to memory mode, return a pointer to
2113 the XML file in memory.
2114 */
2115 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002116 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002117 }
2118 /**
2119 If in print to memory mode, return the size
2120 of the XML file in memory. (Note the size returned
2121 includes the terminating null.)
2122 */
2123 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002124 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002125 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002126 /**
2127 If in print to memory mode, reset the buffer to the
2128 beginning.
2129 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002130 void ClearBuffer() {
2131 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002132 _buffer.Push(0);
2133 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002134
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002135protected:
Alexander Maid740b642014-05-20 22:04:42 +02002136 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002137
Lee Thomasonc18eb232014-02-21 17:31:17 -08002138 /** Prints out the space before an element. You may override to change
2139 the space and tabs used. A PrintSpace() override should call Print().
2140 */
2141 virtual void PrintSpace( int depth );
2142 void Print( const char* format, ... );
2143
Dmitry-Mea092bc12014-12-23 17:57:05 +03002144 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002145 bool _elementJustOpened;
2146 DynArray< const char*, 10 > _stack;
2147
2148private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002149 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002150
Lee Thomason624d43f2012-10-12 10:58:48 -07002151 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002152 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002153 int _depth;
2154 int _textDepth;
2155 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002156 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002157
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002158 enum {
2159 ENTITY_RANGE = 64,
2160 BUF_SIZE = 200
2161 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002162 bool _entityFlag[ENTITY_RANGE];
2163 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002164
Lee Thomason624d43f2012-10-12 10:58:48 -07002165 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002166};
2167
2168
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002169} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002170
PKEuS95060352013-07-26 10:42:44 +02002171#if defined(_MSC_VER)
2172# pragma warning(pop)
2173#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002174
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002175#endif // TINYXML2_INCLUDED