blob: 332e124ce02dbbaaceb364909e6b33d2ced8d159 [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
Matthew Woehlkea8e7ea72016-08-09 13:16:26 -040075#elif __GNUC__ >= 4
76# define TINYXML2_LIB __attribute__((visibility("default")))
PKEuS16ed47d2013-07-06 12:02:43 +020077#else
78# define TINYXML2_LIB
79#endif
80
81
U-Lama\Lee4cee6112011-12-31 14:58:18 -080082#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070083# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030084# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070085# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070086# elif defined (ANDROID_NDK)
87# include <android/log.h>
88# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89# else
90# include <assert.h>
91# define TIXMLASSERT assert
92# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070093#else
94# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080095#endif
96
U-Lama\Leee13c3e62011-12-28 14:36:55 -080097
Lee Thomasonc18eb232014-02-21 17:31:17 -080098/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080099 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800100*/
Lee Thomason6ba2a072016-07-17 22:40:43 -0700101static const int TIXML2_MAJOR_VERSION = 4;
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason74d44ac2016-07-17 22:57:36 -0700103static const int TIXML2_PATCH_VERSION = 1;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800111class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800112class XMLDeclaration;
113class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800114class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800115
U-Stream\Leeae25a442012-02-17 17:48:16 -0800116/*
117 A class that wraps strings. Normally stores the start and end
118 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800119 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800120 manage) a traditional char[]
121*/
PKEuS95060352013-07-26 10:42:44 +0200122class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800123{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800124public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700125 enum {
126 NEEDS_ENTITY_PROCESSING = 0x01,
127 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300128 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800129
selfpoisede77e1952013-03-13 14:08:29 +0800130 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700131 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800132 ATTRIBUTE_NAME = 0,
133 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
134 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
135 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700136 };
Lee Thomason39ede242012-01-20 11:27:56 -0800137
Lee Thomason120b3a62012-10-12 10:06:59 -0700138 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700139 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800140
Lee Thomason120b3a62012-10-12 10:06:59 -0700141 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700142 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 _start = start;
144 _end = end;
145 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700146 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700147
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700151 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 }
Lee Thomason39ede242012-01-20 11:27:56 -0800153
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 void SetInternedStr( const char* str ) {
155 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700158
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 char* ParseText( char* in, const char* endTag, int strFlags );
162 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800163
Lee Thomason29658802014-11-27 22:31:11 -0800164 void TransferTo( StrPair* other );
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomason120b3a62012-10-12 10:06:59 -0700175 int _flags;
176 char* _start;
177 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300178
179 StrPair( const StrPair& other ); // not supported
180 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800181};
182
U-Lama\Lee560bd472011-12-28 19:42:49 -0800183
U-Stream\Leeae25a442012-02-17 17:48:16 -0800184/*
185 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
186 Has a small initial memory pool, so that low or no usage will not
187 cause a call to new/delete
188*/
Dmitry-Me04009222015-04-06 18:07:18 +0300189template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200190class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800191{
192public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300193 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700194 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300195 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700196 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700198
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700199 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700200 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700201 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700202 }
203 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700204
Lee Thomasonce0510b2013-11-26 21:29:37 -0800205 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100206 _size = 0;
207 }
208
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700209 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300210 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700211 EnsureCapacity( _size+1 );
212 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300216 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300217 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700218 EnsureCapacity( _size+count );
219 T* ret = &_mem[_size];
220 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700221 return ret;
222 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300225 TIXMLASSERT( _size > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700226 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700227 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700228
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700229 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700230 TIXMLASSERT( _size >= count );
231 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800233
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700234 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700235 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700240 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700241 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700242
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700243 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700244 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700245 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700247
Lee Thomasonf07b9522014-10-30 13:25:12 -0700248 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500249 TIXMLASSERT( _size > 0 );
250 return _mem[ _size - 1];
251 }
252
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700253 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300254 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700255 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700256 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700257
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700258 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300259 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300264 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700265 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700266 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700267
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300269 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700270 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800272
Lee Thomason2c85a712012-01-31 08:24:24 -0800273private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300274 DynArray( const DynArray& ); // not supported
275 void operator=( const DynArray& ); // not supported
276
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700277 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300278 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700279 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300280 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700281 int newAllocated = cap * 2;
282 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700283 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
284 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700285 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700286 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700287 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700288 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700289 }
290 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800291
Lee Thomason624d43f2012-10-12 10:58:48 -0700292 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300293 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700294 int _allocated; // objects allocated
295 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800296};
297
Lee Thomason50adb4c2012-02-13 15:07:09 -0800298
U-Stream\Leeae25a442012-02-17 17:48:16 -0800299/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200300 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800301 and deallocation of objects.
302*/
PKEuS95060352013-07-26 10:42:44 +0200303class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800304{
305public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 MemPool() {}
307 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800308
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700309 virtual int ItemSize() const = 0;
310 virtual void* Alloc() = 0;
311 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800312 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700313 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800314};
315
Lee Thomason50adb4c2012-02-13 15:07:09 -0800316
U-Stream\Leeae25a442012-02-17 17:48:16 -0800317/*
318 Template child class to create pools of the correct type.
319*/
Dmitry-Me88145b82016-08-09 17:59:31 +0300320template< int ITEM_SIZE >
PKEuS95060352013-07-26 10:42:44 +0200321class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800322{
323public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800324 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700326 Clear();
327 }
328
329 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700330 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700331 while( !_blockPtrs.Empty()) {
332 Block* b = _blockPtrs.Pop();
333 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700334 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700335 _root = 0;
336 _currentAllocs = 0;
337 _nAllocs = 0;
338 _maxAllocs = 0;
339 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 }
Lee Thomasond1983222012-02-06 08:41:24 -0800341
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 virtual int ItemSize() const {
Dmitry-Me88145b82016-08-09 17:59:31 +0300343 return ITEM_SIZE;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 }
345 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700347 }
Lee Thomasond1983222012-02-06 08:41:24 -0800348
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700351 // Need a new block.
352 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700353 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800354
Dmitry-Me88145b82016-08-09 17:59:31 +0300355 Item* blockItems = block->items;
356 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
357 blockItems[i].next = &(blockItems[i + 1]);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700358 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300359 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
360 _root = blockItems;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300362 Item* const result = _root;
363 TIXMLASSERT( result != 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800365
Lee Thomason624d43f2012-10-12 10:58:48 -0700366 ++_currentAllocs;
367 if ( _currentAllocs > _maxAllocs ) {
368 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700370 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800371 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700372 return result;
373 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700374
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700375 virtual void Free( void* mem ) {
376 if ( !mem ) {
377 return;
378 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700379 --_currentAllocs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300380 Item* item = static_cast<Item*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700381#ifdef DEBUG
Dmitry-Me88145b82016-08-09 17:59:31 +0300382 memset( item, 0xfe, sizeof( *item ) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700383#endif
Dmitry-Me88145b82016-08-09 17:59:31 +0300384 item->next = _root;
385 _root = item;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700386 }
387 void Trace( const char* name ) {
388 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Dmitry-Me88145b82016-08-09 17:59:31 +0300389 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
390 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700391 }
Lee Thomasond1983222012-02-06 08:41:24 -0800392
Lee Thomason5b0a6772012-11-19 13:54:42 -0800393 void SetTracked() {
394 _nUntracked--;
395 }
396
397 int Untracked() const {
398 return _nUntracked;
399 }
400
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800401 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
402 // The test file is large, 170k.
403 // Release: VS2010 gcc(no opt)
404 // 1k: 4000
405 // 2k: 4000
406 // 4k: 3900 21000
407 // 16k: 5200
408 // 32k: 4300
409 // 64k: 4000 21000
Dmitry-Me88145b82016-08-09 17:59:31 +0300410 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
411 // in private part if ITEMS_PER_BLOCK is private
412 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
Jerome Martinez7921df12012-10-24 11:45:44 +0200413
Lee Thomasond1983222012-02-06 08:41:24 -0800414private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300415 MemPoolT( const MemPoolT& ); // not supported
416 void operator=( const MemPoolT& ); // not supported
417
Dmitry-Me88145b82016-08-09 17:59:31 +0300418 union Item {
419 Item* next;
420 char itemData[ITEM_SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700421 };
422 struct Block {
Dmitry-Me88145b82016-08-09 17:59:31 +0300423 Item items[ITEMS_PER_BLOCK];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700424 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700425 DynArray< Block*, 10 > _blockPtrs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300426 Item* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800427
Lee Thomason624d43f2012-10-12 10:58:48 -0700428 int _currentAllocs;
429 int _nAllocs;
430 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800431 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800432};
433
Lee Thomason2c85a712012-01-31 08:24:24 -0800434
Lee Thomason56bdd022012-02-09 18:16:58 -0800435
436/**
437 Implements the interface to the "Visitor pattern" (see the Accept() method.)
438 If you call the Accept() method, it requires being passed a XMLVisitor
439 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200440 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800441 are simply called with Visit().
442
443 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700444 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800445
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700446 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800447 visiting). You need to only override methods that are interesting to you.
448
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600449 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800450
451 You should never change the document from a callback.
452
453 @sa XMLNode::Accept()
454*/
PKEuS16ed47d2013-07-06 12:02:43 +0200455class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800456{
457public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700458 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800459
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700460 /// Visit a document.
461 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
462 return true;
463 }
464 /// Visit a document.
465 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
466 return true;
467 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800468
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700469 /// Visit an element.
470 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
471 return true;
472 }
473 /// Visit an element.
474 virtual bool VisitExit( const XMLElement& /*element*/ ) {
475 return true;
476 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800477
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700478 /// Visit a declaration.
479 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
480 return true;
481 }
482 /// Visit a text node.
483 virtual bool Visit( const XMLText& /*text*/ ) {
484 return true;
485 }
486 /// Visit a comment node.
487 virtual bool Visit( const XMLComment& /*comment*/ ) {
488 return true;
489 }
490 /// Visit an unknown node.
491 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
492 return true;
493 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800494};
495
Dmitry-Me66d2a842014-11-08 15:24:52 +0300496// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900497enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900498 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900499 XML_NO_ATTRIBUTE,
500 XML_WRONG_ATTRIBUTE_TYPE,
501 XML_ERROR_FILE_NOT_FOUND,
502 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
503 XML_ERROR_FILE_READ_ERROR,
504 XML_ERROR_ELEMENT_MISMATCH,
505 XML_ERROR_PARSING_ELEMENT,
506 XML_ERROR_PARSING_ATTRIBUTE,
507 XML_ERROR_IDENTIFYING_TAG,
508 XML_ERROR_PARSING_TEXT,
509 XML_ERROR_PARSING_CDATA,
510 XML_ERROR_PARSING_COMMENT,
511 XML_ERROR_PARSING_DECLARATION,
512 XML_ERROR_PARSING_UNKNOWN,
513 XML_ERROR_EMPTY_DOCUMENT,
514 XML_ERROR_MISMATCHED_ELEMENT,
515 XML_ERROR_PARSING,
516 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700517 XML_NO_TEXT_NODE,
518
519 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900520};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900521
numatrumpetcd8550c2014-09-08 16:59:39 +0900522
U-Stream\Leeae25a442012-02-17 17:48:16 -0800523/*
524 Utility functionality.
525*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800526class XMLUtil
527{
Lee Thomasond1983222012-02-06 08:41:24 -0800528public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700529 static const char* SkipWhiteSpace( const char* p ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300530 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300531 while( IsWhiteSpace(*p) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700532 ++p;
533 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300534 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700535 return p;
536 }
537 static char* SkipWhiteSpace( char* p ) {
Dmitry-Me9de541f2014-09-24 14:21:36 +0400538 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700539 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300540
541 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
542 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700543 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100544 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700545 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200546
547 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300548 if ( ch >= 128 ) {
549 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
550 return true;
551 }
552 if ( isalpha( ch ) ) {
553 return true;
554 }
555 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200556 }
557
558 inline static bool IsNameChar( unsigned char ch ) {
559 return IsNameStartChar( ch )
560 || isdigit( ch )
561 || ch == '.'
562 || ch == '-';
563 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800564
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700565 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700566 if ( p == q ) {
567 return true;
568 }
Lee Thomason598a88d2015-10-09 14:42:12 -0700569 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700570 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200571
Dmitry-Me7865aad2015-06-19 16:23:35 +0300572 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400573 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700574 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800575
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 static const char* ReadBOM( const char* p, bool* hasBOM );
577 // p is the starting location,
578 // the UTF-8 value of the entity will be placed in value, and length filled in.
579 static const char* GetCharacterRef( const char* p, char* value, int* length );
580 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700581
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700582 // converts primitive types to strings
583 static void ToStr( int v, char* buffer, int bufferSize );
584 static void ToStr( unsigned v, char* buffer, int bufferSize );
585 static void ToStr( bool v, char* buffer, int bufferSize );
586 static void ToStr( float v, char* buffer, int bufferSize );
587 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700588 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700589
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700590 // converts strings to primitive types
591 static bool ToInt( const char* str, int* value );
592 static bool ToUnsigned( const char* str, unsigned* value );
593 static bool ToBool( const char* str, bool* value );
594 static bool ToFloat( const char* str, float* value );
595 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700596 static bool ToInt64(const char* str, int64_t* value);
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800597};
598
Lee Thomason5cae8972012-01-24 18:03:07 -0800599
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800600/** XMLNode is a base class for every object that is in the
601 XML Document Object Model (DOM), except XMLAttributes.
602 Nodes have siblings, a parent, and children which can
603 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700604 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800605 be cast to its more defined type.
606
Thomas Roß08bdf502012-05-12 14:21:23 +0200607 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800608 When the XMLDocument gets deleted, all its Nodes
609 will also be deleted.
610
611 @verbatim
612 A Document can contain: Element (container or leaf)
613 Comment (leaf)
614 Unknown (leaf)
615 Declaration( leaf )
616
617 An Element can contain: Element (container or leaf)
618 Text (leaf)
619 Attributes (not on tree)
620 Comment (leaf)
621 Unknown (leaf)
622
623 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800624*/
PKEuS16ed47d2013-07-06 12:02:43 +0200625class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800626{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700627 friend class XMLDocument;
628 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800629public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800630
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700631 /// Get the XMLDocument that owns this XMLNode.
632 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300633 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700634 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700635 }
636 /// Get the XMLDocument that owns this XMLNode.
637 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300638 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700639 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700640 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800641
Lee Thomason2fa81722012-11-09 12:37:46 -0800642 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700643 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100644 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800646 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100648 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800650 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100652 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800654 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100656 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800658 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100660 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800662 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100664 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800666
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 virtual const XMLElement* ToElement() const {
668 return 0;
669 }
670 virtual const XMLText* ToText() const {
671 return 0;
672 }
673 virtual const XMLComment* ToComment() const {
674 return 0;
675 }
676 virtual const XMLDocument* ToDocument() const {
677 return 0;
678 }
679 virtual const XMLDeclaration* ToDeclaration() const {
680 return 0;
681 }
682 virtual const XMLUnknown* ToUnknown() const {
683 return 0;
684 }
Lee Thomason751da522012-02-10 08:50:51 -0800685
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 /** The meaning of 'value' changes for the specific type.
687 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530688 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700689 Element: name of the element
690 Comment: the comment text
691 Unknown: the tag contents
692 Text: the text string
693 @endverbatim
694 */
Michael Daumling21626882013-10-22 17:03:37 +0200695 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100696
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 /** Set the Value of an XML node.
698 @sa Value()
699 */
700 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800701
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700702 /// Get the parent of this node on the DOM.
703 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700704 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100706
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700708 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 }
Lee Thomason751da522012-02-10 08:50:51 -0800710
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700711 /// Returns true if this node has no children.
712 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700713 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700714 }
Lee Thomason751da522012-02-10 08:50:51 -0800715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 /// Get the first child node, or null if none exists.
717 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700718 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700722 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100724
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700725 /** Get the first child element, or optionally the first child
726 element with the specified name.
727 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300728 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700729
Dmitry-Me886ad972015-07-22 11:00:51 +0300730 XMLElement* FirstChildElement( const char* name = 0 ) {
731 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 /// Get the last child node, or null if none exists.
735 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700736 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700738
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300740 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800742
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 /** Get the last child element or optionally the last child
744 element with the specified name.
745 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300746 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700747
Dmitry-Me886ad972015-07-22 11:00:51 +0300748 XMLElement* LastChildElement( const char* name = 0 ) {
749 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700750 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700751
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 /// Get the previous (left) sibling node of this node.
753 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700754 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700756
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700758 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700759 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800760
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700761 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300762 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700763
Dmitry-Me886ad972015-07-22 11:00:51 +0300764 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
765 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700767
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 /// Get the next (right) sibling node of this node.
769 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700770 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700772
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700774 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700776
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700777 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300778 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700779
Dmitry-Me886ad972015-07-22 11:00:51 +0300780 XMLElement* NextSiblingElement( const char* name = 0 ) {
781 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800783
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 /**
785 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200786 If the child node is already part of the document,
787 it is moved from its old location to the new location.
788 Returns the addThis argument or 0 if the node does not
789 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 */
791 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800792
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 XMLNode* LinkEndChild( XMLNode* addThis ) {
794 return InsertEndChild( addThis );
795 }
796 /**
797 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200798 If the child node is already part of the document,
799 it is moved from its old location to the new location.
800 Returns the addThis argument or 0 if the node does not
801 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700802 */
803 XMLNode* InsertFirstChild( XMLNode* addThis );
804 /**
805 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200806 If the child node is already part of the document,
807 it is moved from its old location to the new location.
808 Returns the addThis argument or 0 if the afterThis node
809 is not a child of this node, or if the node does not
810 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 */
812 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700813
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700814 /**
815 Delete all the children of this node.
816 */
817 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800818
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 /**
820 Delete a child of this node.
821 */
822 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800823
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700824 /**
825 Make a copy of this node, but not its children.
826 You may pass in a Document pointer that will be
827 the owner of the new Node. If the 'document' is
828 null, then the node returned will be allocated
829 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800830
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700831 Note: if called on a XMLDocument, this will return null.
832 */
833 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800834
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700835 /**
836 Test if 2 nodes are the same, but don't test children.
837 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800838
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700839 Note: if called on a XMLDocument, this will return false.
840 */
841 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800842
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600843 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600845 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800846
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600847 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
848 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800850
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700851 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800852
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700853 - http://www.saxproject.org/
854 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800855
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800857
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700858 An example of using Accept():
859 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600860 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700861 tinyxmlDoc.Accept( &printer );
862 const char* xmlcstr = printer.CStr();
863 @endverbatim
864 */
865 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800866
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700867 /**
868 Set user data into the XMLNode. TinyXML-2 in
869 no way processes or interprets user data.
870 It is initially 0.
871 */
872 void SetUserData(void* userData) { _userData = userData; }
873
874 /**
875 Get user data set into the XMLNode. TinyXML-2 in
876 no way processes or interprets user data.
877 It is initially 0.
878 */
879 void* GetUserData() const { return _userData; }
880
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800881protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700882 XMLNode( XMLDocument* );
883 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700884
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300885 virtual char* ParseDeep( char*, StrPair* );
886
Lee Thomason624d43f2012-10-12 10:58:48 -0700887 XMLDocument* _document;
888 XMLNode* _parent;
889 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800890
Lee Thomason624d43f2012-10-12 10:58:48 -0700891 XMLNode* _firstChild;
892 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800893
Lee Thomason624d43f2012-10-12 10:58:48 -0700894 XMLNode* _prev;
895 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800896
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700897 void* _userData;
898
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800899private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700900 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700901 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400902 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800903 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300904
905 XMLNode( const XMLNode& ); // not supported
906 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800907};
908
909
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800910/** XML text.
911
912 Note that a text node can have child element nodes, for example:
913 @verbatim
914 <root>This is <b>bold</b></root>
915 @endverbatim
916
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700917 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800918 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 -0700919 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600920 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800921*/
PKEuS16ed47d2013-07-06 12:02:43 +0200922class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800923{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700924 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800925public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700926 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800927
Lee Thomason624d43f2012-10-12 10:58:48 -0700928 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700929 return this;
930 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700931 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700932 return this;
933 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800934
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700935 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700936 void SetCData( bool isCData ) {
937 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700938 }
939 /// Returns true if this is a CDATA text element.
940 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700941 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700942 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800943
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
945 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800946
Lee Thomason5492a1c2012-01-23 15:32:10 -0800947protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700948 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700949 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800950
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300951 char* ParseDeep( char*, StrPair* endTag );
952
Lee Thomason5492a1c2012-01-23 15:32:10 -0800953private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700954 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300955
956 XMLText( const XMLText& ); // not supported
957 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800958};
959
960
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800961/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200962class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800963{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800965public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 virtual XMLComment* ToComment() {
967 return this;
968 }
969 virtual const XMLComment* ToComment() const {
970 return this;
971 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800972
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700973 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800974
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700975 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
976 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800977
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800978protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700979 XMLComment( XMLDocument* doc );
980 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800981
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300982 char* ParseDeep( char*, StrPair* endTag );
983
Lee Thomason3f57d272012-01-11 15:30:03 -0800984private:
Dmitry-Mef547a992015-01-09 15:17:09 +0300985 XMLComment( const XMLComment& ); // not supported
986 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800987};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800988
989
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800990/** In correct XML the declaration is the first entry in the file.
991 @verbatim
992 <?xml version="1.0" standalone="yes"?>
993 @endverbatim
994
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600995 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800996 however.
997
998 The text of the declaration isn't interpreted. It is parsed
999 and written as a string.
1000*/
PKEuS16ed47d2013-07-06 12:02:43 +02001001class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001002{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001003 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001004public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001005 virtual XMLDeclaration* ToDeclaration() {
1006 return this;
1007 }
1008 virtual const XMLDeclaration* ToDeclaration() const {
1009 return this;
1010 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001011
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001012 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001013
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1015 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001016
1017protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 XMLDeclaration( XMLDocument* doc );
1019 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +03001020
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001021 char* ParseDeep( char*, StrPair* endTag );
1022
Dmitry-Mef547a992015-01-09 15:17:09 +03001023private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001024 XMLDeclaration( const XMLDeclaration& ); // not supported
1025 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001026};
1027
1028
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001029/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001030 unknown. It is a tag of text, but should not be modified.
1031 It will be written back to the XML, unchanged, when the file
1032 is saved.
1033
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001034 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001035*/
PKEuS16ed47d2013-07-06 12:02:43 +02001036class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001037{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001038 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001039public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001040 virtual XMLUnknown* ToUnknown() {
1041 return this;
1042 }
1043 virtual const XMLUnknown* ToUnknown() const {
1044 return this;
1045 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001046
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001048
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001049 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1050 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001051
1052protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 XMLUnknown( XMLDocument* doc );
1054 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001055
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001056 char* ParseDeep( char*, StrPair* endTag );
1057
Dmitry-Mef547a992015-01-09 15:17:09 +03001058private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001059 XMLUnknown( const XMLUnknown& ); // not supported
1060 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001061};
1062
1063
Lee Thomason1ff38e02012-02-14 18:18:16 -08001064
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001065/** An attribute is a name-value pair. Elements have an arbitrary
1066 number of attributes, each with a unique name.
1067
1068 @note The attributes are not XMLNodes. You may only query the
1069 Next() attribute in a list.
1070*/
PKEuS16ed47d2013-07-06 12:02:43 +02001071class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001072{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001074public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001075 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001076 const char* Name() const;
1077
Lee Thomason2fa81722012-11-09 12:37:46 -08001078 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001079 const char* Value() const;
1080
Lee Thomason2fa81722012-11-09 12:37:46 -08001081 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001082 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001083 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001084 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001085
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001086 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001088 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001089 */
Lee Thomason51c12712016-06-04 20:18:49 -07001090 int IntValue() const {
1091 int i = 0;
1092 QueryIntValue(&i);
1093 return i;
1094 }
1095
1096 int64_t Int64Value() const {
1097 int64_t i = 0;
1098 QueryInt64Value(&i);
1099 return i;
1100 }
1101
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001102 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001103 unsigned UnsignedValue() const {
1104 unsigned i=0;
1105 QueryUnsignedValue( &i );
1106 return i;
1107 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001108 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001109 bool BoolValue() const {
1110 bool b=false;
1111 QueryBoolValue( &b );
1112 return b;
1113 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001114 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001115 double DoubleValue() const {
1116 double d=0;
1117 QueryDoubleValue( &d );
1118 return d;
1119 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001120 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001121 float FloatValue() const {
1122 float f=0;
1123 QueryFloatValue( &f );
1124 return f;
1125 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001126
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001127 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001128 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001129 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1130 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001131 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001132 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001133 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001134 /// See QueryIntValue
1135 XMLError QueryInt64Value(int64_t* value) const;
1136 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001137 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001138 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001139 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001140 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001141 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 /// Set the attribute to a string value.
1144 void SetAttribute( const char* value );
1145 /// Set the attribute to value.
1146 void SetAttribute( int value );
1147 /// Set the attribute to value.
1148 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001149 /// Set the attribute to value.
1150 void SetAttribute(int64_t value);
1151 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001152 void SetAttribute( bool value );
1153 /// Set the attribute to value.
1154 void SetAttribute( double value );
1155 /// Set the attribute to value.
1156 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001157
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001158private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001159 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001160
Thomas Roß61892312013-05-12 14:07:38 +02001161 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001162 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001163
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001164 XMLAttribute( const XMLAttribute& ); // not supported
1165 void operator=( const XMLAttribute& ); // not supported
1166 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001167
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001168 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001169
Lee Thomason624d43f2012-10-12 10:58:48 -07001170 mutable StrPair _name;
1171 mutable StrPair _value;
1172 XMLAttribute* _next;
1173 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001174};
1175
1176
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001177/** The element is a container class. It has a value, the element name,
1178 and can contain other elements, text, comments, and unknowns.
1179 Elements also contain an arbitrary number of attributes.
1180*/
PKEuS16ed47d2013-07-06 12:02:43 +02001181class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001182{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001183 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001184public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001185 /// Get the name of an element (which is the Value() of the node.)
1186 const char* Name() const {
1187 return Value();
1188 }
1189 /// Set the name of the element.
1190 void SetName( const char* str, bool staticMem=false ) {
1191 SetValue( str, staticMem );
1192 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001193
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001194 virtual XMLElement* ToElement() {
1195 return this;
1196 }
1197 virtual const XMLElement* ToElement() const {
1198 return this;
1199 }
1200 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001201
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001202 /** Given an attribute name, Attribute() returns the value
1203 for the attribute of that name, or null if none
1204 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001205
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001206 @verbatim
1207 const char* value = ele->Attribute( "foo" );
1208 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001209
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001210 The 'value' parameter is normally null. However, if specified,
1211 the attribute will only be returned if the 'name' and 'value'
1212 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001213
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 @verbatim
1215 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1216 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001217
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 rather than:
1219 @verbatim
1220 if ( ele->Attribute( "foo" ) ) {
1221 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1222 }
1223 @endverbatim
1224 */
1225 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001226
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001227 /** Given an attribute name, IntAttribute() returns the value
1228 of the attribute interpreted as an integer. 0 will be
1229 returned if there is an error. For a method with error
1230 checking, see QueryIntAttribute()
1231 */
1232 int IntAttribute( const char* name ) const {
1233 int i=0;
1234 QueryIntAttribute( name, &i );
1235 return i;
1236 }
Lee Thomason51c12712016-06-04 20:18:49 -07001237
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 /// See IntAttribute()
1239 unsigned UnsignedAttribute( const char* name ) const {
1240 unsigned i=0;
1241 QueryUnsignedAttribute( name, &i );
1242 return i;
1243 }
Lee Thomason51c12712016-06-04 20:18:49 -07001244
1245 /// See IntAttribute()
1246 int64_t Int64Attribute(const char* name) const {
1247 int64_t i = 0;
1248 QueryInt64Attribute(name, &i);
1249 return i;
1250 }
1251
1252 /// See IntAttribute()
1253 bool BoolAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001254 bool b=false;
1255 QueryBoolAttribute( name, &b );
1256 return b;
1257 }
1258 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001259 double DoubleAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 double d=0;
1261 QueryDoubleAttribute( name, &d );
1262 return d;
1263 }
1264 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001265 float FloatAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001266 float f=0;
1267 QueryFloatAttribute( name, &f );
1268 return f;
1269 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001270
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 /** Given an attribute name, QueryIntAttribute() returns
1272 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1273 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1274 doesn't exist. If successful, the result of the conversion
1275 will be written to 'value'. If not successful, nothing will
1276 be written to 'value'. This allows you to provide default
1277 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001278
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001279 @verbatim
1280 int value = 10;
1281 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1282 @endverbatim
1283 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001284 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 const XMLAttribute* a = FindAttribute( name );
1286 if ( !a ) {
1287 return XML_NO_ATTRIBUTE;
1288 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001289 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 }
Lee Thomason51c12712016-06-04 20:18:49 -07001291
1292 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001293 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001294 const XMLAttribute* a = FindAttribute( name );
1295 if ( !a ) {
1296 return XML_NO_ATTRIBUTE;
1297 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001298 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 }
Lee Thomason51c12712016-06-04 20:18:49 -07001300
1301 /// See QueryIntAttribute()
1302 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1303 const XMLAttribute* a = FindAttribute(name);
1304 if (!a) {
1305 return XML_NO_ATTRIBUTE;
1306 }
1307 return a->QueryInt64Value(value);
1308 }
1309
1310 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001311 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 const XMLAttribute* a = FindAttribute( name );
1313 if ( !a ) {
1314 return XML_NO_ATTRIBUTE;
1315 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001316 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 }
1318 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001319 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001320 const XMLAttribute* a = FindAttribute( name );
1321 if ( !a ) {
1322 return XML_NO_ATTRIBUTE;
1323 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001324 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001325 }
1326 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001327 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001328 const XMLAttribute* a = FindAttribute( name );
1329 if ( !a ) {
1330 return XML_NO_ATTRIBUTE;
1331 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001332 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001334
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001335
1336 /** Given an attribute name, QueryAttribute() returns
1337 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1338 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1339 doesn't exist. It is overloaded for the primitive types,
1340 and is a generally more convenient replacement of
1341 QueryIntAttribute() and related functions.
1342
1343 If successful, the result of the conversion
1344 will be written to 'value'. If not successful, nothing will
1345 be written to 'value'. This allows you to provide default
1346 value:
1347
1348 @verbatim
1349 int value = 10;
1350 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1351 @endverbatim
1352 */
1353 int QueryAttribute( const char* name, int* value ) const {
1354 return QueryIntAttribute( name, value );
1355 }
1356
1357 int QueryAttribute( const char* name, unsigned int* value ) const {
1358 return QueryUnsignedAttribute( name, value );
1359 }
1360
Lee Thomason51c12712016-06-04 20:18:49 -07001361 int QueryAttribute(const char* name, int64_t* value) const {
1362 return QueryInt64Attribute(name, value);
1363 }
1364
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001365 int QueryAttribute( const char* name, bool* value ) const {
1366 return QueryBoolAttribute( name, value );
1367 }
1368
1369 int QueryAttribute( const char* name, double* value ) const {
1370 return QueryDoubleAttribute( name, value );
1371 }
1372
1373 int QueryAttribute( const char* name, float* value ) const {
1374 return QueryFloatAttribute( name, value );
1375 }
1376
1377 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001378 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001380 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 }
1382 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001383 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001385 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 }
1387 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001388 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001389 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001390 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 }
Lee Thomason51c12712016-06-04 20:18:49 -07001392
1393 /// Sets the named attribute to value.
1394 void SetAttribute(const char* name, int64_t value) {
1395 XMLAttribute* a = FindOrCreateAttribute(name);
1396 a->SetAttribute(value);
1397 }
1398
1399 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001402 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 }
1404 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001405 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001406 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001407 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001409 /// Sets the named attribute to value.
1410 void SetAttribute( const char* name, float value ) {
1411 XMLAttribute* a = FindOrCreateAttribute( name );
1412 a->SetAttribute( value );
1413 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001414
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 /**
1416 Delete an attribute.
1417 */
1418 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001419
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 /// Return the first attribute in the list.
1421 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001422 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001423 }
1424 /// Query a specific attribute in the list.
1425 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001426
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001428 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001430
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001431 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001433
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 This is a convenient method for getting the text of simple contained text:
1435 @verbatim
1436 <foo>This is text</foo>
1437 const char* str = fooElement->GetText();
1438 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001439
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001440 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 Note that this function can be misleading. If the element foo was created from
1443 this XML:
1444 @verbatim
1445 <foo><b>This is text</b></foo>
1446 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001447
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001448 then the value of str would be null. The first child node isn't a text node, it is
1449 another element. From this XML:
1450 @verbatim
1451 <foo>This is <b>text</b></foo>
1452 @endverbatim
1453 GetText() will return "This is ".
1454 */
1455 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001456
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001457 /** Convenience function for easy access to the text inside an element. Although easy
1458 and concise, SetText() is limited compared to creating an XMLText child
1459 and mutating it directly.
1460
1461 If the first child of 'this' is a XMLText, SetText() sets its value to
1462 the given string, otherwise it will create a first child that is an XMLText.
1463
1464 This is a convenient method for setting the text of simple contained text:
1465 @verbatim
1466 <foo>This is text</foo>
1467 fooElement->SetText( "Hullaballoo!" );
1468 <foo>Hullaballoo!</foo>
1469 @endverbatim
1470
1471 Note that this function can be misleading. If the element foo was created from
1472 this XML:
1473 @verbatim
1474 <foo><b>This is text</b></foo>
1475 @endverbatim
1476
1477 then it will not change "This is text", but rather prefix it with a text element:
1478 @verbatim
1479 <foo>Hullaballoo!<b>This is text</b></foo>
1480 @endverbatim
1481
1482 For this XML:
1483 @verbatim
1484 <foo />
1485 @endverbatim
1486 SetText() will generate
1487 @verbatim
1488 <foo>Hullaballoo!</foo>
1489 @endverbatim
1490 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001491 void SetText( const char* inText );
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( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001494 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001495 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001496 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1497 void SetText(int64_t value);
1498 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001499 void SetText( bool 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( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001502 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001503 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001504
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 /**
1506 Convenience method to query the value of a child text node. This is probably best
1507 shown by example. Given you have a document is this form:
1508 @verbatim
1509 <point>
1510 <x>1</x>
1511 <y>1.4</y>
1512 </point>
1513 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001514
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001515 The QueryIntText() and similar functions provide a safe and easier way to get to the
1516 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001517
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001518 @verbatim
1519 int x = 0;
1520 float y = 0; // types of x and y are contrived for example
1521 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1522 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1523 xElement->QueryIntText( &x );
1524 yElement->QueryFloatText( &y );
1525 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001526
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001527 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1528 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 -07001529
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001531 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001533 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001534 /// See QueryIntText()
1535 XMLError QueryInt64Text(int64_t* uval) const;
1536 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001537 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001538 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001539 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001540 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001541 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001542
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001543 // internal:
1544 enum {
1545 OPEN, // <foo>
1546 CLOSED, // <foo/>
1547 CLOSING // </foo>
1548 };
1549 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001550 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001551 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001552 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1553 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001554
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001555protected:
1556 char* ParseDeep( char* p, StrPair* endTag );
1557
Lee Thomason50adb4c2012-02-13 15:07:09 -08001558private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001559 XMLElement( XMLDocument* doc );
1560 virtual ~XMLElement();
1561 XMLElement( const XMLElement& ); // not supported
1562 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001563
Dmitry-Me1227d512014-12-05 13:41:45 +03001564 XMLAttribute* FindAttribute( const char* name ) {
1565 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1566 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 XMLAttribute* FindOrCreateAttribute( const char* name );
1568 //void LinkAttribute( XMLAttribute* attrib );
1569 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001570 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001571
Lee Thomason5bb2d802014-01-24 10:42:57 -08001572 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001573 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001574 // The attribute list is ordered; there is no 'lastAttribute'
1575 // because the list needs to be scanned for dupes before adding
1576 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001577 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001578};
1579
1580
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001581enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001582 PRESERVE_WHITESPACE,
1583 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001584};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001585
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001586
1587/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001588 It can be saved, loaded, and printed to the screen.
1589 All Nodes are connected and allocated to a Document.
1590 If the Document is deleted, all its Nodes are also deleted.
1591*/
PKEuS16ed47d2013-07-06 12:02:43 +02001592class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001593{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001594 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001595public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 /// constructor
1597 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1598 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001599
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001601 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 return this;
1603 }
1604 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001605 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 return this;
1607 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001608
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001609 /**
1610 Parse an XML file from a character string.
1611 Returns XML_NO_ERROR (0) on success, or
1612 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001613
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 You may optionally pass in the 'nBytes', which is
1615 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001616 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001617 null terminated string.
1618 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001619 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001620
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001621 /**
1622 Load an XML file from disk.
1623 Returns XML_NO_ERROR (0) on success, or
1624 an errorID.
1625 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001626 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001627
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 /**
1629 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001630 for providing and closing the FILE*.
1631
1632 NOTE: The file should be opened as binary ("rb")
1633 not text in order for TinyXML-2 to correctly
1634 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001635
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001636 Returns XML_NO_ERROR (0) on success, or
1637 an errorID.
1638 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001639 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001640
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001641 /**
1642 Save the XML file to disk.
1643 Returns XML_NO_ERROR (0) on success, or
1644 an errorID.
1645 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001646 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001647
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001648 /**
1649 Save the XML file to disk. You are responsible
1650 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001651
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001652 Returns XML_NO_ERROR (0) on success, or
1653 an errorID.
1654 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001655 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001656
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001658 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 }
1660 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001661 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001662 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001663
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 /**
1665 Returns true if this document has a leading Byte Order Mark of UTF8.
1666 */
1667 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001668 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001669 }
1670 /** Sets whether to write the BOM when writing the file.
1671 */
1672 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001673 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001674 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001675
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001676 /** Return the root element of DOM. Equivalent to FirstChildElement().
1677 To get the first node, use FirstChild().
1678 */
1679 XMLElement* RootElement() {
1680 return FirstChildElement();
1681 }
1682 const XMLElement* RootElement() const {
1683 return FirstChildElement();
1684 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001685
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 /** Print the Document. If the Printer is not provided, it will
1687 print to stdout. If you provide Printer, this can print to a file:
1688 @verbatim
1689 XMLPrinter printer( fp );
1690 doc.Print( &printer );
1691 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001692
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001693 Or you can use a printer to print to memory:
1694 @verbatim
1695 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001696 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 // printer.CStr() has a const char* to the XML
1698 @endverbatim
1699 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001700 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001702
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 /**
1704 Create a new Element associated with
1705 this Document. The memory for the Element
1706 is managed by the Document.
1707 */
1708 XMLElement* NewElement( const char* name );
1709 /**
1710 Create a new Comment associated with
1711 this Document. The memory for the Comment
1712 is managed by the Document.
1713 */
1714 XMLComment* NewComment( const char* comment );
1715 /**
1716 Create a new Text associated with
1717 this Document. The memory for the Text
1718 is managed by the Document.
1719 */
1720 XMLText* NewText( const char* text );
1721 /**
1722 Create a new Declaration associated with
1723 this Document. The memory for the object
1724 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001725
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 If the 'text' param is null, the standard
1727 declaration is used.:
1728 @verbatim
1729 <?xml version="1.0" encoding="UTF-8"?>
1730 @endverbatim
1731 */
1732 XMLDeclaration* NewDeclaration( const char* text=0 );
1733 /**
1734 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001735 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 is managed by the Document.
1737 */
1738 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001739
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001740 /**
1741 Delete a node associated with this document.
1742 It will be unlinked from the DOM.
1743 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001744 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001745
Lee Thomason2fa81722012-11-09 12:37:46 -08001746 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001747
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 /// Return true if there was an error parsing the document.
1749 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001750 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001751 }
1752 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001753 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001754 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001755 }
Lee Thomason331596e2014-09-11 14:56:43 -07001756 const char* ErrorName() const;
1757
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001758 /// Return a possibly helpful diagnostic location or string.
1759 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001760 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001761 }
1762 /// Return a possibly helpful secondary diagnostic location or string.
1763 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001764 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
1766 /// If there is an error, print it to stdout.
1767 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001768
1769 /// Clear the document, resetting it to the initial state.
1770 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001771
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001772 // internal
1773 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001774
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001775 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1776 return 0;
1777 }
1778 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1779 return false;
1780 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001781
Lee Thomason3f57d272012-01-11 15:30:03 -08001782private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 XMLDocument( const XMLDocument& ); // not supported
1784 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001785
Lee Thomason2fa81722012-11-09 12:37:46 -08001786 bool _writeBOM;
1787 bool _processEntities;
1788 XMLError _errorID;
1789 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001790 const char* _errorStr1;
1791 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001792 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001793
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 MemPoolT< sizeof(XMLElement) > _elementPool;
1795 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1796 MemPoolT< sizeof(XMLText) > _textPool;
1797 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001798
1799 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001800
1801 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001802};
1803
Lee Thomason7c913cd2012-01-26 18:32:34 -08001804
Lee Thomason3ffdd392012-03-28 17:27:55 -07001805/**
1806 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001807 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001808 DOM structure. It is a separate utility class.
1809
1810 Take an example:
1811 @verbatim
1812 <Document>
1813 <Element attributeA = "valueA">
1814 <Child attributeB = "value1" />
1815 <Child attributeB = "value2" />
1816 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001817 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001818 @endverbatim
1819
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001820 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001821 easy to write a *lot* of code that looks like:
1822
1823 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001824 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001825 if ( root )
1826 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001827 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001828 if ( element )
1829 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001830 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001831 if ( child )
1832 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001833 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001834 if ( child2 )
1835 {
1836 // Finally do something useful.
1837 @endverbatim
1838
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001839 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001840 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001841 and correct to use:
1842
1843 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001844 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001845 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001846 if ( child2 )
1847 {
1848 // do something useful
1849 @endverbatim
1850
1851 Which is MUCH more concise and useful.
1852
1853 It is also safe to copy handles - internally they are nothing more than node pointers.
1854 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001855 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001856 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001857
1858 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001859*/
PKEuS16ed47d2013-07-06 12:02:43 +02001860class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001861{
1862public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001863 /// 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 -07001864 XMLHandle( XMLNode* node ) {
1865 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 }
1867 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001868 XMLHandle( XMLNode& node ) {
1869 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001870 }
1871 /// Copy constructor
1872 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001873 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001874 }
1875 /// Assignment
1876 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001878 return *this;
1879 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001880
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001881 /// Get the first child of this handle.
1882 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001883 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 }
1885 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001886 XMLHandle FirstChildElement( const char* name = 0 ) {
1887 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001888 }
1889 /// Get the last child of this handle.
1890 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001891 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 }
1893 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001894 XMLHandle LastChildElement( const char* name = 0 ) {
1895 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001896 }
1897 /// Get the previous sibling of this handle.
1898 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001899 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001900 }
1901 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001902 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1903 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001904 }
1905 /// Get the next sibling of this handle.
1906 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001907 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001908 }
1909 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001910 XMLHandle NextSiblingElement( const char* name = 0 ) {
1911 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001912 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001913
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001914 /// Safe cast to XMLNode. This can return null.
1915 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001916 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001917 }
1918 /// Safe cast to XMLElement. This can return null.
1919 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001920 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001921 }
1922 /// Safe cast to XMLText. This can return null.
1923 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001924 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001925 }
1926 /// Safe cast to XMLUnknown. This can return null.
1927 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001928 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001929 }
1930 /// Safe cast to XMLDeclaration. This can return null.
1931 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001932 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001934
1935private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001936 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001937};
1938
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001939
1940/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001941 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1942 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001943*/
PKEuS16ed47d2013-07-06 12:02:43 +02001944class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001945{
1946public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001947 XMLConstHandle( const XMLNode* node ) {
1948 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001949 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001950 XMLConstHandle( const XMLNode& node ) {
1951 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001952 }
1953 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001954 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 }
Lee Thomason8b899812012-04-04 15:58:16 -07001956
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001957 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001958 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001959 return *this;
1960 }
Lee Thomason8b899812012-04-04 15:58:16 -07001961
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001962 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001963 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001964 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001965 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1966 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001967 }
1968 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001969 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001970 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001971 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1972 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001973 }
1974 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001975 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001976 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001977 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1978 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001979 }
1980 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001981 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001982 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001983 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1984 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001985 }
Lee Thomason8b899812012-04-04 15:58:16 -07001986
1987
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001988 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001989 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001990 }
1991 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001992 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001993 }
1994 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001995 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 }
1997 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001998 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001999 }
2000 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002001 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002002 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002003
Lee Thomason5cae8972012-01-24 18:03:07 -08002004private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002005 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002006};
Lee Thomason6f381b72012-03-02 12:59:39 -08002007
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002008
2009/**
2010 Printing functionality. The XMLPrinter gives you more
2011 options than the XMLDocument::Print() method.
2012
2013 It can:
2014 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002015 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002016 -# Print XML without a XMLDocument.
2017
2018 Print to Memory
2019
2020 @verbatim
2021 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002022 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002023 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002024 @endverbatim
2025
2026 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002027
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002028 You provide the file pointer.
2029 @verbatim
2030 XMLPrinter printer( fp );
2031 doc.Print( &printer );
2032 @endverbatim
2033
2034 Print without a XMLDocument
2035
2036 When loading, an XML parser is very useful. However, sometimes
2037 when saving, it just gets in the way. The code is often set up
2038 for streaming, and constructing the DOM is just overhead.
2039
2040 The Printer supports the streaming case. The following code
2041 prints out a trivially simple XML file without ever creating
2042 an XML document.
2043
2044 @verbatim
2045 XMLPrinter printer( fp );
2046 printer.OpenElement( "foo" );
2047 printer.PushAttribute( "foo", "bar" );
2048 printer.CloseElement();
2049 @endverbatim
2050*/
PKEuS16ed47d2013-07-06 12:02:43 +02002051class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002052{
2053public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002054 /** Construct the printer. If the FILE* is specified,
2055 this will print to the FILE. Else it will print
2056 to memory, and the result is available in CStr().
2057 If 'compact' is set to true, then output is created
2058 with only required whitespace and newlines.
2059 */
PKEuS1bfb9542013-08-04 13:51:17 +02002060 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002061 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002062
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002063 /** If streaming, write the BOM and declaration. */
2064 void PushHeader( bool writeBOM, bool writeDeclaration );
2065 /** If streaming, start writing an element.
2066 The element must be closed with CloseElement()
2067 */
Lee Thomason256adb62014-04-06 14:41:46 -07002068 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002069 /// If streaming, add an attribute to an open element.
2070 void PushAttribute( const char* name, const char* value );
2071 void PushAttribute( const char* name, int value );
2072 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002073 void PushAttribute(const char* name, int64_t value);
2074 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002075 void PushAttribute( const char* name, double value );
2076 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002077 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002078
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002079 /// Add a text node.
2080 void PushText( const char* text, bool cdata=false );
2081 /// Add a text node from an integer.
2082 void PushText( int value );
2083 /// Add a text node from an unsigned.
2084 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002085 /// Add a text node from an unsigned.
2086 void PushText(int64_t value);
2087 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002088 void PushText( bool value );
2089 /// Add a text node from a float.
2090 void PushText( float value );
2091 /// Add a text node from a double.
2092 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002093
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002094 /// Add a comment
2095 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002096
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002097 void PushDeclaration( const char* value );
2098 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002099
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002100 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2101 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2102 return true;
2103 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002104
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002105 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2106 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002107
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002108 virtual bool Visit( const XMLText& text );
2109 virtual bool Visit( const XMLComment& comment );
2110 virtual bool Visit( const XMLDeclaration& declaration );
2111 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002112
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002113 /**
2114 If in print to memory mode, return a pointer to
2115 the XML file in memory.
2116 */
2117 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002118 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002119 }
2120 /**
2121 If in print to memory mode, return the size
2122 of the XML file in memory. (Note the size returned
2123 includes the terminating null.)
2124 */
2125 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002126 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002127 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002128 /**
2129 If in print to memory mode, reset the buffer to the
2130 beginning.
2131 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002132 void ClearBuffer() {
2133 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002134 _buffer.Push(0);
2135 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002136
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002137protected:
Alexander Maid740b642014-05-20 22:04:42 +02002138 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002139
Lee Thomasonc18eb232014-02-21 17:31:17 -08002140 /** Prints out the space before an element. You may override to change
2141 the space and tabs used. A PrintSpace() override should call Print().
2142 */
2143 virtual void PrintSpace( int depth );
2144 void Print( const char* format, ... );
2145
Dmitry-Mea092bc12014-12-23 17:57:05 +03002146 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002147 bool _elementJustOpened;
2148 DynArray< const char*, 10 > _stack;
2149
2150private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002151 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002152
Lee Thomason624d43f2012-10-12 10:58:48 -07002153 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002154 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002155 int _depth;
2156 int _textDepth;
2157 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002158 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002159
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002160 enum {
2161 ENTITY_RANGE = 64,
2162 BUF_SIZE = 200
2163 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002164 bool _entityFlag[ENTITY_RANGE];
2165 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002166
Lee Thomason624d43f2012-10-12 10:58:48 -07002167 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002168};
2169
2170
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002171} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002172
PKEuS95060352013-07-26 10:42:44 +02002173#if defined(_MSC_VER)
2174# pragma warning(pop)
2175#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002176
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002177#endif // TINYXML2_INCLUDED