blob: cafc4225a137e19bdc8d4c8a729655660ddf8a4a [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 Wittner3a621f52016-09-12 19:17:54 -07001234 int IntAttribute(const char* name, int defaultValue = 0) const {
1235 int i=defaultValue;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001236 QueryIntAttribute( name, &i );
1237 return i;
1238 }
Lee Thomason51c12712016-06-04 20:18:49 -07001239
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001240 /// See IntAttribute()
Josh Wittner3a621f52016-09-12 19:17:54 -07001241 unsigned UnsignedAttribute(const char* name , unsigned defaultValue = 0) const {
1242 unsigned i=defaultValue;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001243 QueryUnsignedAttribute( name, &i );
1244 return i;
1245 }
Lee Thomason51c12712016-06-04 20:18:49 -07001246
1247 /// See IntAttribute()
Josh Wittner3a621f52016-09-12 19:17:54 -07001248 int64_t Int64Attribute(const char* name, int64_t defaultValue = 0) const {
1249 int64_t i = defaultValue;
Lee Thomason51c12712016-06-04 20:18:49 -07001250 QueryInt64Attribute(name, &i);
1251 return i;
1252 }
1253
1254 /// See IntAttribute()
Josh Wittner3a621f52016-09-12 19:17:54 -07001255 bool BoolAttribute( const char* name, bool defaultValue = false ) const {
1256 bool b=defaultValue;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 QueryBoolAttribute( name, &b );
1258 return b;
1259 }
1260 /// See IntAttribute()
Josh Wittner3a621f52016-09-12 19:17:54 -07001261 double DoubleAttribute( const char* name, double defaultValue=0 ) const {
1262 double d=defaultValue;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001263 QueryDoubleAttribute( name, &d );
1264 return d;
1265 }
1266 /// See IntAttribute()
Josh Wittner3a621f52016-09-12 19:17:54 -07001267 float FloatAttribute( const char* name, float defaultValue=0 ) const {
1268 float f=defaultValue;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001269 QueryFloatAttribute( name, &f );
1270 return f;
1271 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001272
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001273 /** Given an attribute name, QueryIntAttribute() returns
1274 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1275 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1276 doesn't exist. If successful, the result of the conversion
1277 will be written to 'value'. If not successful, nothing will
1278 be written to 'value'. This allows you to provide default
1279 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001280
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001281 @verbatim
1282 int value = 10;
1283 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1284 @endverbatim
1285 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001286 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 const XMLAttribute* a = FindAttribute( name );
1288 if ( !a ) {
1289 return XML_NO_ATTRIBUTE;
1290 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001291 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
Lee Thomason51c12712016-06-04 20:18:49 -07001293
1294 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001295 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 const XMLAttribute* a = FindAttribute( name );
1297 if ( !a ) {
1298 return XML_NO_ATTRIBUTE;
1299 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 }
Lee Thomason51c12712016-06-04 20:18:49 -07001302
1303 /// See QueryIntAttribute()
1304 XMLError QueryInt64Attribute(const char* name, int64_t* value) const {
1305 const XMLAttribute* a = FindAttribute(name);
1306 if (!a) {
1307 return XML_NO_ATTRIBUTE;
1308 }
1309 return a->QueryInt64Value(value);
1310 }
1311
1312 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001313 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 const XMLAttribute* a = FindAttribute( name );
1315 if ( !a ) {
1316 return XML_NO_ATTRIBUTE;
1317 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 }
1320 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001321 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 const XMLAttribute* a = FindAttribute( name );
1323 if ( !a ) {
1324 return XML_NO_ATTRIBUTE;
1325 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001326 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 }
1328 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001329 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001330 const XMLAttribute* a = FindAttribute( name );
1331 if ( !a ) {
1332 return XML_NO_ATTRIBUTE;
1333 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001334 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001336
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001337
1338 /** Given an attribute name, QueryAttribute() returns
1339 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1340 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1341 doesn't exist. It is overloaded for the primitive types,
1342 and is a generally more convenient replacement of
1343 QueryIntAttribute() and related functions.
1344
1345 If successful, the result of the conversion
1346 will be written to 'value'. If not successful, nothing will
1347 be written to 'value'. This allows you to provide default
1348 value:
1349
1350 @verbatim
1351 int value = 10;
1352 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1353 @endverbatim
1354 */
1355 int QueryAttribute( const char* name, int* value ) const {
1356 return QueryIntAttribute( name, value );
1357 }
1358
1359 int QueryAttribute( const char* name, unsigned int* value ) const {
1360 return QueryUnsignedAttribute( name, value );
1361 }
1362
Lee Thomason51c12712016-06-04 20:18:49 -07001363 int QueryAttribute(const char* name, int64_t* value) const {
1364 return QueryInt64Attribute(name, value);
1365 }
1366
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001367 int QueryAttribute( const char* name, bool* value ) const {
1368 return QueryBoolAttribute( name, value );
1369 }
1370
1371 int QueryAttribute( const char* name, double* value ) const {
1372 return QueryDoubleAttribute( name, value );
1373 }
1374
1375 int QueryAttribute( const char* name, float* value ) const {
1376 return QueryFloatAttribute( name, value );
1377 }
1378
1379 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001380 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001382 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 }
1384 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001385 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001387 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001388 }
1389 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001390 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001392 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001393 }
Lee Thomason51c12712016-06-04 20:18:49 -07001394
1395 /// Sets the named attribute to value.
1396 void SetAttribute(const char* name, int64_t value) {
1397 XMLAttribute* a = FindOrCreateAttribute(name);
1398 a->SetAttribute(value);
1399 }
1400
1401 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001402 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001404 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 }
1406 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001407 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001408 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001409 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001410 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001411 /// Sets the named attribute to value.
1412 void SetAttribute( const char* name, float value ) {
1413 XMLAttribute* a = FindOrCreateAttribute( name );
1414 a->SetAttribute( value );
1415 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001416
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001417 /**
1418 Delete an attribute.
1419 */
1420 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001421
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001422 /// Return the first attribute in the list.
1423 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001424 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001425 }
1426 /// Query a specific attribute in the list.
1427 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001428
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001430 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001432
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001433 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001435
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001436 This is a convenient method for getting the text of simple contained text:
1437 @verbatim
1438 <foo>This is text</foo>
1439 const char* str = fooElement->GetText();
1440 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001441
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001442 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001443
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 Note that this function can be misleading. If the element foo was created from
1445 this XML:
1446 @verbatim
1447 <foo><b>This is text</b></foo>
1448 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001449
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 then the value of str would be null. The first child node isn't a text node, it is
1451 another element. From this XML:
1452 @verbatim
1453 <foo>This is <b>text</b></foo>
1454 @endverbatim
1455 GetText() will return "This is ".
1456 */
1457 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001458
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001459 /** Convenience function for easy access to the text inside an element. Although easy
1460 and concise, SetText() is limited compared to creating an XMLText child
1461 and mutating it directly.
1462
1463 If the first child of 'this' is a XMLText, SetText() sets its value to
1464 the given string, otherwise it will create a first child that is an XMLText.
1465
1466 This is a convenient method for setting the text of simple contained text:
1467 @verbatim
1468 <foo>This is text</foo>
1469 fooElement->SetText( "Hullaballoo!" );
1470 <foo>Hullaballoo!</foo>
1471 @endverbatim
1472
1473 Note that this function can be misleading. If the element foo was created from
1474 this XML:
1475 @verbatim
1476 <foo><b>This is text</b></foo>
1477 @endverbatim
1478
1479 then it will not change "This is text", but rather prefix it with a text element:
1480 @verbatim
1481 <foo>Hullaballoo!<b>This is text</b></foo>
1482 @endverbatim
1483
1484 For this XML:
1485 @verbatim
1486 <foo />
1487 @endverbatim
1488 SetText() will generate
1489 @verbatim
1490 <foo>Hullaballoo!</foo>
1491 @endverbatim
1492 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001493 void SetText( const char* inText );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001494 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001495 void SetText( int value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001496 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001497 void SetText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07001498 /// Convenience method for setting text inside an element. See SetText() for important limitations.
1499 void SetText(int64_t value);
1500 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001501 void SetText( bool value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001502 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001503 void SetText( double value );
Dmitry-Me9e9c85b2015-10-19 18:04:46 +03001504 /// Convenience method for setting text inside an element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001505 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /**
1508 Convenience method to query the value of a child text node. This is probably best
1509 shown by example. Given you have a document is this form:
1510 @verbatim
1511 <point>
1512 <x>1</x>
1513 <y>1.4</y>
1514 </point>
1515 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 The QueryIntText() and similar functions provide a safe and easier way to get to the
1518 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 @verbatim
1521 int x = 0;
1522 float y = 0; // types of x and y are contrived for example
1523 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1524 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1525 xElement->QueryIntText( &x );
1526 yElement->QueryFloatText( &y );
1527 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001528
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001529 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1530 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001531
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001533 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001534 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001535 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomason51c12712016-06-04 20:18:49 -07001536 /// See QueryIntText()
1537 XMLError QueryInt64Text(int64_t* uval) const;
1538 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001539 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001540 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001541 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001542 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001543 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001544
Josh Wittner3a621f52016-09-12 19:17:54 -07001545 int IntText(int defaultValue = 0) const
1546 {
1547 int i = defaultValue;
1548 QueryIntText(&i);
1549 return i;
1550 }
1551 /// See QueryIntText()
1552 unsigned UnsignedText(unsigned defaultValue = 0) const
1553 {
1554 unsigned i = defaultValue;
1555 QueryUnsignedText(&i);
1556 return i;
1557 }
1558 /// See QueryIntText()
1559 int64_t Int64Text(int64_t defaultValue = 0) const
1560 {
1561 int64_t i = defaultValue;
1562 QueryInt64Text(&i);
1563 return i;
1564 }
1565 /// See QueryIntText()
1566 bool BoolText(bool defaultValue = false) const
1567 {
1568 bool b = defaultValue;
1569 QueryBoolText(&b);
1570 return b;
1571 }
1572 /// See QueryIntText()
1573 double DoubleText(double defaultValue = 0) const
1574 {
1575 double d = defaultValue;
1576 QueryDoubleText(&d);
1577 return d;
1578 }
1579 /// See QueryIntText()
1580 float FloatText(float defaultValue = 0) const
1581 {
1582 float f = defaultValue;
1583 QueryFloatText(&f);
1584 return f;
1585 }
1586
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001587 // internal:
1588 enum {
1589 OPEN, // <foo>
1590 CLOSED, // <foo/>
1591 CLOSING // </foo>
1592 };
1593 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001594 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001595 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1597 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001598
Dmitry-Me9b0f1772015-04-03 10:37:31 +03001599protected:
1600 char* ParseDeep( char* p, StrPair* endTag );
1601
Lee Thomason50adb4c2012-02-13 15:07:09 -08001602private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 XMLElement( XMLDocument* doc );
1604 virtual ~XMLElement();
1605 XMLElement( const XMLElement& ); // not supported
1606 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001607
Dmitry-Me1227d512014-12-05 13:41:45 +03001608 XMLAttribute* FindAttribute( const char* name ) {
1609 return const_cast<XMLAttribute*>(const_cast<const XMLElement*>(this)->FindAttribute( name ));
1610 }
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001611 XMLAttribute* FindOrCreateAttribute( const char* name );
1612 //void LinkAttribute( XMLAttribute* attrib );
1613 char* ParseAttributes( char* p );
Dmitry-Mee3225b12014-09-03 11:03:11 +04001614 static void DeleteAttribute( XMLAttribute* attribute );
Lee Thomason67d61312012-01-24 16:01:51 -08001615
Lee Thomason5bb2d802014-01-24 10:42:57 -08001616 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001617 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001618 // The attribute list is ordered; there is no 'lastAttribute'
1619 // because the list needs to be scanned for dupes before adding
1620 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001621 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001622};
1623
1624
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001625enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001626 PRESERVE_WHITESPACE,
1627 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001628};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001629
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001630
1631/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001632 It can be saved, loaded, and printed to the screen.
1633 All Nodes are connected and allocated to a Document.
1634 If the Document is deleted, all its Nodes are also deleted.
1635*/
PKEuS16ed47d2013-07-06 12:02:43 +02001636class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001637{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001638 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001639public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001640 /// constructor
1641 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1642 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001643
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001644 virtual XMLDocument* ToDocument() {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001645 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001646 return this;
1647 }
1648 virtual const XMLDocument* ToDocument() const {
Dmitry-Me66487eb2015-07-20 18:21:04 +03001649 TIXMLASSERT( this == _document );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001650 return this;
1651 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001652
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001653 /**
1654 Parse an XML file from a character string.
1655 Returns XML_NO_ERROR (0) on success, or
1656 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001657
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001658 You may optionally pass in the 'nBytes', which is
1659 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001660 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001661 null terminated string.
1662 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001663 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001664
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001665 /**
1666 Load an XML file from disk.
1667 Returns XML_NO_ERROR (0) on success, or
1668 an errorID.
1669 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001670 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001671
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001672 /**
1673 Load an XML file from disk. You are responsible
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001674 for providing and closing the FILE*.
1675
1676 NOTE: The file should be opened as binary ("rb")
1677 not text in order for TinyXML-2 to correctly
1678 do newline normalization.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001679
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001680 Returns XML_NO_ERROR (0) on success, or
1681 an errorID.
1682 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001683 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001684
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001685 /**
1686 Save the XML file to disk.
1687 Returns XML_NO_ERROR (0) on success, or
1688 an errorID.
1689 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001690 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001691
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001692 /**
1693 Save the XML file to disk. You are responsible
1694 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001695
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001696 Returns XML_NO_ERROR (0) on success, or
1697 an errorID.
1698 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001699 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001700
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001702 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 }
1704 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001705 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001707
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 /**
1709 Returns true if this document has a leading Byte Order Mark of UTF8.
1710 */
1711 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001712 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001713 }
1714 /** Sets whether to write the BOM when writing the file.
1715 */
1716 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001719
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001720 /** Return the root element of DOM. Equivalent to FirstChildElement().
1721 To get the first node, use FirstChild().
1722 */
1723 XMLElement* RootElement() {
1724 return FirstChildElement();
1725 }
1726 const XMLElement* RootElement() const {
1727 return FirstChildElement();
1728 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001729
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001730 /** Print the Document. If the Printer is not provided, it will
1731 print to stdout. If you provide Printer, this can print to a file:
1732 @verbatim
1733 XMLPrinter printer( fp );
1734 doc.Print( &printer );
1735 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001736
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001737 Or you can use a printer to print to memory:
1738 @verbatim
1739 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001740 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 // printer.CStr() has a const char* to the XML
1742 @endverbatim
1743 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001744 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001745 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001746
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001747 /**
1748 Create a new Element associated with
1749 this Document. The memory for the Element
1750 is managed by the Document.
1751 */
1752 XMLElement* NewElement( const char* name );
1753 /**
1754 Create a new Comment associated with
1755 this Document. The memory for the Comment
1756 is managed by the Document.
1757 */
1758 XMLComment* NewComment( const char* comment );
1759 /**
1760 Create a new Text associated with
1761 this Document. The memory for the Text
1762 is managed by the Document.
1763 */
1764 XMLText* NewText( const char* text );
1765 /**
1766 Create a new Declaration associated with
1767 this Document. The memory for the object
1768 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001769
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001770 If the 'text' param is null, the standard
1771 declaration is used.:
1772 @verbatim
1773 <?xml version="1.0" encoding="UTF-8"?>
1774 @endverbatim
1775 */
1776 XMLDeclaration* NewDeclaration( const char* text=0 );
1777 /**
1778 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001779 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 is managed by the Document.
1781 */
1782 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001783
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001784 /**
1785 Delete a node associated with this document.
1786 It will be unlinked from the DOM.
1787 */
Lee Thomasoncd011bc2014-12-17 10:41:34 -08001788 void DeleteNode( XMLNode* node );
U-Stream\Leeae25a442012-02-17 17:48:16 -08001789
Lee Thomason2fa81722012-11-09 12:37:46 -08001790 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001791
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 /// Return true if there was an error parsing the document.
1793 bool Error() const {
Lee Thomason85536252016-06-04 19:10:53 -07001794 return _errorID != XML_SUCCESS;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
1796 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001797 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 }
Lee Thomason331596e2014-09-11 14:56:43 -07001800 const char* ErrorName() const;
1801
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 /// Return a possibly helpful diagnostic location or string.
1803 const char* GetErrorStr1() const {
Lee Thomason584af572016-09-05 14:14:16 -07001804 return _errorStr1.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001805 }
1806 /// Return a possibly helpful secondary diagnostic location or string.
1807 const char* GetErrorStr2() const {
Lee Thomason584af572016-09-05 14:14:16 -07001808 return _errorStr2.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 }
1810 /// If there is an error, print it to stdout.
1811 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001812
1813 /// Clear the document, resetting it to the initial state.
1814 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001815
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 // internal
1817 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001818
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1820 return 0;
1821 }
1822 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1823 return false;
1824 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001825
Lee Thomason3f57d272012-01-11 15:30:03 -08001826private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001827 XMLDocument( const XMLDocument& ); // not supported
1828 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001829
Lee Thomason2fa81722012-11-09 12:37:46 -08001830 bool _writeBOM;
1831 bool _processEntities;
1832 XMLError _errorID;
1833 Whitespace _whitespace;
Lee Thomason584af572016-09-05 14:14:16 -07001834 mutable StrPair _errorStr1;
1835 mutable StrPair _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001836 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001837
Lee Thomason624d43f2012-10-12 10:58:48 -07001838 MemPoolT< sizeof(XMLElement) > _elementPool;
1839 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1840 MemPoolT< sizeof(XMLText) > _textPool;
1841 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason331596e2014-09-11 14:56:43 -07001842
1843 static const char* _errorNames[XML_ERROR_COUNT];
Dmitry-Me97476b72015-01-01 16:15:57 +03001844
1845 void Parse();
Lee Thomason5cae8972012-01-24 18:03:07 -08001846};
1847
Lee Thomason7c913cd2012-01-26 18:32:34 -08001848
Lee Thomason3ffdd392012-03-28 17:27:55 -07001849/**
1850 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001851 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001852 DOM structure. It is a separate utility class.
1853
1854 Take an example:
1855 @verbatim
1856 <Document>
1857 <Element attributeA = "valueA">
1858 <Child attributeB = "value1" />
1859 <Child attributeB = "value2" />
1860 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001861 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001862 @endverbatim
1863
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001864 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001865 easy to write a *lot* of code that looks like:
1866
1867 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001868 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001869 if ( root )
1870 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001871 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001872 if ( element )
1873 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001874 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001875 if ( child )
1876 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001877 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001878 if ( child2 )
1879 {
1880 // Finally do something useful.
1881 @endverbatim
1882
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001883 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001884 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001885 and correct to use:
1886
1887 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001888 XMLHandle docHandle( &document );
Dmitry-Mea317bd62014-12-08 10:35:37 +03001889 XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001890 if ( child2 )
1891 {
1892 // do something useful
1893 @endverbatim
1894
1895 Which is MUCH more concise and useful.
1896
1897 It is also safe to copy handles - internally they are nothing more than node pointers.
1898 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001899 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001900 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001901
1902 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001903*/
PKEuS16ed47d2013-07-06 12:02:43 +02001904class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001905{
1906public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001907 /// 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 -07001908 XMLHandle( XMLNode* node ) {
1909 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001910 }
1911 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001912 XMLHandle( XMLNode& node ) {
1913 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001914 }
1915 /// Copy constructor
1916 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001917 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 }
1919 /// Assignment
1920 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001921 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001922 return *this;
1923 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001924
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001925 /// Get the first child of this handle.
1926 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001927 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001928 }
1929 /// Get the first child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001930 XMLHandle FirstChildElement( const char* name = 0 ) {
1931 return XMLHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001932 }
1933 /// Get the last child of this handle.
1934 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001935 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001936 }
1937 /// Get the last child element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001938 XMLHandle LastChildElement( const char* name = 0 ) {
1939 return XMLHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001940 }
1941 /// Get the previous sibling of this handle.
1942 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001943 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001944 }
1945 /// Get the previous sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001946 XMLHandle PreviousSiblingElement( const char* name = 0 ) {
1947 return XMLHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001948 }
1949 /// Get the next sibling of this handle.
1950 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001951 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001952 }
1953 /// Get the next sibling element of this handle.
Dmitry-Me886ad972015-07-22 11:00:51 +03001954 XMLHandle NextSiblingElement( const char* name = 0 ) {
1955 return XMLHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001956 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001957
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001958 /// Safe cast to XMLNode. This can return null.
1959 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001960 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001961 }
1962 /// Safe cast to XMLElement. This can return null.
1963 XMLElement* ToElement() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001964 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001965 }
1966 /// Safe cast to XMLText. This can return null.
1967 XMLText* ToText() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001968 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001969 }
1970 /// Safe cast to XMLUnknown. This can return null.
1971 XMLUnknown* ToUnknown() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001972 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001973 }
1974 /// Safe cast to XMLDeclaration. This can return null.
1975 XMLDeclaration* ToDeclaration() {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04001976 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001977 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001978
1979private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001980 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001981};
1982
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001983
1984/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001985 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1986 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001987*/
PKEuS16ed47d2013-07-06 12:02:43 +02001988class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001989{
1990public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001991 XMLConstHandle( const XMLNode* node ) {
1992 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001993 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001994 XMLConstHandle( const XMLNode& node ) {
1995 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 }
1997 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001998 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001999 }
Lee Thomason8b899812012-04-04 15:58:16 -07002000
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002001 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07002002 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002003 return *this;
2004 }
Lee Thomason8b899812012-04-04 15:58:16 -07002005
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002006 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002007 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002008 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002009 const XMLConstHandle FirstChildElement( const char* name = 0 ) const {
2010 return XMLConstHandle( _node ? _node->FirstChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002011 }
2012 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002013 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002014 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002015 const XMLConstHandle LastChildElement( const char* name = 0 ) const {
2016 return XMLConstHandle( _node ? _node->LastChildElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002017 }
2018 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002019 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002020 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002021 const XMLConstHandle PreviousSiblingElement( const char* name = 0 ) const {
2022 return XMLConstHandle( _node ? _node->PreviousSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002023 }
2024 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002025 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002026 }
Dmitry-Me886ad972015-07-22 11:00:51 +03002027 const XMLConstHandle NextSiblingElement( const char* name = 0 ) const {
2028 return XMLConstHandle( _node ? _node->NextSiblingElement( name ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002029 }
Lee Thomason8b899812012-04-04 15:58:16 -07002030
2031
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002032 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002033 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002034 }
2035 const XMLElement* ToElement() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002036 return ( ( _node == 0 ) ? 0 : _node->ToElement() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002037 }
2038 const XMLText* ToText() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002039 return ( ( _node == 0 ) ? 0 : _node->ToText() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002040 }
2041 const XMLUnknown* ToUnknown() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002042 return ( ( _node == 0 ) ? 0 : _node->ToUnknown() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002043 }
2044 const XMLDeclaration* ToDeclaration() const {
Dmitry-Meb6b4e822014-08-27 17:17:47 +04002045 return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002046 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08002047
Lee Thomason5cae8972012-01-24 18:03:07 -08002048private:
Lee Thomason624d43f2012-10-12 10:58:48 -07002049 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08002050};
Lee Thomason6f381b72012-03-02 12:59:39 -08002051
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002052
2053/**
2054 Printing functionality. The XMLPrinter gives you more
2055 options than the XMLDocument::Print() method.
2056
2057 It can:
2058 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02002059 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002060 -# Print XML without a XMLDocument.
2061
2062 Print to Memory
2063
2064 @verbatim
2065 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06002066 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02002067 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002068 @endverbatim
2069
2070 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07002071
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002072 You provide the file pointer.
2073 @verbatim
2074 XMLPrinter printer( fp );
2075 doc.Print( &printer );
2076 @endverbatim
2077
2078 Print without a XMLDocument
2079
2080 When loading, an XML parser is very useful. However, sometimes
2081 when saving, it just gets in the way. The code is often set up
2082 for streaming, and constructing the DOM is just overhead.
2083
2084 The Printer supports the streaming case. The following code
2085 prints out a trivially simple XML file without ever creating
2086 an XML document.
2087
2088 @verbatim
2089 XMLPrinter printer( fp );
2090 printer.OpenElement( "foo" );
2091 printer.PushAttribute( "foo", "bar" );
2092 printer.CloseElement();
2093 @endverbatim
2094*/
PKEuS16ed47d2013-07-06 12:02:43 +02002095class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002096{
2097public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002098 /** Construct the printer. If the FILE* is specified,
2099 this will print to the FILE. Else it will print
2100 to memory, and the result is available in CStr().
2101 If 'compact' is set to true, then output is created
2102 with only required whitespace and newlines.
2103 */
PKEuS1bfb9542013-08-04 13:51:17 +02002104 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002105 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002106
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002107 /** If streaming, write the BOM and declaration. */
2108 void PushHeader( bool writeBOM, bool writeDeclaration );
2109 /** If streaming, start writing an element.
2110 The element must be closed with CloseElement()
2111 */
Lee Thomason256adb62014-04-06 14:41:46 -07002112 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002113 /// If streaming, add an attribute to an open element.
2114 void PushAttribute( const char* name, const char* value );
2115 void PushAttribute( const char* name, int value );
2116 void PushAttribute( const char* name, unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002117 void PushAttribute(const char* name, int64_t value);
2118 void PushAttribute( const char* name, bool value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002119 void PushAttribute( const char* name, double value );
2120 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07002121 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002122
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002123 /// Add a text node.
2124 void PushText( const char* text, bool cdata=false );
2125 /// Add a text node from an integer.
2126 void PushText( int value );
2127 /// Add a text node from an unsigned.
2128 void PushText( unsigned value );
Lee Thomason51c12712016-06-04 20:18:49 -07002129 /// Add a text node from an unsigned.
2130 void PushText(int64_t value);
2131 /// Add a text node from a bool.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002132 void PushText( bool value );
2133 /// Add a text node from a float.
2134 void PushText( float value );
2135 /// Add a text node from a double.
2136 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07002137
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002138 /// Add a comment
2139 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002140
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002141 void PushDeclaration( const char* value );
2142 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002143
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002144 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
2145 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
2146 return true;
2147 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002148
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002149 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2150 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002151
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002152 virtual bool Visit( const XMLText& text );
2153 virtual bool Visit( const XMLComment& comment );
2154 virtual bool Visit( const XMLDeclaration& declaration );
2155 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002156
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002157 /**
2158 If in print to memory mode, return a pointer to
2159 the XML file in memory.
2160 */
2161 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002162 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002163 }
2164 /**
2165 If in print to memory mode, return the size
2166 of the XML file in memory. (Note the size returned
2167 includes the terminating null.)
2168 */
2169 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002170 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002171 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002172 /**
2173 If in print to memory mode, reset the buffer to the
2174 beginning.
2175 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002176 void ClearBuffer() {
2177 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002178 _buffer.Push(0);
2179 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002180
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002181protected:
Alexander Maid740b642014-05-20 22:04:42 +02002182 virtual bool CompactMode( const XMLElement& ) { return _compactMode; }
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002183
Lee Thomasonc18eb232014-02-21 17:31:17 -08002184 /** Prints out the space before an element. You may override to change
2185 the space and tabs used. A PrintSpace() override should call Print().
2186 */
2187 virtual void PrintSpace( int depth );
2188 void Print( const char* format, ... );
2189
Dmitry-Mea092bc12014-12-23 17:57:05 +03002190 void SealElementIfJustOpened();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002191 bool _elementJustOpened;
2192 DynArray< const char*, 10 > _stack;
2193
2194private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002195 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002196
Lee Thomason624d43f2012-10-12 10:58:48 -07002197 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002198 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002199 int _depth;
2200 int _textDepth;
2201 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002202 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002203
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002204 enum {
2205 ENTITY_RANGE = 64,
2206 BUF_SIZE = 200
2207 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002208 bool _entityFlag[ENTITY_RANGE];
2209 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002210
Lee Thomason624d43f2012-10-12 10:58:48 -07002211 DynArray< char, 20 > _buffer;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002212};
2213
2214
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002215} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002216
PKEuS95060352013-07-26 10:42:44 +02002217#if defined(_MSC_VER)
2218# pragma warning(pop)
2219#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002220
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002221#endif // TINYXML2_INCLUDED