blob: d4c091919f21b7bdcd0e03428b263a51cb637c62 [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
selfpoisede77e1952013-03-13 14:08:29 +0800119static const int TIXML2_MAJOR_VERSION = 1;
120static const int TIXML2_MINOR_VERSION = 0;
121static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800122
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800123namespace tinyxml2
124{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800125class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800126class XMLElement;
127class XMLAttribute;
128class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800129class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800130class XMLDeclaration;
131class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800132class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800133
U-Stream\Leeae25a442012-02-17 17:48:16 -0800134/*
135 A class that wraps strings. Normally stores the start and end
136 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800137 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800138 manage) a traditional char[]
139*/
PKEuS95060352013-07-26 10:42:44 +0200140class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800141{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800142public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 enum {
144 NEEDS_ENTITY_PROCESSING = 0x01,
145 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800146 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800147
selfpoisede77e1952013-03-13 14:08:29 +0800148 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800150 ATTRIBUTE_NAME = 0,
151 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
152 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
153 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 };
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800158
Lee Thomason120b3a62012-10-12 10:06:59 -0700159 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700161 _start = start;
162 _end = end;
163 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700165
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700169 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 }
Lee Thomason39ede242012-01-20 11:27:56 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 void SetInternedStr( const char* str ) {
173 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700174 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700176
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700177 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800178
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700179 char* ParseText( char* in, const char* endTag, int strFlags );
180 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800181
Lee Thomason39ede242012-01-20 11:27:56 -0800182private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 void Reset();
184 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800185
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700186 enum {
187 NEEDS_FLUSH = 0x100,
188 NEEDS_DELETE = 0x200
189 };
Lee Thomasone4422302012-01-20 17:59:50 -0800190
selfpoised4dd59bc2013-03-13 16:54:15 +0800191 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700192 int _flags;
193 char* _start;
194 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800195};
196
U-Lama\Lee560bd472011-12-28 19:42:49 -0800197
U-Stream\Leeae25a442012-02-17 17:48:16 -0800198/*
199 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
200 Has a small initial memory pool, so that low or no usage will not
201 cause a call to new/delete
202*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800203template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200204class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800205{
206public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700208 _mem = _pool;
209 _allocated = INIT;
210 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700212
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700214 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700215 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 EnsureCapacity( _size+1 );
221 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 EnsureCapacity( _size+count );
226 T* ret = &_mem[_size];
227 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 return ret;
229 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700234
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700236 TIXMLASSERT( _size >= count );
237 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800239
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700241 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700243
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700245 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700246 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700248
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700250 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700253
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500254 const T& PeekTop() const {
255 TIXMLASSERT( _size > 0 );
256 return _mem[ _size - 1];
257 }
258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700267 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700270
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700272 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800274
Lee Thomason2c85a712012-01-31 08:24:24 -0800275private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 int newAllocated = cap * 2;
279 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700280 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
281 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700282 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700284 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700285 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700286 }
287 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800288
Lee Thomason624d43f2012-10-12 10:58:48 -0700289 T* _mem;
290 T _pool[INIT];
291 int _allocated; // objects allocated
292 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800293};
294
Lee Thomason50adb4c2012-02-13 15:07:09 -0800295
U-Stream\Leeae25a442012-02-17 17:48:16 -0800296/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200297 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800298 and deallocation of objects.
299*/
PKEuS95060352013-07-26 10:42:44 +0200300class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800301{
302public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 MemPool() {}
304 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const = 0;
307 virtual void* Alloc() = 0;
308 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800309 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800310};
311
Lee Thomason50adb4c2012-02-13 15:07:09 -0800312
U-Stream\Leeae25a442012-02-17 17:48:16 -0800313/*
314 Template child class to create pools of the correct type.
315*/
Lee Thomasond1983222012-02-06 08:41:24 -0800316template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200317class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800318{
319public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800320 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700321 ~MemPoolT() {
322 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 for( int i=0; i<_blockPtrs.Size(); ++i ) {
324 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
326 }
Lee Thomasond1983222012-02-06 08:41:24 -0800327
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 virtual int ItemSize() const {
329 return SIZE;
330 }
331 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 }
Lee Thomasond1983222012-02-06 08:41:24 -0800334
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700336 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700337 // Need a new block.
338 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800340
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 for( int i=0; i<COUNT-1; ++i ) {
342 block->chunk[i].next = &block->chunk[i+1];
343 }
344 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700345 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700347 void* result = _root;
348 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800349
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 ++_currentAllocs;
351 if ( _currentAllocs > _maxAllocs ) {
352 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800355 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 return result;
357 }
358 virtual void Free( void* mem ) {
359 if ( !mem ) {
360 return;
361 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700364#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700366#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700367 chunk->next = _root;
368 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
370 void Trace( const char* name ) {
371 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 }
Lee Thomasond1983222012-02-06 08:41:24 -0800374
Lee Thomason5b0a6772012-11-19 13:54:42 -0800375 void SetTracked() {
376 _nUntracked--;
377 }
378
379 int Untracked() const {
380 return _nUntracked;
381 }
382
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800383 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
384 // The test file is large, 170k.
385 // Release: VS2010 gcc(no opt)
386 // 1k: 4000
387 // 2k: 4000
388 // 4k: 3900 21000
389 // 16k: 5200
390 // 32k: 4300
391 // 64k: 4000 21000
392 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 +0200393
Lee Thomasond1983222012-02-06 08:41:24 -0800394private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700396 Chunk* next;
397 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700398 };
399 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700400 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700401 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700402 DynArray< Block*, 10 > _blockPtrs;
403 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800404
Lee Thomason624d43f2012-10-12 10:58:48 -0700405 int _currentAllocs;
406 int _nAllocs;
407 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800408 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800409};
410
Lee Thomason2c85a712012-01-31 08:24:24 -0800411
Lee Thomason56bdd022012-02-09 18:16:58 -0800412
413/**
414 Implements the interface to the "Visitor pattern" (see the Accept() method.)
415 If you call the Accept() method, it requires being passed a XMLVisitor
416 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200417 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800418 are simply called with Visit().
419
420 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700421 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800422
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700423 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800424 visiting). You need to only override methods that are interesting to you.
425
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600426 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800427
428 You should never change the document from a callback.
429
430 @sa XMLNode::Accept()
431*/
PKEuS16ed47d2013-07-06 12:02:43 +0200432class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800433{
434public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700435 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800436
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700437 /// Visit a document.
438 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
439 return true;
440 }
441 /// Visit a document.
442 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
443 return true;
444 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800445
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700446 /// Visit an element.
447 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
448 return true;
449 }
450 /// Visit an element.
451 virtual bool VisitExit( const XMLElement& /*element*/ ) {
452 return true;
453 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800454
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700455 /// Visit a declaration.
456 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
457 return true;
458 }
459 /// Visit a text node.
460 virtual bool Visit( const XMLText& /*text*/ ) {
461 return true;
462 }
463 /// Visit a comment node.
464 virtual bool Visit( const XMLComment& /*comment*/ ) {
465 return true;
466 }
467 /// Visit an unknown node.
468 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
469 return true;
470 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800471};
472
473
U-Stream\Leeae25a442012-02-17 17:48:16 -0800474/*
475 Utility functionality.
476*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800477class XMLUtil
478{
Lee Thomasond1983222012-02-06 08:41:24 -0800479public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
481 // correct, but simple, and usually works.
482 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100483 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700484 ++p;
485 }
486 return p;
487 }
488 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100489 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700490 ++p;
491 }
492 return p;
493 }
494 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100495 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700496 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200497
498 inline static bool IsNameStartChar( unsigned char ch ) {
499 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
500 || ch == ':'
501 || ch == '_';
502 }
503
504 inline static bool IsNameChar( unsigned char ch ) {
505 return IsNameStartChar( ch )
506 || isdigit( ch )
507 || ch == '.'
508 || ch == '-';
509 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800510
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700511 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
512 int n = 0;
513 if ( p == q ) {
514 return true;
515 }
516 while( *p && *q && *p == *q && n<nChar ) {
517 ++p;
518 ++q;
519 ++n;
520 }
521 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
522 return true;
523 }
524 return false;
525 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200526
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 inline static int IsUTF8Continuation( const char p ) {
528 return p & 0x80;
529 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 static const char* ReadBOM( const char* p, bool* hasBOM );
532 // p is the starting location,
533 // the UTF-8 value of the entity will be placed in value, and length filled in.
534 static const char* GetCharacterRef( const char* p, char* value, int* length );
535 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700536
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 // converts primitive types to strings
538 static void ToStr( int v, char* buffer, int bufferSize );
539 static void ToStr( unsigned v, char* buffer, int bufferSize );
540 static void ToStr( bool v, char* buffer, int bufferSize );
541 static void ToStr( float v, char* buffer, int bufferSize );
542 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700543
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700544 // converts strings to primitive types
545 static bool ToInt( const char* str, int* value );
546 static bool ToUnsigned( const char* str, unsigned* value );
547 static bool ToBool( const char* str, bool* value );
548 static bool ToFloat( const char* str, float* value );
549 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800550};
551
Lee Thomason5cae8972012-01-24 18:03:07 -0800552
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800553/** XMLNode is a base class for every object that is in the
554 XML Document Object Model (DOM), except XMLAttributes.
555 Nodes have siblings, a parent, and children which can
556 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700557 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800558 be cast to its more defined type.
559
Thomas Roß08bdf502012-05-12 14:21:23 +0200560 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800561 When the XMLDocument gets deleted, all its Nodes
562 will also be deleted.
563
564 @verbatim
565 A Document can contain: Element (container or leaf)
566 Comment (leaf)
567 Unknown (leaf)
568 Declaration( leaf )
569
570 An Element can contain: Element (container or leaf)
571 Text (leaf)
572 Attributes (not on tree)
573 Comment (leaf)
574 Unknown (leaf)
575
576 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800577*/
PKEuS16ed47d2013-07-06 12:02:43 +0200578class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 friend class XMLDocument;
581 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800582public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800583
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 /// Get the XMLDocument that owns this XMLNode.
585 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700586 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 }
588 /// Get the XMLDocument that owns this XMLNode.
589 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700590 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592
Lee Thomason2fa81722012-11-09 12:37:46 -0800593 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100595 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700596 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800597 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100599 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800601 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100603 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800605 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100607 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800609 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100611 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800613 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100615 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800617
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 virtual const XMLElement* ToElement() const {
619 return 0;
620 }
621 virtual const XMLText* ToText() const {
622 return 0;
623 }
624 virtual const XMLComment* ToComment() const {
625 return 0;
626 }
627 virtual const XMLDocument* ToDocument() const {
628 return 0;
629 }
630 virtual const XMLDeclaration* ToDeclaration() const {
631 return 0;
632 }
633 virtual const XMLUnknown* ToUnknown() const {
634 return 0;
635 }
Lee Thomason751da522012-02-10 08:50:51 -0800636
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 /** The meaning of 'value' changes for the specific type.
638 @verbatim
639 Document: empty
640 Element: name of the element
641 Comment: the comment text
642 Unknown: the tag contents
643 Text: the text string
644 @endverbatim
645 */
Michael Daumling21626882013-10-22 17:03:37 +0200646 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100647
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 /** Set the Value of an XML node.
649 @sa Value()
650 */
651 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800652
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 /// Get the parent of this node on the DOM.
654 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700655 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100657
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700659 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 }
Lee Thomason751da522012-02-10 08:50:51 -0800661
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700662 /// Returns true if this node has no children.
663 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700664 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 }
Lee Thomason751da522012-02-10 08:50:51 -0800666
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 /// Get the first child node, or null if none exists.
668 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700669 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100671
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700673 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100675
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 /** Get the first child element, or optionally the first child
677 element with the specified name.
678 */
679 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700680
681 XMLElement* FirstChildElement( const char* value=0 ) {
682 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800684
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700685 /// Get the last child node, or null if none exists.
686 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700687 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700689
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 XMLNode* LastChild() {
691 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
692 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800693
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 /** Get the last child element or optionally the last child
695 element with the specified name.
696 */
697 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700698
699 XMLElement* LastChildElement( const char* value=0 ) {
700 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700702
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 /// Get the previous (left) sibling node of this node.
704 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700705 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700706 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700707
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700709 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800711
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700712 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700714
715 XMLElement* PreviousSiblingElement( const char* value=0 ) {
716 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700718
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 /// Get the next (right) sibling node of this node.
720 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700721 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700722 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700725 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700727
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700728 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700730
731 XMLElement* NextSiblingElement( const char* value=0 ) {
732 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800734
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 /**
736 Add a child node as the last (right) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200737 If the child node is already part of the document,
738 it is moved from its old location to the new location.
739 Returns the addThis argument or 0 if the node does not
740 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700741 */
742 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800743
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700744 XMLNode* LinkEndChild( XMLNode* addThis ) {
745 return InsertEndChild( addThis );
746 }
747 /**
748 Add a child node as the first (left) child.
Michael Daumlinged523282013-10-23 07:47:29 +0200749 If the child node is already part of the document,
750 it is moved from its old location to the new location.
751 Returns the addThis argument or 0 if the node does not
752 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 */
754 XMLNode* InsertFirstChild( XMLNode* addThis );
755 /**
756 Add a node after the specified child node.
Michael Daumlinged523282013-10-23 07:47:29 +0200757 If the child node is already part of the document,
758 it is moved from its old location to the new location.
759 Returns the addThis argument or 0 if the afterThis node
760 is not a child of this node, or if the node does not
761 belong to the same document.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 */
763 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700764
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700765 /**
766 Delete all the children of this node.
767 */
768 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800769
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700770 /**
771 Delete a child of this node.
772 */
773 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 /**
776 Make a copy of this node, but not its children.
777 You may pass in a Document pointer that will be
778 the owner of the new Node. If the 'document' is
779 null, then the node returned will be allocated
780 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800781
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 Note: if called on a XMLDocument, this will return null.
783 */
784 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800785
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 /**
787 Test if 2 nodes are the same, but don't test children.
788 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800789
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 Note: if called on a XMLDocument, this will return false.
791 */
792 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800793
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600794 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700795 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600796 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800797
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600798 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
799 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800801
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700802 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800803
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700804 - http://www.saxproject.org/
805 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800806
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800808
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 An example of using Accept():
810 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600811 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 tinyxmlDoc.Accept( &printer );
813 const char* xmlcstr = printer.CStr();
814 @endverbatim
815 */
816 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800817
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700818 // internal
819 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800820
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800821protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700822 XMLNode( XMLDocument* );
823 virtual ~XMLNode();
824 XMLNode( const XMLNode& ); // not supported
825 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700826
Lee Thomason624d43f2012-10-12 10:58:48 -0700827 XMLDocument* _document;
828 XMLNode* _parent;
829 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800830
Lee Thomason624d43f2012-10-12 10:58:48 -0700831 XMLNode* _firstChild;
832 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800833
Lee Thomason624d43f2012-10-12 10:58:48 -0700834 XMLNode* _prev;
835 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800836
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800837private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700838 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700839 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800840};
841
842
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800843/** XML text.
844
845 Note that a text node can have child element nodes, for example:
846 @verbatim
847 <root>This is <b>bold</b></root>
848 @endverbatim
849
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700850 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800851 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 -0700852 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600853 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800854*/
PKEuS16ed47d2013-07-06 12:02:43 +0200855class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800856{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 friend class XMLBase;
858 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800859public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700860 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800861
Lee Thomason624d43f2012-10-12 10:58:48 -0700862 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 return this;
864 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700865 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700866 return this;
867 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800868
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700869 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700870 void SetCData( bool isCData ) {
871 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700872 }
873 /// Returns true if this is a CDATA text element.
874 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700875 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700876 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800877
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700878 char* ParseDeep( char*, StrPair* endTag );
879 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
880 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800881
Lee Thomason5492a1c2012-01-23 15:32:10 -0800882protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700883 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700884 virtual ~XMLText() {}
885 XMLText( const XMLText& ); // not supported
886 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800887
888private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700889 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800890};
891
892
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800893/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200894class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800895{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700896 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800897public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700898 virtual XMLComment* ToComment() {
899 return this;
900 }
901 virtual const XMLComment* ToComment() const {
902 return this;
903 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800904
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700905 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800906
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700907 char* ParseDeep( char*, StrPair* endTag );
908 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
909 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800910
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800911protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700912 XMLComment( XMLDocument* doc );
913 virtual ~XMLComment();
914 XMLComment( const XMLComment& ); // not supported
915 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800916
Lee Thomason3f57d272012-01-11 15:30:03 -0800917private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800918};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800919
920
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800921/** In correct XML the declaration is the first entry in the file.
922 @verbatim
923 <?xml version="1.0" standalone="yes"?>
924 @endverbatim
925
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600926 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800927 however.
928
929 The text of the declaration isn't interpreted. It is parsed
930 and written as a string.
931*/
PKEuS16ed47d2013-07-06 12:02:43 +0200932class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800933{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800935public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 virtual XMLDeclaration* ToDeclaration() {
937 return this;
938 }
939 virtual const XMLDeclaration* ToDeclaration() const {
940 return this;
941 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800942
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700943 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800944
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700945 char* ParseDeep( char*, StrPair* endTag );
946 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
947 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800948
949protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 XMLDeclaration( XMLDocument* doc );
951 virtual ~XMLDeclaration();
952 XMLDeclaration( const XMLDeclaration& ); // not supported
953 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800954};
955
956
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600957/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800958 unknown. It is a tag of text, but should not be modified.
959 It will be written back to the XML, unchanged, when the file
960 is saved.
961
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600962 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800963*/
PKEuS16ed47d2013-07-06 12:02:43 +0200964class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800965{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800967public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700968 virtual XMLUnknown* ToUnknown() {
969 return this;
970 }
971 virtual const XMLUnknown* ToUnknown() const {
972 return this;
973 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800974
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700975 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800976
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 char* ParseDeep( char*, StrPair* endTag );
978 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
979 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800980
981protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700982 XMLUnknown( XMLDocument* doc );
983 virtual ~XMLUnknown();
984 XMLUnknown( const XMLUnknown& ); // not supported
985 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800986};
987
988
Lee Thomason2fa81722012-11-09 12:37:46 -0800989enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700990 XML_NO_ERROR = 0,
991 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800992
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700993 XML_NO_ATTRIBUTE,
994 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800995
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700996 XML_ERROR_FILE_NOT_FOUND,
997 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
998 XML_ERROR_FILE_READ_ERROR,
999 XML_ERROR_ELEMENT_MISMATCH,
1000 XML_ERROR_PARSING_ELEMENT,
1001 XML_ERROR_PARSING_ATTRIBUTE,
1002 XML_ERROR_IDENTIFYING_TAG,
1003 XML_ERROR_PARSING_TEXT,
1004 XML_ERROR_PARSING_CDATA,
1005 XML_ERROR_PARSING_COMMENT,
1006 XML_ERROR_PARSING_DECLARATION,
1007 XML_ERROR_PARSING_UNKNOWN,
1008 XML_ERROR_EMPTY_DOCUMENT,
1009 XML_ERROR_MISMATCHED_ELEMENT,
1010 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -07001011
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001012 XML_CAN_NOT_CONVERT_TEXT,
1013 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001014};
1015
1016
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001017/** An attribute is a name-value pair. Elements have an arbitrary
1018 number of attributes, each with a unique name.
1019
1020 @note The attributes are not XMLNodes. You may only query the
1021 Next() attribute in a list.
1022*/
PKEuS16ed47d2013-07-06 12:02:43 +02001023class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001024{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001026public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001027 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001028 const char* Name() const;
1029
Lee Thomason2fa81722012-11-09 12:37:46 -08001030 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001031 const char* Value() const;
1032
Lee Thomason2fa81722012-11-09 12:37:46 -08001033 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001034 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001035 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001036 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001037
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001038 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001040 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001041 */
1042 int IntValue() const {
1043 int i=0;
1044 QueryIntValue( &i );
1045 return i;
1046 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001047 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001048 unsigned UnsignedValue() const {
1049 unsigned i=0;
1050 QueryUnsignedValue( &i );
1051 return i;
1052 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001053 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001054 bool BoolValue() const {
1055 bool b=false;
1056 QueryBoolValue( &b );
1057 return b;
1058 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001059 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001060 double DoubleValue() const {
1061 double d=0;
1062 QueryDoubleValue( &d );
1063 return d;
1064 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001065 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001066 float FloatValue() const {
1067 float f=0;
1068 QueryFloatValue( &f );
1069 return f;
1070 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001071
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001072 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001073 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001074 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1075 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001076 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001077 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001078 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001079 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001080 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001081 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001082 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001083 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001084 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001085
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001086 /// Set the attribute to a string value.
1087 void SetAttribute( const char* value );
1088 /// Set the attribute to value.
1089 void SetAttribute( int value );
1090 /// Set the attribute to value.
1091 void SetAttribute( unsigned value );
1092 /// Set the attribute to value.
1093 void SetAttribute( bool value );
1094 /// Set the attribute to value.
1095 void SetAttribute( double value );
1096 /// Set the attribute to value.
1097 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001098
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001099private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001100 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001101
Thomas Roß61892312013-05-12 14:07:38 +02001102 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001103 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001104
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001105 XMLAttribute( const XMLAttribute& ); // not supported
1106 void operator=( const XMLAttribute& ); // not supported
1107 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001108
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001109 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001110
Lee Thomason624d43f2012-10-12 10:58:48 -07001111 mutable StrPair _name;
1112 mutable StrPair _value;
1113 XMLAttribute* _next;
1114 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001115};
1116
1117
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001118/** The element is a container class. It has a value, the element name,
1119 and can contain other elements, text, comments, and unknowns.
1120 Elements also contain an arbitrary number of attributes.
1121*/
PKEuS16ed47d2013-07-06 12:02:43 +02001122class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001123{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001124 friend class XMLBase;
1125 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001127 /// Get the name of an element (which is the Value() of the node.)
1128 const char* Name() const {
1129 return Value();
1130 }
1131 /// Set the name of the element.
1132 void SetName( const char* str, bool staticMem=false ) {
1133 SetValue( str, staticMem );
1134 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001135
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001136 virtual XMLElement* ToElement() {
1137 return this;
1138 }
1139 virtual const XMLElement* ToElement() const {
1140 return this;
1141 }
1142 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001143
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001144 /** Given an attribute name, Attribute() returns the value
1145 for the attribute of that name, or null if none
1146 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001147
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001148 @verbatim
1149 const char* value = ele->Attribute( "foo" );
1150 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001151
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001152 The 'value' parameter is normally null. However, if specified,
1153 the attribute will only be returned if the 'name' and 'value'
1154 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001155
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001156 @verbatim
1157 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1158 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001159
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001160 rather than:
1161 @verbatim
1162 if ( ele->Attribute( "foo" ) ) {
1163 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1164 }
1165 @endverbatim
1166 */
1167 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001168
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001169 /** Given an attribute name, IntAttribute() returns the value
1170 of the attribute interpreted as an integer. 0 will be
1171 returned if there is an error. For a method with error
1172 checking, see QueryIntAttribute()
1173 */
1174 int IntAttribute( const char* name ) const {
1175 int i=0;
1176 QueryIntAttribute( name, &i );
1177 return i;
1178 }
1179 /// See IntAttribute()
1180 unsigned UnsignedAttribute( const char* name ) const {
1181 unsigned i=0;
1182 QueryUnsignedAttribute( name, &i );
1183 return i;
1184 }
1185 /// See IntAttribute()
1186 bool BoolAttribute( const char* name ) const {
1187 bool b=false;
1188 QueryBoolAttribute( name, &b );
1189 return b;
1190 }
1191 /// See IntAttribute()
1192 double DoubleAttribute( const char* name ) const {
1193 double d=0;
1194 QueryDoubleAttribute( name, &d );
1195 return d;
1196 }
1197 /// See IntAttribute()
1198 float FloatAttribute( const char* name ) const {
1199 float f=0;
1200 QueryFloatAttribute( name, &f );
1201 return f;
1202 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001203
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 /** Given an attribute name, QueryIntAttribute() returns
1205 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1206 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1207 doesn't exist. If successful, the result of the conversion
1208 will be written to 'value'. If not successful, nothing will
1209 be written to 'value'. This allows you to provide default
1210 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001211
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001212 @verbatim
1213 int value = 10;
1214 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1215 @endverbatim
1216 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001217 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 const XMLAttribute* a = FindAttribute( name );
1219 if ( !a ) {
1220 return XML_NO_ATTRIBUTE;
1221 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001222 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 }
1224 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001225 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001226 const XMLAttribute* a = FindAttribute( name );
1227 if ( !a ) {
1228 return XML_NO_ATTRIBUTE;
1229 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001230 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001231 }
1232 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001233 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001234 const XMLAttribute* a = FindAttribute( name );
1235 if ( !a ) {
1236 return XML_NO_ATTRIBUTE;
1237 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001238 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001239 }
1240 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001241 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001242 const XMLAttribute* a = FindAttribute( name );
1243 if ( !a ) {
1244 return XML_NO_ATTRIBUTE;
1245 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001246 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001247 }
1248 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001249 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001250 const XMLAttribute* a = FindAttribute( name );
1251 if ( !a ) {
1252 return XML_NO_ATTRIBUTE;
1253 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001254 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001255 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001256
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001257
1258 /** Given an attribute name, QueryAttribute() returns
1259 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1260 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1261 doesn't exist. It is overloaded for the primitive types,
1262 and is a generally more convenient replacement of
1263 QueryIntAttribute() and related functions.
1264
1265 If successful, the result of the conversion
1266 will be written to 'value'. If not successful, nothing will
1267 be written to 'value'. This allows you to provide default
1268 value:
1269
1270 @verbatim
1271 int value = 10;
1272 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1273 @endverbatim
1274 */
1275 int QueryAttribute( const char* name, int* value ) const {
1276 return QueryIntAttribute( name, value );
1277 }
1278
1279 int QueryAttribute( const char* name, unsigned int* value ) const {
1280 return QueryUnsignedAttribute( name, value );
1281 }
1282
1283 int QueryAttribute( const char* name, bool* value ) const {
1284 return QueryBoolAttribute( name, value );
1285 }
1286
1287 int QueryAttribute( const char* name, double* value ) const {
1288 return QueryDoubleAttribute( name, value );
1289 }
1290
1291 int QueryAttribute( const char* name, float* value ) const {
1292 return QueryFloatAttribute( name, value );
1293 }
1294
1295 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001296 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001297 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001298 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 }
1300 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001301 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001302 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001303 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 }
1305 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001306 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001308 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 }
1310 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001311 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001313 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 }
1315 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001316 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001318 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001319 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001320
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 /**
1322 Delete an attribute.
1323 */
1324 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001325
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 /// Return the first attribute in the list.
1327 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001328 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 }
1330 /// Query a specific attribute in the list.
1331 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001334 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001336
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001337 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001338 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001339
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001340 This is a convenient method for getting the text of simple contained text:
1341 @verbatim
1342 <foo>This is text</foo>
1343 const char* str = fooElement->GetText();
1344 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001345
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001346 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001347
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001348 Note that this function can be misleading. If the element foo was created from
1349 this XML:
1350 @verbatim
1351 <foo><b>This is text</b></foo>
1352 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001353
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001354 then the value of str would be null. The first child node isn't a text node, it is
1355 another element. From this XML:
1356 @verbatim
1357 <foo>This is <b>text</b></foo>
1358 @endverbatim
1359 GetText() will return "This is ".
1360 */
1361 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 /**
1364 Convenience method to query the value of a child text node. This is probably best
1365 shown by example. Given you have a document is this form:
1366 @verbatim
1367 <point>
1368 <x>1</x>
1369 <y>1.4</y>
1370 </point>
1371 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001372
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 The QueryIntText() and similar functions provide a safe and easier way to get to the
1374 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001375
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001376 @verbatim
1377 int x = 0;
1378 float y = 0; // types of x and y are contrived for example
1379 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1380 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1381 xElement->QueryIntText( &x );
1382 yElement->QueryFloatText( &y );
1383 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001384
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001385 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1386 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 -07001387
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001388 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001389 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001390 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001391 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001392 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001393 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001394 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001395 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001397 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001398
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001399 // internal:
1400 enum {
1401 OPEN, // <foo>
1402 CLOSED, // <foo/>
1403 CLOSING // </foo>
1404 };
1405 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001406 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 }
1408 char* ParseDeep( char* p, StrPair* endTag );
1409 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1410 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001411
Lee Thomason50adb4c2012-02-13 15:07:09 -08001412private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 XMLElement( XMLDocument* doc );
1414 virtual ~XMLElement();
1415 XMLElement( const XMLElement& ); // not supported
1416 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001417
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001418 XMLAttribute* FindAttribute( const char* name );
1419 XMLAttribute* FindOrCreateAttribute( const char* name );
1420 //void LinkAttribute( XMLAttribute* attrib );
1421 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001422
Lee Thomason624d43f2012-10-12 10:58:48 -07001423 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001424 // The attribute list is ordered; there is no 'lastAttribute'
1425 // because the list needs to be scanned for dupes before adding
1426 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001427 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001428};
1429
1430
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001431enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 PRESERVE_WHITESPACE,
1433 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001434};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001435
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001436
1437/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001438 It can be saved, loaded, and printed to the screen.
1439 All Nodes are connected and allocated to a Document.
1440 If the Document is deleted, all its Nodes are also deleted.
1441*/
PKEuS16ed47d2013-07-06 12:02:43 +02001442class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001443{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001445public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001446 /// constructor
1447 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1448 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001449
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 virtual XMLDocument* ToDocument() {
1451 return this;
1452 }
1453 virtual const XMLDocument* ToDocument() const {
1454 return this;
1455 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001456
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001457 /**
1458 Parse an XML file from a character string.
1459 Returns XML_NO_ERROR (0) on success, or
1460 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001461
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001462 You may optionally pass in the 'nBytes', which is
1463 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001464 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001465 null terminated string.
1466 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001467 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001468
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001469 /**
1470 Load an XML file from disk.
1471 Returns XML_NO_ERROR (0) on success, or
1472 an errorID.
1473 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001474 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001475
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 /**
1477 Load an XML file from disk. You are responsible
1478 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001479
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001480 Returns XML_NO_ERROR (0) on success, or
1481 an errorID.
1482 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001483 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001484
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001485 /**
1486 Save the XML file to disk.
1487 Returns XML_NO_ERROR (0) on success, or
1488 an errorID.
1489 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001490 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001491
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001492 /**
1493 Save the XML file to disk. You are responsible
1494 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001495
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 Returns XML_NO_ERROR (0) on success, or
1497 an errorID.
1498 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001499 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001500
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001501 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001502 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 }
1504 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001505 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001506 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 /**
1509 Returns true if this document has a leading Byte Order Mark of UTF8.
1510 */
1511 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001512 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 }
1514 /** Sets whether to write the BOM when writing the file.
1515 */
1516 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001517 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001518 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 /** Return the root element of DOM. Equivalent to FirstChildElement().
1521 To get the first node, use FirstChild().
1522 */
1523 XMLElement* RootElement() {
1524 return FirstChildElement();
1525 }
1526 const XMLElement* RootElement() const {
1527 return FirstChildElement();
1528 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001529
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 /** Print the Document. If the Printer is not provided, it will
1531 print to stdout. If you provide Printer, this can print to a file:
1532 @verbatim
1533 XMLPrinter printer( fp );
1534 doc.Print( &printer );
1535 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001536
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001537 Or you can use a printer to print to memory:
1538 @verbatim
1539 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001540 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001541 // printer.CStr() has a const char* to the XML
1542 @endverbatim
1543 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001544 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001545 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001546
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001547 /**
1548 Create a new Element associated with
1549 this Document. The memory for the Element
1550 is managed by the Document.
1551 */
1552 XMLElement* NewElement( const char* name );
1553 /**
1554 Create a new Comment associated with
1555 this Document. The memory for the Comment
1556 is managed by the Document.
1557 */
1558 XMLComment* NewComment( const char* comment );
1559 /**
1560 Create a new Text associated with
1561 this Document. The memory for the Text
1562 is managed by the Document.
1563 */
1564 XMLText* NewText( const char* text );
1565 /**
1566 Create a new Declaration associated with
1567 this Document. The memory for the object
1568 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001569
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001570 If the 'text' param is null, the standard
1571 declaration is used.:
1572 @verbatim
1573 <?xml version="1.0" encoding="UTF-8"?>
1574 @endverbatim
1575 */
1576 XMLDeclaration* NewDeclaration( const char* text=0 );
1577 /**
1578 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001579 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 is managed by the Document.
1581 */
1582 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001583
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 /**
1585 Delete a node associated with this document.
1586 It will be unlinked from the DOM.
1587 */
1588 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001589 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001590 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001591
Lee Thomason2fa81722012-11-09 12:37:46 -08001592 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001593
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001594 /// Return true if there was an error parsing the document.
1595 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001596 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001597 }
1598 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001599 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001600 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001601 }
1602 /// Return a possibly helpful diagnostic location or string.
1603 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001604 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001605 }
1606 /// Return a possibly helpful secondary diagnostic location or string.
1607 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001608 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001609 }
1610 /// If there is an error, print it to stdout.
1611 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001612
1613 /// Clear the document, resetting it to the initial state.
1614 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001615
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001616 // internal
1617 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001618
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001619 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1620 return 0;
1621 }
1622 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1623 return false;
1624 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001625
Lee Thomason3f57d272012-01-11 15:30:03 -08001626private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001627 XMLDocument( const XMLDocument& ); // not supported
1628 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001629
Lee Thomason2fa81722012-11-09 12:37:46 -08001630 bool _writeBOM;
1631 bool _processEntities;
1632 XMLError _errorID;
1633 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001634 const char* _errorStr1;
1635 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001636 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001637
Lee Thomason624d43f2012-10-12 10:58:48 -07001638 MemPoolT< sizeof(XMLElement) > _elementPool;
1639 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1640 MemPoolT< sizeof(XMLText) > _textPool;
1641 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001642};
1643
Lee Thomason7c913cd2012-01-26 18:32:34 -08001644
Lee Thomason3ffdd392012-03-28 17:27:55 -07001645/**
1646 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001647 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001648 DOM structure. It is a separate utility class.
1649
1650 Take an example:
1651 @verbatim
1652 <Document>
1653 <Element attributeA = "valueA">
1654 <Child attributeB = "value1" />
1655 <Child attributeB = "value2" />
1656 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001657 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001658 @endverbatim
1659
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001660 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001661 easy to write a *lot* of code that looks like:
1662
1663 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001664 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001665 if ( root )
1666 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001667 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001668 if ( element )
1669 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001670 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001671 if ( child )
1672 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001673 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001674 if ( child2 )
1675 {
1676 // Finally do something useful.
1677 @endverbatim
1678
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001679 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001680 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001681 and correct to use:
1682
1683 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001684 XMLHandle docHandle( &document );
1685 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001686 if ( child2 )
1687 {
1688 // do something useful
1689 @endverbatim
1690
1691 Which is MUCH more concise and useful.
1692
1693 It is also safe to copy handles - internally they are nothing more than node pointers.
1694 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001695 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001696 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001697
1698 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001699*/
PKEuS16ed47d2013-07-06 12:02:43 +02001700class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001701{
1702public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001703 /// 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 -07001704 XMLHandle( XMLNode* node ) {
1705 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 }
1707 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001708 XMLHandle( XMLNode& node ) {
1709 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001710 }
1711 /// Copy constructor
1712 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001713 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001714 }
1715 /// Assignment
1716 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001717 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001718 return *this;
1719 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001720
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001721 /// Get the first child of this handle.
1722 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001723 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 }
1725 /// Get the first child element of this handle.
1726 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001727 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 }
1729 /// Get the last child of this handle.
1730 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001731 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 }
1733 /// Get the last child element of this handle.
1734 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001735 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 }
1737 /// Get the previous sibling of this handle.
1738 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001739 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001740 }
1741 /// Get the previous sibling element of this handle.
1742 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001743 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
1745 /// Get the next sibling of this handle.
1746 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
1749 /// Get the next sibling element of this handle.
1750 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001753
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001754 /// Safe cast to XMLNode. This can return null.
1755 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001756 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001757 }
1758 /// Safe cast to XMLElement. This can return null.
1759 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001760 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001761 }
1762 /// Safe cast to XMLText. This can return null.
1763 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001764 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001765 }
1766 /// Safe cast to XMLUnknown. This can return null.
1767 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001768 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001769 }
1770 /// Safe cast to XMLDeclaration. This can return null.
1771 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001772 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001773 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001774
1775private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001776 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001777};
1778
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001779
1780/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001781 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1782 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001783*/
PKEuS16ed47d2013-07-06 12:02:43 +02001784class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001785{
1786public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001787 XMLConstHandle( const XMLNode* node ) {
1788 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001790 XMLConstHandle( const XMLNode& node ) {
1791 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 }
1793 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
Lee Thomason8b899812012-04-04 15:58:16 -07001796
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001797 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 return *this;
1800 }
Lee Thomason8b899812012-04-04 15:58:16 -07001801
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001803 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001804 }
1805 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001806 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 }
1808 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001809 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001810 }
1811 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001812 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 }
1814 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 }
1817 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001818 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 }
1820 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001821 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001822 }
1823 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001824 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001825 }
Lee Thomason8b899812012-04-04 15:58:16 -07001826
1827
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001828 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001829 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001830 }
1831 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001832 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001833 }
1834 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001835 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001836 }
1837 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001838 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001839 }
1840 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001841 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001842 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001843
Lee Thomason5cae8972012-01-24 18:03:07 -08001844private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001845 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001846};
Lee Thomason6f381b72012-03-02 12:59:39 -08001847
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001848
1849/**
1850 Printing functionality. The XMLPrinter gives you more
1851 options than the XMLDocument::Print() method.
1852
1853 It can:
1854 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001855 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001856 -# Print XML without a XMLDocument.
1857
1858 Print to Memory
1859
1860 @verbatim
1861 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001862 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001863 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001864 @endverbatim
1865
1866 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001867
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001868 You provide the file pointer.
1869 @verbatim
1870 XMLPrinter printer( fp );
1871 doc.Print( &printer );
1872 @endverbatim
1873
1874 Print without a XMLDocument
1875
1876 When loading, an XML parser is very useful. However, sometimes
1877 when saving, it just gets in the way. The code is often set up
1878 for streaming, and constructing the DOM is just overhead.
1879
1880 The Printer supports the streaming case. The following code
1881 prints out a trivially simple XML file without ever creating
1882 an XML document.
1883
1884 @verbatim
1885 XMLPrinter printer( fp );
1886 printer.OpenElement( "foo" );
1887 printer.PushAttribute( "foo", "bar" );
1888 printer.CloseElement();
1889 @endverbatim
1890*/
PKEuS16ed47d2013-07-06 12:02:43 +02001891class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001892{
1893public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001894 /** Construct the printer. If the FILE* is specified,
1895 this will print to the FILE. Else it will print
1896 to memory, and the result is available in CStr().
1897 If 'compact' is set to true, then output is created
1898 with only required whitespace and newlines.
1899 */
PKEuS1bfb9542013-08-04 13:51:17 +02001900 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001901 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001902
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001903 /** If streaming, write the BOM and declaration. */
1904 void PushHeader( bool writeBOM, bool writeDeclaration );
1905 /** If streaming, start writing an element.
1906 The element must be closed with CloseElement()
1907 */
1908 void OpenElement( const char* name );
1909 /// If streaming, add an attribute to an open element.
1910 void PushAttribute( const char* name, const char* value );
1911 void PushAttribute( const char* name, int value );
1912 void PushAttribute( const char* name, unsigned value );
1913 void PushAttribute( const char* name, bool value );
1914 void PushAttribute( const char* name, double value );
1915 /// If streaming, close the Element.
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001916 virtual void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001917
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 /// Add a text node.
1919 void PushText( const char* text, bool cdata=false );
1920 /// Add a text node from an integer.
1921 void PushText( int value );
1922 /// Add a text node from an unsigned.
1923 void PushText( unsigned value );
1924 /// Add a text node from a bool.
1925 void PushText( bool value );
1926 /// Add a text node from a float.
1927 void PushText( float value );
1928 /// Add a text node from a double.
1929 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001930
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001931 /// Add a comment
1932 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001933
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001934 void PushDeclaration( const char* value );
1935 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001936
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1938 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1939 return true;
1940 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001941
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001942 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1943 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001944
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001945 virtual bool Visit( const XMLText& text );
1946 virtual bool Visit( const XMLComment& comment );
1947 virtual bool Visit( const XMLDeclaration& declaration );
1948 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001949
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 /**
1951 If in print to memory mode, return a pointer to
1952 the XML file in memory.
1953 */
1954 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001955 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001956 }
1957 /**
1958 If in print to memory mode, return the size
1959 of the XML file in memory. (Note the size returned
1960 includes the terminating null.)
1961 */
1962 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001963 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001964 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001965
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001966protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001967 void SealElement();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001968 bool _elementJustOpened;
1969 DynArray< const char*, 10 > _stack;
1970
1971private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001972 void PrintSpace( int depth );
1973 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1974 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001975
Lee Thomason624d43f2012-10-12 10:58:48 -07001976 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001977 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001978 int _depth;
1979 int _textDepth;
1980 bool _processEntities;
1981 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001982
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001983 enum {
1984 ENTITY_RANGE = 64,
1985 BUF_SIZE = 200
1986 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001987 bool _entityFlag[ENTITY_RANGE];
1988 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001989
Lee Thomason624d43f2012-10-12 10:58:48 -07001990 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001991#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001992 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001993#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001994};
1995
1996
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001997} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001998
PKEuS95060352013-07-26 10:42:44 +02001999#if defined(_MSC_VER)
2000# pragma warning(pop)
2001#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002002
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002003#endif // TINYXML2_INCLUDED