blob: a72699c4fc9942f3a241f27dc42436ba359684e3 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Anton Indrawanf59e2d62014-11-18 20:50:42 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
Lee Thomasona572db12016-06-04 19:16:24 -070033# if defined(__PS3__)
34# include <stddef.h>
35# endif
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070036#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070037# include <cctype>
38# include <climits>
39# include <cstdio>
40# include <cstdlib>
41# include <cstring>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason1889c3e2016-06-04 20:22:57 -070043#include <stdint.h>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070044
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070045/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080046 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080047*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080048/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070049 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080050 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010051
Lee Thomasona9cf3f92012-10-11 16:56:51 -070052 Formatting, Artistic Style:
53 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080054*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080055
U-Lama\Lee4cee6112011-12-31 14:58:18 -080056#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070057# ifndef DEBUG
58# define DEBUG
59# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080060#endif
61
PKEuS95060352013-07-26 10:42:44 +020062#ifdef _MSC_VER
63# pragma warning(push)
64# pragma warning(disable: 4251)
65#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080066
PKEuS16ed47d2013-07-06 12:02:43 +020067#ifdef _WIN32
68# ifdef TINYXML2_EXPORT
69# define TINYXML2_LIB __declspec(dllexport)
70# elif defined(TINYXML2_IMPORT)
71# define TINYXML2_LIB __declspec(dllimport)
72# else
73# define TINYXML2_LIB
74# endif
Matthew Woehlkea8e7ea72016-08-09 13:16:26 -040075#elif __GNUC__ >= 4
76# define TINYXML2_LIB __attribute__((visibility("default")))
PKEuS16ed47d2013-07-06 12:02:43 +020077#else
78# define TINYXML2_LIB
79#endif
80
81
U-Lama\Lee4cee6112011-12-31 14:58:18 -080082#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070083# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030084# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070085# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070086# elif defined (ANDROID_NDK)
87# include <android/log.h>
88# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89# else
90# include <assert.h>
91# define TIXMLASSERT assert
92# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070093#else
94# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080095#endif
96
U-Lama\Leee13c3e62011-12-28 14:36:55 -080097
Lee Thomasonc18eb232014-02-21 17:31:17 -080098/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080099 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800100*/
Lee Thomason6ba2a072016-07-17 22:40:43 -0700101static const int TIXML2_MAJOR_VERSION = 4;
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason74d44ac2016-07-17 22:57:36 -0700103static const int TIXML2_PATCH_VERSION = 1;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800111class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800112class XMLDeclaration;
113class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800114class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800115
U-Stream\Leeae25a442012-02-17 17:48:16 -0800116/*
117 A class that wraps strings. Normally stores the start and end
118 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800119 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800120 manage) a traditional char[]
121*/
PKEuS95060352013-07-26 10:42:44 +0200122class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800123{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800124public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700125 enum {
126 NEEDS_ENTITY_PROCESSING = 0x01,
127 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300128 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800129
Lee Thomason584af572016-09-05 14:14:16 -0700130 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700131 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason584af572016-09-05 14:14:16 -0700132 ATTRIBUTE_NAME = 0,
133 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
134 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
135 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700136 };
Lee Thomason39ede242012-01-20 11:27:56 -0800137
Lee Thomason120b3a62012-10-12 10:06:59 -0700138 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700139 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800140
Lee Thomason120b3a62012-10-12 10:06:59 -0700141 void Set( char* start, char* end, int flags ) {
Dmitry-Me6fc38ec2016-09-01 17:59:44 +0300142 TIXMLASSERT( start );
143 TIXMLASSERT( end );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
kezenator4f756162016-11-29 19:46:27 +1000163 char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason29658802014-11-27 22:31:11 -0800166 void TransferTo( StrPair* other );
Lee Thomason584af572016-09-05 14:14:16 -0700167 void Reset();
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300168
Lee Thomason39ede242012-01-20 11:27:56 -0800169private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 enum {
173 NEEDS_FLUSH = 0x100,
174 NEEDS_DELETE = 0x200
175 };
Lee Thomasone4422302012-01-20 17:59:50 -0800176
Lee Thomason120b3a62012-10-12 10:06:59 -0700177 int _flags;
178 char* _start;
179 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300180
181 StrPair( const StrPair& other ); // not supported
182 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800183};
184
U-Lama\Lee560bd472011-12-28 19:42:49 -0800185
U-Stream\Leeae25a442012-02-17 17:48:16 -0800186/*
187 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
188 Has a small initial memory pool, so that low or no usage will not
189 cause a call to new/delete
190*/
Dmitry-Me04009222015-04-06 18:07:18 +0300191template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200192class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800193{
194public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300195 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700196 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300197 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700199 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700200
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700201 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700202 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700203 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700204 }
205 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700206
Lee Thomasonce0510b2013-11-26 21:29:37 -0800207 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100208 _size = 0;
209 }
210
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300212 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700213 EnsureCapacity( _size+1 );
Dmitry-Mefed51122016-09-06 18:08:55 +0300214 _mem[_size] = t;
215 ++_size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800217
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700218 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300219 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300220 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700221 EnsureCapacity( _size+count );
222 T* ret = &_mem[_size];
223 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 return ret;
225 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700226
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700227 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300228 TIXMLASSERT( _size > 0 );
Dmitry-Mefed51122016-09-06 18:08:55 +0300229 --_size;
230 return _mem[_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 TIXMLASSERT( _size >= count );
235 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700244 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700246
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700248 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700249 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700251
Lee Thomasonf07b9522014-10-30 13:25:12 -0700252 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500253 TIXMLASSERT( _size > 0 );
254 return _mem[ _size - 1];
255 }
256
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300258 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700259 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700261
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300263 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee 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:
kezenator4f756162016-11-29 19:46:27 +1000533 static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr ) {
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') {
kezenator4f756162016-11-29 19:46:27 +1000537 ++(*curLineNumPtr);
kezenatorec694152016-11-26 17:21:43 +1000538 }
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 }
kezenator4f756162016-11-29 19:46:27 +1000544 static char* SkipWhiteSpace( char* p, int* curLineNumPtr ) {
545 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
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.
kezenator19d8ea82016-11-29 19:50:27 +1000713 int GetLineNum() const { return _parseLineNum; }
kezenatorec694152016-11-26 17:21:43 +1000714
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
kezenator4f756162016-11-29 19:46:27 +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
kezenator4f756162016-11-29 19:46:27 +1000966 char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
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
kezenator4f756162016-11-29 19:46:27 +1000997 char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr);
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
kezenator4f756162016-11-29 19:46:27 +10001036 char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
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
kezenator4f756162016-11-29 19:46:27 +10001071 char* ParseDeep( char*, StrPair* endTag, int* curLineNumPtr );
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.
kezenator19d8ea82016-11-29 19:50:27 +10001097 int GetLineNum() const { return _parseLineNum; }
kezenatorec694152016-11-26 17:21:43 +10001098
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
kezenator4f756162016-11-29 19:46:27 +10001186 char* ParseDeep( char* p, bool processEntities, int* curLineNumPtr );
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:
kezenator4f756162016-11-29 19:46:27 +10001562 char* ParseDeep( char* p, StrPair* endTag, int* curLineNumPtr );
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 );
kezenator4f756162016-11-29 19:46:27 +10001575 char* ParseAttributes( char* p, int* curLineNumPtr );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001576 static void DeleteAttribute( XMLAttribute* attribute );
Dmitry-Mea60caa22016-11-22 18:28:08 +03001577 XMLAttribute* CreateAttribute();
Lee Thomason67d61312012-01-24 16:01:51 -08001578
Lee Thomason5bb2d802014-01-24 10:42:57 -08001579 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001580 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001581 // The attribute list is ordered; there is no 'lastAttribute'
1582 // because the list needs to be scanned for dupes before adding
1583 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001584 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001585};
1586
1587
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001588enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001589 PRESERVE_WHITESPACE,
1590 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001591};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001592
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001593
1594/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001595 It can be saved, loaded, and printed to the screen.
1596 All Nodes are connected and allocated to a Document.
1597 If the Document is deleted, all its Nodes are also deleted.
1598*/
PKEuS16ed47d2013-07-06 12:02:43 +02001599class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001600{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001601 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001602public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 /// constructor
1604 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1605 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001606
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001608 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001609 return this;
1610 }
1611 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001612 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001613 return this;
1614 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001615
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 /**
1617 Parse an XML file from a character string.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001618 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001620
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001621 You may optionally pass in the 'nBytes', which is
1622 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001623 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001624 null terminated string.
1625 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001626 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001627
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001628 /**
1629 Load an XML file from disk.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001630 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001631 an errorID.
1632 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001633 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001634
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001635 /**
1636 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001637 for providing and closing the FILE*.
1638
1639 NOTE: The file should be opened as binary ("rb")
1640 not text in order for TinyXML-2 to correctly
1641 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001642
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001643 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001644 an errorID.
1645 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001646 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001647
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001648 /**
1649 Save the XML file to disk.
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001650 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001651 an errorID.
1652 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001653 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001654
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001655 /**
1656 Save the XML file to disk. You are responsible
1657 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001658
Benjamin Doherty3b9cf992016-09-23 18:42:23 -06001659 Returns XML_SUCCESS (0) on success, or
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001660 an errorID.
1661 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001662 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001663
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001665 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001666 }
1667 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001668 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001669 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001670
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 /**
1672 Returns true if this document has a leading Byte Order Mark of UTF8.
1673 */
1674 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001675 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001676 }
1677 /** Sets whether to write the BOM when writing the file.
1678 */
1679 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001680 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001682
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001683 /** Return the root element of DOM. Equivalent to FirstChildElement().
1684 To get the first node, use FirstChild().
1685 */
1686 XMLElement* RootElement() {
1687 return FirstChildElement();
1688 }
1689 const XMLElement* RootElement() const {
1690 return FirstChildElement();
1691 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001692
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001693 /** Print the Document. If the Printer is not provided, it will
1694 print to stdout. If you provide Printer, this can print to a file:
1695 @verbatim
1696 XMLPrinter printer( fp );
1697 doc.Print( &printer );
1698 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001699
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001700 Or you can use a printer to print to memory:
1701 @verbatim
1702 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001703 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001704 // printer.CStr() has a const char* to the XML
1705 @endverbatim
1706 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001707 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001709
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001710 /**
1711 Create a new Element associated with
1712 this Document. The memory for the Element
1713 is managed by the Document.
1714 */
1715 XMLElement* NewElement( const char* name );
1716 /**
1717 Create a new Comment associated with
1718 this Document. The memory for the Comment
1719 is managed by the Document.
1720 */
1721 XMLComment* NewComment( const char* comment );
1722 /**
1723 Create a new Text associated with
1724 this Document. The memory for the Text
1725 is managed by the Document.
1726 */
1727 XMLText* NewText( const char* text );
1728 /**
1729 Create a new Declaration associated with
1730 this Document. The memory for the object
1731 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001732
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001733 If the 'text' param is null, the standard
1734 declaration is used.:
1735 @verbatim
1736 <?xml version="1.0" encoding="UTF-8"?>
1737 @endverbatim
1738 */
1739 XMLDeclaration* NewDeclaration( const char* text=0 );
1740 /**
1741 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001742 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 is managed by the Document.
1744 */
1745 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001746
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001747 /**
1748 Delete a node associated with this document.
1749 It will be unlinked from the DOM.
1750 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001751 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001752
kezenatorec694152016-11-26 17:21:43 +10001753 void SetError( XMLError error, const char* str1, const char* str2, int lineNum );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001754
Dmitry-Me0d2cef02016-11-25 18:39:52 +03001755 void ClearError() {
kezenator2489afc2016-11-29 19:33:44 +10001756 SetError(XML_SUCCESS, 0, 0, 0);
Dmitry-Me0d2cef02016-11-25 18:39:52 +03001757 }
1758
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001759 /// Return true if there was an error parsing the document.
1760 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001761 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001762 }
1763 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001764 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001765 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001766 }
Lee Thomason331596e2014-09-11 14:56:43 -07001767 const char* ErrorName() const;
kezenator5a700712016-11-26 13:54:42 +10001768 static const char* ErrorName(XMLError errorID);
Lee Thomason331596e2014-09-11 14:56:43 -07001769
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001770 /// Return a possibly helpful diagnostic location or string.
1771 const char* GetErrorStr1() const {
Lee Thomason584af572016-09-05 14:14:16 -07001772 return _errorStr1.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001773 }
1774 /// Return a possibly helpful secondary diagnostic location or string.
1775 const char* GetErrorStr2() const {
Lee Thomason584af572016-09-05 14:14:16 -07001776 return _errorStr2.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 }
kezenatorec694152016-11-26 17:21:43 +10001778 /// Return the line where the error occured, or zero if unknown.
1779 int GetErrorLineNum() const
1780 {
1781 return _errorLineNum;
1782 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 /// If there is an error, print it to stdout.
1784 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001785
1786 /// Clear the document, resetting it to the initial state.
1787 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001788
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 // internal
1790 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001791
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1793 return 0;
1794 }
1795 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1796 return false;
1797 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001798
Lee Thomason3f57d272012-01-11 15:30:03 -08001799private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001800 XMLDocument( const XMLDocument& ); // not supported
1801 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001802
Lee Thomason2fa81722012-11-09 12:37:46 -08001803 bool _writeBOM;
1804 bool _processEntities;
1805 XMLError _errorID;
1806 Whitespace _whitespace;
Lee Thomason584af572016-09-05 14:14:16 -07001807 mutable StrPair _errorStr1;
1808 mutable StrPair _errorStr2;
kezenatorec694152016-11-26 17:21:43 +10001809 int _errorLineNum;
Lee Thomason2fa81722012-11-09 12:37:46 -08001810 char* _charBuffer;
kezenatorec694152016-11-26 17:21:43 +10001811 int _parseCurLineNum;
Lee Thomasond1983222012-02-06 08:41:24 -08001812
Lee Thomason624d43f2012-10-12 10:58:48 -07001813 MemPoolT< sizeof(XMLElement) > _elementPool;
1814 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1815 MemPoolT< sizeof(XMLText) > _textPool;
1816 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001817
1818 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001819
1820 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001821};
1822
Lee Thomason7c913cd2012-01-26 18:32:34 -08001823
Lee Thomason3ffdd392012-03-28 17:27:55 -07001824/**
1825 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001826 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001827 DOM structure. It is a separate utility class.
1828
1829 Take an example:
1830 @verbatim
1831 <Document>
1832 <Element attributeA = "valueA">
1833 <Child attributeB = "value1" />
1834 <Child attributeB = "value2" />
1835 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001836 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001837 @endverbatim
1838
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001839 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001840 easy to write a *lot* of code that looks like:
1841
1842 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001843 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001844 if ( root )
1845 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001846 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001847 if ( element )
1848 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001849 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001850 if ( child )
1851 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001852 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001853 if ( child2 )
1854 {
1855 // Finally do something useful.
1856 @endverbatim
1857
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001858 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001859 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001860 and correct to use:
1861
1862 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001863 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001864 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001865 if ( child2 )
1866 {
1867 // do something useful
1868 @endverbatim
1869
1870 Which is MUCH more concise and useful.
1871
1872 It is also safe to copy handles - internally they are nothing more than node pointers.
1873 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001874 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001875 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001876
1877 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001878*/
PKEuS16ed47d2013-07-06 12:02:43 +02001879class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001880{
1881public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 /// 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 -07001883 XMLHandle( XMLNode* node ) {
1884 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001885 }
1886 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001887 XMLHandle( XMLNode& node ) {
1888 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001889 }
1890 /// Copy constructor
1891 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001892 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001893 }
1894 /// Assignment
1895 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001896 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001897 return *this;
1898 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001899
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001900 /// Get the first child of this handle.
1901 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001902 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001903 }
1904 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001905 XMLHandle FirstChildElement( const char* name = 0 ) {
1906 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001907 }
1908 /// Get the last child of this handle.
1909 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001910 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001911 }
1912 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001913 XMLHandle LastChildElement( const char* name = 0 ) {
1914 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001915 }
1916 /// Get the previous sibling of this handle.
1917 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001918 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001919 }
1920 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001921 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1922 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001923 }
1924 /// Get the next sibling of this handle.
1925 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001926 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001927 }
1928 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001929 XMLHandle NextSiblingElement( const char* name = 0 ) {
1930 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001932
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 /// Safe cast to XMLNode. This can return null.
1934 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001935 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001936 }
1937 /// Safe cast to XMLElement. This can return null.
1938 XMLElement* ToElement() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001939 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001940 }
1941 /// Safe cast to XMLText. This can return null.
1942 XMLText* ToText() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001943 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001944 }
1945 /// Safe cast to XMLUnknown. This can return null.
1946 XMLUnknown* ToUnknown() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001947 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001948 }
1949 /// Safe cast to XMLDeclaration. This can return null.
1950 XMLDeclaration* ToDeclaration() {
Dmitry-Meebb16602016-11-16 17:22:45 +03001951 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001952 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001953
1954private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001955 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001956};
1957
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001958
1959/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001960 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1961 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001962*/
PKEuS16ed47d2013-07-06 12:02:43 +02001963class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001964{
1965public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001966 XMLConstHandle( const XMLNode* node ) {
1967 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001968 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001969 XMLConstHandle( const XMLNode& node ) {
1970 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001971 }
1972 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001973 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001974 }
Lee Thomason8b899812012-04-04 15:58:16 -07001975
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001976 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001978 return *this;
1979 }
Lee Thomason8b899812012-04-04 15:58:16 -07001980
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001981 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001982 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001983 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001984 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1985 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001986 }
1987 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001988 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001989 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001990 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1991 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001992 }
1993 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001994 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001995 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001996 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1997 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001998 }
1999 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002000 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002001 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002002 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
2003 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002004 }
Lee Thomason8b899812012-04-04 15:58:16 -07002005
2006
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002007 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002008 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002009 }
2010 const XMLElement* ToElement() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002011 return ( _node ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002012 }
2013 const XMLText* ToText() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002014 return ( _node ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002015 }
2016 const XMLUnknown* ToUnknown() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002017 return ( _node ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002018 }
2019 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meebb16602016-11-16 17:22:45 +03002020 return ( _node ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002021 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002022
Lee Thomason5cae8972012-01-24 18:03:07 -08002023private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002024 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002025};
Lee Thomason6f381b72012-03-02 12:59:39 -08002026
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002027
2028/**
2029 Printing functionality. The XMLPrinter gives you more
2030 options than the XMLDocument::Print() method.
2031
2032 It can:
2033 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002034 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002035 -# Print XML without a XMLDocument.
2036
2037 Print to Memory
2038
2039 @verbatim
2040 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002041 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002042 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002043 @endverbatim
2044
2045 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002046
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002047 You provide the file pointer.
2048 @verbatim
2049 XMLPrinter printer( fp );
2050 doc.Print( &printer );
2051 @endverbatim
2052
2053 Print without a XMLDocument
2054
2055 When loading, an XML parser is very useful. However, sometimes
2056 when saving, it just gets in the way. The code is often set up
2057 for streaming, and constructing the DOM is just overhead.
2058
2059 The Printer supports the streaming case. The following code
2060 prints out a trivially simple XML file without ever creating
2061 an XML document.
2062
2063 @verbatim
2064 XMLPrinter printer( fp );
2065 printer.OpenElement( "foo" );
2066 printer.PushAttribute( "foo", "bar" );
2067 printer.CloseElement();
2068 @endverbatim
2069*/
PKEuS16ed47d2013-07-06 12:02:43 +02002070class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002071{
2072public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002073 /** Construct the printer. If the FILE* is specified,
2074 this will print to the FILE. Else it will print
2075 to memory, and the result is available in CStr().
2076 If 'compact' is set to true, then output is created
2077 with only required whitespace and newlines.
2078 */
PKEuS1bfb9542013-08-04 13:51:17 +02002079 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002080 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002081
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002082 /** If streaming, write the BOM and declaration. */
2083 void PushHeader( bool writeBOM, bool writeDeclaration );
2084 /** If streaming, start writing an element.
2085 The element must be closed with CloseElement()
2086 */
Lee Thomason256adb62014-04-06 14:41:46 -07002087 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002088 /// If streaming, add an attribute to an open element.
2089 void PushAttribute( const char* name, const char* value );
2090 void PushAttribute( const char* name, int value );
2091 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002092 void PushAttribute(const char* name, int64_t value);
2093 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002094 void PushAttribute( const char* name, double value );
2095 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002096 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002097
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002098 /// Add a text node.
2099 void PushText( const char* text, bool cdata=false );
2100 /// Add a text node from an integer.
2101 void PushText( int value );
2102 /// Add a text node from an unsigned.
2103 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002104 /// Add a text node from an unsigned.
2105 void PushText(int64_t value);
2106 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002107 void PushText( bool value );
2108 /// Add a text node from a float.
2109 void PushText( float value );
2110 /// Add a text node from a double.
2111 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002112
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002113 /// Add a comment
2114 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002115
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002116 void PushDeclaration( const char* value );
2117 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002118
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002119 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2120 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2121 return true;
2122 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002123
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002124 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2125 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002126
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002127 virtual bool Visit( const XMLText& text );
2128 virtual bool Visit( const XMLComment& comment );
2129 virtual bool Visit( const XMLDeclaration& declaration );
2130 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002131
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002132 /**
2133 If in print to memory mode, return a pointer to
2134 the XML file in memory.
2135 */
2136 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002137 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002138 }
2139 /**
2140 If in print to memory mode, return the size
2141 of the XML file in memory. (Note the size returned
2142 includes the terminating null.)
2143 */
2144 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002145 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002146 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002147 /**
2148 If in print to memory mode, reset the buffer to the
2149 beginning.
2150 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002151 void ClearBuffer() {
2152 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002153 _buffer.Push(0);
2154 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002155
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002156protected:
Alexander Maid740b642014-05-20 22:04:42 +02002157 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002158
Lee Thomasonc18eb232014-02-21 17:31:17 -08002159 /** Prints out the space before an element. You may override to change
2160 the space and tabs used. A PrintSpace() override should call Print().
2161 */
2162 virtual void PrintSpace( int depth );
2163 void Print( const char* format, ... );
2164
Dmitry-Mea092bc12014-12-23 17:57:05 +03002165 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002166 bool _elementJustOpened;
2167 DynArray< const char*, 10 > _stack;
2168
2169private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002170 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002171
Lee Thomason624d43f2012-10-12 10:58:48 -07002172 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002173 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002174 int _depth;
2175 int _textDepth;
2176 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002177 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002178
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002179 enum {
2180 ENTITY_RANGE = 64,
2181 BUF_SIZE = 200
2182 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002183 bool _entityFlag[ENTITY_RANGE];
2184 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002185
Lee Thomason624d43f2012-10-12 10:58:48 -07002186 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002187};
2188
2189
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002190} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002191
PKEuS95060352013-07-26 10:42:44 +02002192#if defined(_MSC_VER)
2193# pragma warning(pop)
2194#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002195
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002196#endif // TINYXML2_INCLUDED