blob: 6468e1631cbbc92cc49873e5853ba14d006c493e [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Anton Indrawanf59e2d62014-11-18 20:50:42 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
Lee Thomasona572db12016-06-04 19:16:24 -070033# if defined(__PS3__)
34# include <stddef.h>
35# endif
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070036#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070037# include <cctype>
38# include <climits>
39# include <cstdio>
40# include <cstdlib>
41# include <cstring>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason1889c3e2016-06-04 20:22:57 -070043#include <stdint.h>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070044
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070045/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080046 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080047*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080048/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070049 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080050 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010051
Lee Thomasona9cf3f92012-10-11 16:56:51 -070052 Formatting, Artistic Style:
53 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080054*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080055
U-Lama\Lee4cee6112011-12-31 14:58:18 -080056#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070057# ifndef DEBUG
58# define DEBUG
59# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080060#endif
61
PKEuS95060352013-07-26 10:42:44 +020062#ifdef _MSC_VER
63# pragma warning(push)
64# pragma warning(disable: 4251)
65#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080066
PKEuS16ed47d2013-07-06 12:02:43 +020067#ifdef _WIN32
68# ifdef TINYXML2_EXPORT
69# define TINYXML2_LIB __declspec(dllexport)
70# elif defined(TINYXML2_IMPORT)
71# define TINYXML2_LIB __declspec(dllimport)
72# else
73# define TINYXML2_LIB
74# endif
Matthew Woehlkea8e7ea72016-08-09 13:16:26 -040075#elif __GNUC__ >= 4
76# define TINYXML2_LIB __attribute__((visibility("default")))
PKEuS16ed47d2013-07-06 12:02:43 +020077#else
78# define TINYXML2_LIB
79#endif
80
81
U-Lama\Lee4cee6112011-12-31 14:58:18 -080082#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070083# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030084# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070085# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070086# elif defined (ANDROID_NDK)
87# include <android/log.h>
88# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89# else
90# include <assert.h>
91# define TIXMLASSERT assert
92# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070093#else
94# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080095#endif
96
U-Lama\Leee13c3e62011-12-28 14:36:55 -080097
Lee Thomasonc18eb232014-02-21 17:31:17 -080098/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080099 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800100*/
Lee Thomason6ba2a072016-07-17 22:40:43 -0700101static const int TIXML2_MAJOR_VERSION = 4;
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason74d44ac2016-07-17 22:57:36 -0700103static const int TIXML2_PATCH_VERSION = 1;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800111class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800112class XMLDeclaration;
113class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800114class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800115
U-Stream\Leeae25a442012-02-17 17:48:16 -0800116/*
117 A class that wraps strings. Normally stores the start and end
118 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800119 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800120 manage) a traditional char[]
121*/
PKEuS95060352013-07-26 10:42:44 +0200122class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800123{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800124public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700125 enum {
126 NEEDS_ENTITY_PROCESSING = 0x01,
127 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300128 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800129
selfpoisede77e1952013-03-13 14:08:29 +0800130 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700131 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800132 ATTRIBUTE_NAME = 0,
133 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
134 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
135 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700136 };
Lee Thomason39ede242012-01-20 11:27:56 -0800137
Lee Thomason120b3a62012-10-12 10:06:59 -0700138 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700139 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800140
Lee Thomason120b3a62012-10-12 10:06:59 -0700141 void Set( char* start, char* end, int flags ) {
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
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason29658802014-11-27 22:31:11 -0800166 void TransferTo( StrPair* other );
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300167
Lee Thomason39ede242012-01-20 11:27:56 -0800168private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700169 void Reset();
170 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 );
214 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800216
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 T* PushArr( int count ) {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300218 TIXMLASSERT( count >= 0 );
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300219 TIXMLASSERT( _size <= INT_MAX - count );
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 EnsureCapacity( _size+count );
221 T* ret = &_mem[_size];
222 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700223 return ret;
224 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700225
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 T Pop() {
Dmitry-Me74fb8702015-01-13 10:27:36 +0300227 TIXMLASSERT( _size > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700228 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700229 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 TIXMLASSERT( _size >= count );
233 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700234 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800235
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700237 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700239
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700241 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700242 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700243 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700244
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700246 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasonf07b9522014-10-30 13:25:12 -0700250 const T& PeekTop() const {
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500251 TIXMLASSERT( _size > 0 );
252 return _mem[ _size - 1];
253 }
254
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 int Size() const {
Dmitry-Me30bdc972015-01-14 08:32:23 +0300256 TIXMLASSERT( _size >= 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700257 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700258 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700259
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 int Capacity() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300261 TIXMLASSERT( _allocated >= INITIAL_SIZE );
Lee Thomason624d43f2012-10-12 10:58:48 -0700262 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700264
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 const T* Mem() const {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300266 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700267 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700269
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 T* Mem() {
Dmitry-Me2f5a1032015-06-18 16:40:09 +0300271 TIXMLASSERT( _mem );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700272 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800274
Lee Thomason2c85a712012-01-31 08:24:24 -0800275private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300276 DynArray( const DynArray& ); // not supported
277 void operator=( const DynArray& ); // not supported
278
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700279 void EnsureCapacity( int cap ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300280 TIXMLASSERT( cap > 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700281 if ( cap > _allocated ) {
Dmitry-Me9fae8692014-12-22 17:59:59 +0300282 TIXMLASSERT( cap <= INT_MAX / 2 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 int newAllocated = cap * 2;
284 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700285 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
286 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700287 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700288 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700289 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700290 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700291 }
292 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800293
Lee Thomason624d43f2012-10-12 10:58:48 -0700294 T* _mem;
Dmitry-Me04009222015-04-06 18:07:18 +0300295 T _pool[INITIAL_SIZE];
Lee Thomason624d43f2012-10-12 10:58:48 -0700296 int _allocated; // objects allocated
297 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800298};
299
Lee Thomason50adb4c2012-02-13 15:07:09 -0800300
U-Stream\Leeae25a442012-02-17 17:48:16 -0800301/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200302 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800303 and deallocation of objects.
304*/
PKEuS95060352013-07-26 10:42:44 +0200305class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800306{
307public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700308 MemPool() {}
309 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800310
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700311 virtual int ItemSize() const = 0;
312 virtual void* Alloc() = 0;
313 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800314 virtual void SetTracked() = 0;
Lee Thomasonf07b9522014-10-30 13:25:12 -0700315 virtual void Clear() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800316};
317
Lee Thomason50adb4c2012-02-13 15:07:09 -0800318
U-Stream\Leeae25a442012-02-17 17:48:16 -0800319/*
320 Template child class to create pools of the correct type.
321*/
Dmitry-Me88145b82016-08-09 17:59:31 +0300322template< int ITEM_SIZE >
PKEuS95060352013-07-26 10:42:44 +0200323class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800324{
325public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800326 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700327 ~MemPoolT() {
Lee Thomasonf07b9522014-10-30 13:25:12 -0700328 Clear();
329 }
330
331 void Clear() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 // Delete the blocks.
Lee Thomasonf07b9522014-10-30 13:25:12 -0700333 while( !_blockPtrs.Empty()) {
334 Block* b = _blockPtrs.Pop();
335 delete b;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700336 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700337 _root = 0;
338 _currentAllocs = 0;
339 _nAllocs = 0;
340 _maxAllocs = 0;
341 _nUntracked = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 }
Lee Thomasond1983222012-02-06 08:41:24 -0800343
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 virtual int ItemSize() const {
Dmitry-Me88145b82016-08-09 17:59:31 +0300345 return ITEM_SIZE;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
347 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700348 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 }
Lee Thomasond1983222012-02-06 08:41:24 -0800350
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700351 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700352 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 // Need a new block.
354 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700355 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800356
Dmitry-Me88145b82016-08-09 17:59:31 +0300357 Item* blockItems = block->items;
358 for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
359 blockItems[i].next = &(blockItems[i + 1]);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300361 blockItems[ITEMS_PER_BLOCK - 1].next = 0;
362 _root = blockItems;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 }
Dmitry-Me88145b82016-08-09 17:59:31 +0300364 Item* const result = _root;
365 TIXMLASSERT( result != 0 );
Lee Thomason624d43f2012-10-12 10:58:48 -0700366 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800367
Lee Thomason624d43f2012-10-12 10:58:48 -0700368 ++_currentAllocs;
369 if ( _currentAllocs > _maxAllocs ) {
370 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700371 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800373 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700374 return result;
375 }
Lee Thomasonf07b9522014-10-30 13:25:12 -0700376
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700377 virtual void Free( void* mem ) {
378 if ( !mem ) {
379 return;
380 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700381 --_currentAllocs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300382 Item* item = static_cast<Item*>( mem );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700383#ifdef DEBUG
Dmitry-Me88145b82016-08-09 17:59:31 +0300384 memset( item, 0xfe, sizeof( *item ) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700385#endif
Dmitry-Me88145b82016-08-09 17:59:31 +0300386 item->next = _root;
387 _root = item;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700388 }
389 void Trace( const char* name ) {
390 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Dmitry-Me88145b82016-08-09 17:59:31 +0300391 name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
392 ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 }
Lee Thomasond1983222012-02-06 08:41:24 -0800394
Lee Thomason5b0a6772012-11-19 13:54:42 -0800395 void SetTracked() {
396 _nUntracked--;
397 }
398
399 int Untracked() const {
400 return _nUntracked;
401 }
402
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800403 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
404 // The test file is large, 170k.
405 // Release: VS2010 gcc(no opt)
406 // 1k: 4000
407 // 2k: 4000
408 // 4k: 3900 21000
409 // 16k: 5200
410 // 32k: 4300
411 // 64k: 4000 21000
Dmitry-Me88145b82016-08-09 17:59:31 +0300412 // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
413 // in private part if ITEMS_PER_BLOCK is private
414 enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };
Jerome Martinez7921df12012-10-24 11:45:44 +0200415
Lee Thomasond1983222012-02-06 08:41:24 -0800416private:
Dmitry-Me3e0af372015-01-09 15:30:00 +0300417 MemPoolT( const MemPoolT& ); // not supported
418 void operator=( const MemPoolT& ); // not supported
419
Dmitry-Me88145b82016-08-09 17:59:31 +0300420 union Item {
421 Item* next;
422 char itemData[ITEM_SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700423 };
424 struct Block {
Dmitry-Me88145b82016-08-09 17:59:31 +0300425 Item items[ITEMS_PER_BLOCK];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700426 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700427 DynArray< Block*, 10 > _blockPtrs;
Dmitry-Me88145b82016-08-09 17:59:31 +0300428 Item* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800429
Lee Thomason624d43f2012-10-12 10:58:48 -0700430 int _currentAllocs;
431 int _nAllocs;
432 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800433 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800434};
435
Lee Thomason2c85a712012-01-31 08:24:24 -0800436
Lee Thomason56bdd022012-02-09 18:16:58 -0800437
438/**
439 Implements the interface to the "Visitor pattern" (see the Accept() method.)
440 If you call the Accept() method, it requires being passed a XMLVisitor
441 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200442 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800443 are simply called with Visit().
444
445 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700446 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800447
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700448 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800449 visiting). You need to only override methods that are interesting to you.
450
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600451 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800452
453 You should never change the document from a callback.
454
455 @sa XMLNode::Accept()
456*/
PKEuS16ed47d2013-07-06 12:02:43 +0200457class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800458{
459public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700460 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800461
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700462 /// Visit a document.
463 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
464 return true;
465 }
466 /// Visit a document.
467 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
468 return true;
469 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800470
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700471 /// Visit an element.
472 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
473 return true;
474 }
475 /// Visit an element.
476 virtual bool VisitExit( const XMLElement& /*element*/ ) {
477 return true;
478 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800479
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 /// Visit a declaration.
481 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
482 return true;
483 }
484 /// Visit a text node.
485 virtual bool Visit( const XMLText& /*text*/ ) {
486 return true;
487 }
488 /// Visit a comment node.
489 virtual bool Visit( const XMLComment& /*comment*/ ) {
490 return true;
491 }
492 /// Visit an unknown node.
493 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
494 return true;
495 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800496};
497
Dmitry-Me66d2a842014-11-08 15:24:52 +0300498// WARNING: must match XMLDocument::_errorNames[]
numatrumpetbb5ffac2014-09-06 22:56:46 +0900499enum XMLError {
numatrumpetcd8550c2014-09-08 16:59:39 +0900500 XML_SUCCESS = 0,
numatrumpetcd8550c2014-09-08 16:59:39 +0900501 XML_NO_ATTRIBUTE,
502 XML_WRONG_ATTRIBUTE_TYPE,
503 XML_ERROR_FILE_NOT_FOUND,
504 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
505 XML_ERROR_FILE_READ_ERROR,
506 XML_ERROR_ELEMENT_MISMATCH,
507 XML_ERROR_PARSING_ELEMENT,
508 XML_ERROR_PARSING_ATTRIBUTE,
509 XML_ERROR_IDENTIFYING_TAG,
510 XML_ERROR_PARSING_TEXT,
511 XML_ERROR_PARSING_CDATA,
512 XML_ERROR_PARSING_COMMENT,
513 XML_ERROR_PARSING_DECLARATION,
514 XML_ERROR_PARSING_UNKNOWN,
515 XML_ERROR_EMPTY_DOCUMENT,
516 XML_ERROR_MISMATCHED_ELEMENT,
517 XML_ERROR_PARSING,
518 XML_CAN_NOT_CONVERT_TEXT,
Lee Thomason331596e2014-09-11 14:56:43 -0700519 XML_NO_TEXT_NODE,
520
521 XML_ERROR_COUNT
numatrumpetbb5ffac2014-09-06 22:56:46 +0900522};
numatrumpetbb5ffac2014-09-06 22:56:46 +0900523
numatrumpetcd8550c2014-09-08 16:59:39 +0900524
U-Stream\Leeae25a442012-02-17 17:48:16 -0800525/*
526 Utility functionality.
527*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800528class XMLUtil
529{
Lee Thomasond1983222012-02-06 08:41:24 -0800530public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 static const char* SkipWhiteSpace( const char* p ) {
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300532 TIXMLASSERT( p );
Dmitry-Mefa20b222014-10-31 12:53:04 +0300533 while( IsWhiteSpace(*p) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 ++p;
535 }
Dmitry-Mebb836dc2014-12-24 11:54:05 +0300536 TIXMLASSERT( p );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 return p;
538 }
539 static char* SkipWhiteSpace( char* p ) {
Dmitry-Me9de541f2014-09-24 14:21:36 +0400540 return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p) ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 }
Dmitry-Mefa20b222014-10-31 12:53:04 +0300542
543 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
544 // correct, but simple, and usually works.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700545 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100546 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700547 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200548
549 inline static bool IsNameStartChar( unsigned char ch ) {
Dmitry-Meea617f92015-01-01 16:32:01 +0300550 if ( ch >= 128 ) {
551 // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
552 return true;
553 }
554 if ( isalpha( ch ) ) {
555 return true;
556 }
557 return ch == ':' || ch == '_';
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200558 }
559
560 inline static bool IsNameChar( unsigned char ch ) {
561 return IsNameStartChar( ch )
562 || isdigit( ch )
563 || ch == '.'
564 || ch == '-';
565 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800566
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700567 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700568 if ( p == q ) {
569 return true;
570 }
Lee Thomason598a88d2015-10-09 14:42:12 -0700571 return strncmp( p, q, nChar ) == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200573
Dmitry-Me7865aad2015-06-19 16:23:35 +0300574 inline static bool IsUTF8Continuation( char p ) {
Dmitry-Me72bb0ec2014-09-24 16:14:24 +0400575 return ( p & 0x80 ) != 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800577
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700578 static const char* ReadBOM( const char* p, bool* hasBOM );
579 // p is the starting location,
580 // the UTF-8 value of the entity will be placed in value, and length filled in.
581 static const char* GetCharacterRef( const char* p, char* value, int* length );
582 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700583
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 // converts primitive types to strings
585 static void ToStr( int v, char* buffer, int bufferSize );
586 static void ToStr( unsigned v, char* buffer, int bufferSize );
587 static void ToStr( bool v, char* buffer, int bufferSize );
588 static void ToStr( float v, char* buffer, int bufferSize );
589 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason51c12712016-06-04 20:18:49 -0700590 static void ToStr(int64_t v, char* buffer, int bufferSize);
Lee Thomason21be8822012-07-15 17:27:22 -0700591
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 // converts strings to primitive types
593 static bool ToInt( const char* str, int* value );
594 static bool ToUnsigned( const char* str, unsigned* value );
595 static bool ToBool( const char* str, bool* value );
596 static bool ToFloat( const char* str, float* value );
597 static bool ToDouble( const char* str, double* value );
Lee Thomason51c12712016-06-04 20:18:49 -0700598 static bool ToInt64(const char* str, int64_t* value);
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800599};
600
Lee Thomason5cae8972012-01-24 18:03:07 -0800601
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800602/** XMLNode is a base class for every object that is in the
603 XML Document Object Model (DOM), except XMLAttributes.
604 Nodes have siblings, a parent, and children which can
605 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700606 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800607 be cast to its more defined type.
608
Thomas Roß08bdf502012-05-12 14:21:23 +0200609 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800610 When the XMLDocument gets deleted, all its Nodes
611 will also be deleted.
612
613 @verbatim
614 A Document can contain: Element (container or leaf)
615 Comment (leaf)
616 Unknown (leaf)
617 Declaration( leaf )
618
619 An Element can contain: Element (container or leaf)
620 Text (leaf)
621 Attributes (not on tree)
622 Comment (leaf)
623 Unknown (leaf)
624
625 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800626*/
PKEuS16ed47d2013-07-06 12:02:43 +0200627class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800628{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 friend class XMLDocument;
630 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800631public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800632
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700633 /// Get the XMLDocument that owns this XMLNode.
634 const XMLDocument* GetDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300635 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700636 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 }
638 /// Get the XMLDocument that owns this XMLNode.
639 XMLDocument* GetDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +0300640 TIXMLASSERT( _document );
Lee Thomason624d43f2012-10-12 10:58:48 -0700641 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700642 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800643
Lee Thomason2fa81722012-11-09 12:37:46 -0800644 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100646 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800648 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700649 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100650 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800652 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800656 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 virtual XMLDocument* ToDocument() {
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 Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 virtual XMLDeclaration* ToDeclaration() {
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 an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100666 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800668
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 virtual const XMLElement* ToElement() const {
670 return 0;
671 }
672 virtual const XMLText* ToText() const {
673 return 0;
674 }
675 virtual const XMLComment* ToComment() const {
676 return 0;
677 }
678 virtual const XMLDocument* ToDocument() const {
679 return 0;
680 }
681 virtual const XMLDeclaration* ToDeclaration() const {
682 return 0;
683 }
684 virtual const XMLUnknown* ToUnknown() const {
685 return 0;
686 }
Lee Thomason751da522012-02-10 08:50:51 -0800687
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 /** The meaning of 'value' changes for the specific type.
689 @verbatim
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530690 Document: empty (NULL is returned, not an empty string)
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700691 Element: name of the element
692 Comment: the comment text
693 Unknown: the tag contents
694 Text: the text string
695 @endverbatim
696 */
Michael Daumling21626882013-10-22 17:03:37 +0200697 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100698
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 /** Set the Value of an XML node.
700 @sa Value()
701 */
702 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800703
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 /// Get the parent of this node on the DOM.
705 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700706 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100708
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700710 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700711 }
Lee Thomason751da522012-02-10 08:50:51 -0800712
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 /// Returns true if this node has no children.
714 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700715 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 }
Lee Thomason751da522012-02-10 08:50:51 -0800717
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 /// Get the first child node, or null if none exists.
719 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700720 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100722
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700724 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700725 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100726
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 /** Get the first child element, or optionally the first child
728 element with the specified name.
729 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300730 const XMLElement* FirstChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700731
Dmitry-Me886ad972015-07-22 11:00:51 +0300732 XMLElement* FirstChildElement( const char* name = 0 ) {
733 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( name ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800735
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700736 /// Get the last child node, or null if none exists.
737 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700738 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700740
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 XMLNode* LastChild() {
Dmitry-Me8d4e0ec2015-03-30 12:58:28 +0300742 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700743 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800744
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700745 /** Get the last child element or optionally the last child
746 element with the specified name.
747 */
Dmitry-Me886ad972015-07-22 11:00:51 +0300748 const XMLElement* LastChildElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700749
Dmitry-Me886ad972015-07-22 11:00:51 +0300750 XMLElement* LastChildElement( const char* name = 0 ) {
751 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(name) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700753
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 /// Get the previous (left) sibling node of this node.
755 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700756 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700758
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700759 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700760 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700761 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800762
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700763 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300764 const XMLElement* PreviousSiblingElement( const char* name = 0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700765
Dmitry-Me886ad972015-07-22 11:00:51 +0300766 XMLElement* PreviousSiblingElement( const char* name = 0 ) {
767 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700769
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700770 /// Get the next (right) sibling node of this node.
771 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700772 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700776 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700778
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700779 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Dmitry-Me886ad972015-07-22 11:00:51 +0300780 const XMLElement* NextSiblingElement( const char* name = 0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700781
Dmitry-Me886ad972015-07-22 11:00:51 +0300782 XMLElement* NextSiblingElement( const char* name = 0 ) {
783 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( name ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800785
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 /**
787 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200788 If the child node is already part of the document,
789 it is moved from its old location to the new location.
790 Returns the addThis argument or 0 if the node does not
791 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700792 */
793 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800794
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700795 XMLNode* LinkEndChild( XMLNode* addThis ) {
796 return InsertEndChild( addThis );
797 }
798 /**
799 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200800 If the child node is already part of the document,
801 it is moved from its old location to the new location.
802 Returns the addThis argument or 0 if the node does not
803 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700804 */
805 XMLNode* InsertFirstChild( XMLNode* addThis );
806 /**
807 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200808 If the child node is already part of the document,
809 it is moved from its old location to the new location.
810 Returns the addThis argument or 0 if the afterThis node
811 is not a child of this node, or if the node does not
812 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700813 */
814 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700815
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700816 /**
817 Delete all the children of this node.
818 */
819 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800820
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700821 /**
822 Delete a child of this node.
823 */
824 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800825
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700826 /**
827 Make a copy of this node, but not its children.
828 You may pass in a Document pointer that will be
829 the owner of the new Node. If the 'document' is
830 null, then the node returned will be allocated
831 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800832
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700833 Note: if called on a XMLDocument, this will return null.
834 */
835 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800836
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700837 /**
838 Test if 2 nodes are the same, but don't test children.
839 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800840
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700841 Note: if called on a XMLDocument, this will return false.
842 */
843 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800844
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600845 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600847 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800848
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600849 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
850 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700851 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800852
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700853 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800854
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 - http://www.saxproject.org/
856 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800857
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700858 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800859
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700860 An example of using Accept():
861 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600862 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 tinyxmlDoc.Accept( &printer );
864 const char* xmlcstr = printer.CStr();
865 @endverbatim
866 */
867 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800868
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700869 /**
870 Set user data into the XMLNode. TinyXML-2 in
871 no way processes or interprets user data.
872 It is initially 0.
873 */
874 void SetUserData(void* userData) { _userData = userData; }
875
876 /**
877 Get user data set into the XMLNode. TinyXML-2 in
878 no way processes or interprets user data.
879 It is initially 0.
880 */
881 void* GetUserData() const { return _userData; }
882
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800883protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700884 XMLNode( XMLDocument* );
885 virtual ~XMLNode();
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700886
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300887 virtual char* ParseDeep( char*, StrPair* );
888
Lee Thomason624d43f2012-10-12 10:58:48 -0700889 XMLDocument* _document;
890 XMLNode* _parent;
891 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800892
Lee Thomason624d43f2012-10-12 10:58:48 -0700893 XMLNode* _firstChild;
894 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800895
Lee Thomason624d43f2012-10-12 10:58:48 -0700896 XMLNode* _prev;
897 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800898
Lee Thomasonaf9bce12016-07-17 22:35:52 -0700899 void* _userData;
900
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800901private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700902 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700903 void Unlink( XMLNode* child );
Dmitry-Mee3225b12014-09-03 11:03:11 +0400904 static void DeleteNode( XMLNode* node );
Lee Thomason3cebdc42015-01-05 17:16:28 -0800905 void InsertChildPreamble( XMLNode* insertThis ) const;
Dmitry-Mef547a992015-01-09 15:17:09 +0300906
907 XMLNode( const XMLNode& ); // not supported
908 XMLNode& operator=( const XMLNode& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800909};
910
911
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800912/** XML text.
913
914 Note that a text node can have child element nodes, for example:
915 @verbatim
916 <root>This is <b>bold</b></root>
917 @endverbatim
918
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700919 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800920 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 -0700921 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600922 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800923*/
PKEuS16ed47d2013-07-06 12:02:43 +0200924class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800925{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700926 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800927public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700928 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800929
Lee Thomason624d43f2012-10-12 10:58:48 -0700930 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700931 return this;
932 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700933 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 return this;
935 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800936
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700937 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700938 void SetCData( bool isCData ) {
939 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700940 }
941 /// Returns true if this is a CDATA text element.
942 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700943 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700944 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800945
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700946 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800948
Lee Thomason5492a1c2012-01-23 15:32:10 -0800949protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700950 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700951 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800952
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300953 char* ParseDeep( char*, StrPair* endTag );
954
Lee Thomason5492a1c2012-01-23 15:32:10 -0800955private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700956 bool _isCData;
Dmitry-Mef547a992015-01-09 15:17:09 +0300957
958 XMLText( const XMLText& ); // not supported
959 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800960};
961
962
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800963/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200964class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800965{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800967public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700968 virtual XMLComment* ToComment() {
969 return this;
970 }
971 virtual const XMLComment* ToComment() const {
972 return this;
973 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800974
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700975 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800976
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
978 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800979
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800980protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700981 XMLComment( XMLDocument* doc );
982 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800983
Dmitry-Me9b0f1772015-04-03 10:37:31 +0300984 char* ParseDeep( char*, StrPair* endTag );
985
Lee Thomason3f57d272012-01-11 15:30:03 -0800986private:
Dmitry-Mef547a992015-01-09 15:17:09 +0300987 XMLComment( const XMLComment& ); // not supported
988 XMLComment& operator=( const XMLComment& ); // not supported
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800989};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800990
991
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800992/** In correct XML the declaration is the first entry in the file.
993 @verbatim
994 <?xml version="1.0" standalone="yes"?>
995 @endverbatim
996
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600997 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800998 however.
999
1000 The text of the declaration isn't interpreted. It is parsed
1001 and written as a string.
1002*/
PKEuS16ed47d2013-07-06 12:02:43 +02001003class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001004{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001005 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001006public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001007 virtual XMLDeclaration* ToDeclaration() {
1008 return this;
1009 }
1010 virtual const XMLDeclaration* ToDeclaration() const {
1011 return this;
1012 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001013
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001015
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1017 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001018
1019protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001020 XMLDeclaration( XMLDocument* doc );
1021 virtual ~XMLDeclaration();
Dmitry-Mef547a992015-01-09 15:17:09 +03001022
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001023 char* ParseDeep( char*, StrPair* endTag );
1024
Dmitry-Mef547a992015-01-09 15:17:09 +03001025private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001026 XMLDeclaration( const XMLDeclaration& ); // not supported
1027 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001028};
1029
1030
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001031/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001032 unknown. It is a tag of text, but should not be modified.
1033 It will be written back to the XML, unchanged, when the file
1034 is saved.
1035
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001036 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001037*/
PKEuS16ed47d2013-07-06 12:02:43 +02001038class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -08001039{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001040 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -08001041public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 virtual XMLUnknown* ToUnknown() {
1043 return this;
1044 }
1045 virtual const XMLUnknown* ToUnknown() const {
1046 return this;
1047 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001048
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001049 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001050
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1052 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -08001053
1054protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001055 XMLUnknown( XMLDocument* doc );
1056 virtual ~XMLUnknown();
Dmitry-Mef547a992015-01-09 15:17:09 +03001057
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001058 char* ParseDeep( char*, StrPair* endTag );
1059
Dmitry-Mef547a992015-01-09 15:17:09 +03001060private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001061 XMLUnknown( const XMLUnknown& ); // not supported
1062 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -08001063};
1064
1065
Lee Thomason1ff38e02012-02-14 18:18:16 -08001066
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001067/** An attribute is a name-value pair. Elements have an arbitrary
1068 number of attributes, each with a unique name.
1069
1070 @note The attributes are not XMLNodes. You may only query the
1071 Next() attribute in a list.
1072*/
PKEuS16ed47d2013-07-06 12:02:43 +02001073class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001074{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001075 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001076public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001077 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001078 const char* Name() const;
1079
Lee Thomason2fa81722012-11-09 12:37:46 -08001080 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001081 const char* Value() const;
1082
Lee Thomason2fa81722012-11-09 12:37:46 -08001083 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001084 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001085 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001086 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001087
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001088 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001089 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001090 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001091 */
Lee Thomason51c12712016-06-04 20:18:49 -07001092 int IntValue() const {
1093 int i = 0;
1094 QueryIntValue(&i);
1095 return i;
1096 }
1097
1098 int64_t Int64Value() const {
1099 int64_t i = 0;
1100 QueryInt64Value(&i);
1101 return i;
1102 }
1103
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001104 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 unsigned UnsignedValue() const {
1106 unsigned i=0;
1107 QueryUnsignedValue( &i );
1108 return i;
1109 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001110 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001111 bool BoolValue() const {
1112 bool b=false;
1113 QueryBoolValue( &b );
1114 return b;
1115 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001116 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001117 double DoubleValue() const {
1118 double d=0;
1119 QueryDoubleValue( &d );
1120 return d;
1121 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001122 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001123 float FloatValue() const {
1124 float f=0;
1125 QueryFloatValue( &f );
1126 return f;
1127 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001128
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001129 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001130 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001131 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1132 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001133 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001134 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001135 XMLError QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001136 /// See QueryIntValue
1137 XMLError QueryInt64Value(int64_t* value) const;
1138 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001139 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001140 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001141 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001142 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001143 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001144
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001145 /// Set the attribute to a string value.
1146 void SetAttribute( const char* value );
1147 /// Set the attribute to value.
1148 void SetAttribute( int value );
1149 /// Set the attribute to value.
1150 void SetAttribute( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001151 /// Set the attribute to value.
1152 void SetAttribute(int64_t value);
1153 /// Set the attribute to value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001154 void SetAttribute( bool value );
1155 /// Set the attribute to value.
1156 void SetAttribute( double value );
1157 /// Set the attribute to value.
1158 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001159
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001160private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001161 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001162
Thomas Roß61892312013-05-12 14:07:38 +02001163 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001164 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001165
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001166 XMLAttribute( const XMLAttribute& ); // not supported
1167 void operator=( const XMLAttribute& ); // not supported
1168 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001169
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001170 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001171
Lee Thomason624d43f2012-10-12 10:58:48 -07001172 mutable StrPair _name;
1173 mutable StrPair _value;
1174 XMLAttribute* _next;
1175 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001176};
1177
1178
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001179/** The element is a container class. It has a value, the element name,
1180 and can contain other elements, text, comments, and unknowns.
1181 Elements also contain an arbitrary number of attributes.
1182*/
PKEuS16ed47d2013-07-06 12:02:43 +02001183class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001184{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001185 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001186public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001187 /// Get the name of an element (which is the Value() of the node.)
1188 const char* Name() const {
1189 return Value();
1190 }
1191 /// Set the name of the element.
1192 void SetName( const char* str, bool staticMem=false ) {
1193 SetValue( str, staticMem );
1194 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001195
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001196 virtual XMLElement* ToElement() {
1197 return this;
1198 }
1199 virtual const XMLElement* ToElement() const {
1200 return this;
1201 }
1202 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001203
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 /** Given an attribute name, Attribute() returns the value
1205 for the attribute of that name, or null if none
1206 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001207
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001208 @verbatim
1209 const char* value = ele->Attribute( "foo" );
1210 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001211
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 The 'value' parameter is normally null. However, if specified,
1213 the attribute will only be returned if the 'name' and 'value'
1214 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001215
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 @verbatim
1217 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1218 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001219
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 rather than:
1221 @verbatim
1222 if ( ele->Attribute( "foo" ) ) {
1223 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1224 }
1225 @endverbatim
1226 */
1227 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001228
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 /** Given an attribute name, IntAttribute() returns the value
1230 of the attribute interpreted as an integer. 0 will be
1231 returned if there is an error. For a method with error
1232 checking, see QueryIntAttribute()
1233 */
1234 int IntAttribute( const char* name ) const {
1235 int i=0;
1236 QueryIntAttribute( name, &i );
1237 return i;
1238 }
Lee Thomason51c12712016-06-04 20:18:49 -07001239
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001240 /// See IntAttribute()
1241 unsigned UnsignedAttribute( const char* name ) const {
1242 unsigned i=0;
1243 QueryUnsignedAttribute( name, &i );
1244 return i;
1245 }
Lee Thomason51c12712016-06-04 20:18:49 -07001246
1247 /// See IntAttribute()
1248 int64_t Int64Attribute(const char* name) const {
1249 int64_t i = 0;
1250 QueryInt64Attribute(name, &i);
1251 return i;
1252 }
1253
1254 /// See IntAttribute()
1255 bool BoolAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001256 bool b=false;
1257 QueryBoolAttribute( name, &b );
1258 return b;
1259 }
1260 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001261 double DoubleAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001262 double d=0;
1263 QueryDoubleAttribute( name, &d );
1264 return d;
1265 }
1266 /// See IntAttribute()
Lee Thomason51c12712016-06-04 20:18:49 -07001267 float FloatAttribute( const char* name ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001268 float f=0;
1269 QueryFloatAttribute( name, &f );
1270 return f;
1271 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001272
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001273 /** Given an attribute name, QueryIntAttribute() returns
1274 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1275 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1276 doesn't exist. If successful, the result of the conversion
1277 will be written to 'value'. If not successful, nothing will
1278 be written to 'value'. This allows you to provide default
1279 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001280
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001281 @verbatim
1282 int value = 10;
1283 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1284 @endverbatim
1285 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001286 XMLError QueryIntAttribute( const char* name, 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->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
Lee Thomason51c12712016-06-04 20:18:49 -07001293
1294 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001295 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 const XMLAttribute* a = FindAttribute( name );
1297 if ( !a ) {
1298 return XML_NO_ATTRIBUTE;
1299 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 }
Lee Thomason51c12712016-06-04 20:18:49 -07001302
1303 /// See QueryIntAttribute()
1304 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1305 const XMLAttribute* a = FindAttribute(name);
1306 if (!a) {
1307 return XML_NO_ATTRIBUTE;
1308 }
1309 return a->QueryInt64Value(value);
1310 }
1311
1312 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001313 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 const XMLAttribute* a = FindAttribute( name );
1315 if ( !a ) {
1316 return XML_NO_ATTRIBUTE;
1317 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 }
1320 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001321 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 const XMLAttribute* a = FindAttribute( name );
1323 if ( !a ) {
1324 return XML_NO_ATTRIBUTE;
1325 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001326 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 }
1328 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001329 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001330 const XMLAttribute* a = FindAttribute( name );
1331 if ( !a ) {
1332 return XML_NO_ATTRIBUTE;
1333 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001334 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001336
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001337
1338 /** Given an attribute name, QueryAttribute() returns
1339 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1340 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1341 doesn't exist. It is overloaded for the primitive types,
1342 and is a generally more convenient replacement of
1343 QueryIntAttribute() and related functions.
1344
1345 If successful, the result of the conversion
1346 will be written to 'value'. If not successful, nothing will
1347 be written to 'value'. This allows you to provide default
1348 value:
1349
1350 @verbatim
1351 int value = 10;
1352 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1353 @endverbatim
1354 */
1355 int QueryAttribute( const char* name, int* value ) const {
1356 return QueryIntAttribute( name, value );
1357 }
1358
1359 int QueryAttribute( const char* name, unsigned int* value ) const {
1360 return QueryUnsignedAttribute( name, value );
1361 }
1362
Lee Thomason51c12712016-06-04 20:18:49 -07001363 int QueryAttribute(const char* name, int64_t* value) const {
1364 return QueryInt64Attribute(name, value);
1365 }
1366
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001367 int QueryAttribute( const char* name, bool* value ) const {
1368 return QueryBoolAttribute( name, value );
1369 }
1370
1371 int QueryAttribute( const char* name, double* value ) const {
1372 return QueryDoubleAttribute( name, value );
1373 }
1374
1375 int QueryAttribute( const char* name, float* value ) const {
1376 return QueryFloatAttribute( name, value );
1377 }
1378
1379 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001380 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001382 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 }
1384 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001385 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001387 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001388 }
1389 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001390 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001392 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001393 }
Lee Thomason51c12712016-06-04 20:18:49 -07001394
1395 /// Sets the named attribute to value.
1396 void SetAttribute(const char* name, int64_t value) {
1397 XMLAttribute* a = FindOrCreateAttribute(name);
1398 a->SetAttribute(value);
1399 }
1400
1401 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001402 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001404 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 }
1406 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001407 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001409 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001410 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001411 /// Sets the named attribute to value.
1412 void SetAttribute( const char* name, float value ) {
1413 XMLAttribute* a = FindOrCreateAttribute( name );
1414 a->SetAttribute( value );
1415 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001416
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001417 /**
1418 Delete an attribute.
1419 */
1420 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001421
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001422 /// Return the first attribute in the list.
1423 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001424 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001425 }
1426 /// Query a specific attribute in the list.
1427 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001428
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001430 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001432
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001433 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001435
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001436 This is a convenient method for getting the text of simple contained text:
1437 @verbatim
1438 <foo>This is text</foo>
1439 const char* str = fooElement->GetText();
1440 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001443
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 Note that this function can be misleading. If the element foo was created from
1445 this XML:
1446 @verbatim
1447 <foo><b>This is text</b></foo>
1448 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001449
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 then the value of str would be null. The first child node isn't a text node, it is
1451 another element. From this XML:
1452 @verbatim
1453 <foo>This is <b>text</b></foo>
1454 @endverbatim
1455 GetText() will return "This is ".
1456 */
1457 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001458
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001459 /** Convenience function for easy access to the text inside an element. Although easy
1460 and concise, SetText() is limited compared to creating an XMLText child
1461 and mutating it directly.
1462
1463 If the first child of 'this' is a XMLText, SetText() sets its value to
1464 the given string, otherwise it will create a first child that is an XMLText.
1465
1466 This is a convenient method for setting the text of simple contained text:
1467 @verbatim
1468 <foo>This is text</foo>
1469 fooElement->SetText( "Hullaballoo!" );
1470 <foo>Hullaballoo!</foo>
1471 @endverbatim
1472
1473 Note that this function can be misleading. If the element foo was created from
1474 this XML:
1475 @verbatim
1476 <foo><b>This is text</b></foo>
1477 @endverbatim
1478
1479 then it will not change "This is text", but rather prefix it with a text element:
1480 @verbatim
1481 <foo>Hullaballoo!<b>This is text</b></foo>
1482 @endverbatim
1483
1484 For this XML:
1485 @verbatim
1486 <foo />
1487 @endverbatim
1488 SetText() will generate
1489 @verbatim
1490 <foo>Hullaballoo!</foo>
1491 @endverbatim
1492 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001493 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001494 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001495 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001496 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001497 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001498 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1499 void SetText(int64_t value);
1500 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001501 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001502 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001503 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001504 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001505 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /**
1508 Convenience method to query the value of a child text node. This is probably best
1509 shown by example. Given you have a document is this form:
1510 @verbatim
1511 <point>
1512 <x>1</x>
1513 <y>1.4</y>
1514 </point>
1515 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 The QueryIntText() and similar functions provide a safe and easier way to get to the
1518 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 @verbatim
1521 int x = 0;
1522 float y = 0; // types of x and y are contrived for example
1523 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1524 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1525 xElement->QueryIntText( &x );
1526 yElement->QueryFloatText( &y );
1527 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001528
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001529 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1530 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 -07001531
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001533 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001534 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001535 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001536 /// See QueryIntText()
1537 XMLError QueryInt64Text(int64_t* uval) const;
1538 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001539 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001540 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001541 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001543 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001544
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001545 // internal:
1546 enum {
1547 OPEN, // <foo>
1548 CLOSED, // <foo/>
1549 CLOSING // </foo>
1550 };
1551 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001552 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001553 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001554 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1555 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001556
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001557protected:
1558 char* ParseDeep( char* p, StrPair* endTag );
1559
Lee Thomason50adb4c2012-02-13 15:07:09 -08001560private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001561 XMLElement( XMLDocument* doc );
1562 virtual ~XMLElement();
1563 XMLElement( const XMLElement& ); // not supported
1564 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001565
Dmitry-Me1227d512014-12-05 13:41:45 +03001566 XMLAttribute* FindAttribute( const char* name ) {
1567 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1568 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001569 XMLAttribute* FindOrCreateAttribute( const char* name );
1570 //void LinkAttribute( XMLAttribute* attrib );
1571 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001572 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001573
Lee Thomason5bb2d802014-01-24 10:42:57 -08001574 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001575 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001576 // The attribute list is ordered; there is no 'lastAttribute'
1577 // because the list needs to be scanned for dupes before adding
1578 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001579 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001580};
1581
1582
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001583enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 PRESERVE_WHITESPACE,
1585 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001586};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001587
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001588
1589/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001590 It can be saved, loaded, and printed to the screen.
1591 All Nodes are connected and allocated to a Document.
1592 If the Document is deleted, all its Nodes are also deleted.
1593*/
PKEuS16ed47d2013-07-06 12:02:43 +02001594class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001595{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001597public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001598 /// constructor
1599 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1600 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001601
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001603 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001604 return this;
1605 }
1606 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001607 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001608 return this;
1609 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001610
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001611 /**
1612 Parse an XML file from a character string.
1613 Returns XML_NO_ERROR (0) on success, or
1614 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001615
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 You may optionally pass in the 'nBytes', which is
1617 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001618 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 null terminated string.
1620 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001621 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001622
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001623 /**
1624 Load an XML file from disk.
1625 Returns XML_NO_ERROR (0) on success, or
1626 an errorID.
1627 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001628 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001629
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001630 /**
1631 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001632 for providing and closing the FILE*.
1633
1634 NOTE: The file should be opened as binary ("rb")
1635 not text in order for TinyXML-2 to correctly
1636 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001637
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001638 Returns XML_NO_ERROR (0) on success, or
1639 an errorID.
1640 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001641 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001642
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001643 /**
1644 Save the XML file to disk.
1645 Returns XML_NO_ERROR (0) on success, or
1646 an errorID.
1647 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001648 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001649
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 /**
1651 Save the XML file to disk. You are responsible
1652 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001653
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001654 Returns XML_NO_ERROR (0) on success, or
1655 an errorID.
1656 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001657 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001658
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001659 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001660 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001661 }
1662 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001663 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001665
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001666 /**
1667 Returns true if this document has a leading Byte Order Mark of UTF8.
1668 */
1669 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001670 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001671 }
1672 /** Sets whether to write the BOM when writing the file.
1673 */
1674 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001675 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001676 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001677
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001678 /** Return the root element of DOM. Equivalent to FirstChildElement().
1679 To get the first node, use FirstChild().
1680 */
1681 XMLElement* RootElement() {
1682 return FirstChildElement();
1683 }
1684 const XMLElement* RootElement() const {
1685 return FirstChildElement();
1686 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001687
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001688 /** Print the Document. If the Printer is not provided, it will
1689 print to stdout. If you provide Printer, this can print to a file:
1690 @verbatim
1691 XMLPrinter printer( fp );
1692 doc.Print( &printer );
1693 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001694
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001695 Or you can use a printer to print to memory:
1696 @verbatim
1697 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001698 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001699 // printer.CStr() has a const char* to the XML
1700 @endverbatim
1701 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001702 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001704
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 /**
1706 Create a new Element associated with
1707 this Document. The memory for the Element
1708 is managed by the Document.
1709 */
1710 XMLElement* NewElement( const char* name );
1711 /**
1712 Create a new Comment associated with
1713 this Document. The memory for the Comment
1714 is managed by the Document.
1715 */
1716 XMLComment* NewComment( const char* comment );
1717 /**
1718 Create a new Text associated with
1719 this Document. The memory for the Text
1720 is managed by the Document.
1721 */
1722 XMLText* NewText( const char* text );
1723 /**
1724 Create a new Declaration associated with
1725 this Document. The memory for the object
1726 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001727
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 If the 'text' param is null, the standard
1729 declaration is used.:
1730 @verbatim
1731 <?xml version="1.0" encoding="UTF-8"?>
1732 @endverbatim
1733 */
1734 XMLDeclaration* NewDeclaration( const char* text=0 );
1735 /**
1736 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001737 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001738 is managed by the Document.
1739 */
1740 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001741
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001742 /**
1743 Delete a node associated with this document.
1744 It will be unlinked from the DOM.
1745 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001746 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001747
Lee Thomason2fa81722012-11-09 12:37:46 -08001748 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001749
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001750 /// Return true if there was an error parsing the document.
1751 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001752 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 }
1754 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001755 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001756 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001757 }
Lee Thomason331596e2014-09-11 14:56:43 -07001758 const char* ErrorName() const;
1759
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001760 /// Return a possibly helpful diagnostic location or string.
1761 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001762 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001763 }
1764 /// Return a possibly helpful secondary diagnostic location or string.
1765 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001766 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001767 }
1768 /// If there is an error, print it to stdout.
1769 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001770
1771 /// Clear the document, resetting it to the initial state.
1772 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001773
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001774 // internal
1775 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001776
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1778 return 0;
1779 }
1780 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1781 return false;
1782 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001783
Lee Thomason3f57d272012-01-11 15:30:03 -08001784private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001785 XMLDocument( const XMLDocument& ); // not supported
1786 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001787
Lee Thomason2fa81722012-11-09 12:37:46 -08001788 bool _writeBOM;
1789 bool _processEntities;
1790 XMLError _errorID;
1791 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001792 const char* _errorStr1;
1793 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001794 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001795
Lee Thomason624d43f2012-10-12 10:58:48 -07001796 MemPoolT< sizeof(XMLElement) > _elementPool;
1797 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1798 MemPoolT< sizeof(XMLText) > _textPool;
1799 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001800
1801 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001802
1803 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001804};
1805
Lee Thomason7c913cd2012-01-26 18:32:34 -08001806
Lee Thomason3ffdd392012-03-28 17:27:55 -07001807/**
1808 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001809 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001810 DOM structure. It is a separate utility class.
1811
1812 Take an example:
1813 @verbatim
1814 <Document>
1815 <Element attributeA = "valueA">
1816 <Child attributeB = "value1" />
1817 <Child attributeB = "value2" />
1818 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001819 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001820 @endverbatim
1821
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001822 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001823 easy to write a *lot* of code that looks like:
1824
1825 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001826 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001827 if ( root )
1828 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001829 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001830 if ( element )
1831 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001832 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001833 if ( child )
1834 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001835 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001836 if ( child2 )
1837 {
1838 // Finally do something useful.
1839 @endverbatim
1840
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001841 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001842 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001843 and correct to use:
1844
1845 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001846 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001847 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001848 if ( child2 )
1849 {
1850 // do something useful
1851 @endverbatim
1852
1853 Which is MUCH more concise and useful.
1854
1855 It is also safe to copy handles - internally they are nothing more than node pointers.
1856 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001857 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001858 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001859
1860 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001861*/
PKEuS16ed47d2013-07-06 12:02:43 +02001862class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001863{
1864public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001865 /// 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 -07001866 XMLHandle( XMLNode* node ) {
1867 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001868 }
1869 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001870 XMLHandle( XMLNode& node ) {
1871 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 }
1873 /// Copy constructor
1874 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001875 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001876 }
1877 /// Assignment
1878 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001879 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 return *this;
1881 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001882
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001883 /// Get the first child of this handle.
1884 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001885 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001886 }
1887 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001888 XMLHandle FirstChildElement( const char* name = 0 ) {
1889 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 }
1891 /// Get the last child of this handle.
1892 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001893 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001894 }
1895 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001896 XMLHandle LastChildElement( const char* name = 0 ) {
1897 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 /// Get the previous sibling of this handle.
1900 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001901 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001902 }
1903 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001904 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1905 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001906 }
1907 /// Get the next sibling of this handle.
1908 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001909 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001910 }
1911 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001912 XMLHandle NextSiblingElement( const char* name = 0 ) {
1913 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001914 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001915
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001916 /// Safe cast to XMLNode. This can return null.
1917 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001918 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001919 }
1920 /// Safe cast to XMLElement. This can return null.
1921 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001922 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001923 }
1924 /// Safe cast to XMLText. This can return null.
1925 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001926 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001927 }
1928 /// Safe cast to XMLUnknown. This can return null.
1929 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001930 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 }
1932 /// Safe cast to XMLDeclaration. This can return null.
1933 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001934 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001935 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001936
1937private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001938 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001939};
1940
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001941
1942/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001943 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1944 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001945*/
PKEuS16ed47d2013-07-06 12:02:43 +02001946class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001947{
1948public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001949 XMLConstHandle( const XMLNode* node ) {
1950 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001951 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001952 XMLConstHandle( const XMLNode& node ) {
1953 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001954 }
1955 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001956 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001957 }
Lee Thomason8b899812012-04-04 15:58:16 -07001958
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001959 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001960 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001961 return *this;
1962 }
Lee Thomason8b899812012-04-04 15:58:16 -07001963
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001964 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001965 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001966 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001967 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1968 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001969 }
1970 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001971 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001972 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001973 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1974 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001975 }
1976 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001978 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001979 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1980 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001981 }
1982 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001983 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001984 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001985 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1986 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001987 }
Lee Thomason8b899812012-04-04 15:58:16 -07001988
1989
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001990 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001991 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001992 }
1993 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001994 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001995 }
1996 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001997 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001998 }
1999 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002000 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002001 }
2002 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002003 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002004 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002005
Lee Thomason5cae8972012-01-24 18:03:07 -08002006private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002007 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002008};
Lee Thomason6f381b72012-03-02 12:59:39 -08002009
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002010
2011/**
2012 Printing functionality. The XMLPrinter gives you more
2013 options than the XMLDocument::Print() method.
2014
2015 It can:
2016 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002017 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002018 -# Print XML without a XMLDocument.
2019
2020 Print to Memory
2021
2022 @verbatim
2023 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002024 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002025 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002026 @endverbatim
2027
2028 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002029
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002030 You provide the file pointer.
2031 @verbatim
2032 XMLPrinter printer( fp );
2033 doc.Print( &printer );
2034 @endverbatim
2035
2036 Print without a XMLDocument
2037
2038 When loading, an XML parser is very useful. However, sometimes
2039 when saving, it just gets in the way. The code is often set up
2040 for streaming, and constructing the DOM is just overhead.
2041
2042 The Printer supports the streaming case. The following code
2043 prints out a trivially simple XML file without ever creating
2044 an XML document.
2045
2046 @verbatim
2047 XMLPrinter printer( fp );
2048 printer.OpenElement( "foo" );
2049 printer.PushAttribute( "foo", "bar" );
2050 printer.CloseElement();
2051 @endverbatim
2052*/
PKEuS16ed47d2013-07-06 12:02:43 +02002053class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002054{
2055public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002056 /** Construct the printer. If the FILE* is specified,
2057 this will print to the FILE. Else it will print
2058 to memory, and the result is available in CStr().
2059 If 'compact' is set to true, then output is created
2060 with only required whitespace and newlines.
2061 */
PKEuS1bfb9542013-08-04 13:51:17 +02002062 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002063 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002064
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002065 /** If streaming, write the BOM and declaration. */
2066 void PushHeader( bool writeBOM, bool writeDeclaration );
2067 /** If streaming, start writing an element.
2068 The element must be closed with CloseElement()
2069 */
Lee Thomason256adb62014-04-06 14:41:46 -07002070 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002071 /// If streaming, add an attribute to an open element.
2072 void PushAttribute( const char* name, const char* value );
2073 void PushAttribute( const char* name, int value );
2074 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002075 void PushAttribute(const char* name, int64_t value);
2076 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002077 void PushAttribute( const char* name, double value );
2078 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002079 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002080
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002081 /// Add a text node.
2082 void PushText( const char* text, bool cdata=false );
2083 /// Add a text node from an integer.
2084 void PushText( int value );
2085 /// Add a text node from an unsigned.
2086 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002087 /// Add a text node from an unsigned.
2088 void PushText(int64_t value);
2089 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002090 void PushText( bool value );
2091 /// Add a text node from a float.
2092 void PushText( float value );
2093 /// Add a text node from a double.
2094 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002096 /// Add a comment
2097 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002098
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002099 void PushDeclaration( const char* value );
2100 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002101
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002102 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2103 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2104 return true;
2105 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002106
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002107 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2108 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002109
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002110 virtual bool Visit( const XMLText& text );
2111 virtual bool Visit( const XMLComment& comment );
2112 virtual bool Visit( const XMLDeclaration& declaration );
2113 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002114
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002115 /**
2116 If in print to memory mode, return a pointer to
2117 the XML file in memory.
2118 */
2119 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002120 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002121 }
2122 /**
2123 If in print to memory mode, return the size
2124 of the XML file in memory. (Note the size returned
2125 includes the terminating null.)
2126 */
2127 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002128 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002129 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002130 /**
2131 If in print to memory mode, reset the buffer to the
2132 beginning.
2133 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002134 void ClearBuffer() {
2135 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002136 _buffer.Push(0);
2137 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002138
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002139protected:
Alexander Maid740b642014-05-20 22:04:42 +02002140 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002141
Lee Thomasonc18eb232014-02-21 17:31:17 -08002142 /** Prints out the space before an element. You may override to change
2143 the space and tabs used. A PrintSpace() override should call Print().
2144 */
2145 virtual void PrintSpace( int depth );
2146 void Print( const char* format, ... );
2147
Dmitry-Mea092bc12014-12-23 17:57:05 +03002148 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002149 bool _elementJustOpened;
2150 DynArray< const char*, 10 > _stack;
2151
2152private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002153 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002154
Lee Thomason624d43f2012-10-12 10:58:48 -07002155 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002156 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002157 int _depth;
2158 int _textDepth;
2159 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002160 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002161
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002162 enum {
2163 ENTITY_RANGE = 64,
2164 BUF_SIZE = 200
2165 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002166 bool _entityFlag[ENTITY_RANGE];
2167 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002168
Lee Thomason624d43f2012-10-12 10:58:48 -07002169 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002170};
2171
2172
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002173} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002174
PKEuS95060352013-07-26 10:42:44 +02002175#if defined(_MSC_VER)
2176# pragma warning(pop)
2177#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002178
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002179#endif // TINYXML2_INCLUDED