blob: 9f5dbf7d69000a5a7ffc83f9b856fe5b56f90446 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Anton Indrawanf59e2d62014-11-18 20:50:42 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
Lee Thomasona572db12016-06-04 19:16:24 -070033# if defined(__PS3__)
34# include <stddef.h>
35# endif
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070036#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070037# include <cctype>
38# include <climits>
39# include <cstdio>
40# include <cstdlib>
41# include <cstring>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason1889c3e2016-06-04 20:22:57 -070043#include <stdint.h>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070044
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070045/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080046 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080047*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080048/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070049 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080050 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010051
Lee Thomasona9cf3f92012-10-11 16:56:51 -070052 Formatting, Artistic Style:
53 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080054*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080055
U-Lama\Lee4cee6112011-12-31 14:58:18 -080056#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070057# ifndef DEBUG
58# define DEBUG
59# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080060#endif
61
PKEuS95060352013-07-26 10:42:44 +020062#ifdef _MSC_VER
63# pragma warning(push)
64# pragma warning(disable: 4251)
65#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080066
PKEuS16ed47d2013-07-06 12:02:43 +020067#ifdef _WIN32
68# ifdef TINYXML2_EXPORT
69# define TINYXML2_LIB __declspec(dllexport)
70# elif defined(TINYXML2_IMPORT)
71# define TINYXML2_LIB __declspec(dllimport)
72# else
73# define TINYXML2_LIB
74# endif
Matthew Woehlkea8e7ea72016-08-09 13:16:26 -040075#elif __GNUC__ >= 4
76# define TINYXML2_LIB __attribute__((visibility("default")))
PKEuS16ed47d2013-07-06 12:02:43 +020077#else
78# define TINYXML2_LIB
79#endif
80
81
U-Lama\Lee4cee6112011-12-31 14:58:18 -080082#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070083# if defined(_MSC_VER)
Dmitry-Me4bcbf142014-12-25 19:05:18 +030084# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
Lee Thomason598a88d2015-10-09 14:42:12 -070085# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); }
Lee Thomasona9cf3f92012-10-11 16:56:51 -070086# elif defined (ANDROID_NDK)
87# include <android/log.h>
88# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
89# else
90# include <assert.h>
91# define TIXMLASSERT assert
92# endif
Lee Thomason598a88d2015-10-09 14:42:12 -070093#else
94# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080095#endif
96
U-Lama\Leee13c3e62011-12-28 14:36:55 -080097
Lee Thomasonc18eb232014-02-21 17:31:17 -080098/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -080099 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800100*/
Lee Thomason6ba2a072016-07-17 22:40:43 -0700101static const int TIXML2_MAJOR_VERSION = 4;
Sarat Addepalli9afd1d02015-05-19 12:56:27 +0530102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason74d44ac2016-07-17 22:57:36 -0700103static const int TIXML2_PATCH_VERSION = 1;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800111class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800112class XMLDeclaration;
113class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800114class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800115
U-Stream\Leeae25a442012-02-17 17:48:16 -0800116/*
117 A class that wraps strings. Normally stores the start and end
118 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800119 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800120 manage) a traditional char[]
121*/
PKEuS95060352013-07-26 10:42:44 +0200122class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800123{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800124public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700125 enum {
126 NEEDS_ENTITY_PROCESSING = 0x01,
127 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Dmitry-Me5420e542015-05-20 10:51:26 +0300128 NEEDS_WHITESPACE_COLLAPSING = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800129
Lee Thomason584af572016-09-05 14:14:16 -0700130 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700131 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason584af572016-09-05 14:14:16 -0700132 ATTRIBUTE_NAME = 0,
133 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
134 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
135 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700136 };
Lee Thomason39ede242012-01-20 11:27:56 -0800137
Lee Thomason120b3a62012-10-12 10:06:59 -0700138 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700139 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800140
Lee Thomason120b3a62012-10-12 10:06:59 -0700141 void Set( char* start, char* end, int flags ) {
Dmitry-Me6fc38ec2016-09-01 17:59:44 +0300142 TIXMLASSERT( start );
143 TIXMLASSERT( end );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
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 );
Lee Thomason584af572016-09-05 14:14:16 -0700167 void Reset();
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300168
Lee Thomason39ede242012-01-20 11:27:56 -0800169private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 enum {
173 NEEDS_FLUSH = 0x100,
174 NEEDS_DELETE = 0x200
175 };
Lee Thomasone4422302012-01-20 17:59:50 -0800176
Lee Thomason120b3a62012-10-12 10:06:59 -0700177 int _flags;
178 char* _start;
179 char* _end;
Dmitry-Me08b40dd2014-11-10 11:17:21 +0300180
181 StrPair( const StrPair& other ); // not supported
182 void operator=( StrPair& other ); // not supported, use TransferTo()
Lee Thomason39ede242012-01-20 11:27:56 -0800183};
184
U-Lama\Lee560bd472011-12-28 19:42:49 -0800185
U-Stream\Leeae25a442012-02-17 17:48:16 -0800186/*
187 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
188 Has a small initial memory pool, so that low or no usage will not
189 cause a call to new/delete
190*/
Dmitry-Me04009222015-04-06 18:07:18 +0300191template <class T, int INITIAL_SIZE>
PKEuS95060352013-07-26 10:42:44 +0200192class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800193{
194public:
Dmitry-Me9a5a48d2015-01-14 08:27:32 +0300195 DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700196 _mem = _pool;
Dmitry-Me04009222015-04-06 18:07:18 +0300197 _allocated = INITIAL_SIZE;
Lee Thomason624d43f2012-10-12 10:58:48 -0700198 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700199 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700200
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700201 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700202 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700203 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700204 }
205 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700206
Lee Thomasonce0510b2013-11-26 21:29:37 -0800207 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100208 _size = 0;
209 }
210
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 void Push( T t ) {
Dmitry-Meed7a7dc2015-01-14 08:36:12 +0300212 TIXMLASSERT( _size < INT_MAX );
Lee Thomason624d43f2012-10-12 10:58:48 -0700213 EnsureCapacity( _size+1 );
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 }
Dmitry-Me3161a332016-09-02 16:58:06 +0300372 ++_nAllocs;
373 ++_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() {
Dmitry-Me3161a332016-09-02 16:58:06 +0300396 --_nUntracked;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800397 }
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 */
Josh Wittnercf3dd092016-10-11 18:57:17 -07001234 int IntAttribute(const char* name, int defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001236 unsigned UnsignedAttribute(const char* name, unsigned defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001237 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001238 int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001239 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001240 bool BoolAttribute(const char* name, bool defaultValue = false) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001242 double DoubleAttribute(const char* name, double defaultValue = 0) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001243 /// See IntAttribute()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001244 float FloatAttribute(const char* name, float defaultValue = 0) const;
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001245
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001246 /** Given an attribute name, QueryIntAttribute() returns
1247 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1248 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1249 doesn't exist. If successful, the result of the conversion
1250 will be written to 'value'. If not successful, nothing will
1251 be written to 'value'. This allows you to provide default
1252 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001253
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001254 @verbatim
1255 int value = 10;
1256 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1257 @endverbatim
1258 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001259 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001260 const XMLAttribute* a = FindAttribute( name );
1261 if ( !a ) {
1262 return XML_NO_ATTRIBUTE;
1263 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001264 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001265 }
Lee Thomason51c12712016-06-04 20:18:49 -07001266
1267 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001268 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 const XMLAttribute* a = FindAttribute( name );
1270 if ( !a ) {
1271 return XML_NO_ATTRIBUTE;
1272 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001273 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001274 }
Lee Thomason51c12712016-06-04 20:18:49 -07001275
1276 /// See QueryIntAttribute()
1277 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1278 const XMLAttribute* a = FindAttribute(name);
1279 if (!a) {
1280 return XML_NO_ATTRIBUTE;
1281 }
1282 return a->QueryInt64Value(value);
1283 }
1284
1285 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001286 XMLError QueryBoolAttribute( const char* name, bool* 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->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
1293 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001294 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 const XMLAttribute* a = FindAttribute( name );
1296 if ( !a ) {
1297 return XML_NO_ATTRIBUTE;
1298 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001299 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 }
1301 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001302 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 const XMLAttribute* a = FindAttribute( name );
1304 if ( !a ) {
1305 return XML_NO_ATTRIBUTE;
1306 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001307 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001309
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001310
1311 /** Given an attribute name, QueryAttribute() returns
1312 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1313 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1314 doesn't exist. It is overloaded for the primitive types,
1315 and is a generally more convenient replacement of
1316 QueryIntAttribute() and related functions.
1317
1318 If successful, the result of the conversion
1319 will be written to 'value'. If not successful, nothing will
1320 be written to 'value'. This allows you to provide default
1321 value:
1322
1323 @verbatim
1324 int value = 10;
1325 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1326 @endverbatim
1327 */
1328 int QueryAttribute( const char* name, int* value ) const {
1329 return QueryIntAttribute( name, value );
1330 }
1331
1332 int QueryAttribute( const char* name, unsigned int* value ) const {
1333 return QueryUnsignedAttribute( name, value );
1334 }
1335
Lee Thomason51c12712016-06-04 20:18:49 -07001336 int QueryAttribute(const char* name, int64_t* value) const {
1337 return QueryInt64Attribute(name, value);
1338 }
1339
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001340 int QueryAttribute( const char* name, bool* value ) const {
1341 return QueryBoolAttribute( name, value );
1342 }
1343
1344 int QueryAttribute( const char* name, double* value ) const {
1345 return QueryDoubleAttribute( name, value );
1346 }
1347
1348 int QueryAttribute( const char* name, float* value ) const {
1349 return QueryFloatAttribute( name, value );
1350 }
1351
1352 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001353 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001354 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001355 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001356 }
1357 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001358 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001360 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 }
1362 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001363 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001365 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001366 }
Lee Thomason51c12712016-06-04 20:18:49 -07001367
1368 /// Sets the named attribute to value.
1369 void SetAttribute(const char* name, int64_t value) {
1370 XMLAttribute* a = FindOrCreateAttribute(name);
1371 a->SetAttribute(value);
1372 }
1373
1374 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001375 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001376 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001377 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001378 }
1379 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001380 void SetAttribute( const char* name, double 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 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001384 /// Sets the named attribute to value.
1385 void SetAttribute( const char* name, float value ) {
1386 XMLAttribute* a = FindOrCreateAttribute( name );
1387 a->SetAttribute( value );
1388 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001389
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001390 /**
1391 Delete an attribute.
1392 */
1393 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001394
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001395 /// Return the first attribute in the list.
1396 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001397 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001398 }
1399 /// Query a specific attribute in the list.
1400 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001401
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001402 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001403 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001404 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001405
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001406 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001408
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001409 This is a convenient method for getting the text of simple contained text:
1410 @verbatim
1411 <foo>This is text</foo>
1412 const char* str = fooElement->GetText();
1413 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001414
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001416
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001417 Note that this function can be misleading. If the element foo was created from
1418 this XML:
1419 @verbatim
1420 <foo><b>This is text</b></foo>
1421 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001422
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001423 then the value of str would be null. The first child node isn't a text node, it is
1424 another element. From this XML:
1425 @verbatim
1426 <foo>This is <b>text</b></foo>
1427 @endverbatim
1428 GetText() will return "This is ".
1429 */
1430 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001431
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001432 /** Convenience function for easy access to the text inside an element. Although easy
1433 and concise, SetText() is limited compared to creating an XMLText child
1434 and mutating it directly.
1435
1436 If the first child of 'this' is a XMLText, SetText() sets its value to
1437 the given string, otherwise it will create a first child that is an XMLText.
1438
1439 This is a convenient method for setting the text of simple contained text:
1440 @verbatim
1441 <foo>This is text</foo>
1442 fooElement->SetText( "Hullaballoo!" );
1443 <foo>Hullaballoo!</foo>
1444 @endverbatim
1445
1446 Note that this function can be misleading. If the element foo was created from
1447 this XML:
1448 @verbatim
1449 <foo><b>This is text</b></foo>
1450 @endverbatim
1451
1452 then it will not change "This is text", but rather prefix it with a text element:
1453 @verbatim
1454 <foo>Hullaballoo!<b>This is text</b></foo>
1455 @endverbatim
1456
1457 For this XML:
1458 @verbatim
1459 <foo />
1460 @endverbatim
1461 SetText() will generate
1462 @verbatim
1463 <foo>Hullaballoo!</foo>
1464 @endverbatim
1465 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001466 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001467 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001468 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001469 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001470 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001471 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1472 void SetText(int64_t value);
1473 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001474 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001475 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001476 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001477 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001478 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001479
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001480 /**
1481 Convenience method to query the value of a child text node. This is probably best
1482 shown by example. Given you have a document is this form:
1483 @verbatim
1484 <point>
1485 <x>1</x>
1486 <y>1.4</y>
1487 </point>
1488 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001489
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001490 The QueryIntText() and similar functions provide a safe and easier way to get to the
1491 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001492
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001493 @verbatim
1494 int x = 0;
1495 float y = 0; // types of x and y are contrived for example
1496 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1497 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1498 xElement->QueryIntText( &x );
1499 yElement->QueryFloatText( &y );
1500 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001501
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001502 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1503 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 -07001504
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001506 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001508 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001509 /// See QueryIntText()
1510 XMLError QueryInt64Text(int64_t* uval) const;
1511 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001512 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001514 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001515 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001516 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001517
Josh Wittnercf3dd092016-10-11 18:57:17 -07001518 int IntText(int defaultValue = 0) const;
1519
Josh Wittner3a621f52016-09-12 19:17:54 -07001520 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001521 unsigned UnsignedText(unsigned defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001522 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001523 int64_t Int64Text(int64_t defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001524 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001525 bool BoolText(bool defaultValue = false) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001526 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001527 double DoubleText(double defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001528 /// See QueryIntText()
Josh Wittnercf3dd092016-10-11 18:57:17 -07001529 float FloatText(float defaultValue = 0) const;
Josh Wittner3a621f52016-09-12 19:17:54 -07001530
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001531 // internal:
1532 enum {
1533 OPEN, // <foo>
1534 CLOSED, // <foo/>
1535 CLOSING // </foo>
1536 };
1537 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001538 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001540 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1541 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001542
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001543protected:
1544 char* ParseDeep( char* p, StrPair* endTag );
1545
Lee Thomason50adb4c2012-02-13 15:07:09 -08001546private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001547 XMLElement( XMLDocument* doc );
1548 virtual ~XMLElement();
1549 XMLElement( const XMLElement& ); // not supported
1550 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001551
Dmitry-Me1227d512014-12-05 13:41:45 +03001552 XMLAttribute* FindAttribute( const char* name ) {
1553 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1554 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001555 XMLAttribute* FindOrCreateAttribute( const char* name );
1556 //void LinkAttribute( XMLAttribute* attrib );
1557 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001558 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001559
Lee Thomason5bb2d802014-01-24 10:42:57 -08001560 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001561 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001562 // The attribute list is ordered; there is no 'lastAttribute'
1563 // because the list needs to be scanned for dupes before adding
1564 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001565 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001566};
1567
1568
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001569enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001570 PRESERVE_WHITESPACE,
1571 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001572};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001573
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001574
1575/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001576 It can be saved, loaded, and printed to the screen.
1577 All Nodes are connected and allocated to a Document.
1578 If the Document is deleted, all its Nodes are also deleted.
1579*/
PKEuS16ed47d2013-07-06 12:02:43 +02001580class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001581{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001582 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001583public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 /// constructor
1585 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1586 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001587
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001589 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001590 return this;
1591 }
1592 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001593 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001594 return this;
1595 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001596
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001597 /**
1598 Parse an XML file from a character string.
1599 Returns XML_NO_ERROR (0) on success, or
1600 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001601
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 You may optionally pass in the 'nBytes', which is
1603 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001604 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001605 null terminated string.
1606 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001607 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001608
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001609 /**
1610 Load an XML file from disk.
1611 Returns XML_NO_ERROR (0) on success, or
1612 an errorID.
1613 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001614 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001615
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 /**
1617 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001618 for providing and closing the FILE*.
1619
1620 NOTE: The file should be opened as binary ("rb")
1621 not text in order for TinyXML-2 to correctly
1622 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001623
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001624 Returns XML_NO_ERROR (0) on success, or
1625 an errorID.
1626 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001627 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001628
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001629 /**
1630 Save the XML file to disk.
1631 Returns XML_NO_ERROR (0) on success, or
1632 an errorID.
1633 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001634 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001635
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001636 /**
1637 Save the XML file to disk. You are responsible
1638 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001639
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 Returns XML_NO_ERROR (0) on success, or
1641 an errorID.
1642 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001643 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001644
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001645 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001646 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001647 }
1648 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001649 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001651
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001652 /**
1653 Returns true if this document has a leading Byte Order Mark of UTF8.
1654 */
1655 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001656 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 }
1658 /** Sets whether to write the BOM when writing the file.
1659 */
1660 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001661 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001662 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001663
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 /** Return the root element of DOM. Equivalent to FirstChildElement().
1665 To get the first node, use FirstChild().
1666 */
1667 XMLElement* RootElement() {
1668 return FirstChildElement();
1669 }
1670 const XMLElement* RootElement() const {
1671 return FirstChildElement();
1672 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001673
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001674 /** Print the Document. If the Printer is not provided, it will
1675 print to stdout. If you provide Printer, this can print to a file:
1676 @verbatim
1677 XMLPrinter printer( fp );
1678 doc.Print( &printer );
1679 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001680
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001681 Or you can use a printer to print to memory:
1682 @verbatim
1683 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001684 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001685 // printer.CStr() has a const char* to the XML
1686 @endverbatim
1687 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001688 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001689 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001690
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 /**
1692 Create a new Element associated with
1693 this Document. The memory for the Element
1694 is managed by the Document.
1695 */
1696 XMLElement* NewElement( const char* name );
1697 /**
1698 Create a new Comment associated with
1699 this Document. The memory for the Comment
1700 is managed by the Document.
1701 */
1702 XMLComment* NewComment( const char* comment );
1703 /**
1704 Create a new Text associated with
1705 this Document. The memory for the Text
1706 is managed by the Document.
1707 */
1708 XMLText* NewText( const char* text );
1709 /**
1710 Create a new Declaration associated with
1711 this Document. The memory for the object
1712 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001713
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 If the 'text' param is null, the standard
1715 declaration is used.:
1716 @verbatim
1717 <?xml version="1.0" encoding="UTF-8"?>
1718 @endverbatim
1719 */
1720 XMLDeclaration* NewDeclaration( const char* text=0 );
1721 /**
1722 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001723 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 is managed by the Document.
1725 */
1726 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001727
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 /**
1729 Delete a node associated with this document.
1730 It will be unlinked from the DOM.
1731 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001732 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001733
Lee Thomason2fa81722012-11-09 12:37:46 -08001734 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001735
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 /// Return true if there was an error parsing the document.
1737 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001738 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
1740 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001741 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
Lee Thomason331596e2014-09-11 14:56:43 -07001744 const char* ErrorName() const;
1745
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001746 /// Return a possibly helpful diagnostic location or string.
1747 const char* GetErrorStr1() const {
Lee Thomason584af572016-09-05 14:14:16 -07001748 return _errorStr1.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001749 }
1750 /// Return a possibly helpful secondary diagnostic location or string.
1751 const char* GetErrorStr2() const {
Lee Thomason584af572016-09-05 14:14:16 -07001752 return _errorStr2.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 }
1754 /// If there is an error, print it to stdout.
1755 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001756
1757 /// Clear the document, resetting it to the initial state.
1758 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001759
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001760 // internal
1761 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001762
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001763 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1764 return 0;
1765 }
1766 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1767 return false;
1768 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001769
Lee Thomason3f57d272012-01-11 15:30:03 -08001770private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001771 XMLDocument( const XMLDocument& ); // not supported
1772 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001773
Lee Thomason2fa81722012-11-09 12:37:46 -08001774 bool _writeBOM;
1775 bool _processEntities;
1776 XMLError _errorID;
1777 Whitespace _whitespace;
Lee Thomason584af572016-09-05 14:14:16 -07001778 mutable StrPair _errorStr1;
1779 mutable StrPair _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001780 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001781
Lee Thomason624d43f2012-10-12 10:58:48 -07001782 MemPoolT< sizeof(XMLElement) > _elementPool;
1783 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1784 MemPoolT< sizeof(XMLText) > _textPool;
1785 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001786
1787 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001788
1789 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001790};
1791
Lee Thomason7c913cd2012-01-26 18:32:34 -08001792
Lee Thomason3ffdd392012-03-28 17:27:55 -07001793/**
1794 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001795 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001796 DOM structure. It is a separate utility class.
1797
1798 Take an example:
1799 @verbatim
1800 <Document>
1801 <Element attributeA = "valueA">
1802 <Child attributeB = "value1" />
1803 <Child attributeB = "value2" />
1804 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001805 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001806 @endverbatim
1807
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001808 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001809 easy to write a *lot* of code that looks like:
1810
1811 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001812 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001813 if ( root )
1814 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001815 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001816 if ( element )
1817 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001818 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001819 if ( child )
1820 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001821 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001822 if ( child2 )
1823 {
1824 // Finally do something useful.
1825 @endverbatim
1826
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001827 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001828 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001829 and correct to use:
1830
1831 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001832 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001833 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001834 if ( child2 )
1835 {
1836 // do something useful
1837 @endverbatim
1838
1839 Which is MUCH more concise and useful.
1840
1841 It is also safe to copy handles - internally they are nothing more than node pointers.
1842 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001843 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001844 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001845
1846 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001847*/
PKEuS16ed47d2013-07-06 12:02:43 +02001848class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001849{
1850public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001851 /// 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 -07001852 XMLHandle( XMLNode* node ) {
1853 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001854 }
1855 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001856 XMLHandle( XMLNode& node ) {
1857 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001858 }
1859 /// Copy constructor
1860 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001861 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001862 }
1863 /// Assignment
1864 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 return *this;
1867 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001868
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001869 /// Get the first child of this handle.
1870 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001871 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 }
1873 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001874 XMLHandle FirstChildElement( const char* name = 0 ) {
1875 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001876 }
1877 /// Get the last child of this handle.
1878 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001879 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001880 }
1881 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001882 XMLHandle LastChildElement( const char* name = 0 ) {
1883 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 }
1885 /// Get the previous sibling of this handle.
1886 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001887 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001888 }
1889 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001890 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1891 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 }
1893 /// Get the next sibling of this handle.
1894 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001895 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001896 }
1897 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001898 XMLHandle NextSiblingElement( const char* name = 0 ) {
1899 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001900 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001901
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001902 /// Safe cast to XMLNode. This can return null.
1903 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001904 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001905 }
1906 /// Safe cast to XMLElement. This can return null.
1907 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001908 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001909 }
1910 /// Safe cast to XMLText. This can return null.
1911 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001912 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001913 }
1914 /// Safe cast to XMLUnknown. This can return null.
1915 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001916 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001917 }
1918 /// Safe cast to XMLDeclaration. This can return null.
1919 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001920 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001921 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001922
1923private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001924 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001925};
1926
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001927
1928/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001929 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1930 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001931*/
PKEuS16ed47d2013-07-06 12:02:43 +02001932class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001933{
1934public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001935 XMLConstHandle( const XMLNode* node ) {
1936 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001938 XMLConstHandle( const XMLNode& node ) {
1939 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001940 }
1941 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001942 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001943 }
Lee Thomason8b899812012-04-04 15:58:16 -07001944
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001945 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001946 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 return *this;
1948 }
Lee Thomason8b899812012-04-04 15:58:16 -07001949
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001951 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001952 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001953 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
1954 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 }
1956 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001957 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001958 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001959 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
1960 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001961 }
1962 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001963 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001964 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001965 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
1966 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001967 }
1968 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001969 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001970 }
Dmitry-Me886ad972015-07-22 11:00:51 +03001971 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
1972 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001973 }
Lee Thomason8b899812012-04-04 15:58:16 -07001974
1975
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001976 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001978 }
1979 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001980 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001981 }
1982 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001983 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001984 }
1985 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001986 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001987 }
1988 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001989 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001990 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001991
Lee Thomason5cae8972012-01-24 18:03:07 -08001992private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001993 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001994};
Lee Thomason6f381b72012-03-02 12:59:39 -08001995
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001996
1997/**
1998 Printing functionality. The XMLPrinter gives you more
1999 options than the XMLDocument::Print() method.
2000
2001 It can:
2002 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002003 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002004 -# Print XML without a XMLDocument.
2005
2006 Print to Memory
2007
2008 @verbatim
2009 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002010 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002011 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002012 @endverbatim
2013
2014 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002015
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002016 You provide the file pointer.
2017 @verbatim
2018 XMLPrinter printer( fp );
2019 doc.Print( &printer );
2020 @endverbatim
2021
2022 Print without a XMLDocument
2023
2024 When loading, an XML parser is very useful. However, sometimes
2025 when saving, it just gets in the way. The code is often set up
2026 for streaming, and constructing the DOM is just overhead.
2027
2028 The Printer supports the streaming case. The following code
2029 prints out a trivially simple XML file without ever creating
2030 an XML document.
2031
2032 @verbatim
2033 XMLPrinter printer( fp );
2034 printer.OpenElement( "foo" );
2035 printer.PushAttribute( "foo", "bar" );
2036 printer.CloseElement();
2037 @endverbatim
2038*/
PKEuS16ed47d2013-07-06 12:02:43 +02002039class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002040{
2041public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002042 /** Construct the printer. If the FILE* is specified,
2043 this will print to the FILE. Else it will print
2044 to memory, and the result is available in CStr().
2045 If 'compact' is set to true, then output is created
2046 with only required whitespace and newlines.
2047 */
PKEuS1bfb9542013-08-04 13:51:17 +02002048 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002049 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002050
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002051 /** If streaming, write the BOM and declaration. */
2052 void PushHeader( bool writeBOM, bool writeDeclaration );
2053 /** If streaming, start writing an element.
2054 The element must be closed with CloseElement()
2055 */
Lee Thomason256adb62014-04-06 14:41:46 -07002056 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002057 /// If streaming, add an attribute to an open element.
2058 void PushAttribute( const char* name, const char* value );
2059 void PushAttribute( const char* name, int value );
2060 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002061 void PushAttribute(const char* name, int64_t value);
2062 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002063 void PushAttribute( const char* name, double value );
2064 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002065 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002066
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002067 /// Add a text node.
2068 void PushText( const char* text, bool cdata=false );
2069 /// Add a text node from an integer.
2070 void PushText( int value );
2071 /// Add a text node from an unsigned.
2072 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002073 /// Add a text node from an unsigned.
2074 void PushText(int64_t value);
2075 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002076 void PushText( bool value );
2077 /// Add a text node from a float.
2078 void PushText( float value );
2079 /// Add a text node from a double.
2080 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002081
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002082 /// Add a comment
2083 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002084
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002085 void PushDeclaration( const char* value );
2086 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002087
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002088 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2089 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2090 return true;
2091 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002092
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002093 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2094 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002096 virtual bool Visit( const XMLText& text );
2097 virtual bool Visit( const XMLComment& comment );
2098 virtual bool Visit( const XMLDeclaration& declaration );
2099 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002100
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002101 /**
2102 If in print to memory mode, return a pointer to
2103 the XML file in memory.
2104 */
2105 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002106 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002107 }
2108 /**
2109 If in print to memory mode, return the size
2110 of the XML file in memory. (Note the size returned
2111 includes the terminating null.)
2112 */
2113 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002114 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002115 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002116 /**
2117 If in print to memory mode, reset the buffer to the
2118 beginning.
2119 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002120 void ClearBuffer() {
2121 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002122 _buffer.Push(0);
2123 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002124
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002125protected:
Alexander Maid740b642014-05-20 22:04:42 +02002126 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002127
Lee Thomasonc18eb232014-02-21 17:31:17 -08002128 /** Prints out the space before an element. You may override to change
2129 the space and tabs used. A PrintSpace() override should call Print().
2130 */
2131 virtual void PrintSpace( int depth );
2132 void Print( const char* format, ... );
2133
Dmitry-Mea092bc12014-12-23 17:57:05 +03002134 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002135 bool _elementJustOpened;
2136 DynArray< const char*, 10 > _stack;
2137
2138private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002139 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002140
Lee Thomason624d43f2012-10-12 10:58:48 -07002141 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002142 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002143 int _depth;
2144 int _textDepth;
2145 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002146 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002147
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002148 enum {
2149 ENTITY_RANGE = 64,
2150 BUF_SIZE = 200
2151 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002152 bool _entityFlag[ENTITY_RANGE];
2153 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002154
Lee Thomason624d43f2012-10-12 10:58:48 -07002155 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002156};
2157
2158
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002159} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002160
PKEuS95060352013-07-26 10:42:44 +02002161#if defined(_MSC_VER)
2162# pragma warning(pop)
2163#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002164
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002165#endif // TINYXML2_INCLUDED