blob: b15da9e65589d16a3e8ef11215423859c51d6fcf [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
kezenatorec694152016-11-26 17:21:43 +1000163 char* ParseText( char* in, const char* endTag, int strFlags, int& curLineNum );
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 Thomasona9cf3f92012-10-11 16:56:51 -0700267 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300268 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700269 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700271
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700272 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300273 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700274 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800276
Lee Thomason2c85a712012-01-31 08:24:24 -0800277private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300278 DynArray( const DynArray& ); // not supported
279 void operator=( const DynArray& ); // not supported
280
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700281 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300282 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700283 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300284 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 int newAllocated = cap * 2;
286 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700287 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
288 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700289 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700290 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700291 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700292 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700293 }
294 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800295
Lee Thomason624d43f2012-10-12 10:58:48 -0700296 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300297 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700298 int _allocated; // objects allocated
299 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800300};
301
Lee Thomason50adb4c2012-02-13 15:07:09 -0800302
U-Stream\Leeae25a442012-02-17 17:48:16 -0800303/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200304 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800305 and deallocation of objects.
306*/
PKEuS95060352013-07-26 10:42:44 +0200307class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800308{
309public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700310 MemPool() {}
311 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual int ItemSize() const = 0;
314 virtual void* Alloc() = 0;
315 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800316 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700317 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800318};
319
Lee Thomason50adb4c2012-02-13 15:07:09 -0800320
U-Stream\Leeae25a442012-02-17 17:48:16 -0800321/*
322 Template child class to create pools of the correct type.
323*/
Dmitry-Me88145b82016-08-09 17:59:31 +0300324template< int ITEM_SIZE >
PKEuS95060352013-07-26 10:42:44 +0200325class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800326{
327public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800328 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700329 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700330 Clear();
331 }
332
333 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700334 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700335 while( !_blockPtrs.Empty()) {
336 Block* b = _blockPtrs.Pop();
337 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700338 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700339 _root = 0;
340 _currentAllocs = 0;
341 _nAllocs = 0;
342 _maxAllocs = 0;
343 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 }
Lee Thomasond1983222012-02-06 08:41:24 -0800345
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 virtual int ItemSize() const {
Dmitry-Me88145b82016-08-09 17:59:31 +0300347 return ITEM_SIZE;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 }
349 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 return _currentAllocs;
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 void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700355 // Need a new block.
356 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700357 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800358
Dmitry-Me88145b82016-08-09 17:59:31 +0300359 Item* blockItems = block->items;
360 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
361 blockItems[i].next = &(blockItems[i + 1]);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700362 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300363 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
364 _root = blockItems;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300366 Item* const result = _root;
367 TIXMLASSERT( result != 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700368 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800369
Lee Thomason624d43f2012-10-12 10:58:48 -0700370 ++_currentAllocs;
371 if ( _currentAllocs > _maxAllocs ) {
372 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 }
Dmitry-Me3161a332016-09-02 16:58:06 +0300374 ++_nAllocs;
375 ++_nUntracked;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700376 return result;
377 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700378
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700379 virtual void Free( void* mem ) {
380 if ( !mem ) {
381 return;
382 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700383 --_currentAllocs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300384 Item* item = static_cast<Item*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700385#ifdef DEBUG
Dmitry-Me88145b82016-08-09 17:59:31 +0300386 memset( item, 0xfe, sizeof( *item ) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700387#endif
Dmitry-Me88145b82016-08-09 17:59:31 +0300388 item->next = _root;
389 _root = item;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700390 }
391 void Trace( const char* name ) {
392 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Dmitry-Me88145b82016-08-09 17:59:31 +0300393 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
394 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 }
Lee Thomasond1983222012-02-06 08:41:24 -0800396
Lee Thomason5b0a6772012-11-19 13:54:42 -0800397 void SetTracked() {
Dmitry-Me3161a332016-09-02 16:58:06 +0300398 --_nUntracked;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800399 }
400
401 int Untracked() const {
402 return _nUntracked;
403 }
404
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800405 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
406 // The test file is large, 170k.
407 // Release: VS2010 gcc(no opt)
408 // 1k: 4000
409 // 2k: 4000
410 // 4k: 3900 21000
411 // 16k: 5200
412 // 32k: 4300
413 // 64k: 4000 21000
Dmitry-Me88145b82016-08-09 17:59:31 +0300414 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
415 // in private part if ITEMS_PER_BLOCK is private
416 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
Jerome Martinez7921df12012-10-24 11:45:44 +0200417
Lee Thomasond1983222012-02-06 08:41:24 -0800418private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300419 MemPoolT( const MemPoolT& ); // not supported
420 void operator=( const MemPoolT& ); // not supported
421
Dmitry-Me88145b82016-08-09 17:59:31 +0300422 union Item {
423 Item* next;
424 char itemData[ITEM_SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700425 };
426 struct Block {
Dmitry-Me88145b82016-08-09 17:59:31 +0300427 Item items[ITEMS_PER_BLOCK];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700428 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700429 DynArray< Block*, 10 > _blockPtrs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300430 Item* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800431
Lee Thomason624d43f2012-10-12 10:58:48 -0700432 int _currentAllocs;
433 int _nAllocs;
434 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800435 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800436};
437
Lee Thomason2c85a712012-01-31 08:24:24 -0800438
Lee Thomason56bdd022012-02-09 18:16:58 -0800439
440/**
441 Implements the interface to the "Visitor pattern" (see the Accept() method.)
442 If you call the Accept() method, it requires being passed a XMLVisitor
443 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200444 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800445 are simply called with Visit().
446
447 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700448 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800449
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700450 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800451 visiting). You need to only override methods that are interesting to you.
452
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600453 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800454
455 You should never change the document from a callback.
456
457 @sa XMLNode::Accept()
458*/
PKEuS16ed47d2013-07-06 12:02:43 +0200459class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800460{
461public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700462 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800463
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700464 /// Visit a document.
465 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
466 return true;
467 }
468 /// Visit a document.
469 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
470 return true;
471 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800472
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700473 /// Visit an element.
474 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
475 return true;
476 }
477 /// Visit an element.
478 virtual bool VisitExit( const XMLElement& /*element*/ ) {
479 return true;
480 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800481
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700482 /// Visit a declaration.
483 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
484 return true;
485 }
486 /// Visit a text node.
487 virtual bool Visit( const XMLText& /*text*/ ) {
488 return true;
489 }
490 /// Visit a comment node.
491 virtual bool Visit( const XMLComment& /*comment*/ ) {
492 return true;
493 }
494 /// Visit an unknown node.
495 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
496 return true;
497 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800498};
499
Dmitry-Me66d2a842014-11-08 15:24:52 +0300500// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900501enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900502 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900503 XML_NO_ATTRIBUTE,
504 XML_WRONG_ATTRIBUTE_TYPE,
505 XML_ERROR_FILE_NOT_FOUND,
506 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
507 XML_ERROR_FILE_READ_ERROR,
508 XML_ERROR_ELEMENT_MISMATCH,
509 XML_ERROR_PARSING_ELEMENT,
510 XML_ERROR_PARSING_ATTRIBUTE,
511 XML_ERROR_IDENTIFYING_TAG,
512 XML_ERROR_PARSING_TEXT,
513 XML_ERROR_PARSING_CDATA,
514 XML_ERROR_PARSING_COMMENT,
515 XML_ERROR_PARSING_DECLARATION,
516 XML_ERROR_PARSING_UNKNOWN,
517 XML_ERROR_EMPTY_DOCUMENT,
518 XML_ERROR_MISMATCHED_ELEMENT,
519 XML_ERROR_PARSING,
520 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700521 XML_NO_TEXT_NODE,
522
523 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900524};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900525
numatrumpetcd8550c2014-09-08 16:59:39 +0900526
U-Stream\Leeae25a442012-02-17 17:48:16 -0800527/*
528 Utility functionality.
529*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800530class XMLUtil
531{
Lee Thomasond1983222012-02-06 08:41:24 -0800532public:
kezenatorec694152016-11-26 17:21:43 +1000533 static const char* SkipWhiteSpace( const char* p, int& curLineNum ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300534 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300535 while( IsWhiteSpace(*p) ) {
kezenatorec694152016-11-26 17:21:43 +1000536 if (*p == '\n') {
537 ++curLineNum;
538 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700539 ++p;
540 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300541 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700542 return p;
543 }
kezenatorec694152016-11-26 17:21:43 +1000544 static char* SkipWhiteSpace( char* p, int& curLineNum ) {
545 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNum ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700546 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300547
548 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
549 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700550 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100551 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700552 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200553
554 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300555 if ( ch >= 128 ) {
556 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
557 return true;
558 }
559 if ( isalpha( ch ) ) {
560 return true;
561 }
562 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200563 }
564
565 inline static bool IsNameChar( unsigned char ch ) {
566 return IsNameStartChar( ch )
567 || isdigit( ch )
568 || ch == '.'
569 || ch == '-';
570 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800571
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700573 if ( p == q ) {
574 return true;
575 }
Dmitry-Me21f99692016-10-03 13:01:57 +0300576 TIXMLASSERT( p );
577 TIXMLASSERT( q );
578 TIXMLASSERT( nChar >= 0 );
Lee Thomason598a88d2015-10-09 14:42:12 -0700579 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200581
Dmitry-Me7865aad2015-06-19 16:23:35 +0300582 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400583 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800585
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700586 static const char* ReadBOM( const char* p, bool* hasBOM );
587 // p is the starting location,
588 // the UTF-8 value of the entity will be placed in value, and length filled in.
589 static const char* GetCharacterRef( const char* p, char* value, int* length );
590 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700591
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 // converts primitive types to strings
593 static void ToStr( int v, char* buffer, int bufferSize );
594 static void ToStr( unsigned v, char* buffer, int bufferSize );
595 static void ToStr( bool v, char* buffer, int bufferSize );
596 static void ToStr( float v, char* buffer, int bufferSize );
597 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700598 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700599
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 // converts strings to primitive types
601 static bool ToInt( const char* str, int* value );
602 static bool ToUnsigned( const char* str, unsigned* value );
603 static bool ToBool( const char* str, bool* value );
604 static bool ToFloat( const char* str, float* value );
605 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700606 static bool ToInt64(const char* str, int64_t* value);
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800607};
608
Lee Thomason5cae8972012-01-24 18:03:07 -0800609
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800610/** XMLNode is a base class for every object that is in the
611 XML Document Object Model (DOM), except XMLAttributes.
612 Nodes have siblings, a parent, and children which can
613 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700614 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800615 be cast to its more defined type.
616
Thomas Roß08bdf502012-05-12 14:21:23 +0200617 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800618 When the XMLDocument gets deleted, all its Nodes
619 will also be deleted.
620
621 @verbatim
622 A Document can contain: Element (container or leaf)
623 Comment (leaf)
624 Unknown (leaf)
625 Declaration( leaf )
626
627 An Element can contain: Element (container or leaf)
628 Text (leaf)
629 Attributes (not on tree)
630 Comment (leaf)
631 Unknown (leaf)
632
633 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800634*/
PKEuS16ed47d2013-07-06 12:02:43 +0200635class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800636{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 friend class XMLDocument;
638 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800639public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800640
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700641 /// Get the XMLDocument that owns this XMLNode.
642 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300643 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700644 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 }
646 /// Get the XMLDocument that owns this XMLNode.
647 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300648 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700649 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800651
Lee Thomason2fa81722012-11-09 12:37:46 -0800652 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800656 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100658 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800660 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100662 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800664 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100666 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800668 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100670 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700671 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800672 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700673 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100674 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800676
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700677 virtual const XMLElement* ToElement() const {
678 return 0;
679 }
680 virtual const XMLText* ToText() const {
681 return 0;
682 }
683 virtual const XMLComment* ToComment() const {
684 return 0;
685 }
686 virtual const XMLDocument* ToDocument() const {
687 return 0;
688 }
689 virtual const XMLDeclaration* ToDeclaration() const {
690 return 0;
691 }
692 virtual const XMLUnknown* ToUnknown() const {
693 return 0;
694 }
Lee Thomason751da522012-02-10 08:50:51 -0800695
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 /** The meaning of 'value' changes for the specific type.
697 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530698 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 Element: name of the element
700 Comment: the comment text
701 Unknown: the tag contents
702 Text: the text string
703 @endverbatim
704 */
Michael Daumling21626882013-10-22 17:03:37 +0200705 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100706
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 /** Set the Value of an XML node.
708 @sa Value()
709 */
710 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800711
kezenatorec694152016-11-26 17:21:43 +1000712 /// Gets the line number the node is in, if the document was parsed from a file.
713 int GetParseLineNum() const { return _parseLineNum; }
714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 /// Get the parent of this node on the DOM.
716 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700717 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100719
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700721 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700722 }
Lee Thomason751da522012-02-10 08:50:51 -0800723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 /// Returns true if this node has no children.
725 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700726 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 }
Lee Thomason751da522012-02-10 08:50:51 -0800728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 /// Get the first child node, or null if none exists.
730 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700731 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700735 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700736 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 /** Get the first child element, or optionally the first child
739 element with the specified name.
740 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300741 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700742
Dmitry-Me886ad972015-07-22 11:00:51 +0300743 XMLElement* FirstChildElement( const char* name = 0 ) {
744 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800746
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700747 /// Get the last child node, or null if none exists.
748 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700749 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700750 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700751
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300753 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800755
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700756 /** Get the last child element or optionally the last child
757 element with the specified name.
758 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300759 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700760
Dmitry-Me886ad972015-07-22 11:00:51 +0300761 XMLElement* LastChildElement( const char* name = 0 ) {
762 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700763 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700764
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700765 /// Get the previous (left) sibling node of this node.
766 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700767 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700769
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700770 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700771 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800773
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700774 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300775 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700776
Dmitry-Me886ad972015-07-22 11:00:51 +0300777 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
778 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700779 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700780
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700781 /// Get the next (right) sibling node of this node.
782 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700783 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700785
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700787 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700788 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700789
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700790 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300791 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700792
Dmitry-Me886ad972015-07-22 11:00:51 +0300793 XMLElement* NextSiblingElement( const char* name = 0 ) {
794 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700795 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800796
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700797 /**
798 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200799 If the child node is already part of the document,
800 it is moved from its old location to the new location.
801 Returns the addThis argument or 0 if the node does not
802 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 */
804 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800805
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 XMLNode* LinkEndChild( XMLNode* addThis ) {
807 return InsertEndChild( addThis );
808 }
809 /**
810 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200811 If the child node is already part of the document,
812 it is moved from its old location to the new location.
813 Returns the addThis argument or 0 if the node does not
814 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700815 */
816 XMLNode* InsertFirstChild( XMLNode* addThis );
817 /**
818 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200819 If the child node is already part of the document,
820 it is moved from its old location to the new location.
821 Returns the addThis argument or 0 if the afterThis node
822 is not a child of this node, or if the node does not
823 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700824 */
825 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700826
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700827 /**
828 Delete all the children of this node.
829 */
830 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800831
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700832 /**
833 Delete a child of this node.
834 */
835 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800836
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700837 /**
838 Make a copy of this node, but not its children.
839 You may pass in a Document pointer that will be
840 the owner of the new Node. If the 'document' is
841 null, then the node returned will be allocated
842 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800843
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 Note: if called on a XMLDocument, this will return null.
845 */
846 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800847
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700848 /**
849 Test if 2 nodes are the same, but don't test children.
850 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800851
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 Note: if called on a XMLDocument, this will return false.
853 */
854 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800855
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600856 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600858 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800859
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600860 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
861 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700862 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800863
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700864 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800865
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700866 - http://www.saxproject.org/
867 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800868
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700869 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800870
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700871 An example of using Accept():
872 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600873 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700874 tinyxmlDoc.Accept( &printer );
875 const char* xmlcstr = printer.CStr();
876 @endverbatim
877 */
878 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800879
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700880 /**
881 Set user data into the XMLNode. TinyXML-2 in
882 no way processes or interprets user data.
883 It is initially 0.
884 */
885 void SetUserData(void* userData) { _userData = userData; }
886
887 /**
888 Get user data set into the XMLNode. TinyXML-2 in
889 no way processes or interprets user data.
890 It is initially 0.
891 */
892 void* GetUserData() const { return _userData; }
893
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800894protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700895 XMLNode( XMLDocument* );
896 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700897
kezenatorec694152016-11-26 17:21:43 +1000898 virtual char* ParseDeep( char*, StrPair*, int& );
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300899
Lee Thomason624d43f2012-10-12 10:58:48 -0700900 XMLDocument* _document;
901 XMLNode* _parent;
902 mutable StrPair _value;
kezenatorec694152016-11-26 17:21:43 +1000903 int _parseLineNum;
Lee Thomason3f57d272012-01-11 15:30:03 -0800904
Lee Thomason624d43f2012-10-12 10:58:48 -0700905 XMLNode* _firstChild;
906 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800907
Lee Thomason624d43f2012-10-12 10:58:48 -0700908 XMLNode* _prev;
909 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800910
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700911 void* _userData;
912
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800913private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700914 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400916 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800917 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Meecb9b072016-10-12 16:44:59 +0300918 const XMLElement* ToElementWithName( const char* name ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300919
920 XMLNode( const XMLNode& ); // not supported
921 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800922};
923
924
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800925/** XML text.
926
927 Note that a text node can have child element nodes, for example:
928 @verbatim
929 <root>This is <b>bold</b></root>
930 @endverbatim
931
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700932 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800933 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 -0700934 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600935 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800936*/
PKEuS16ed47d2013-07-06 12:02:43 +0200937class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800938{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700939 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800940public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700941 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800942
Lee Thomason624d43f2012-10-12 10:58:48 -0700943 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 return this;
945 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700946 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700947 return this;
948 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800949
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700951 void SetCData( bool isCData ) {
952 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700953 }
954 /// Returns true if this is a CDATA text element.
955 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700956 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700957 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800958
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700959 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
960 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800961
Lee Thomason5492a1c2012-01-23 15:32:10 -0800962protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700963 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800965
kezenatorec694152016-11-26 17:21:43 +1000966 char* ParseDeep( char*, StrPair* endTag, int& curLineNum );
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300967
Lee Thomason5492a1c2012-01-23 15:32:10 -0800968private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700969 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300970
971 XMLText( const XMLText& ); // not supported
972 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800973};
974
975
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800976/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200977class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800978{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700979 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800980public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700981 virtual XMLComment* ToComment() {
982 return this;
983 }
984 virtual const XMLComment* ToComment() const {
985 return this;
986 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800987
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700988 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800989
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700990 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
991 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800992
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800993protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700994 XMLComment( XMLDocument* doc );
995 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800996
kezenatorec694152016-11-26 17:21:43 +1000997 char* ParseDeep( char*, StrPair* endTag, int& curLineNum);
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300998
Lee Thomason3f57d272012-01-11 15:30:03 -0800999private:
Dmitry-Mef547a992015-01-09 15:17:09 +03001000 XMLComment( const XMLComment& ); // not supported
1001 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -08001002};
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001003
1004
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001005/** In correct XML the declaration is the first entry in the file.
1006 @verbatim
1007 <?xml version="1.0" standalone="yes"?>
1008 @endverbatim
1009
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001010 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001011 however.
1012
1013 The text of the declaration isn't interpreted. It is parsed
1014 and written as a string.
1015*/
PKEuS16ed47d2013-07-06 12:02:43 +02001016class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001017{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001019public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001020 virtual XMLDeclaration* ToDeclaration() {
1021 return this;
1022 }
1023 virtual const XMLDeclaration* ToDeclaration() const {
1024 return this;
1025 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001026
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001027 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001028
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001029 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1030 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001031
1032protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001033 XMLDeclaration( XMLDocument* doc );
1034 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +03001035
kezenatorec694152016-11-26 17:21:43 +10001036 char* ParseDeep( char*, StrPair* endTag, int& curLineNum );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001037
Dmitry-Mef547a992015-01-09 15:17:09 +03001038private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 XMLDeclaration( const XMLDeclaration& ); // not supported
1040 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001041};
1042
1043
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001044/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001045 unknown. It is a tag of text, but should not be modified.
1046 It will be written back to the XML, unchanged, when the file
1047 is saved.
1048
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001049 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001050*/
PKEuS16ed47d2013-07-06 12:02:43 +02001051class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001052{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001054public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001055 virtual XMLUnknown* ToUnknown() {
1056 return this;
1057 }
1058 virtual const XMLUnknown* ToUnknown() const {
1059 return this;
1060 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001061
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001062 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001063
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001064 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1065 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001066
1067protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001068 XMLUnknown( XMLDocument* doc );
1069 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001070
kezenatorec694152016-11-26 17:21:43 +10001071 char* ParseDeep( char*, StrPair* endTag, int& curLineNum );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001072
Dmitry-Mef547a992015-01-09 15:17:09 +03001073private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001074 XMLUnknown( const XMLUnknown& ); // not supported
1075 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001076};
1077
1078
Lee Thomason1ff38e02012-02-14 18:18:16 -08001079
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001080/** An attribute is a name-value pair. Elements have an arbitrary
1081 number of attributes, each with a unique name.
1082
1083 @note The attributes are not XMLNodes. You may only query the
1084 Next() attribute in a list.
1085*/
PKEuS16ed47d2013-07-06 12:02:43 +02001086class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001087{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001089public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001090 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001091 const char* Name() const;
1092
Lee Thomason2fa81722012-11-09 12:37:46 -08001093 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001094 const char* Value() const;
1095
kezenatorec694152016-11-26 17:21:43 +10001096 /// Gets the line number the attribute is in, if the document was parsed from a file.
1097 int GetParseLineNum() const { return _parseLineNum; }
1098
Lee Thomason2fa81722012-11-09 12:37:46 -08001099 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001100 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001101 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001102 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001103
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001104 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001106 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 */
Lee Thomason51c12712016-06-04 20:18:49 -07001108 int IntValue() const {
1109 int i = 0;
1110 QueryIntValue(&i);
1111 return i;
1112 }
1113
1114 int64_t Int64Value() const {
1115 int64_t i = 0;
1116 QueryInt64Value(&i);
1117 return i;
1118 }
1119
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001120 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001121 unsigned UnsignedValue() const {
1122 unsigned i=0;
1123 QueryUnsignedValue( &i );
1124 return i;
1125 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001126 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001127 bool BoolValue() const {
1128 bool b=false;
1129 QueryBoolValue( &b );
1130 return b;
1131 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001132 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001133 double DoubleValue() const {
1134 double d=0;
1135 QueryDoubleValue( &d );
1136 return d;
1137 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001138 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 float FloatValue() const {
1140 float f=0;
1141 QueryFloatValue( &f );
1142 return f;
1143 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001144
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001145 /** QueryIntValue interprets the attribute as an integer, and returns the value
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001146 in the provided parameter. The function will return XML_SUCCESS on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001147 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1148 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001149 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001150 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001151 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001152 /// See QueryIntValue
1153 XMLError QueryInt64Value(int64_t* value) const;
1154 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001155 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001156 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001157 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001158 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001159 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001160
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001161 /// Set the attribute to a string value.
1162 void SetAttribute( const char* value );
1163 /// Set the attribute to value.
1164 void SetAttribute( int value );
1165 /// Set the attribute to value.
1166 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001167 /// Set the attribute to value.
1168 void SetAttribute(int64_t value);
1169 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001170 void SetAttribute( bool value );
1171 /// Set the attribute to value.
1172 void SetAttribute( double value );
1173 /// Set the attribute to value.
1174 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001175
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001176private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001177 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001178
Thomas Roß61892312013-05-12 14:07:38 +02001179 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001180 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001181
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001182 XMLAttribute( const XMLAttribute& ); // not supported
1183 void operator=( const XMLAttribute& ); // not supported
1184 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001185
kezenatorec694152016-11-26 17:21:43 +10001186 char* ParseDeep( char* p, bool processEntities, int& curLineNum );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001187
Lee Thomason624d43f2012-10-12 10:58:48 -07001188 mutable StrPair _name;
1189 mutable StrPair _value;
kezenatorec694152016-11-26 17:21:43 +10001190 int _parseLineNum;
Lee Thomason624d43f2012-10-12 10:58:48 -07001191 XMLAttribute* _next;
1192 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001193};
1194
1195
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001196/** The element is a container class. It has a value, the element name,
1197 and can contain other elements, text, comments, and unknowns.
1198 Elements also contain an arbitrary number of attributes.
1199*/
PKEuS16ed47d2013-07-06 12:02:43 +02001200class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001201{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001202 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001203public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 /// Get the name of an element (which is the Value() of the node.)
1205 const char* Name() const {
1206 return Value();
1207 }
1208 /// Set the name of the element.
1209 void SetName( const char* str, bool staticMem=false ) {
1210 SetValue( str, staticMem );
1211 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001212
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001213 virtual XMLElement* ToElement() {
1214 return this;
1215 }
1216 virtual const XMLElement* ToElement() const {
1217 return this;
1218 }
1219 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001220
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 /** Given an attribute name, Attribute() returns the value
1222 for the attribute of that name, or null if none
1223 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001224
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 @verbatim
1226 const char* value = ele->Attribute( "foo" );
1227 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001228
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 The 'value' parameter is normally null. However, if specified,
1230 the attribute will only be returned if the 'name' and 'value'
1231 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001232
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 @verbatim
1234 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1235 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001236
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 rather than:
1238 @verbatim
1239 if ( ele->Attribute( "foo" ) ) {
1240 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1241 }
1242 @endverbatim
1243 */
1244 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001245
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001246 /** Given an attribute name, IntAttribute() returns the value
Lee Thomason13cbc9a2016-10-27 14:55:07 -07001247 of the attribute interpreted as an integer. The default
1248 value will be returned if the attribute isn't present,
1249 or if there is an error. (For a method with error
1250 checking, see QueryIntAttribute()).
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001251 */
Josh Wittnercf3dd092016-10-11 18:57:17 -07001252 int IntAttribute(const char* name, int defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001253 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001254 unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001255 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001256 int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001257 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001258 bool BoolAttribute(const char* name, bool defaultValue = false) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001259 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001260 double DoubleAttribute(const char* name, double defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001261 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001262 float FloatAttribute(const char* name, float defaultValue = 0) const;
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001263
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001264 /** Given an attribute name, QueryIntAttribute() returns
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001265 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001266 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1267 doesn't exist. If successful, the result of the conversion
1268 will be written to 'value'. If not successful, nothing will
1269 be written to 'value'. This allows you to provide default
1270 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001271
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001272 @verbatim
1273 int value = 10;
1274 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1275 @endverbatim
1276 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001277 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001278 const XMLAttribute* a = FindAttribute( name );
1279 if ( !a ) {
1280 return XML_NO_ATTRIBUTE;
1281 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001282 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001283 }
Lee Thomason51c12712016-06-04 20:18:49 -07001284
1285 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001286 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 const XMLAttribute* a = FindAttribute( name );
1288 if ( !a ) {
1289 return XML_NO_ATTRIBUTE;
1290 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001291 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
Lee Thomason51c12712016-06-04 20:18:49 -07001293
1294 /// See QueryIntAttribute()
1295 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1296 const XMLAttribute* a = FindAttribute(name);
1297 if (!a) {
1298 return XML_NO_ATTRIBUTE;
1299 }
1300 return a->QueryInt64Value(value);
1301 }
1302
1303 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001304 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001305 const XMLAttribute* a = FindAttribute( name );
1306 if ( !a ) {
1307 return XML_NO_ATTRIBUTE;
1308 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001309 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001310 }
1311 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001312 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001313 const XMLAttribute* a = FindAttribute( name );
1314 if ( !a ) {
1315 return XML_NO_ATTRIBUTE;
1316 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001317 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 }
1319 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001320 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 const XMLAttribute* a = FindAttribute( name );
1322 if ( !a ) {
1323 return XML_NO_ATTRIBUTE;
1324 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001325 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001327
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001328
1329 /** Given an attribute name, QueryAttribute() returns
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001330 XML_SUCCESS, XML_WRONG_ATTRIBUTE_TYPE if the conversion
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001331 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1332 doesn't exist. It is overloaded for the primitive types,
1333 and is a generally more convenient replacement of
1334 QueryIntAttribute() and related functions.
1335
1336 If successful, the result of the conversion
1337 will be written to 'value'. If not successful, nothing will
1338 be written to 'value'. This allows you to provide default
1339 value:
1340
1341 @verbatim
1342 int value = 10;
1343 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1344 @endverbatim
1345 */
1346 int QueryAttribute( const char* name, int* value ) const {
1347 return QueryIntAttribute( name, value );
1348 }
1349
1350 int QueryAttribute( const char* name, unsigned int* value ) const {
1351 return QueryUnsignedAttribute( name, value );
1352 }
1353
Lee Thomason51c12712016-06-04 20:18:49 -07001354 int QueryAttribute(const char* name, int64_t* value) const {
1355 return QueryInt64Attribute(name, value);
1356 }
1357
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001358 int QueryAttribute( const char* name, bool* value ) const {
1359 return QueryBoolAttribute( name, value );
1360 }
1361
1362 int QueryAttribute( const char* name, double* value ) const {
1363 return QueryDoubleAttribute( name, value );
1364 }
1365
1366 int QueryAttribute( const char* name, float* value ) const {
1367 return QueryFloatAttribute( name, value );
1368 }
1369
1370 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001371 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001372 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001373 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001374 }
1375 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001376 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001378 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 }
1380 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001381 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001382 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001383 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 }
Lee Thomason51c12712016-06-04 20:18:49 -07001385
1386 /// Sets the named attribute to value.
1387 void SetAttribute(const char* name, int64_t value) {
1388 XMLAttribute* a = FindOrCreateAttribute(name);
1389 a->SetAttribute(value);
1390 }
1391
1392 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001393 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001394 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001395 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 }
1397 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001398 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001399 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001400 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001402 /// Sets the named attribute to value.
1403 void SetAttribute( const char* name, float value ) {
1404 XMLAttribute* a = FindOrCreateAttribute( name );
1405 a->SetAttribute( value );
1406 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001407
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 /**
1409 Delete an attribute.
1410 */
1411 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001412
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 /// Return the first attribute in the list.
1414 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001415 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001416 }
1417 /// Query a specific attribute in the list.
1418 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001419
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001421 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001422 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001423
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001424 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001425 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001426
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 This is a convenient method for getting the text of simple contained text:
1428 @verbatim
1429 <foo>This is text</foo>
1430 const char* str = fooElement->GetText();
1431 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001432
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001433 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001434
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001435 Note that this function can be misleading. If the element foo was created from
1436 this XML:
1437 @verbatim
1438 <foo><b>This is text</b></foo>
1439 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001440
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 then the value of str would be null. The first child node isn't a text node, it is
1442 another element. From this XML:
1443 @verbatim
1444 <foo>This is <b>text</b></foo>
1445 @endverbatim
1446 GetText() will return "This is ".
1447 */
1448 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001449
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001450 /** Convenience function for easy access to the text inside an element. Although easy
1451 and concise, SetText() is limited compared to creating an XMLText child
1452 and mutating it directly.
1453
1454 If the first child of 'this' is a XMLText, SetText() sets its value to
1455 the given string, otherwise it will create a first child that is an XMLText.
1456
1457 This is a convenient method for setting the text of simple contained text:
1458 @verbatim
1459 <foo>This is text</foo>
1460 fooElement->SetText( "Hullaballoo!" );
1461 <foo>Hullaballoo!</foo>
1462 @endverbatim
1463
1464 Note that this function can be misleading. If the element foo was created from
1465 this XML:
1466 @verbatim
1467 <foo><b>This is text</b></foo>
1468 @endverbatim
1469
1470 then it will not change "This is text", but rather prefix it with a text element:
1471 @verbatim
1472 <foo>Hullaballoo!<b>This is text</b></foo>
1473 @endverbatim
1474
1475 For this XML:
1476 @verbatim
1477 <foo />
1478 @endverbatim
1479 SetText() will generate
1480 @verbatim
1481 <foo>Hullaballoo!</foo>
1482 @endverbatim
1483 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001484 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001485 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001486 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001487 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001488 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001489 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1490 void SetText(int64_t value);
1491 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001492 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001493 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001494 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001495 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001496 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001497
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001498 /**
1499 Convenience method to query the value of a child text node. This is probably best
1500 shown by example. Given you have a document is this form:
1501 @verbatim
1502 <point>
1503 <x>1</x>
1504 <y>1.4</y>
1505 </point>
1506 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 The QueryIntText() and similar functions provide a safe and easier way to get to the
1509 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001510
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001511 @verbatim
1512 int x = 0;
1513 float y = 0; // types of x and y are contrived for example
1514 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1515 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1516 xElement->QueryIntText( &x );
1517 yElement->QueryFloatText( &y );
1518 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1521 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 -07001522
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001523 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001524 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001525 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001526 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001527 /// See QueryIntText()
1528 XMLError QueryInt64Text(int64_t* uval) const;
1529 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001530 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001532 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001533 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001534 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001535
Josh Wittnercf3dd092016-10-11 18:57:17 -07001536 int IntText(int defaultValue = 0) const;
1537
Josh Wittner3a621f52016-09-12 19:17:54 -07001538 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001539 unsigned UnsignedText(unsigned defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001540 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001541 int64_t Int64Text(int64_t defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001542 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001543 bool BoolText(bool defaultValue = false) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001544 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001545 double DoubleText(double defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001546 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001547 float FloatText(float defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001548
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001549 // internal:
1550 enum {
1551 OPEN, // <foo>
1552 CLOSED, // <foo/>
1553 CLOSING // </foo>
1554 };
1555 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001556 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001557 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001558 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1559 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001560
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001561protected:
kezenatorec694152016-11-26 17:21:43 +10001562 char* ParseDeep( char* p, StrPair* endTag, int& curLineNum );
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001563
Lee Thomason50adb4c2012-02-13 15:07:09 -08001564private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001565 XMLElement( XMLDocument* doc );
1566 virtual ~XMLElement();
1567 XMLElement( const XMLElement& ); // not supported
1568 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001569
Dmitry-Me1227d512014-12-05 13:41:45 +03001570 XMLAttribute* FindAttribute( const char* name ) {
1571 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1572 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001573 XMLAttribute* FindOrCreateAttribute( const char* name );
1574 //void LinkAttribute( XMLAttribute* attrib );
kezenatorec694152016-11-26 17:21:43 +10001575 char* ParseAttributes( char* p, int& curLineNum );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001576 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001577
Lee Thomason5bb2d802014-01-24 10:42:57 -08001578 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001579 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 // The attribute list is ordered; there is no 'lastAttribute'
1581 // because the list needs to be scanned for dupes before adding
1582 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001583 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001584};
1585
1586
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001587enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 PRESERVE_WHITESPACE,
1589 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001590};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001591
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001592
1593/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001594 It can be saved, loaded, and printed to the screen.
1595 All Nodes are connected and allocated to a Document.
1596 If the Document is deleted, all its Nodes are also deleted.
1597*/
PKEuS16ed47d2013-07-06 12:02:43 +02001598class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001599{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001601public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 /// constructor
1603 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1604 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001605
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001607 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001608 return this;
1609 }
1610 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001611 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001612 return this;
1613 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001614
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001615 /**
1616 Parse an XML file from a character string.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001617 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001618 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001619
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001620 You may optionally pass in the 'nBytes', which is
1621 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001622 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001623 null terminated string.
1624 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001625 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001626
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001627 /**
1628 Load an XML file from disk.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001629 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001630 an errorID.
1631 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001632 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001633
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001634 /**
1635 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001636 for providing and closing the FILE*.
1637
1638 NOTE: The file should be opened as binary ("rb")
1639 not text in order for TinyXML-2 to correctly
1640 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001641
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001642 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001643 an errorID.
1644 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001645 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001646
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 /**
1648 Save the XML file to 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 SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001653
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 /**
1655 Save the XML file to disk. You are responsible
1656 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001657
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001658 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 an errorID.
1660 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001661 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001662
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001663 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001664 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001665 }
1666 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001667 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001668 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001669
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001670 /**
1671 Returns true if this document has a leading Byte Order Mark of UTF8.
1672 */
1673 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001674 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001675 }
1676 /** Sets whether to write the BOM when writing the file.
1677 */
1678 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001679 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001680 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001681
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001682 /** Return the root element of DOM. Equivalent to FirstChildElement().
1683 To get the first node, use FirstChild().
1684 */
1685 XMLElement* RootElement() {
1686 return FirstChildElement();
1687 }
1688 const XMLElement* RootElement() const {
1689 return FirstChildElement();
1690 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001691
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001692 /** Print the Document. If the Printer is not provided, it will
1693 print to stdout. If you provide Printer, this can print to a file:
1694 @verbatim
1695 XMLPrinter printer( fp );
1696 doc.Print( &printer );
1697 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001698
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001699 Or you can use a printer to print to memory:
1700 @verbatim
1701 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001702 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 // printer.CStr() has a const char* to the XML
1704 @endverbatim
1705 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001706 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001707 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001708
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 /**
1710 Create a new Element associated with
1711 this Document. The memory for the Element
1712 is managed by the Document.
1713 */
1714 XMLElement* NewElement( const char* name );
1715 /**
1716 Create a new Comment associated with
1717 this Document. The memory for the Comment
1718 is managed by the Document.
1719 */
1720 XMLComment* NewComment( const char* comment );
1721 /**
1722 Create a new Text associated with
1723 this Document. The memory for the Text
1724 is managed by the Document.
1725 */
1726 XMLText* NewText( const char* text );
1727 /**
1728 Create a new Declaration associated with
1729 this Document. The memory for the object
1730 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001731
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 If the 'text' param is null, the standard
1733 declaration is used.:
1734 @verbatim
1735 <?xml version="1.0" encoding="UTF-8"?>
1736 @endverbatim
1737 */
1738 XMLDeclaration* NewDeclaration( const char* text=0 );
1739 /**
1740 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001741 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001742 is managed by the Document.
1743 */
1744 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001745
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001746 /**
1747 Delete a node associated with this document.
1748 It will be unlinked from the DOM.
1749 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001750 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001751
kezenatorec694152016-11-26 17:21:43 +10001752 void SetError( XMLError error, const char* str1, const char* str2, int lineNum );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001753
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001754 /// Return true if there was an error parsing the document.
1755 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001756 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001757 }
1758 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001759 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001760 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001761 }
Lee Thomason331596e2014-09-11 14:56:43 -07001762 const char* ErrorName() const;
kezenator5a700712016-11-26 13:54:42 +10001763 static const char* ErrorName(XMLError errorID);
Lee Thomason331596e2014-09-11 14:56:43 -07001764
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 /// Return a possibly helpful diagnostic location or string.
1766 const char* GetErrorStr1() const {
Lee Thomason584af572016-09-05 14:14:16 -07001767 return _errorStr1.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001768 }
1769 /// Return a possibly helpful secondary diagnostic location or string.
1770 const char* GetErrorStr2() const {
Lee Thomason584af572016-09-05 14:14:16 -07001771 return _errorStr2.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001772 }
kezenatorec694152016-11-26 17:21:43 +10001773 /// Return the line where the error occured, or zero if unknown.
1774 int GetErrorLineNum() const
1775 {
1776 return _errorLineNum;
1777 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001778 /// If there is an error, print it to stdout.
1779 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001780
1781 /// Clear the document, resetting it to the initial state.
1782 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001783
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001784 // internal
1785 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001786
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1788 return 0;
1789 }
1790 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1791 return false;
1792 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001793
Lee Thomason3f57d272012-01-11 15:30:03 -08001794private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 XMLDocument( const XMLDocument& ); // not supported
1796 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001797
Lee Thomason2fa81722012-11-09 12:37:46 -08001798 bool _writeBOM;
1799 bool _processEntities;
1800 XMLError _errorID;
1801 Whitespace _whitespace;
Lee Thomason584af572016-09-05 14:14:16 -07001802 mutable StrPair _errorStr1;
1803 mutable StrPair _errorStr2;
kezenatorec694152016-11-26 17:21:43 +10001804 int _errorLineNum;
Lee Thomason2fa81722012-11-09 12:37:46 -08001805 char* _charBuffer;
kezenatorec694152016-11-26 17:21:43 +10001806 int _parseCurLineNum;
Lee Thomasond1983222012-02-06 08:41:24 -08001807
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 MemPoolT< sizeof(XMLElement) > _elementPool;
1809 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1810 MemPoolT< sizeof(XMLText) > _textPool;
1811 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001812
1813 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001814
1815 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001816};
1817
Lee Thomason7c913cd2012-01-26 18:32:34 -08001818
Lee Thomason3ffdd392012-03-28 17:27:55 -07001819/**
1820 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001821 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001822 DOM structure. It is a separate utility class.
1823
1824 Take an example:
1825 @verbatim
1826 <Document>
1827 <Element attributeA = "valueA">
1828 <Child attributeB = "value1" />
1829 <Child attributeB = "value2" />
1830 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001831 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001832 @endverbatim
1833
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001834 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001835 easy to write a *lot* of code that looks like:
1836
1837 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001838 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001839 if ( root )
1840 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001841 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001842 if ( element )
1843 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001844 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001845 if ( child )
1846 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001847 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001848 if ( child2 )
1849 {
1850 // Finally do something useful.
1851 @endverbatim
1852
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001853 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001854 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001855 and correct to use:
1856
1857 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001858 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001859 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001860 if ( child2 )
1861 {
1862 // do something useful
1863 @endverbatim
1864
1865 Which is MUCH more concise and useful.
1866
1867 It is also safe to copy handles - internally they are nothing more than node pointers.
1868 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001869 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001870 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001871
1872 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001873*/
PKEuS16ed47d2013-07-06 12:02:43 +02001874class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001875{
1876public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001877 /// 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 -07001878 XMLHandle( XMLNode* node ) {
1879 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 }
1881 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001882 XMLHandle( XMLNode& node ) {
1883 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 }
1885 /// Copy constructor
1886 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001887 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001888 }
1889 /// Assignment
1890 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001891 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 return *this;
1893 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001894
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001895 /// Get the first child of this handle.
1896 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001897 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001900 XMLHandle FirstChildElement( const char* name = 0 ) {
1901 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001902 }
1903 /// Get the last child of this handle.
1904 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001905 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001906 }
1907 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001908 XMLHandle LastChildElement( const char* name = 0 ) {
1909 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001910 }
1911 /// Get the previous sibling of this handle.
1912 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001913 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001914 }
1915 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001916 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1917 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 }
1919 /// Get the next sibling of this handle.
1920 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001921 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001922 }
1923 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001924 XMLHandle NextSiblingElement( const char* name = 0 ) {
1925 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001926 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001927
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001928 /// Safe cast to XMLNode. This can return null.
1929 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001930 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 }
1932 /// Safe cast to XMLElement. This can return null.
1933 XMLElement* ToElement() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001934 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001935 }
1936 /// Safe cast to XMLText. This can return null.
1937 XMLText* ToText() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001938 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001939 }
1940 /// Safe cast to XMLUnknown. This can return null.
1941 XMLUnknown* ToUnknown() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001942 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001943 }
1944 /// Safe cast to XMLDeclaration. This can return null.
1945 XMLDeclaration* ToDeclaration() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001946 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001948
1949private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001950 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001951};
1952
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001953
1954/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001955 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1956 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001957*/
PKEuS16ed47d2013-07-06 12:02:43 +02001958class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001959{
1960public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001961 XMLConstHandle( const XMLNode* node ) {
1962 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001963 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001964 XMLConstHandle( const XMLNode& node ) {
1965 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001966 }
1967 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001968 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001969 }
Lee Thomason8b899812012-04-04 15:58:16 -07001970
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001972 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001973 return *this;
1974 }
Lee Thomason8b899812012-04-04 15:58:16 -07001975
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001976 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001978 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001979 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1980 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001981 }
1982 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001983 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001984 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001985 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1986 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001987 }
1988 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001989 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001990 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001991 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1992 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001993 }
1994 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001995 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001997 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1998 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001999 }
Lee Thomason8b899812012-04-04 15:58:16 -07002000
2001
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002002 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002003 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002004 }
2005 const XMLElement* ToElement() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002006 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002007 }
2008 const XMLText* ToText() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002009 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002010 }
2011 const XMLUnknown* ToUnknown() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002012 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002013 }
2014 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002015 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002016 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002017
Lee Thomason5cae8972012-01-24 18:03:07 -08002018private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002019 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002020};
Lee Thomason6f381b72012-03-02 12:59:39 -08002021
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002022
2023/**
2024 Printing functionality. The XMLPrinter gives you more
2025 options than the XMLDocument::Print() method.
2026
2027 It can:
2028 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002029 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002030 -# Print XML without a XMLDocument.
2031
2032 Print to Memory
2033
2034 @verbatim
2035 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002036 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002037 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002038 @endverbatim
2039
2040 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002041
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002042 You provide the file pointer.
2043 @verbatim
2044 XMLPrinter printer( fp );
2045 doc.Print( &printer );
2046 @endverbatim
2047
2048 Print without a XMLDocument
2049
2050 When loading, an XML parser is very useful. However, sometimes
2051 when saving, it just gets in the way. The code is often set up
2052 for streaming, and constructing the DOM is just overhead.
2053
2054 The Printer supports the streaming case. The following code
2055 prints out a trivially simple XML file without ever creating
2056 an XML document.
2057
2058 @verbatim
2059 XMLPrinter printer( fp );
2060 printer.OpenElement( "foo" );
2061 printer.PushAttribute( "foo", "bar" );
2062 printer.CloseElement();
2063 @endverbatim
2064*/
PKEuS16ed47d2013-07-06 12:02:43 +02002065class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002066{
2067public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002068 /** Construct the printer. If the FILE* is specified,
2069 this will print to the FILE. Else it will print
2070 to memory, and the result is available in CStr().
2071 If 'compact' is set to true, then output is created
2072 with only required whitespace and newlines.
2073 */
PKEuS1bfb9542013-08-04 13:51:17 +02002074 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002075 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002076
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002077 /** If streaming, write the BOM and declaration. */
2078 void PushHeader( bool writeBOM, bool writeDeclaration );
2079 /** If streaming, start writing an element.
2080 The element must be closed with CloseElement()
2081 */
Lee Thomason256adb62014-04-06 14:41:46 -07002082 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002083 /// If streaming, add an attribute to an open element.
2084 void PushAttribute( const char* name, const char* value );
2085 void PushAttribute( const char* name, int value );
2086 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002087 void PushAttribute(const char* name, int64_t value);
2088 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002089 void PushAttribute( const char* name, double value );
2090 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002091 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002092
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002093 /// Add a text node.
2094 void PushText( const char* text, bool cdata=false );
2095 /// Add a text node from an integer.
2096 void PushText( int value );
2097 /// Add a text node from an unsigned.
2098 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002099 /// Add a text node from an unsigned.
2100 void PushText(int64_t value);
2101 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002102 void PushText( bool value );
2103 /// Add a text node from a float.
2104 void PushText( float value );
2105 /// Add a text node from a double.
2106 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002107
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002108 /// Add a comment
2109 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002110
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002111 void PushDeclaration( const char* value );
2112 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002113
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002114 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2115 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2116 return true;
2117 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002118
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002119 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2120 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002121
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002122 virtual bool Visit( const XMLText& text );
2123 virtual bool Visit( const XMLComment& comment );
2124 virtual bool Visit( const XMLDeclaration& declaration );
2125 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002126
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002127 /**
2128 If in print to memory mode, return a pointer to
2129 the XML file in memory.
2130 */
2131 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002132 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002133 }
2134 /**
2135 If in print to memory mode, return the size
2136 of the XML file in memory. (Note the size returned
2137 includes the terminating null.)
2138 */
2139 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002140 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002141 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002142 /**
2143 If in print to memory mode, reset the buffer to the
2144 beginning.
2145 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002146 void ClearBuffer() {
2147 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002148 _buffer.Push(0);
2149 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002150
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002151protected:
Alexander Maid740b642014-05-20 22:04:42 +02002152 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002153
Lee Thomasonc18eb232014-02-21 17:31:17 -08002154 /** Prints out the space before an element. You may override to change
2155 the space and tabs used. A PrintSpace() override should call Print().
2156 */
2157 virtual void PrintSpace( int depth );
2158 void Print( const char* format, ... );
2159
Dmitry-Mea092bc12014-12-23 17:57:05 +03002160 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002161 bool _elementJustOpened;
2162 DynArray< const char*, 10 > _stack;
2163
2164private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002165 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002166
Lee Thomason624d43f2012-10-12 10:58:48 -07002167 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002168 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002169 int _depth;
2170 int _textDepth;
2171 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002172 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002173
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002174 enum {
2175 ENTITY_RANGE = 64,
2176 BUF_SIZE = 200
2177 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002178 bool _entityFlag[ENTITY_RANGE];
2179 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002180
Lee Thomason624d43f2012-10-12 10:58:48 -07002181 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002182};
2183
2184
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002185} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002186
PKEuS95060352013-07-26 10:42:44 +02002187#if defined(_MSC_VER)
2188# pragma warning(pop)
2189#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002190
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002191#endif // TINYXML2_INCLUDED