blob: 23ea80b1795fe62d2bb244571918c9b166bf7d67 [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
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -070017
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -0800182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080024
Lee Thomason7d00b9a2012-02-27 17:54:22 -080025#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080026#define TINYXML2_INCLUDED
27
Jerome Martinez242c3ea2013-01-06 12:20:04 +010028#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070029# include <ctype.h>
30# include <limits.h>
31# include <stdio.h>
32# include <stdlib.h>
33# include <string.h>
34# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070035#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070036# include <cctype>
37# include <climits>
38# include <cstdio>
39# include <cstdlib>
40# include <cstring>
41# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070043
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070044/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080045 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080046*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080047/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070048 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080049 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010050
Lee Thomasona9cf3f92012-10-11 16:56:51 -070051 Formatting, Artistic Style:
52 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080053*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080054
U-Lama\Lee4cee6112011-12-31 14:58:18 -080055#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070056# ifndef DEBUG
57# define DEBUG
58# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080059#endif
60
PKEuS95060352013-07-26 10:42:44 +020061#ifdef _MSC_VER
62# pragma warning(push)
63# pragma warning(disable: 4251)
64#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080065
PKEuS16ed47d2013-07-06 12:02:43 +020066#ifdef _WIN32
67# ifdef TINYXML2_EXPORT
68# define TINYXML2_LIB __declspec(dllexport)
69# elif defined(TINYXML2_IMPORT)
70# define TINYXML2_LIB __declspec(dllimport)
71# else
72# define TINYXML2_LIB
73# endif
74#else
75# define TINYXML2_LIB
76#endif
77
78
U-Lama\Lee4cee6112011-12-31 14:58:18 -080079#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070080# if defined(_MSC_VER)
81# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
82# elif defined (ANDROID_NDK)
83# include <android/log.h>
84# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85# else
86# include <assert.h>
87# define TIXMLASSERT assert
88# endif
89# else
90# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080091#endif
92
U-Lama\Leee13c3e62011-12-28 14:36:55 -080093
Lee Thomason1a1d4a72012-02-15 09:09:25 -080094#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// Microsoft visual studio, version 2005 and higher.
96/*int _snprintf_s(
97 char *buffer,
98 size_t sizeOfBuffer,
99 size_t count,
100 const char *format [,
101 argument] ...
102);*/
103inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
104{
105 va_list va;
106 va_start( va, format );
107 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
108 va_end( va );
109 return result;
110}
111#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700112#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700113// GCC version 3 and higher
114//#warning( "Using sn* functions." )
115#define TIXML_SNPRINTF snprintf
116#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800117#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800118
Lee Thomasonc18eb232014-02-21 17:31:17 -0800119/* Versioning, past 1.0.14:
Lee Thomason85afe9c2014-02-23 21:42:16 -0800120 http://semver.org/
Lee Thomasonc18eb232014-02-21 17:31:17 -0800121*/
Lee Thomason85afe9c2014-02-23 21:42:16 -0800122static const int TIXML2_MAJOR_VERSION = 2;
123static const int TIXML2_MINOR_VERSION = 0;
Lee Thomasonb59ac452014-03-16 20:18:41 -0700124static const int TIXML2_PATCH_VERSION = 2;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800125
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800126namespace tinyxml2
127{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800128class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800129class XMLElement;
130class XMLAttribute;
131class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800132class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800133class XMLDeclaration;
134class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800135class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800136
U-Stream\Leeae25a442012-02-17 17:48:16 -0800137/*
138 A class that wraps strings. Normally stores the start and end
139 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800140 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800141 manage) a traditional char[]
142*/
PKEuS95060352013-07-26 10:42:44 +0200143class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800144{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800145public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700146 enum {
147 NEEDS_ENTITY_PROCESSING = 0x01,
148 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800149 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800150
selfpoisede77e1952013-03-13 14:08:29 +0800151 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800153 ATTRIBUTE_NAME = 0,
154 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
155 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
156 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 };
Lee Thomason39ede242012-01-20 11:27:56 -0800158
Lee Thomason120b3a62012-10-12 10:06:59 -0700159 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800161
Lee Thomason120b3a62012-10-12 10:06:59 -0700162 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700164 _start = start;
165 _end = end;
166 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700168
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700169 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700170
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700171 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700172 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700173 }
Lee Thomason39ede242012-01-20 11:27:56 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 void SetInternedStr( const char* str ) {
176 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700177 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700178 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700179
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700180 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800181
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700182 char* ParseText( char* in, const char* endTag, int strFlags );
183 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800184
Lee Thomason39ede242012-01-20 11:27:56 -0800185private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700186 void Reset();
187 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800188
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700189 enum {
190 NEEDS_FLUSH = 0x100,
191 NEEDS_DELETE = 0x200
192 };
Lee Thomasone4422302012-01-20 17:59:50 -0800193
selfpoised4dd59bc2013-03-13 16:54:15 +0800194 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700195 int _flags;
196 char* _start;
197 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800198};
199
U-Lama\Lee560bd472011-12-28 19:42:49 -0800200
U-Stream\Leeae25a442012-02-17 17:48:16 -0800201/*
202 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
203 Has a small initial memory pool, so that low or no usage will not
204 cause a call to new/delete
205*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800206template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200207class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800208{
209public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700210 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700211 _mem = _pool;
212 _allocated = INIT;
213 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700214 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700215
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700217 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700218 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 }
220 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700221
Lee Thomasonce0510b2013-11-26 21:29:37 -0800222 void Clear() {
Reinhard Klambauer4e74b132013-11-22 14:01:58 +0100223 _size = 0;
224 }
225
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700227 EnsureCapacity( _size+1 );
228 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700229 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 EnsureCapacity( _size+count );
233 T* ret = &_mem[_size];
234 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 return ret;
236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700239 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 TIXMLASSERT( _size >= count );
244 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800246
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700248 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700250
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700251 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700252 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700253 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700254 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700255
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700256 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700257 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700258 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700260
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500261 const T& PeekTop() const {
262 TIXMLASSERT( _size > 0 );
263 return _mem[ _size - 1];
264 }
265
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700266 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700267 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700269
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700271 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700272 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700273
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700274 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700275 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700277
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700279 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700280 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800281
Lee Thomason2c85a712012-01-31 08:24:24 -0800282private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700284 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 int newAllocated = cap * 2;
286 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700287 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
288 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700289 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700290 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700291 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700292 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700293 }
294 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800295
Lee Thomason624d43f2012-10-12 10:58:48 -0700296 T* _mem;
297 T _pool[INIT];
298 int _allocated; // objects allocated
299 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800300};
301
Lee Thomason50adb4c2012-02-13 15:07:09 -0800302
U-Stream\Leeae25a442012-02-17 17:48:16 -0800303/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200304 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800305 and deallocation of objects.
306*/
PKEuS95060352013-07-26 10:42:44 +0200307class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800308{
309public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700310 MemPool() {}
311 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual int ItemSize() const = 0;
314 virtual void* Alloc() = 0;
315 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800316 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800317};
318
Lee Thomason50adb4c2012-02-13 15:07:09 -0800319
U-Stream\Leeae25a442012-02-17 17:48:16 -0800320/*
321 Template child class to create pools of the correct type.
322*/
Lee Thomasond1983222012-02-06 08:41:24 -0800323template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200324class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800325{
326public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800327 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 ~MemPoolT() {
329 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700330 for( int i=0; i<_blockPtrs.Size(); ++i ) {
331 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 }
333 }
Lee Thomasond1983222012-02-06 08:41:24 -0800334
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 virtual int ItemSize() const {
336 return SIZE;
337 }
338 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700340 }
Lee Thomasond1983222012-02-06 08:41:24 -0800341
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700343 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 // Need a new block.
345 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800347
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 for( int i=0; i<COUNT-1; ++i ) {
349 block->chunk[i].next = &block->chunk[i+1];
350 }
351 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700352 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 void* result = _root;
355 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800356
Lee Thomason624d43f2012-10-12 10:58:48 -0700357 ++_currentAllocs;
358 if ( _currentAllocs > _maxAllocs ) {
359 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700361 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800362 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 return result;
364 }
365 virtual void Free( void* mem ) {
366 if ( !mem ) {
367 return;
368 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700369 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700370 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700371#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700372 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700373#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700374 chunk->next = _root;
375 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700376 }
377 void Trace( const char* name ) {
378 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700379 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700380 }
Lee Thomasond1983222012-02-06 08:41:24 -0800381
Lee Thomason5b0a6772012-11-19 13:54:42 -0800382 void SetTracked() {
383 _nUntracked--;
384 }
385
386 int Untracked() const {
387 return _nUntracked;
388 }
389
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800390 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
391 // The test file is large, 170k.
392 // Release: VS2010 gcc(no opt)
393 // 1k: 4000
394 // 2k: 4000
395 // 4k: 3900 21000
396 // 16k: 5200
397 // 32k: 4300
398 // 64k: 4000 21000
399 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
Jerome Martinez7921df12012-10-24 11:45:44 +0200400
Lee Thomasond1983222012-02-06 08:41:24 -0800401private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700402 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700403 Chunk* next;
404 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700405 };
406 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700407 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700408 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700409 DynArray< Block*, 10 > _blockPtrs;
410 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800411
Lee Thomason624d43f2012-10-12 10:58:48 -0700412 int _currentAllocs;
413 int _nAllocs;
414 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800415 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800416};
417
Lee Thomason2c85a712012-01-31 08:24:24 -0800418
Lee Thomason56bdd022012-02-09 18:16:58 -0800419
420/**
421 Implements the interface to the "Visitor pattern" (see the Accept() method.)
422 If you call the Accept() method, it requires being passed a XMLVisitor
423 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200424 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800425 are simply called with Visit().
426
427 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700428 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800429
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700430 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800431 visiting). You need to only override methods that are interesting to you.
432
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600433 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800434
435 You should never change the document from a callback.
436
437 @sa XMLNode::Accept()
438*/
PKEuS16ed47d2013-07-06 12:02:43 +0200439class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800440{
441public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700442 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800443
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700444 /// Visit a document.
445 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
446 return true;
447 }
448 /// Visit a document.
449 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
450 return true;
451 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800452
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700453 /// Visit an element.
454 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
455 return true;
456 }
457 /// Visit an element.
458 virtual bool VisitExit( const XMLElement& /*element*/ ) {
459 return true;
460 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800461
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700462 /// Visit a declaration.
463 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
464 return true;
465 }
466 /// Visit a text node.
467 virtual bool Visit( const XMLText& /*text*/ ) {
468 return true;
469 }
470 /// Visit a comment node.
471 virtual bool Visit( const XMLComment& /*comment*/ ) {
472 return true;
473 }
474 /// Visit an unknown node.
475 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
476 return true;
477 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800478};
479
480
U-Stream\Leeae25a442012-02-17 17:48:16 -0800481/*
482 Utility functionality.
483*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800484class XMLUtil
485{
Lee Thomasond1983222012-02-06 08:41:24 -0800486public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700487 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
488 // correct, but simple, and usually works.
489 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100490 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700491 ++p;
492 }
493 return p;
494 }
495 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100496 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700497 ++p;
498 }
499 return p;
500 }
501 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100502 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700503 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200504
505 inline static bool IsNameStartChar( unsigned char ch ) {
506 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
507 || ch == ':'
508 || ch == '_';
509 }
510
511 inline static bool IsNameChar( unsigned char ch ) {
512 return IsNameStartChar( ch )
513 || isdigit( ch )
514 || ch == '.'
515 || ch == '-';
516 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800517
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700518 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
519 int n = 0;
520 if ( p == q ) {
521 return true;
522 }
523 while( *p && *q && *p == *q && n<nChar ) {
524 ++p;
525 ++q;
526 ++n;
527 }
528 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
529 return true;
530 }
531 return false;
532 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200533
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 inline static int IsUTF8Continuation( const char p ) {
535 return p & 0x80;
536 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800537
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700538 static const char* ReadBOM( const char* p, bool* hasBOM );
539 // p is the starting location,
540 // the UTF-8 value of the entity will be placed in value, and length filled in.
541 static const char* GetCharacterRef( const char* p, char* value, int* length );
542 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700543
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700544 // converts primitive types to strings
545 static void ToStr( int v, char* buffer, int bufferSize );
546 static void ToStr( unsigned v, char* buffer, int bufferSize );
547 static void ToStr( bool v, char* buffer, int bufferSize );
548 static void ToStr( float v, char* buffer, int bufferSize );
549 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700550
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700551 // converts strings to primitive types
552 static bool ToInt( const char* str, int* value );
553 static bool ToUnsigned( const char* str, unsigned* value );
554 static bool ToBool( const char* str, bool* value );
555 static bool ToFloat( const char* str, float* value );
556 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800557};
558
Lee Thomason5cae8972012-01-24 18:03:07 -0800559
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800560/** XMLNode is a base class for every object that is in the
561 XML Document Object Model (DOM), except XMLAttributes.
562 Nodes have siblings, a parent, and children which can
563 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700564 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800565 be cast to its more defined type.
566
Thomas Roß08bdf502012-05-12 14:21:23 +0200567 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800568 When the XMLDocument gets deleted, all its Nodes
569 will also be deleted.
570
571 @verbatim
572 A Document can contain: Element (container or leaf)
573 Comment (leaf)
574 Unknown (leaf)
575 Declaration( leaf )
576
577 An Element can contain: Element (container or leaf)
578 Text (leaf)
579 Attributes (not on tree)
580 Comment (leaf)
581 Unknown (leaf)
582
583 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800584*/
PKEuS16ed47d2013-07-06 12:02:43 +0200585class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800586{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 friend class XMLDocument;
588 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800589public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800590
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 /// Get the XMLDocument that owns this XMLNode.
592 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700593 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 }
595 /// Get the XMLDocument that owns this XMLNode.
596 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700597 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800599
Lee Thomason2fa81722012-11-09 12:37:46 -0800600 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100602 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700603 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800604 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700605 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100606 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700607 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800608 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700609 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100610 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800612 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700613 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100614 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700615 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800616 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700617 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100618 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700619 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800620 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700621 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100622 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700623 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800624
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700625 virtual const XMLElement* ToElement() const {
626 return 0;
627 }
628 virtual const XMLText* ToText() const {
629 return 0;
630 }
631 virtual const XMLComment* ToComment() const {
632 return 0;
633 }
634 virtual const XMLDocument* ToDocument() const {
635 return 0;
636 }
637 virtual const XMLDeclaration* ToDeclaration() const {
638 return 0;
639 }
640 virtual const XMLUnknown* ToUnknown() const {
641 return 0;
642 }
Lee Thomason751da522012-02-10 08:50:51 -0800643
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700644 /** The meaning of 'value' changes for the specific type.
645 @verbatim
646 Document: empty
647 Element: name of the element
648 Comment: the comment text
649 Unknown: the tag contents
650 Text: the text string
651 @endverbatim
652 */
Michael Daumling21626882013-10-22 17:03:37 +0200653 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100654
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 /** Set the Value of an XML node.
656 @sa Value()
657 */
658 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800659
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 /// Get the parent of this node on the DOM.
661 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700662 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100664
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700666 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 }
Lee Thomason751da522012-02-10 08:50:51 -0800668
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 /// Returns true if this node has no children.
670 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700671 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 }
Lee Thomason751da522012-02-10 08:50:51 -0800673
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 /// Get the first child node, or null if none exists.
675 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700676 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700677 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100678
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700679 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700680 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100682
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 /** Get the first child element, or optionally the first child
684 element with the specified name.
685 */
686 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700687
688 XMLElement* FirstChildElement( const char* value=0 ) {
689 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800691
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 /// Get the last child node, or null if none exists.
693 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700694 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700695 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700696
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 XMLNode* LastChild() {
698 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
699 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800700
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 /** Get the last child element or optionally the last child
702 element with the specified name.
703 */
704 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700705
706 XMLElement* LastChildElement( const char* value=0 ) {
707 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700709
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 /// Get the previous (left) sibling node of this node.
711 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700712 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700714
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700716 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800718
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700719 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700721
722 XMLElement* PreviousSiblingElement( const char* value=0 ) {
723 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 /// Get the next (right) sibling node of this node.
727 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700728 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700730
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700732 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700734
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700735 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700736 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700737
738 XMLElement* NextSiblingElement( const char* value=0 ) {
739 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700740 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800741
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 /**
743 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200744 If the child node is already part of the document,
745 it is moved from its old location to the new location.
746 Returns the addThis argument or 0 if the node does not
747 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700748 */
749 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800750
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 XMLNode* LinkEndChild( XMLNode* addThis ) {
752 return InsertEndChild( addThis );
753 }
754 /**
755 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200756 If the child node is already part of the document,
757 it is moved from its old location to the new location.
758 Returns the addThis argument or 0 if the node does not
759 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 */
761 XMLNode* InsertFirstChild( XMLNode* addThis );
762 /**
763 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200764 If the child node is already part of the document,
765 it is moved from its old location to the new location.
766 Returns the addThis argument or 0 if the afterThis node
767 is not a child of this node, or if the node does not
768 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 */
770 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700771
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 /**
773 Delete all the children of this node.
774 */
775 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800776
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 /**
778 Delete a child of this node.
779 */
780 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800781
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 /**
783 Make a copy of this node, but not its children.
784 You may pass in a Document pointer that will be
785 the owner of the new Node. If the 'document' is
786 null, then the node returned will be allocated
787 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800788
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 Note: if called on a XMLDocument, this will return null.
790 */
791 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800792
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 /**
794 Test if 2 nodes are the same, but don't test children.
795 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800796
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700797 Note: if called on a XMLDocument, this will return false.
798 */
799 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800800
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600801 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700802 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600803 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800804
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600805 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
806 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800808
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800810
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 - http://www.saxproject.org/
812 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800813
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700814 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800815
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700816 An example of using Accept():
817 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600818 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 tinyxmlDoc.Accept( &printer );
820 const char* xmlcstr = printer.CStr();
821 @endverbatim
822 */
823 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800824
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 // internal
826 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800827
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800828protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700829 XMLNode( XMLDocument* );
830 virtual ~XMLNode();
831 XMLNode( const XMLNode& ); // not supported
832 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700833
Lee Thomason624d43f2012-10-12 10:58:48 -0700834 XMLDocument* _document;
835 XMLNode* _parent;
836 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800837
Lee Thomason624d43f2012-10-12 10:58:48 -0700838 XMLNode* _firstChild;
839 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800840
Lee Thomason624d43f2012-10-12 10:58:48 -0700841 XMLNode* _prev;
842 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800843
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800844private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700845 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800847};
848
849
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800850/** XML text.
851
852 Note that a text node can have child element nodes, for example:
853 @verbatim
854 <root>This is <b>bold</b></root>
855 @endverbatim
856
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700857 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800858 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 -0700859 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600860 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800861*/
PKEuS16ed47d2013-07-06 12:02:43 +0200862class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800863{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700864 friend class XMLBase;
865 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800866public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700867 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800868
Lee Thomason624d43f2012-10-12 10:58:48 -0700869 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700870 return this;
871 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700872 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700873 return this;
874 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800875
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700877 void SetCData( bool isCData ) {
878 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700879 }
880 /// Returns true if this is a CDATA text element.
881 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700882 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800884
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 char* ParseDeep( char*, StrPair* endTag );
886 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
887 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800888
Lee Thomason5492a1c2012-01-23 15:32:10 -0800889protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700890 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700891 virtual ~XMLText() {}
892 XMLText( const XMLText& ); // not supported
893 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800894
895private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700896 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800897};
898
899
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800900/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200901class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800902{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700903 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800904public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700905 virtual XMLComment* ToComment() {
906 return this;
907 }
908 virtual const XMLComment* ToComment() const {
909 return this;
910 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800911
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700912 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800913
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700914 char* ParseDeep( char*, StrPair* endTag );
915 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
916 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800917
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800918protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700919 XMLComment( XMLDocument* doc );
920 virtual ~XMLComment();
921 XMLComment( const XMLComment& ); // not supported
922 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800923
Lee Thomason3f57d272012-01-11 15:30:03 -0800924private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800925};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800926
927
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800928/** In correct XML the declaration is the first entry in the file.
929 @verbatim
930 <?xml version="1.0" standalone="yes"?>
931 @endverbatim
932
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600933 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800934 however.
935
936 The text of the declaration isn't interpreted. It is parsed
937 and written as a string.
938*/
PKEuS16ed47d2013-07-06 12:02:43 +0200939class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800940{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700941 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800942public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700943 virtual XMLDeclaration* ToDeclaration() {
944 return this;
945 }
946 virtual const XMLDeclaration* ToDeclaration() const {
947 return this;
948 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800949
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800951
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700952 char* ParseDeep( char*, StrPair* endTag );
953 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
954 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800955
956protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700957 XMLDeclaration( XMLDocument* doc );
958 virtual ~XMLDeclaration();
959 XMLDeclaration( const XMLDeclaration& ); // not supported
960 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800961};
962
963
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600964/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800965 unknown. It is a tag of text, but should not be modified.
966 It will be written back to the XML, unchanged, when the file
967 is saved.
968
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600969 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800970*/
PKEuS16ed47d2013-07-06 12:02:43 +0200971class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800972{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700973 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800974public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700975 virtual XMLUnknown* ToUnknown() {
976 return this;
977 }
978 virtual const XMLUnknown* ToUnknown() const {
979 return this;
980 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800981
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700982 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800983
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700984 char* ParseDeep( char*, StrPair* endTag );
985 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
986 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800987
988protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700989 XMLUnknown( XMLDocument* doc );
990 virtual ~XMLUnknown();
991 XMLUnknown( const XMLUnknown& ); // not supported
992 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800993};
994
995
Lee Thomason2fa81722012-11-09 12:37:46 -0800996enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700997 XML_NO_ERROR = 0,
998 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800999
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001000 XML_NO_ATTRIBUTE,
1001 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001002
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001003 XML_ERROR_FILE_NOT_FOUND,
1004 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
1005 XML_ERROR_FILE_READ_ERROR,
1006 XML_ERROR_ELEMENT_MISMATCH,
1007 XML_ERROR_PARSING_ELEMENT,
1008 XML_ERROR_PARSING_ATTRIBUTE,
1009 XML_ERROR_IDENTIFYING_TAG,
1010 XML_ERROR_PARSING_TEXT,
1011 XML_ERROR_PARSING_CDATA,
1012 XML_ERROR_PARSING_COMMENT,
1013 XML_ERROR_PARSING_DECLARATION,
1014 XML_ERROR_PARSING_UNKNOWN,
1015 XML_ERROR_EMPTY_DOCUMENT,
1016 XML_ERROR_MISMATCHED_ELEMENT,
1017 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -07001018
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 XML_CAN_NOT_CONVERT_TEXT,
1020 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001021};
1022
1023
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001024/** An attribute is a name-value pair. Elements have an arbitrary
1025 number of attributes, each with a unique name.
1026
1027 @note The attributes are not XMLNodes. You may only query the
1028 Next() attribute in a list.
1029*/
PKEuS16ed47d2013-07-06 12:02:43 +02001030class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001031{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001032 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001033public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001034 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001035 const char* Name() const;
1036
Lee Thomason2fa81722012-11-09 12:37:46 -08001037 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001038 const char* Value() const;
1039
Lee Thomason2fa81722012-11-09 12:37:46 -08001040 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001041 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001042 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001043 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001044
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001045 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001046 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001047 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001048 */
1049 int IntValue() const {
1050 int i=0;
1051 QueryIntValue( &i );
1052 return i;
1053 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001054 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001055 unsigned UnsignedValue() const {
1056 unsigned i=0;
1057 QueryUnsignedValue( &i );
1058 return i;
1059 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001060 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001061 bool BoolValue() const {
1062 bool b=false;
1063 QueryBoolValue( &b );
1064 return b;
1065 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001067 double DoubleValue() const {
1068 double d=0;
1069 QueryDoubleValue( &d );
1070 return d;
1071 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001072 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 float FloatValue() const {
1074 float f=0;
1075 QueryFloatValue( &f );
1076 return f;
1077 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001078
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001079 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001080 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001081 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1082 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001083 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001084 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001085 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001086 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001087 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001088 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001089 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001090 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001091 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001092
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 /// Set the attribute to a string value.
1094 void SetAttribute( const char* value );
1095 /// Set the attribute to value.
1096 void SetAttribute( int value );
1097 /// Set the attribute to value.
1098 void SetAttribute( unsigned value );
1099 /// Set the attribute to value.
1100 void SetAttribute( bool value );
1101 /// Set the attribute to value.
1102 void SetAttribute( double value );
1103 /// Set the attribute to value.
1104 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001105
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001106private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001108
Thomas Roß61892312013-05-12 14:07:38 +02001109 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001110 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001111
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001112 XMLAttribute( const XMLAttribute& ); // not supported
1113 void operator=( const XMLAttribute& ); // not supported
1114 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001115
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001116 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001117
Lee Thomason624d43f2012-10-12 10:58:48 -07001118 mutable StrPair _name;
1119 mutable StrPair _value;
1120 XMLAttribute* _next;
1121 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001122};
1123
1124
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001125/** The element is a container class. It has a value, the element name,
1126 and can contain other elements, text, comments, and unknowns.
1127 Elements also contain an arbitrary number of attributes.
1128*/
PKEuS16ed47d2013-07-06 12:02:43 +02001129class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001130{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001131 friend class XMLBase;
1132 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001133public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001134 /// Get the name of an element (which is the Value() of the node.)
1135 const char* Name() const {
1136 return Value();
1137 }
1138 /// Set the name of the element.
1139 void SetName( const char* str, bool staticMem=false ) {
1140 SetValue( str, staticMem );
1141 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 virtual XMLElement* ToElement() {
1144 return this;
1145 }
1146 virtual const XMLElement* ToElement() const {
1147 return this;
1148 }
1149 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001150
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001151 /** Given an attribute name, Attribute() returns the value
1152 for the attribute of that name, or null if none
1153 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001154
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001155 @verbatim
1156 const char* value = ele->Attribute( "foo" );
1157 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001158
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001159 The 'value' parameter is normally null. However, if specified,
1160 the attribute will only be returned if the 'name' and 'value'
1161 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001162
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001163 @verbatim
1164 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1165 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001166
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001167 rather than:
1168 @verbatim
1169 if ( ele->Attribute( "foo" ) ) {
1170 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1171 }
1172 @endverbatim
1173 */
1174 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001175
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001176 /** Given an attribute name, IntAttribute() returns the value
1177 of the attribute interpreted as an integer. 0 will be
1178 returned if there is an error. For a method with error
1179 checking, see QueryIntAttribute()
1180 */
1181 int IntAttribute( const char* name ) const {
1182 int i=0;
1183 QueryIntAttribute( name, &i );
1184 return i;
1185 }
1186 /// See IntAttribute()
1187 unsigned UnsignedAttribute( const char* name ) const {
1188 unsigned i=0;
1189 QueryUnsignedAttribute( name, &i );
1190 return i;
1191 }
1192 /// See IntAttribute()
1193 bool BoolAttribute( const char* name ) const {
1194 bool b=false;
1195 QueryBoolAttribute( name, &b );
1196 return b;
1197 }
1198 /// See IntAttribute()
1199 double DoubleAttribute( const char* name ) const {
1200 double d=0;
1201 QueryDoubleAttribute( name, &d );
1202 return d;
1203 }
1204 /// See IntAttribute()
1205 float FloatAttribute( const char* name ) const {
1206 float f=0;
1207 QueryFloatAttribute( name, &f );
1208 return f;
1209 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001210
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001211 /** Given an attribute name, QueryIntAttribute() returns
1212 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1213 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1214 doesn't exist. If successful, the result of the conversion
1215 will be written to 'value'. If not successful, nothing will
1216 be written to 'value'. This allows you to provide default
1217 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001218
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001219 @verbatim
1220 int value = 10;
1221 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1222 @endverbatim
1223 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001224 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 const XMLAttribute* a = FindAttribute( name );
1226 if ( !a ) {
1227 return XML_NO_ATTRIBUTE;
1228 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001229 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 }
1231 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001232 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 const XMLAttribute* a = FindAttribute( name );
1234 if ( !a ) {
1235 return XML_NO_ATTRIBUTE;
1236 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001237 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 }
1239 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001240 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 const XMLAttribute* a = FindAttribute( name );
1242 if ( !a ) {
1243 return XML_NO_ATTRIBUTE;
1244 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001245 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001246 }
1247 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001248 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001249 const XMLAttribute* a = FindAttribute( name );
1250 if ( !a ) {
1251 return XML_NO_ATTRIBUTE;
1252 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001253 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001254 }
1255 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001256 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001257 const XMLAttribute* a = FindAttribute( name );
1258 if ( !a ) {
1259 return XML_NO_ATTRIBUTE;
1260 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001261 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001262 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001263
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001264
1265 /** Given an attribute name, QueryAttribute() returns
1266 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1267 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1268 doesn't exist. It is overloaded for the primitive types,
1269 and is a generally more convenient replacement of
1270 QueryIntAttribute() and related functions.
1271
1272 If successful, the result of the conversion
1273 will be written to 'value'. If not successful, nothing will
1274 be written to 'value'. This allows you to provide default
1275 value:
1276
1277 @verbatim
1278 int value = 10;
1279 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1280 @endverbatim
1281 */
1282 int QueryAttribute( const char* name, int* value ) const {
1283 return QueryIntAttribute( name, value );
1284 }
1285
1286 int QueryAttribute( const char* name, unsigned int* value ) const {
1287 return QueryUnsignedAttribute( name, value );
1288 }
1289
1290 int QueryAttribute( const char* name, bool* value ) const {
1291 return QueryBoolAttribute( name, value );
1292 }
1293
1294 int QueryAttribute( const char* name, double* value ) const {
1295 return QueryDoubleAttribute( name, value );
1296 }
1297
1298 int QueryAttribute( const char* name, float* value ) const {
1299 return QueryFloatAttribute( name, value );
1300 }
1301
1302 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001303 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001305 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 }
1307 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001308 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001310 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001311 }
1312 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001313 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001315 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 }
1317 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001320 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 }
1322 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001323 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001325 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 }
Lee Thomasonc3708cc2014-01-14 12:30:03 -08001327 /// Sets the named attribute to value.
1328 void SetAttribute( const char* name, float value ) {
1329 XMLAttribute* a = FindOrCreateAttribute( name );
1330 a->SetAttribute( value );
1331 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 /**
1334 Delete an attribute.
1335 */
1336 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001337
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001338 /// Return the first attribute in the list.
1339 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001340 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 }
1342 /// Query a specific attribute in the list.
1343 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001344
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001345 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001346 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001347 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001348
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001349 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001350 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001351
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 This is a convenient method for getting the text of simple contained text:
1353 @verbatim
1354 <foo>This is text</foo>
1355 const char* str = fooElement->GetText();
1356 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001357
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001358 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001359
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001360 Note that this function can be misleading. If the element foo was created from
1361 this XML:
1362 @verbatim
1363 <foo><b>This is text</b></foo>
1364 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001365
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001366 then the value of str would be null. The first child node isn't a text node, it is
1367 another element. From this XML:
1368 @verbatim
1369 <foo>This is <b>text</b></foo>
1370 @endverbatim
1371 GetText() will return "This is ".
1372 */
1373 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001374
Uli Kusterer85fff5e2014-01-21 01:35:30 +01001375 /** Convenience function for easy access to the text inside an element. Although easy
1376 and concise, SetText() is limited compared to creating an XMLText child
1377 and mutating it directly.
1378
1379 If the first child of 'this' is a XMLText, SetText() sets its value to
1380 the given string, otherwise it will create a first child that is an XMLText.
1381
1382 This is a convenient method for setting the text of simple contained text:
1383 @verbatim
1384 <foo>This is text</foo>
1385 fooElement->SetText( "Hullaballoo!" );
1386 <foo>Hullaballoo!</foo>
1387 @endverbatim
1388
1389 Note that this function can be misleading. If the element foo was created from
1390 this XML:
1391 @verbatim
1392 <foo><b>This is text</b></foo>
1393 @endverbatim
1394
1395 then it will not change "This is text", but rather prefix it with a text element:
1396 @verbatim
1397 <foo>Hullaballoo!<b>This is text</b></foo>
1398 @endverbatim
1399
1400 For this XML:
1401 @verbatim
1402 <foo />
1403 @endverbatim
1404 SetText() will generate
1405 @verbatim
1406 <foo>Hullaballoo!</foo>
1407 @endverbatim
1408 */
Lee Thomason5bb2d802014-01-24 10:42:57 -08001409 void SetText( const char* inText );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001410 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001411 void SetText( int value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001412 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001413 void SetText( unsigned value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001414 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001415 void SetText( bool value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001416 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001417 void SetText( double value );
Lee Thomasonc18eb232014-02-21 17:31:17 -08001418 /// Convenience method for setting text inside and element. See SetText() for important limitations.
Lee Thomason5bb2d802014-01-24 10:42:57 -08001419 void SetText( float value );
Uli Kusterer8fe342a2014-01-21 01:12:47 +01001420
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001421 /**
1422 Convenience method to query the value of a child text node. This is probably best
1423 shown by example. Given you have a document is this form:
1424 @verbatim
1425 <point>
1426 <x>1</x>
1427 <y>1.4</y>
1428 </point>
1429 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001430
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 The QueryIntText() and similar functions provide a safe and easier way to get to the
1432 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001433
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 @verbatim
1435 int x = 0;
1436 float y = 0; // types of x and y are contrived for example
1437 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1438 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1439 xElement->QueryIntText( &x );
1440 yElement->QueryFloatText( &y );
1441 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001442
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001443 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1444 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 -07001445
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001447 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001448 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001449 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001451 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001453 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001454 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001455 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001456
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001457 // internal:
1458 enum {
1459 OPEN, // <foo>
1460 CLOSED, // <foo/>
1461 CLOSING // </foo>
1462 };
1463 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001464 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001465 }
1466 char* ParseDeep( char* p, StrPair* endTag );
1467 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1468 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001469
Lee Thomason50adb4c2012-02-13 15:07:09 -08001470private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001471 XMLElement( XMLDocument* doc );
1472 virtual ~XMLElement();
1473 XMLElement( const XMLElement& ); // not supported
1474 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001475
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 XMLAttribute* FindAttribute( const char* name );
1477 XMLAttribute* FindOrCreateAttribute( const char* name );
1478 //void LinkAttribute( XMLAttribute* attrib );
1479 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001480
Lee Thomason5bb2d802014-01-24 10:42:57 -08001481 enum { BUF_SIZE = 200 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001482 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 // The attribute list is ordered; there is no 'lastAttribute'
1484 // because the list needs to be scanned for dupes before adding
1485 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001486 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001487};
1488
1489
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001490enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001491 PRESERVE_WHITESPACE,
1492 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001493};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001494
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001495
1496/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001497 It can be saved, loaded, and printed to the screen.
1498 All Nodes are connected and allocated to a Document.
1499 If the Document is deleted, all its Nodes are also deleted.
1500*/
PKEuS16ed47d2013-07-06 12:02:43 +02001501class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001502{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001504public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 /// constructor
1506 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1507 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001508
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001509 virtual XMLDocument* ToDocument() {
1510 return this;
1511 }
1512 virtual const XMLDocument* ToDocument() const {
1513 return this;
1514 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001515
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001516 /**
1517 Parse an XML file from a character string.
1518 Returns XML_NO_ERROR (0) on success, or
1519 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001520
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001521 You may optionally pass in the 'nBytes', which is
1522 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001523 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 null terminated string.
1525 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001526 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001527
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 /**
1529 Load an XML file from disk.
1530 Returns XML_NO_ERROR (0) on success, or
1531 an errorID.
1532 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001533 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001534
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001535 /**
1536 Load an XML file from disk. You are responsible
1537 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001538
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001539 Returns XML_NO_ERROR (0) on success, or
1540 an errorID.
1541 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001542 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001543
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001544 /**
1545 Save the XML file to disk.
1546 Returns XML_NO_ERROR (0) on success, or
1547 an errorID.
1548 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001549 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001550
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001551 /**
1552 Save the XML file to disk. You are responsible
1553 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001554
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001555 Returns XML_NO_ERROR (0) on success, or
1556 an errorID.
1557 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001558 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001559
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001560 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001561 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001562 }
1563 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001564 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001565 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001566
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 /**
1568 Returns true if this document has a leading Byte Order Mark of UTF8.
1569 */
1570 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001571 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001572 }
1573 /** Sets whether to write the BOM when writing the file.
1574 */
1575 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001576 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001578
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001579 /** Return the root element of DOM. Equivalent to FirstChildElement().
1580 To get the first node, use FirstChild().
1581 */
1582 XMLElement* RootElement() {
1583 return FirstChildElement();
1584 }
1585 const XMLElement* RootElement() const {
1586 return FirstChildElement();
1587 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001588
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001589 /** Print the Document. If the Printer is not provided, it will
1590 print to stdout. If you provide Printer, this can print to a file:
1591 @verbatim
1592 XMLPrinter printer( fp );
1593 doc.Print( &printer );
1594 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001595
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 Or you can use a printer to print to memory:
1597 @verbatim
1598 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001599 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 // printer.CStr() has a const char* to the XML
1601 @endverbatim
1602 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001603 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001604 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001605
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 /**
1607 Create a new Element associated with
1608 this Document. The memory for the Element
1609 is managed by the Document.
1610 */
1611 XMLElement* NewElement( const char* name );
1612 /**
1613 Create a new Comment associated with
1614 this Document. The memory for the Comment
1615 is managed by the Document.
1616 */
1617 XMLComment* NewComment( const char* comment );
1618 /**
1619 Create a new Text associated with
1620 this Document. The memory for the Text
1621 is managed by the Document.
1622 */
1623 XMLText* NewText( const char* text );
1624 /**
1625 Create a new Declaration associated with
1626 this Document. The memory for the object
1627 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001628
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001629 If the 'text' param is null, the standard
1630 declaration is used.:
1631 @verbatim
1632 <?xml version="1.0" encoding="UTF-8"?>
1633 @endverbatim
1634 */
1635 XMLDeclaration* NewDeclaration( const char* text=0 );
1636 /**
1637 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001638 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001639 is managed by the Document.
1640 */
1641 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001642
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001643 /**
1644 Delete a node associated with this document.
1645 It will be unlinked from the DOM.
1646 */
1647 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001648 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001649 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001650
Lee Thomason2fa81722012-11-09 12:37:46 -08001651 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001652
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001653 /// Return true if there was an error parsing the document.
1654 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001655 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001656 }
1657 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001658 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001659 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001660 }
1661 /// Return a possibly helpful diagnostic location or string.
1662 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001663 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001664 }
1665 /// Return a possibly helpful secondary diagnostic location or string.
1666 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001667 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001668 }
1669 /// If there is an error, print it to stdout.
1670 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001671
1672 /// Clear the document, resetting it to the initial state.
1673 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001674
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001675 // internal
1676 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001677
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001678 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1679 return 0;
1680 }
1681 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1682 return false;
1683 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001684
Lee Thomason3f57d272012-01-11 15:30:03 -08001685private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 XMLDocument( const XMLDocument& ); // not supported
1687 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001688
Lee Thomason2fa81722012-11-09 12:37:46 -08001689 bool _writeBOM;
1690 bool _processEntities;
1691 XMLError _errorID;
1692 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001693 const char* _errorStr1;
1694 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001695 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001696
Lee Thomason624d43f2012-10-12 10:58:48 -07001697 MemPoolT< sizeof(XMLElement) > _elementPool;
1698 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1699 MemPoolT< sizeof(XMLText) > _textPool;
1700 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001701};
1702
Lee Thomason7c913cd2012-01-26 18:32:34 -08001703
Lee Thomason3ffdd392012-03-28 17:27:55 -07001704/**
1705 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001706 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001707 DOM structure. It is a separate utility class.
1708
1709 Take an example:
1710 @verbatim
1711 <Document>
1712 <Element attributeA = "valueA">
1713 <Child attributeB = "value1" />
1714 <Child attributeB = "value2" />
1715 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001716 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001717 @endverbatim
1718
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001719 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001720 easy to write a *lot* of code that looks like:
1721
1722 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001723 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001724 if ( root )
1725 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001726 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001727 if ( element )
1728 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001729 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001730 if ( child )
1731 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001732 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001733 if ( child2 )
1734 {
1735 // Finally do something useful.
1736 @endverbatim
1737
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001738 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001739 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001740 and correct to use:
1741
1742 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001743 XMLHandle docHandle( &document );
1744 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001745 if ( child2 )
1746 {
1747 // do something useful
1748 @endverbatim
1749
1750 Which is MUCH more concise and useful.
1751
1752 It is also safe to copy handles - internally they are nothing more than node pointers.
1753 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001754 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001755 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001756
1757 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001758*/
PKEuS16ed47d2013-07-06 12:02:43 +02001759class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001760{
1761public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001762 /// 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 -07001763 XMLHandle( XMLNode* node ) {
1764 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
1766 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001767 XMLHandle( XMLNode& node ) {
1768 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001769 }
1770 /// Copy constructor
1771 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001772 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001773 }
1774 /// Assignment
1775 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001776 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 return *this;
1778 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001779
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 /// Get the first child of this handle.
1781 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001782 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 }
1784 /// Get the first child element of this handle.
1785 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001786 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 }
1788 /// Get the last child of this handle.
1789 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001790 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001791 }
1792 /// Get the last child element of this handle.
1793 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
1796 /// Get the previous sibling of this handle.
1797 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 }
1800 /// Get the previous sibling element of this handle.
1801 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001802 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 }
1804 /// Get the next sibling of this handle.
1805 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001806 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 }
1808 /// Get the next sibling element of this handle.
1809 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001810 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001811 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001812
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 /// Safe cast to XMLNode. This can return null.
1814 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 }
1817 /// Safe cast to XMLElement. This can return null.
1818 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001819 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001820 }
1821 /// Safe cast to XMLText. This can return null.
1822 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001823 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001824 }
1825 /// Safe cast to XMLUnknown. This can return null.
1826 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001827 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001828 }
1829 /// Safe cast to XMLDeclaration. This can return null.
1830 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001831 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001832 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001833
1834private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001835 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001836};
1837
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001838
1839/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001840 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1841 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001842*/
PKEuS16ed47d2013-07-06 12:02:43 +02001843class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001844{
1845public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001846 XMLConstHandle( const XMLNode* node ) {
1847 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001848 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001849 XMLConstHandle( const XMLNode& node ) {
1850 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001851 }
1852 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001853 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001854 }
Lee Thomason8b899812012-04-04 15:58:16 -07001855
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001856 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001857 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001858 return *this;
1859 }
Lee Thomason8b899812012-04-04 15:58:16 -07001860
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001861 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001862 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001863 }
1864 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001865 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001866 }
1867 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001868 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001869 }
1870 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001871 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001872 }
1873 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001874 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001875 }
1876 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001877 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001878 }
1879 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001880 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001881 }
1882 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001883 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 }
Lee Thomason8b899812012-04-04 15:58:16 -07001885
1886
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001887 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001888 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001889 }
1890 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001891 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001892 }
1893 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001894 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001895 }
1896 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001897 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001898 }
1899 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001900 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001901 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001902
Lee Thomason5cae8972012-01-24 18:03:07 -08001903private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001904 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001905};
Lee Thomason6f381b72012-03-02 12:59:39 -08001906
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001907
1908/**
1909 Printing functionality. The XMLPrinter gives you more
1910 options than the XMLDocument::Print() method.
1911
1912 It can:
1913 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001914 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001915 -# Print XML without a XMLDocument.
1916
1917 Print to Memory
1918
1919 @verbatim
1920 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001921 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001922 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001923 @endverbatim
1924
1925 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001926
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001927 You provide the file pointer.
1928 @verbatim
1929 XMLPrinter printer( fp );
1930 doc.Print( &printer );
1931 @endverbatim
1932
1933 Print without a XMLDocument
1934
1935 When loading, an XML parser is very useful. However, sometimes
1936 when saving, it just gets in the way. The code is often set up
1937 for streaming, and constructing the DOM is just overhead.
1938
1939 The Printer supports the streaming case. The following code
1940 prints out a trivially simple XML file without ever creating
1941 an XML document.
1942
1943 @verbatim
1944 XMLPrinter printer( fp );
1945 printer.OpenElement( "foo" );
1946 printer.PushAttribute( "foo", "bar" );
1947 printer.CloseElement();
1948 @endverbatim
1949*/
PKEuS16ed47d2013-07-06 12:02:43 +02001950class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001951{
1952public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001953 /** Construct the printer. If the FILE* is specified,
1954 this will print to the FILE. Else it will print
1955 to memory, and the result is available in CStr().
1956 If 'compact' is set to true, then output is created
1957 with only required whitespace and newlines.
1958 */
PKEuS1bfb9542013-08-04 13:51:17 +02001959 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001960 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001961
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001962 /** If streaming, write the BOM and declaration. */
1963 void PushHeader( bool writeBOM, bool writeDeclaration );
1964 /** If streaming, start writing an element.
1965 The element must be closed with CloseElement()
1966 */
Lee Thomason256adb62014-04-06 14:41:46 -07001967 void OpenElement( const char* name, bool compactMode=false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001968 /// If streaming, add an attribute to an open element.
1969 void PushAttribute( const char* name, const char* value );
1970 void PushAttribute( const char* name, int value );
1971 void PushAttribute( const char* name, unsigned value );
1972 void PushAttribute( const char* name, bool value );
1973 void PushAttribute( const char* name, double value );
1974 /// If streaming, close the Element.
Lee Thomason256adb62014-04-06 14:41:46 -07001975 virtual void CloseElement( bool compactMode=false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001976
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001977 /// Add a text node.
1978 void PushText( const char* text, bool cdata=false );
1979 /// Add a text node from an integer.
1980 void PushText( int value );
1981 /// Add a text node from an unsigned.
1982 void PushText( unsigned value );
1983 /// Add a text node from a bool.
1984 void PushText( bool value );
1985 /// Add a text node from a float.
1986 void PushText( float value );
1987 /// Add a text node from a double.
1988 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001989
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001990 /// Add a comment
1991 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001992
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001993 void PushDeclaration( const char* value );
1994 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001995
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001996 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1997 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1998 return true;
1999 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002000
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002001 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
2002 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002003
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002004 virtual bool Visit( const XMLText& text );
2005 virtual bool Visit( const XMLComment& comment );
2006 virtual bool Visit( const XMLDeclaration& declaration );
2007 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002008
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002009 /**
2010 If in print to memory mode, return a pointer to
2011 the XML file in memory.
2012 */
2013 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002014 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002015 }
2016 /**
2017 If in print to memory mode, return the size
2018 of the XML file in memory. (Note the size returned
2019 includes the terminating null.)
2020 */
2021 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07002022 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002023 }
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002024 /**
2025 If in print to memory mode, reset the buffer to the
2026 beginning.
2027 */
Lee Thomasonce0510b2013-11-26 21:29:37 -08002028 void ClearBuffer() {
2029 _buffer.Clear();
Reinhard Klambauer3bc3d4e2013-11-22 14:05:21 +01002030 _buffer.Push(0);
2031 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002032
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002033protected:
Lee Thomasone6934882014-02-22 16:27:27 -08002034 virtual bool CompactMode( const XMLElement& ) { return _compactMode; };
Uli Kusterer5d1d27e2014-02-20 11:50:22 +01002035
Lee Thomasonc18eb232014-02-21 17:31:17 -08002036 /** Prints out the space before an element. You may override to change
2037 the space and tabs used. A PrintSpace() override should call Print().
2038 */
2039 virtual void PrintSpace( int depth );
2040 void Print( const char* format, ... );
2041
2042 void SealElement();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05002043 bool _elementJustOpened;
2044 DynArray< const char*, 10 > _stack;
2045
2046private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002047 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002048
Lee Thomason624d43f2012-10-12 10:58:48 -07002049 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01002050 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07002051 int _depth;
2052 int _textDepth;
2053 bool _processEntities;
Lee Thomasonc18eb232014-02-21 17:31:17 -08002054 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002055
Lee Thomasona9cf3f92012-10-11 16:56:51 -07002056 enum {
2057 ENTITY_RANGE = 64,
2058 BUF_SIZE = 200
2059 };
Lee Thomason624d43f2012-10-12 10:58:48 -07002060 bool _entityFlag[ENTITY_RANGE];
2061 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002062
Lee Thomason624d43f2012-10-12 10:58:48 -07002063 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07002064#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07002065 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07002066#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002067};
2068
2069
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07002070} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002071
PKEuS95060352013-07-26 10:42:44 +02002072#if defined(_MSC_VER)
2073# pragma warning(pop)
2074#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002075
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002076#endif // TINYXML2_INCLUDED