blob: a740dc32ba0df58e4f9f2e3d56d81ab37c5a4a94 [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
Lee Thomason584af572016-09-05 14:14:16 -0700130 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700131 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason584af572016-09-05 14:14:16 -0700132 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 ) {
Dmitry-Me6fc38ec2016-09-01 17:59:44 +0300142 TIXMLASSERT( start );
143 TIXMLASSERT( end );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
kezenator4f756162016-11-29 19:46:27 +1000163 char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason29658802014-11-27 22:31:11 -0800166 void TransferTo( StrPair* other );
Lee Thomason584af572016-09-05 14:14:16 -0700167 void Reset();
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300168
Lee Thomason39ede242012-01-20 11:27:56 -0800169private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 enum {
173 NEEDS_FLUSH = 0x100,
174 NEEDS_DELETE = 0x200
175 };
Lee Thomasone4422302012-01-20 17:59:50 -0800176
Lee Thomason120b3a62012-10-12 10:06:59 -0700177 int _flags;
178 char* _start;
179 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300180
181 StrPair( const StrPair& other ); // not supported
182 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800183};
184
U-Lama\Lee560bd472011-12-28 19:42:49 -0800185
U-Stream\Leeae25a442012-02-17 17:48:16 -0800186/*
187 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
188 Has a small initial memory pool, so that low or no usage will not
189 cause a call to new/delete
190*/
Dmitry-Me04009222015-04-06 18:07:18 +0300191template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200192class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800193{
194public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300195 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700196 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300197 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700199 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700200
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700201 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700202 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700203 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700204 }
205 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700206
Lee Thomasonce0510b2013-11-26 21:29:37 -0800207 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100208 _size = 0;
209 }
210
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300212 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700213 EnsureCapacity( _size+1 );
Dmitry-Mefed51122016-09-06 18:08:55 +0300214 _mem[_size] = t;
215 ++_size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800217
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700218 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300219 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300220 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700221 EnsureCapacity( _size+count );
222 T* ret = &_mem[_size];
223 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 return ret;
225 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700226
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700227 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300228 TIXMLASSERT( _size > 0 );
Dmitry-Mefed51122016-09-06 18:08:55 +0300229 --_size;
230 return _mem[_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( _size >= count );
235 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700244 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700246
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700248 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700249 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700251
Lee Thomasonf07b9522014-10-30 13:25:12 -0700252 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500253 TIXMLASSERT( _size > 0 );
254 return _mem[ _size - 1];
255 }
256
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300258 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700261
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300263 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomason816d3fa2017-06-05 14:35:55 -0700267 void SwapRemove(int i) {
268 TIXMLASSERT(i < _size);
269 _mem[i] = _mem[_size - 1];
270 --_size;
271 }
272
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300274 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700275 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700277
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300279 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700280 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700281 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800282
Lee Thomason2c85a712012-01-31 08:24:24 -0800283private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300284 DynArray( const DynArray& ); // not supported
285 void operator=( const DynArray& ); // not supported
286
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700287 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300288 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700289 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300290 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700291 int newAllocated = cap * 2;
292 T* newMem = new T[newAllocated];
Dmitry-Me243ddf52017-05-18 17:27:14 +0300293 TIXMLASSERT( newAllocated >= _size );
Lee Thomason624d43f2012-10-12 10:58:48 -0700294 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
295 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700296 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700297 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700298 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700299 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700300 }
301 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800302
Lee Thomason624d43f2012-10-12 10:58:48 -0700303 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300304 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700305 int _allocated; // objects allocated
306 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800307};
308
Lee Thomason50adb4c2012-02-13 15:07:09 -0800309
U-Stream\Leeae25a442012-02-17 17:48:16 -0800310/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200311 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800312 and deallocation of objects.
313*/
PKEuS95060352013-07-26 10:42:44 +0200314class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800315{
316public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700317 MemPool() {}
318 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800319
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700320 virtual int ItemSize() const = 0;
321 virtual void* Alloc() = 0;
322 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800323 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700324 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800325};
326
Lee Thomason50adb4c2012-02-13 15:07:09 -0800327
U-Stream\Leeae25a442012-02-17 17:48:16 -0800328/*
329 Template child class to create pools of the correct type.
330*/
Dmitry-Me88145b82016-08-09 17:59:31 +0300331template< int ITEM_SIZE >
PKEuS95060352013-07-26 10:42:44 +0200332class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800333{
334public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800335 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700336 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700337 Clear();
338 }
339
340 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700342 while( !_blockPtrs.Empty()) {
343 Block* b = _blockPtrs.Pop();
344 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700345 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700346 _root = 0;
347 _currentAllocs = 0;
348 _nAllocs = 0;
349 _maxAllocs = 0;
350 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700351 }
Lee Thomasond1983222012-02-06 08:41:24 -0800352
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 virtual int ItemSize() const {
Dmitry-Me88145b82016-08-09 17:59:31 +0300354 return ITEM_SIZE;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700355 }
356 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700357 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700358 }
Lee Thomasond1983222012-02-06 08:41:24 -0800359
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700361 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700362 // Need a new block.
363 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800365
Dmitry-Me88145b82016-08-09 17:59:31 +0300366 Item* blockItems = block->items;
367 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
368 blockItems[i].next = &(blockItems[i + 1]);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300370 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
371 _root = blockItems;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700372 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300373 Item* const result = _root;
374 TIXMLASSERT( result != 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700375 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800376
Lee Thomason624d43f2012-10-12 10:58:48 -0700377 ++_currentAllocs;
378 if ( _currentAllocs > _maxAllocs ) {
379 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700380 }
Dmitry-Me3161a332016-09-02 16:58:06 +0300381 ++_nAllocs;
382 ++_nUntracked;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700383 return result;
384 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700385
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700386 virtual void Free( void* mem ) {
387 if ( !mem ) {
388 return;
389 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700390 --_currentAllocs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300391 Item* item = static_cast<Item*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700392#ifdef DEBUG
Dmitry-Me88145b82016-08-09 17:59:31 +0300393 memset( item, 0xfe, sizeof( *item ) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700394#endif
Dmitry-Me88145b82016-08-09 17:59:31 +0300395 item->next = _root;
396 _root = item;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700397 }
398 void Trace( const char* name ) {
399 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Dmitry-Me88145b82016-08-09 17:59:31 +0300400 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
401 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700402 }
Lee Thomasond1983222012-02-06 08:41:24 -0800403
Lee Thomason5b0a6772012-11-19 13:54:42 -0800404 void SetTracked() {
Dmitry-Me3161a332016-09-02 16:58:06 +0300405 --_nUntracked;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800406 }
407
408 int Untracked() const {
409 return _nUntracked;
410 }
411
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800412 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
413 // The test file is large, 170k.
414 // Release: VS2010 gcc(no opt)
415 // 1k: 4000
416 // 2k: 4000
417 // 4k: 3900 21000
418 // 16k: 5200
419 // 32k: 4300
420 // 64k: 4000 21000
Dmitry-Me88145b82016-08-09 17:59:31 +0300421 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
422 // in private part if ITEMS_PER_BLOCK is private
423 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
Jerome Martinez7921df12012-10-24 11:45:44 +0200424
Lee Thomasond1983222012-02-06 08:41:24 -0800425private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300426 MemPoolT( const MemPoolT& ); // not supported
427 void operator=( const MemPoolT& ); // not supported
428
Dmitry-Me88145b82016-08-09 17:59:31 +0300429 union Item {
430 Item* next;
431 char itemData[ITEM_SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700432 };
433 struct Block {
Dmitry-Me88145b82016-08-09 17:59:31 +0300434 Item items[ITEMS_PER_BLOCK];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700435 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700436 DynArray< Block*, 10 > _blockPtrs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300437 Item* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800438
Lee Thomason624d43f2012-10-12 10:58:48 -0700439 int _currentAllocs;
440 int _nAllocs;
441 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800442 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800443};
444
Lee Thomason2c85a712012-01-31 08:24:24 -0800445
Lee Thomason56bdd022012-02-09 18:16:58 -0800446
447/**
448 Implements the interface to the "Visitor pattern" (see the Accept() method.)
449 If you call the Accept() method, it requires being passed a XMLVisitor
450 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200451 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800452 are simply called with Visit().
453
454 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700455 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800456
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700457 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800458 visiting). You need to only override methods that are interesting to you.
459
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600460 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800461
462 You should never change the document from a callback.
463
464 @sa XMLNode::Accept()
465*/
PKEuS16ed47d2013-07-06 12:02:43 +0200466class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800467{
468public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700469 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800470
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700471 /// Visit a document.
472 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
473 return true;
474 }
475 /// Visit a document.
476 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
477 return true;
478 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800479
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 /// Visit an element.
481 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
482 return true;
483 }
484 /// Visit an element.
485 virtual bool VisitExit( const XMLElement& /*element*/ ) {
486 return true;
487 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800488
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700489 /// Visit a declaration.
490 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
491 return true;
492 }
493 /// Visit a text node.
494 virtual bool Visit( const XMLText& /*text*/ ) {
495 return true;
496 }
497 /// Visit a comment node.
498 virtual bool Visit( const XMLComment& /*comment*/ ) {
499 return true;
500 }
501 /// Visit an unknown node.
502 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
503 return true;
504 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800505};
506
Dmitry-Me66d2a842014-11-08 15:24:52 +0300507// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900508enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900509 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900510 XML_NO_ATTRIBUTE,
511 XML_WRONG_ATTRIBUTE_TYPE,
512 XML_ERROR_FILE_NOT_FOUND,
513 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
514 XML_ERROR_FILE_READ_ERROR,
515 XML_ERROR_ELEMENT_MISMATCH,
516 XML_ERROR_PARSING_ELEMENT,
517 XML_ERROR_PARSING_ATTRIBUTE,
518 XML_ERROR_IDENTIFYING_TAG,
519 XML_ERROR_PARSING_TEXT,
520 XML_ERROR_PARSING_CDATA,
521 XML_ERROR_PARSING_COMMENT,
522 XML_ERROR_PARSING_DECLARATION,
523 XML_ERROR_PARSING_UNKNOWN,
524 XML_ERROR_EMPTY_DOCUMENT,
525 XML_ERROR_MISMATCHED_ELEMENT,
526 XML_ERROR_PARSING,
527 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700528 XML_NO_TEXT_NODE,
529
530 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900531};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900532
numatrumpetcd8550c2014-09-08 16:59:39 +0900533
U-Stream\Leeae25a442012-02-17 17:48:16 -0800534/*
535 Utility functionality.
536*/
Lee Thomasonce667c92016-12-26 16:45:30 -0800537class TINYXML2_LIB XMLUtil
Lee Thomason56bdd022012-02-09 18:16:58 -0800538{
Lee Thomasond1983222012-02-06 08:41:24 -0800539public:
kezenator4f756162016-11-29 19:46:27 +1000540 static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300541 TIXMLASSERT( p );
Lee Thomasone90e9012016-12-24 07:34:39 -0800542
Dmitry-Mefa20b222014-10-31 12:53:04 +0300543 while( IsWhiteSpace(*p) ) {
Lee Thomasone90e9012016-12-24 07:34:39 -0800544 if (curLineNumPtr && *p == '\n') {
kezenator4f756162016-11-29 19:46:27 +1000545 ++(*curLineNumPtr);
kezenatorec694152016-11-26 17:21:43 +1000546 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700547 ++p;
548 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300549 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700550 return p;
551 }
kezenator4f756162016-11-29 19:46:27 +1000552 static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) {
553 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700554 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300555
556 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
557 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700558 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100559 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700560 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200561
562 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300563 if ( ch >= 128 ) {
564 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
565 return true;
566 }
567 if ( isalpha( ch ) ) {
568 return true;
569 }
570 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200571 }
572
573 inline static bool IsNameChar( unsigned char ch ) {
574 return IsNameStartChar( ch )
575 || isdigit( ch )
576 || ch == '.'
577 || ch == '-';
578 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800579
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700581 if ( p == q ) {
582 return true;
583 }
Dmitry-Me21f99692016-10-03 13:01:57 +0300584 TIXMLASSERT( p );
585 TIXMLASSERT( q );
586 TIXMLASSERT( nChar >= 0 );
Lee Thomason598a88d2015-10-09 14:42:12 -0700587 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200589
Dmitry-Me7865aad2015-06-19 16:23:35 +0300590 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400591 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800593
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 static const char* ReadBOM( const char* p, bool* hasBOM );
595 // p is the starting location,
596 // the UTF-8 value of the entity will be placed in value, and length filled in.
597 static const char* GetCharacterRef( const char* p, char* value, int* length );
598 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700599
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 // converts primitive types to strings
601 static void ToStr( int v, char* buffer, int bufferSize );
602 static void ToStr( unsigned v, char* buffer, int bufferSize );
603 static void ToStr( bool v, char* buffer, int bufferSize );
604 static void ToStr( float v, char* buffer, int bufferSize );
605 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700606 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700607
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 // converts strings to primitive types
609 static bool ToInt( const char* str, int* value );
610 static bool ToUnsigned( const char* str, unsigned* value );
611 static bool ToBool( const char* str, bool* value );
612 static bool ToFloat( const char* str, float* value );
613 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700614 static bool ToInt64(const char* str, int64_t* value);
Lee Thomasonce667c92016-12-26 16:45:30 -0800615
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800616 // Changes what is serialized for a boolean value.
617 // Default to "true" and "false". Shouldn't be changed
618 // unless you have a special testing or compatibility need.
Lee Thomasonce667c92016-12-26 16:45:30 -0800619 // Be careful: static, global, & not thread safe.
620 // Be sure to set static const memory as parameters.
Lee Thomasonc5c99c22016-12-29 11:19:17 -0800621 static void SetBoolSerialization(const char* writeTrue, const char* writeFalse);
Lee Thomasonce667c92016-12-26 16:45:30 -0800622
623private:
Lee Thomasonf458d262016-12-26 22:47:25 -0800624 static const char* writeBoolTrue;
625 static const char* writeBoolFalse;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800626};
627
Lee Thomason5cae8972012-01-24 18:03:07 -0800628
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800629/** XMLNode is a base class for every object that is in the
630 XML Document Object Model (DOM), except XMLAttributes.
631 Nodes have siblings, a parent, and children which can
632 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700633 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800634 be cast to its more defined type.
635
Thomas Roß08bdf502012-05-12 14:21:23 +0200636 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800637 When the XMLDocument gets deleted, all its Nodes
638 will also be deleted.
639
640 @verbatim
641 A Document can contain: Element (container or leaf)
642 Comment (leaf)
643 Unknown (leaf)
644 Declaration( leaf )
645
646 An Element can contain: Element (container or leaf)
647 Text (leaf)
648 Attributes (not on tree)
649 Comment (leaf)
650 Unknown (leaf)
651
652 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800653*/
PKEuS16ed47d2013-07-06 12:02:43 +0200654class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800655{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 friend class XMLDocument;
657 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800658public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800659
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 /// Get the XMLDocument that owns this XMLNode.
661 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300662 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700663 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 }
665 /// Get the XMLDocument that owns this XMLNode.
666 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300667 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700668 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800670
Lee Thomason2fa81722012-11-09 12:37:46 -0800671 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100673 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800675 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100677 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700678 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800679 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700680 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100681 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800683 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100685 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800687 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100689 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800691 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100693 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800695
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 virtual const XMLElement* ToElement() const {
697 return 0;
698 }
699 virtual const XMLText* ToText() const {
700 return 0;
701 }
702 virtual const XMLComment* ToComment() const {
703 return 0;
704 }
705 virtual const XMLDocument* ToDocument() const {
706 return 0;
707 }
708 virtual const XMLDeclaration* ToDeclaration() const {
709 return 0;
710 }
711 virtual const XMLUnknown* ToUnknown() const {
712 return 0;
713 }
Lee Thomason751da522012-02-10 08:50:51 -0800714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 /** The meaning of 'value' changes for the specific type.
716 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530717 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 Element: name of the element
719 Comment: the comment text
720 Unknown: the tag contents
721 Text: the text string
722 @endverbatim
723 */
Michael Daumling21626882013-10-22 17:03:37 +0200724 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 /** Set the Value of an XML node.
727 @sa Value()
728 */
729 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800730
kezenatorec694152016-11-26 17:21:43 +1000731 /// Gets the line number the node is in, if the document was parsed from a file.
kezenator19d8ea82016-11-29 19:50:27 +1000732 int GetLineNum() const { return _parseLineNum; }
kezenatorec694152016-11-26 17:21:43 +1000733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 /// Get the parent of this node on the DOM.
735 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700736 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100738
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700740 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 }
Lee Thomason751da522012-02-10 08:50:51 -0800742
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 /// Returns true if this node has no children.
744 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700745 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700746 }
Lee Thomason751da522012-02-10 08:50:51 -0800747
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700748 /// Get the first child node, or null if none exists.
749 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700750 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100752
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700754 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100756
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 /** Get the first child element, or optionally the first child
758 element with the specified name.
759 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300760 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700761
Dmitry-Me886ad972015-07-22 11:00:51 +0300762 XMLElement* FirstChildElement( const char* name = 0 ) {
763 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700764 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800765
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700766 /// Get the last child node, or null if none exists.
767 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700768 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700770
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300772 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 /** Get the last child element or optionally the last child
776 element with the specified name.
777 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300778 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700779
Dmitry-Me886ad972015-07-22 11:00:51 +0300780 XMLElement* LastChildElement( const char* name = 0 ) {
781 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700783
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 /// Get the previous (left) sibling node of this node.
785 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700786 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700787 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700788
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700790 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800792
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700793 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300794 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700795
Dmitry-Me886ad972015-07-22 11:00:51 +0300796 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
797 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700798 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700799
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 /// Get the next (right) sibling node of this node.
801 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700802 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700804
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700805 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700806 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700808
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700809 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300810 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700811
Dmitry-Me886ad972015-07-22 11:00:51 +0300812 XMLElement* NextSiblingElement( const char* name = 0 ) {
813 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700814 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800815
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700816 /**
817 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200818 If the child node is already part of the document,
819 it is moved from its old location to the new location.
820 Returns the addThis argument or 0 if the node does not
821 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 */
823 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800824
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 XMLNode* LinkEndChild( XMLNode* addThis ) {
826 return InsertEndChild( addThis );
827 }
828 /**
829 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200830 If the child node is already part of the document,
831 it is moved from its old location to the new location.
832 Returns the addThis argument or 0 if the node does not
833 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700834 */
835 XMLNode* InsertFirstChild( XMLNode* addThis );
836 /**
837 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200838 If the child node is already part of the document,
839 it is moved from its old location to the new location.
840 Returns the addThis argument or 0 if the afterThis node
841 is not a child of this node, or if the node does not
842 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700843 */
844 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700845
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 /**
847 Delete all the children of this node.
848 */
849 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800850
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700851 /**
852 Delete a child of this node.
853 */
854 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800855
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 /**
857 Make a copy of this node, but not its children.
858 You may pass in a Document pointer that will be
859 the owner of the new Node. If the 'document' is
860 null, then the node returned will be allocated
861 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800862
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 Note: if called on a XMLDocument, this will return null.
864 */
865 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800866
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700867 /**
868 Test if 2 nodes are the same, but don't test children.
869 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800870
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700871 Note: if called on a XMLDocument, this will return false.
872 */
873 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800874
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600875 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600877 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800878
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600879 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
880 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700881 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800882
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800884
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 - http://www.saxproject.org/
886 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800887
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700888 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800889
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700890 An example of using Accept():
891 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600892 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700893 tinyxmlDoc.Accept( &printer );
894 const char* xmlcstr = printer.CStr();
895 @endverbatim
896 */
897 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800898
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700899 /**
900 Set user data into the XMLNode. TinyXML-2 in
901 no way processes or interprets user data.
902 It is initially 0.
903 */
904 void SetUserData(void* userData) { _userData = userData; }
905
906 /**
907 Get user data set into the XMLNode. TinyXML-2 in
908 no way processes or interprets user data.
909 It is initially 0.
910 */
911 void* GetUserData() const { return _userData; }
912
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800913protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700914 XMLNode( XMLDocument* );
915 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700916
Dmitry-Me10b8ecc2017-04-12 17:57:44 +0300917 virtual char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300918
Lee Thomason624d43f2012-10-12 10:58:48 -0700919 XMLDocument* _document;
920 XMLNode* _parent;
921 mutable StrPair _value;
kezenatorec694152016-11-26 17:21:43 +1000922 int _parseLineNum;
Lee Thomason3f57d272012-01-11 15:30:03 -0800923
Lee Thomason624d43f2012-10-12 10:58:48 -0700924 XMLNode* _firstChild;
925 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800926
Lee Thomason624d43f2012-10-12 10:58:48 -0700927 XMLNode* _prev;
928 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800929
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700930 void* _userData;
931
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800932private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700933 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400935 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800936 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Meecb9b072016-10-12 16:44:59 +0300937 const XMLElement* ToElementWithName( const char* name ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300938
939 XMLNode( const XMLNode& ); // not supported
940 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800941};
942
943
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800944/** XML text.
945
946 Note that a text node can have child element nodes, for example:
947 @verbatim
948 <root>This is <b>bold</b></root>
949 @endverbatim
950
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700951 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800952 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 -0700953 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600954 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800955*/
PKEuS16ed47d2013-07-06 12:02:43 +0200956class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800957{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700958 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800959public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700960 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800961
Lee Thomason624d43f2012-10-12 10:58:48 -0700962 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700963 return this;
964 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700965 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 return this;
967 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800968
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700969 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700970 void SetCData( bool isCData ) {
971 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700972 }
973 /// Returns true if this is a CDATA text element.
974 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700975 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800977
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700978 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
979 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800980
Lee Thomason5492a1c2012-01-23 15:32:10 -0800981protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700982 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800984
Dmitry-Me10b8ecc2017-04-12 17:57:44 +0300985 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300986
Lee Thomason5492a1c2012-01-23 15:32:10 -0800987private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700988 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300989
990 XMLText( const XMLText& ); // not supported
991 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800992};
993
994
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800995/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200996class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800997{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700998 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800999public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001000 virtual XMLComment* ToComment() {
1001 return this;
1002 }
1003 virtual const XMLComment* ToComment() const {
1004 return this;
1005 }
Lee Thomasonce0763e2012-01-11 15:43:54 -08001006
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001007 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001008
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001009 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1010 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -08001011
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001012protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001013 XMLComment( XMLDocument* doc );
1014 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001015
Dmitry-Me10b8ecc2017-04-12 17:57:44 +03001016 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr);
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001017
Lee Thomason3f57d272012-01-11 15:30:03 -08001018private:
Dmitry-Mef547a992015-01-09 15:17:09 +03001019 XMLComment( const XMLComment& ); // not supported
1020 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -08001021};
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001022
1023
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001024/** In correct XML the declaration is the first entry in the file.
1025 @verbatim
1026 <?xml version="1.0" standalone="yes"?>
1027 @endverbatim
1028
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001029 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001030 however.
1031
1032 The text of the declaration isn't interpreted. It is parsed
1033 and written as a string.
1034*/
PKEuS16ed47d2013-07-06 12:02:43 +02001035class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001036{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001037 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001038public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 virtual XMLDeclaration* ToDeclaration() {
1040 return this;
1041 }
1042 virtual const XMLDeclaration* ToDeclaration() const {
1043 return this;
1044 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001045
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001046 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001047
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001048 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1049 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001050
1051protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001052 XMLDeclaration( XMLDocument* doc );
1053 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +03001054
Dmitry-Me10b8ecc2017-04-12 17:57:44 +03001055 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001056
Dmitry-Mef547a992015-01-09 15:17:09 +03001057private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001058 XMLDeclaration( const XMLDeclaration& ); // not supported
1059 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001060};
1061
1062
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001063/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001064 unknown. It is a tag of text, but should not be modified.
1065 It will be written back to the XML, unchanged, when the file
1066 is saved.
1067
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001068 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001069*/
PKEuS16ed47d2013-07-06 12:02:43 +02001070class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001071{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001072 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001073public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001074 virtual XMLUnknown* ToUnknown() {
1075 return this;
1076 }
1077 virtual const XMLUnknown* ToUnknown() const {
1078 return this;
1079 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001080
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001081 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001082
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001083 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1084 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001085
1086protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 XMLUnknown( XMLDocument* doc );
1088 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001089
Dmitry-Me10b8ecc2017-04-12 17:57:44 +03001090 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001091
Dmitry-Mef547a992015-01-09 15:17:09 +03001092private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 XMLUnknown( const XMLUnknown& ); // not supported
1094 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001095};
1096
1097
Lee Thomason1ff38e02012-02-14 18:18:16 -08001098
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001099/** An attribute is a name-value pair. Elements have an arbitrary
1100 number of attributes, each with a unique name.
1101
1102 @note The attributes are not XMLNodes. You may only query the
1103 Next() attribute in a list.
1104*/
PKEuS16ed47d2013-07-06 12:02:43 +02001105class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001106{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001108public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001109 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001110 const char* Name() const;
1111
Lee Thomason2fa81722012-11-09 12:37:46 -08001112 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001113 const char* Value() const;
1114
kezenatorec694152016-11-26 17:21:43 +10001115 /// Gets the line number the attribute is in, if the document was parsed from a file.
kezenator19d8ea82016-11-29 19:50:27 +10001116 int GetLineNum() const { return _parseLineNum; }
kezenatorec694152016-11-26 17:21:43 +10001117
Lee Thomason2fa81722012-11-09 12:37:46 -08001118 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001119 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001120 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001121 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001122
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001123 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001124 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001125 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001126 */
Lee Thomason51c12712016-06-04 20:18:49 -07001127 int IntValue() const {
1128 int i = 0;
1129 QueryIntValue(&i);
1130 return i;
1131 }
1132
1133 int64_t Int64Value() const {
1134 int64_t i = 0;
1135 QueryInt64Value(&i);
1136 return i;
1137 }
1138
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001139 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001140 unsigned UnsignedValue() const {
1141 unsigned i=0;
1142 QueryUnsignedValue( &i );
1143 return i;
1144 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001145 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001146 bool BoolValue() const {
1147 bool b=false;
1148 QueryBoolValue( &b );
1149 return b;
1150 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001151 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001152 double DoubleValue() const {
1153 double d=0;
1154 QueryDoubleValue( &d );
1155 return d;
1156 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001157 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001158 float FloatValue() const {
1159 float f=0;
1160 QueryFloatValue( &f );
1161 return f;
1162 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001163
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001164 /** QueryIntValue interprets the attribute as an integer, and returns the value
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001165 in the provided parameter. The function will return XML_SUCCESS on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1167 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001168 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001169 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001170 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001171 /// See QueryIntValue
1172 XMLError QueryInt64Value(int64_t* value) const;
1173 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001174 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001175 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001176 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001177 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001178 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001179
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001180 /// Set the attribute to a string value.
1181 void SetAttribute( const char* value );
1182 /// Set the attribute to value.
1183 void SetAttribute( int value );
1184 /// Set the attribute to value.
1185 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001186 /// Set the attribute to value.
1187 void SetAttribute(int64_t value);
1188 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001189 void SetAttribute( bool value );
1190 /// Set the attribute to value.
1191 void SetAttribute( double value );
1192 /// Set the attribute to value.
1193 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001194
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001195private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001196 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001197
Dmitry-Med120d642017-01-27 18:35:02 +03001198 XMLAttribute() : _parseLineNum( 0 ), _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001199 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001200
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001201 XMLAttribute( const XMLAttribute& ); // not supported
1202 void operator=( const XMLAttribute& ); // not supported
1203 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001204
kezenator4f756162016-11-29 19:46:27 +10001205 char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001206
Lee Thomason624d43f2012-10-12 10:58:48 -07001207 mutable StrPair _name;
1208 mutable StrPair _value;
kezenatorec694152016-11-26 17:21:43 +10001209 int _parseLineNum;
Lee Thomason624d43f2012-10-12 10:58:48 -07001210 XMLAttribute* _next;
1211 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001212};
1213
1214
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001215/** The element is a container class. It has a value, the element name,
1216 and can contain other elements, text, comments, and unknowns.
1217 Elements also contain an arbitrary number of attributes.
1218*/
PKEuS16ed47d2013-07-06 12:02:43 +02001219class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001220{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001222public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 /// Get the name of an element (which is the Value() of the node.)
1224 const char* Name() const {
1225 return Value();
1226 }
1227 /// Set the name of the element.
1228 void SetName( const char* str, bool staticMem=false ) {
1229 SetValue( str, staticMem );
1230 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001231
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001232 virtual XMLElement* ToElement() {
1233 return this;
1234 }
1235 virtual const XMLElement* ToElement() const {
1236 return this;
1237 }
1238 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001239
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001240 /** Given an attribute name, Attribute() returns the value
1241 for the attribute of that name, or null if none
1242 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001243
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001244 @verbatim
1245 const char* value = ele->Attribute( "foo" );
1246 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001247
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001248 The 'value' parameter is normally null. However, if specified,
1249 the attribute will only be returned if the 'name' and 'value'
1250 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001251
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001252 @verbatim
1253 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1254 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001255
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001256 rather than:
1257 @verbatim
1258 if ( ele->Attribute( "foo" ) ) {
1259 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1260 }
1261 @endverbatim
1262 */
1263 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001264
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001265 /** Given an attribute name, IntAttribute() returns the value
Lee Thomason13cbc9a2016-10-27 14:55:07 -07001266 of the attribute interpreted as an integer. The default
1267 value will be returned if the attribute isn't present,
1268 or if there is an error. (For a method with error
1269 checking, see QueryIntAttribute()).
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001270 */
Josh Wittnercf3dd092016-10-11 18:57:17 -07001271 int IntAttribute(const char* name, int defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001272 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001273 unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001274 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001275 int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001276 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001277 bool BoolAttribute(const char* name, bool defaultValue = false) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001278 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001279 double DoubleAttribute(const char* name, double defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001280 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001281 float FloatAttribute(const char* name, float defaultValue = 0) const;
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001282
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001283 /** Given an attribute name, QueryIntAttribute() returns
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001284 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1286 doesn't exist. If successful, the result of the conversion
1287 will be written to 'value'. If not successful, nothing will
1288 be written to 'value'. This allows you to provide default
1289 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001290
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001291 @verbatim
1292 int value = 10;
1293 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1294 @endverbatim
1295 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001296 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001297 const XMLAttribute* a = FindAttribute( name );
1298 if ( !a ) {
1299 return XML_NO_ATTRIBUTE;
1300 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001301 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001302 }
Lee Thomason51c12712016-06-04 20:18:49 -07001303
1304 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001305 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 const XMLAttribute* a = FindAttribute( name );
1307 if ( !a ) {
1308 return XML_NO_ATTRIBUTE;
1309 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001310 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 }
Lee Thomason51c12712016-06-04 20:18:49 -07001312
1313 /// See QueryIntAttribute()
1314 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1315 const XMLAttribute* a = FindAttribute(name);
1316 if (!a) {
1317 return XML_NO_ATTRIBUTE;
1318 }
1319 return a->QueryInt64Value(value);
1320 }
1321
1322 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001323 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 const XMLAttribute* a = FindAttribute( name );
1325 if ( !a ) {
1326 return XML_NO_ATTRIBUTE;
1327 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001328 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 }
1330 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001331 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001332 const XMLAttribute* a = FindAttribute( name );
1333 if ( !a ) {
1334 return XML_NO_ATTRIBUTE;
1335 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001336 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001337 }
1338 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001339 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001340 const XMLAttribute* a = FindAttribute( name );
1341 if ( !a ) {
1342 return XML_NO_ATTRIBUTE;
1343 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001344 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001345 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001346
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001347
1348 /** Given an attribute name, QueryAttribute() returns
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001349 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001350 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1351 doesn't exist. It is overloaded for the primitive types,
1352 and is a generally more convenient replacement of
1353 QueryIntAttribute() and related functions.
1354
1355 If successful, the result of the conversion
1356 will be written to 'value'. If not successful, nothing will
1357 be written to 'value'. This allows you to provide default
1358 value:
1359
1360 @verbatim
1361 int value = 10;
1362 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1363 @endverbatim
1364 */
1365 int QueryAttribute( const char* name, int* value ) const {
1366 return QueryIntAttribute( name, value );
1367 }
1368
1369 int QueryAttribute( const char* name, unsigned int* value ) const {
1370 return QueryUnsignedAttribute( name, value );
1371 }
1372
Lee Thomason51c12712016-06-04 20:18:49 -07001373 int QueryAttribute(const char* name, int64_t* value) const {
1374 return QueryInt64Attribute(name, value);
1375 }
1376
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001377 int QueryAttribute( const char* name, bool* value ) const {
1378 return QueryBoolAttribute( name, value );
1379 }
1380
1381 int QueryAttribute( const char* name, double* value ) const {
1382 return QueryDoubleAttribute( name, value );
1383 }
1384
1385 int QueryAttribute( const char* name, float* value ) const {
1386 return QueryFloatAttribute( name, value );
1387 }
1388
1389 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001390 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001392 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001393 }
1394 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001395 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001397 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001398 }
1399 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 void SetAttribute( const char* name, unsigned 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 }
Lee Thomason51c12712016-06-04 20:18:49 -07001404
1405 /// Sets the named attribute to value.
1406 void SetAttribute(const char* name, int64_t value) {
1407 XMLAttribute* a = FindOrCreateAttribute(name);
1408 a->SetAttribute(value);
1409 }
1410
1411 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001412 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001414 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 }
1416 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001417 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001419 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001421 /// Sets the named attribute to value.
1422 void SetAttribute( const char* name, float value ) {
1423 XMLAttribute* a = FindOrCreateAttribute( name );
1424 a->SetAttribute( value );
1425 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001426
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 /**
1428 Delete an attribute.
1429 */
1430 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001431
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 /// Return the first attribute in the list.
1433 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001434 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001435 }
1436 /// Query a specific attribute in the list.
1437 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001438
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001439 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001440 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001442
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001443 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001445
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 This is a convenient method for getting the text of simple contained text:
1447 @verbatim
1448 <foo>This is text</foo>
1449 const char* str = fooElement->GetText();
1450 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001451
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001453
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001454 Note that this function can be misleading. If the element foo was created from
1455 this XML:
1456 @verbatim
1457 <foo><b>This is text</b></foo>
1458 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001459
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001460 then the value of str would be null. The first child node isn't a text node, it is
1461 another element. From this XML:
1462 @verbatim
1463 <foo>This is <b>text</b></foo>
1464 @endverbatim
1465 GetText() will return "This is ".
1466 */
1467 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001468
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001469 /** Convenience function for easy access to the text inside an element. Although easy
1470 and concise, SetText() is limited compared to creating an XMLText child
1471 and mutating it directly.
1472
1473 If the first child of 'this' is a XMLText, SetText() sets its value to
1474 the given string, otherwise it will create a first child that is an XMLText.
1475
1476 This is a convenient method for setting the text of simple contained text:
1477 @verbatim
1478 <foo>This is text</foo>
1479 fooElement->SetText( "Hullaballoo!" );
1480 <foo>Hullaballoo!</foo>
1481 @endverbatim
1482
1483 Note that this function can be misleading. If the element foo was created from
1484 this XML:
1485 @verbatim
1486 <foo><b>This is text</b></foo>
1487 @endverbatim
1488
1489 then it will not change "This is text", but rather prefix it with a text element:
1490 @verbatim
1491 <foo>Hullaballoo!<b>This is text</b></foo>
1492 @endverbatim
1493
1494 For this XML:
1495 @verbatim
1496 <foo />
1497 @endverbatim
1498 SetText() will generate
1499 @verbatim
1500 <foo>Hullaballoo!</foo>
1501 @endverbatim
1502 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001503 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001504 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001505 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001506 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001507 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001508 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1509 void SetText(int64_t value);
1510 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001511 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001512 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001513 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001514 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001515 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 /**
1518 Convenience method to query the value of a child text node. This is probably best
1519 shown by example. Given you have a document is this form:
1520 @verbatim
1521 <point>
1522 <x>1</x>
1523 <y>1.4</y>
1524 </point>
1525 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001526
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001527 The QueryIntText() and similar functions provide a safe and easier way to get to the
1528 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001529
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 @verbatim
1531 int x = 0;
1532 float y = 0; // types of x and y are contrived for example
1533 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1534 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1535 xElement->QueryIntText( &x );
1536 yElement->QueryFloatText( &y );
1537 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001538
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1540 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 -07001541
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001543 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001544 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001545 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001546 /// See QueryIntText()
1547 XMLError QueryInt64Text(int64_t* uval) const;
1548 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001549 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001550 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001551 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001552 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001553 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001554
Josh Wittnercf3dd092016-10-11 18:57:17 -07001555 int IntText(int defaultValue = 0) const;
1556
Josh Wittner3a621f52016-09-12 19:17:54 -07001557 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001558 unsigned UnsignedText(unsigned defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001559 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001560 int64_t Int64Text(int64_t defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001561 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001562 bool BoolText(bool defaultValue = false) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001563 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001564 double DoubleText(double defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001565 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001566 float FloatText(float defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001567
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001568 // internal:
Dmitry-Mee5035632017-04-05 18:02:40 +03001569 enum ElementClosingType {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001570 OPEN, // <foo>
1571 CLOSED, // <foo/>
1572 CLOSING // </foo>
1573 };
Dmitry-Mee5035632017-04-05 18:02:40 +03001574 ElementClosingType ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001575 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001576 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1578 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001579
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001580protected:
Dmitry-Me10b8ecc2017-04-12 17:57:44 +03001581 char* ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001582
Lee Thomason50adb4c2012-02-13 15:07:09 -08001583private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 XMLElement( XMLDocument* doc );
1585 virtual ~XMLElement();
1586 XMLElement( const XMLElement& ); // not supported
1587 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001588
Dmitry-Me1227d512014-12-05 13:41:45 +03001589 XMLAttribute* FindAttribute( const char* name ) {
1590 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1591 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 XMLAttribute* FindOrCreateAttribute( const char* name );
1593 //void LinkAttribute( XMLAttribute* attrib );
kezenator4f756162016-11-29 19:46:27 +10001594 char* ParseAttributes( char* p, int* curLineNumPtr );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001595 static void DeleteAttribute( XMLAttribute* attribute );
Dmitry-Mea60caa22016-11-22 18:28:08 +03001596 XMLAttribute* CreateAttribute();
Lee Thomason67d61312012-01-24 16:01:51 -08001597
Lee Thomason5bb2d802014-01-24 10:42:57 -08001598 enum { BUF_SIZE = 200 };
Dmitry-Mee5035632017-04-05 18:02:40 +03001599 ElementClosingType _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 // The attribute list is ordered; there is no 'lastAttribute'
1601 // because the list needs to be scanned for dupes before adding
1602 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001603 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001604};
1605
1606
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001607enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001608 PRESERVE_WHITESPACE,
1609 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001610};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001611
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001612
1613/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001614 It can be saved, loaded, and printed to the screen.
1615 All Nodes are connected and allocated to a Document.
1616 If the Document is deleted, all its Nodes are also deleted.
1617*/
PKEuS16ed47d2013-07-06 12:02:43 +02001618class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001619{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001620 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001621public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001622 /// constructor
Dmitry-Meae8a82a2017-03-03 15:40:32 +03001623 XMLDocument( bool processEntities = true, Whitespace whitespaceMode = PRESERVE_WHITESPACE );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001624 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001625
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001627 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 return this;
1629 }
1630 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001631 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001632 return this;
1633 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001634
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001635 /**
1636 Parse an XML file from a character string.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001637 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001638 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001639
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 You may optionally pass in the 'nBytes', which is
1641 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001642 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001643 null terminated string.
1644 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001645 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001646
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 /**
1648 Load an XML file from disk.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001649 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 an errorID.
1651 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001652 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001653
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 /**
1655 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001656 for providing and closing the FILE*.
1657
1658 NOTE: The file should be opened as binary ("rb")
1659 not text in order for TinyXML-2 to correctly
1660 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001661
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001662 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001663 an errorID.
1664 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001665 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001666
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001667 /**
1668 Save the XML file to disk.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001669 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001670 an errorID.
1671 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001672 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001673
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001674 /**
1675 Save the XML file to disk. You are responsible
1676 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001677
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001678 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001679 an errorID.
1680 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001681 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001682
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001683 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001684 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001685 }
1686 Whitespace WhitespaceMode() const {
Dmitry-Meae8a82a2017-03-03 15:40:32 +03001687 return _whitespaceMode;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001688 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001689
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001690 /**
1691 Returns true if this document has a leading Byte Order Mark of UTF8.
1692 */
1693 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001694 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001695 }
1696 /** Sets whether to write the BOM when writing the file.
1697 */
1698 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001699 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001700 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001701
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001702 /** Return the root element of DOM. Equivalent to FirstChildElement().
1703 To get the first node, use FirstChild().
1704 */
1705 XMLElement* RootElement() {
1706 return FirstChildElement();
1707 }
1708 const XMLElement* RootElement() const {
1709 return FirstChildElement();
1710 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001711
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 /** Print the Document. If the Printer is not provided, it will
1713 print to stdout. If you provide Printer, this can print to a file:
1714 @verbatim
1715 XMLPrinter printer( fp );
1716 doc.Print( &printer );
1717 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001718
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001719 Or you can use a printer to print to memory:
1720 @verbatim
1721 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001722 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 // printer.CStr() has a const char* to the XML
1724 @endverbatim
1725 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001726 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001728
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001729 /**
1730 Create a new Element associated with
1731 this Document. The memory for the Element
1732 is managed by the Document.
1733 */
1734 XMLElement* NewElement( const char* name );
1735 /**
1736 Create a new Comment associated with
1737 this Document. The memory for the Comment
1738 is managed by the Document.
1739 */
1740 XMLComment* NewComment( const char* comment );
1741 /**
1742 Create a new Text associated with
1743 this Document. The memory for the Text
1744 is managed by the Document.
1745 */
1746 XMLText* NewText( const char* text );
1747 /**
1748 Create a new Declaration associated with
1749 this Document. The memory for the object
1750 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001751
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 If the 'text' param is null, the standard
1753 declaration is used.:
1754 @verbatim
1755 <?xml version="1.0" encoding="UTF-8"?>
1756 @endverbatim
1757 */
1758 XMLDeclaration* NewDeclaration( const char* text=0 );
1759 /**
1760 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001761 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001762 is managed by the Document.
1763 */
1764 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001765
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001766 /**
1767 Delete a node associated with this document.
1768 It will be unlinked from the DOM.
1769 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001770 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001771
kezenatorec694152016-11-26 17:21:43 +10001772 void SetError( XMLError error, const char* str1, const char* str2, int lineNum );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001773
Dmitry-Me0d2cef02016-11-25 18:39:52 +03001774 void ClearError() {
kezenator2489afc2016-11-29 19:33:44 +10001775 SetError(XML_SUCCESS, 0, 0, 0);
Dmitry-Me0d2cef02016-11-25 18:39:52 +03001776 }
1777
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001778 /// Return true if there was an error parsing the document.
1779 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001780 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001781 }
1782 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001783 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001784 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001785 }
Lee Thomason331596e2014-09-11 14:56:43 -07001786 const char* ErrorName() const;
Lee Thomasone90e9012016-12-24 07:34:39 -08001787 static const char* ErrorIDToName(XMLError errorID);
Lee Thomason331596e2014-09-11 14:56:43 -07001788
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 /// Return a possibly helpful diagnostic location or string.
1790 const char* GetErrorStr1() const {
Lee Thomason584af572016-09-05 14:14:16 -07001791 return _errorStr1.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 }
1793 /// Return a possibly helpful secondary diagnostic location or string.
1794 const char* GetErrorStr2() const {
Lee Thomason584af572016-09-05 14:14:16 -07001795 return _errorStr2.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 }
kezenatorec694152016-11-26 17:21:43 +10001797 /// Return the line where the error occured, or zero if unknown.
1798 int GetErrorLineNum() const
1799 {
1800 return _errorLineNum;
1801 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 /// If there is an error, print it to stdout.
1803 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001804
1805 /// Clear the document, resetting it to the initial state.
1806 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001807
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001808 // internal
1809 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001810
Lee Thomason816d3fa2017-06-05 14:35:55 -07001811 // internal
1812 void MarkInUse(XMLNode*);
1813
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001814 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1815 return 0;
1816 }
1817 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1818 return false;
1819 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001820
Lee Thomason3f57d272012-01-11 15:30:03 -08001821private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001822 XMLDocument( const XMLDocument& ); // not supported
1823 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001824
Lee Thomasone90e9012016-12-24 07:34:39 -08001825 bool _writeBOM;
1826 bool _processEntities;
1827 XMLError _errorID;
Dmitry-Meae8a82a2017-03-03 15:40:32 +03001828 Whitespace _whitespaceMode;
Lee Thomasone90e9012016-12-24 07:34:39 -08001829 mutable StrPair _errorStr1;
1830 mutable StrPair _errorStr2;
1831 int _errorLineNum;
1832 char* _charBuffer;
1833 int _parseCurLineNum;
Lee Thomason816d3fa2017-06-05 14:35:55 -07001834 // Memory tracking does add some overhead.
1835 // However, the code assumes that you don't
1836 // have a bunch of unlinked nodes around.
1837 // Therefore it takes less memory to track
1838 // in the document vs. a linked list in the XMLNode,
1839 // and the performance is the same.
1840 DynArray<XMLNode*, 10> _unlinked;
Lee Thomasond1983222012-02-06 08:41:24 -08001841
Lee Thomason624d43f2012-10-12 10:58:48 -07001842 MemPoolT< sizeof(XMLElement) > _elementPool;
1843 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1844 MemPoolT< sizeof(XMLText) > _textPool;
1845 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001846
1847 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001848
1849 void Parse();
Dmitry-Me2aebfb72017-02-27 15:53:40 +03001850
1851 template<class NodeType, int PoolElementSize>
1852 NodeType* CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool );
Lee Thomason5cae8972012-01-24 18:03:07 -08001853};
1854
Dmitry-Me2aebfb72017-02-27 15:53:40 +03001855template<class NodeType, int PoolElementSize>
1856inline NodeType* XMLDocument::CreateUnlinkedNode( MemPoolT<PoolElementSize>& pool )
1857{
1858 TIXMLASSERT( sizeof( NodeType ) == PoolElementSize );
1859 TIXMLASSERT( sizeof( NodeType ) == pool.ItemSize() );
1860 NodeType* returnNode = new (pool.Alloc()) NodeType( this );
1861 TIXMLASSERT( returnNode );
1862 returnNode->_memPool = &pool;
Lee Thomason816d3fa2017-06-05 14:35:55 -07001863
1864 _unlinked.Push(returnNode);
Dmitry-Me2aebfb72017-02-27 15:53:40 +03001865 return returnNode;
1866}
Lee Thomason7c913cd2012-01-26 18:32:34 -08001867
Lee Thomason3ffdd392012-03-28 17:27:55 -07001868/**
1869 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001870 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001871 DOM structure. It is a separate utility class.
1872
1873 Take an example:
1874 @verbatim
1875 <Document>
1876 <Element attributeA = "valueA">
1877 <Child attributeB = "value1" />
1878 <Child attributeB = "value2" />
1879 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001880 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001881 @endverbatim
1882
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001883 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001884 easy to write a *lot* of code that looks like:
1885
1886 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001887 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001888 if ( root )
1889 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001890 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001891 if ( element )
1892 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001893 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001894 if ( child )
1895 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001896 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001897 if ( child2 )
1898 {
1899 // Finally do something useful.
1900 @endverbatim
1901
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001902 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001903 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001904 and correct to use:
1905
1906 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001907 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001908 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001909 if ( child2 )
1910 {
1911 // do something useful
1912 @endverbatim
1913
1914 Which is MUCH more concise and useful.
1915
1916 It is also safe to copy handles - internally they are nothing more than node pointers.
1917 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001918 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001919 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001920
1921 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001922*/
PKEuS16ed47d2013-07-06 12:02:43 +02001923class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001924{
1925public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001926 /// 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 -07001927 XMLHandle( XMLNode* node ) {
1928 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001929 }
1930 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001931 XMLHandle( XMLNode& node ) {
1932 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 }
1934 /// Copy constructor
1935 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001936 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 }
1938 /// Assignment
1939 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001940 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001941 return *this;
1942 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001943
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001944 /// Get the first child of this handle.
1945 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001946 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 }
1948 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001949 XMLHandle FirstChildElement( const char* name = 0 ) {
1950 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001951 }
1952 /// Get the last child of this handle.
1953 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001954 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 }
1956 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001957 XMLHandle LastChildElement( const char* name = 0 ) {
1958 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001959 }
1960 /// Get the previous sibling of this handle.
1961 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001962 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001963 }
1964 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001965 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1966 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001967 }
1968 /// Get the next sibling of this handle.
1969 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001970 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 }
1972 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001973 XMLHandle NextSiblingElement( const char* name = 0 ) {
1974 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001975 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001976
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001977 /// Safe cast to XMLNode. This can return null.
1978 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001979 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001980 }
1981 /// Safe cast to XMLElement. This can return null.
1982 XMLElement* ToElement() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001983 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001984 }
1985 /// Safe cast to XMLText. This can return null.
1986 XMLText* ToText() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001987 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001988 }
1989 /// Safe cast to XMLUnknown. This can return null.
1990 XMLUnknown* ToUnknown() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001991 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001992 }
1993 /// Safe cast to XMLDeclaration. This can return null.
1994 XMLDeclaration* ToDeclaration() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001995 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001997
1998private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001999 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07002000};
2001
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08002002
2003/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07002004 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
2005 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07002006*/
PKEuS16ed47d2013-07-06 12:02:43 +02002007class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07002008{
2009public:
Lee Thomason624d43f2012-10-12 10:58:48 -07002010 XMLConstHandle( const XMLNode* node ) {
2011 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002012 }
Lee Thomason624d43f2012-10-12 10:58:48 -07002013 XMLConstHandle( const XMLNode& node ) {
2014 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002015 }
2016 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07002017 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002018 }
Lee Thomason8b899812012-04-04 15:58:16 -07002019
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002020 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07002021 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002022 return *this;
2023 }
Lee Thomason8b899812012-04-04 15:58:16 -07002024
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002025 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002026 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002027 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002028 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
2029 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002030 }
2031 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002032 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002033 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002034 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
2035 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002036 }
2037 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002038 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002039 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002040 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
2041 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002042 }
2043 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002044 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002045 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002046 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
2047 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002048 }
Lee Thomason8b899812012-04-04 15:58:16 -07002049
2050
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002051 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002052 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002053 }
2054 const XMLElement* ToElement() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002055 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002056 }
2057 const XMLText* ToText() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002058 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002059 }
2060 const XMLUnknown* ToUnknown() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002061 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002062 }
2063 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002064 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002065 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002066
Lee Thomason5cae8972012-01-24 18:03:07 -08002067private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002068 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002069};
Lee Thomason6f381b72012-03-02 12:59:39 -08002070
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002071
2072/**
2073 Printing functionality. The XMLPrinter gives you more
2074 options than the XMLDocument::Print() method.
2075
2076 It can:
2077 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002078 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002079 -# Print XML without a XMLDocument.
2080
2081 Print to Memory
2082
2083 @verbatim
2084 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002085 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002086 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002087 @endverbatim
2088
2089 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002090
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002091 You provide the file pointer.
2092 @verbatim
2093 XMLPrinter printer( fp );
2094 doc.Print( &printer );
2095 @endverbatim
2096
2097 Print without a XMLDocument
2098
2099 When loading, an XML parser is very useful. However, sometimes
2100 when saving, it just gets in the way. The code is often set up
2101 for streaming, and constructing the DOM is just overhead.
2102
2103 The Printer supports the streaming case. The following code
2104 prints out a trivially simple XML file without ever creating
2105 an XML document.
2106
2107 @verbatim
2108 XMLPrinter printer( fp );
2109 printer.OpenElement( "foo" );
2110 printer.PushAttribute( "foo", "bar" );
2111 printer.CloseElement();
2112 @endverbatim
2113*/
PKEuS16ed47d2013-07-06 12:02:43 +02002114class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002115{
2116public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002117 /** Construct the printer. If the FILE* is specified,
2118 this will print to the FILE. Else it will print
2119 to memory, and the result is available in CStr().
2120 If 'compact' is set to true, then output is created
2121 with only required whitespace and newlines.
2122 */
PKEuS1bfb9542013-08-04 13:51:17 +02002123 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002124 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002125
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002126 /** If streaming, write the BOM and declaration. */
2127 void PushHeader( bool writeBOM, bool writeDeclaration );
2128 /** If streaming, start writing an element.
2129 The element must be closed with CloseElement()
2130 */
Lee Thomason256adb62014-04-06 14:41:46 -07002131 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002132 /// If streaming, add an attribute to an open element.
2133 void PushAttribute( const char* name, const char* value );
2134 void PushAttribute( const char* name, int value );
2135 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002136 void PushAttribute(const char* name, int64_t value);
2137 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002138 void PushAttribute( const char* name, double value );
2139 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002140 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002141
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002142 /// Add a text node.
2143 void PushText( const char* text, bool cdata=false );
2144 /// Add a text node from an integer.
2145 void PushText( int value );
2146 /// Add a text node from an unsigned.
2147 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002148 /// Add a text node from an unsigned.
2149 void PushText(int64_t value);
2150 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002151 void PushText( bool value );
2152 /// Add a text node from a float.
2153 void PushText( float value );
2154 /// Add a text node from a double.
2155 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002156
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002157 /// Add a comment
2158 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002159
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002160 void PushDeclaration( const char* value );
2161 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002162
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002163 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2164 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2165 return true;
2166 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002167
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002168 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2169 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002170
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002171 virtual bool Visit( const XMLText& text );
2172 virtual bool Visit( const XMLComment& comment );
2173 virtual bool Visit( const XMLDeclaration& declaration );
2174 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002175
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002176 /**
2177 If in print to memory mode, return a pointer to
2178 the XML file in memory.
2179 */
2180 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002181 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002182 }
2183 /**
2184 If in print to memory mode, return the size
2185 of the XML file in memory. (Note the size returned
2186 includes the terminating null.)
2187 */
2188 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002189 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002190 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002191 /**
2192 If in print to memory mode, reset the buffer to the
2193 beginning.
2194 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002195 void ClearBuffer() {
2196 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002197 _buffer.Push(0);
Lee Thomason53858b42017-06-01 19:09:16 -07002198 _firstElement = true;
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002199 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002200
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002201protected:
Alexander Maid740b642014-05-20 22:04:42 +02002202 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002203
Lee Thomasonc18eb232014-02-21 17:31:17 -08002204 /** Prints out the space before an element. You may override to change
2205 the space and tabs used. A PrintSpace() override should call Print().
2206 */
2207 virtual void PrintSpace( int depth );
2208 void Print( const char* format, ... );
2209
Dmitry-Mea092bc12014-12-23 17:57:05 +03002210 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002211 bool _elementJustOpened;
2212 DynArray< const char*, 10 > _stack;
2213
2214private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002215 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002216
Lee Thomason624d43f2012-10-12 10:58:48 -07002217 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002218 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002219 int _depth;
2220 int _textDepth;
2221 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002222 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002223
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002224 enum {
2225 ENTITY_RANGE = 64,
2226 BUF_SIZE = 200
2227 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002228 bool _entityFlag[ENTITY_RANGE];
2229 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002230
Lee Thomason624d43f2012-10-12 10:58:48 -07002231 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002232};
2233
2234
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002235} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002236
PKEuS95060352013-07-26 10:42:44 +02002237#if defined(_MSC_VER)
2238# pragma warning(pop)
2239#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002240
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002241#endif // TINYXML2_INCLUDED