blob: a4aa6d3e74f4c80e877811eb965abd10a51549da [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;
129class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800130class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800131class XMLDeclaration;
132class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800133
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800134class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800135
U-Stream\Leeae25a442012-02-17 17:48:16 -0800136/*
137 A class that wraps strings. Normally stores the start and end
138 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800139 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800140 manage) a traditional char[]
141*/
PKEuS95060352013-07-26 10:42:44 +0200142class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800143{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800144public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700145 enum {
146 NEEDS_ENTITY_PROCESSING = 0x01,
147 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800148 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800149
selfpoisede77e1952013-03-13 14:08:29 +0800150 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700151 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800152 ATTRIBUTE_NAME = 0,
153 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
154 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
155 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 };
Lee Thomason39ede242012-01-20 11:27:56 -0800157
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800160
Lee Thomason120b3a62012-10-12 10:06:59 -0700161 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700162 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700163 _start = start;
164 _end = end;
165 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700171 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 }
Lee Thomason39ede242012-01-20 11:27:56 -0800173
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700174 void SetInternedStr( const char* str ) {
175 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700177 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700178
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700179 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800180
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700181 char* ParseText( char* in, const char* endTag, int strFlags );
182 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800183
Lee Thomason39ede242012-01-20 11:27:56 -0800184private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700185 void Reset();
186 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800187
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700188 enum {
189 NEEDS_FLUSH = 0x100,
190 NEEDS_DELETE = 0x200
191 };
Lee Thomasone4422302012-01-20 17:59:50 -0800192
selfpoised4dd59bc2013-03-13 16:54:15 +0800193 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700194 int _flags;
195 char* _start;
196 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800197};
198
U-Lama\Lee560bd472011-12-28 19:42:49 -0800199
U-Stream\Leeae25a442012-02-17 17:48:16 -0800200/*
201 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
202 Has a small initial memory pool, so that low or no usage will not
203 cause a call to new/delete
204*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800205template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200206class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800207{
208public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700209 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700210 _mem = _pool;
211 _allocated = INIT;
212 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700216 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700217 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700218 }
219 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700220
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700221 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700222 EnsureCapacity( _size+1 );
223 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800225
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700226 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700227 EnsureCapacity( _size+count );
228 T* ret = &_mem[_size];
229 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700230 return ret;
231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700234 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700236
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700237 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700238 TIXMLASSERT( _size >= count );
239 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700243 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700247 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700248 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700250
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700251 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700252 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700253 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700254 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700255
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700256 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700257 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700258 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700259
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700260 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700261 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700263
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700264 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700265 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700266 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700267
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700269 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800271
Lee Thomason2c85a712012-01-31 08:24:24 -0800272private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700274 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 int newAllocated = cap * 2;
276 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
278 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700279 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700280 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700281 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700282 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
284 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800285
Lee Thomason624d43f2012-10-12 10:58:48 -0700286 T* _mem;
287 T _pool[INIT];
288 int _allocated; // objects allocated
289 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800290};
291
Lee Thomason50adb4c2012-02-13 15:07:09 -0800292
U-Stream\Leeae25a442012-02-17 17:48:16 -0800293/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200294 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800295 and deallocation of objects.
296*/
PKEuS95060352013-07-26 10:42:44 +0200297class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800298{
299public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700300 MemPool() {}
301 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800302
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 virtual int ItemSize() const = 0;
304 virtual void* Alloc() = 0;
305 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800306 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800307};
308
Lee Thomason50adb4c2012-02-13 15:07:09 -0800309
U-Stream\Leeae25a442012-02-17 17:48:16 -0800310/*
311 Template child class to create pools of the correct type.
312*/
Lee Thomasond1983222012-02-06 08:41:24 -0800313template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200314class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800315{
316public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800317 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700318 ~MemPoolT() {
319 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700320 for( int i=0; i<_blockPtrs.Size(); ++i ) {
321 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700322 }
323 }
Lee Thomasond1983222012-02-06 08:41:24 -0800324
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 virtual int ItemSize() const {
326 return SIZE;
327 }
328 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700329 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700330 }
Lee Thomasond1983222012-02-06 08:41:24 -0800331
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700332 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700333 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700334 // Need a new block.
335 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700336 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800337
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700338 for( int i=0; i<COUNT-1; ++i ) {
339 block->chunk[i].next = &block->chunk[i+1];
340 }
341 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700342 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700343 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700344 void* result = _root;
345 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800346
Lee Thomason624d43f2012-10-12 10:58:48 -0700347 ++_currentAllocs;
348 if ( _currentAllocs > _maxAllocs ) {
349 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700350 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700351 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800352 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 return result;
354 }
355 virtual void Free( void* mem ) {
356 if ( !mem ) {
357 return;
358 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700359 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700360 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700361#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700362 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700363#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 chunk->next = _root;
365 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700366 }
367 void Trace( const char* name ) {
368 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700369 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700370 }
Lee Thomasond1983222012-02-06 08:41:24 -0800371
Lee Thomason5b0a6772012-11-19 13:54:42 -0800372 void SetTracked() {
373 _nUntracked--;
374 }
375
376 int Untracked() const {
377 return _nUntracked;
378 }
379
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800380 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
381 // The test file is large, 170k.
382 // Release: VS2010 gcc(no opt)
383 // 1k: 4000
384 // 2k: 4000
385 // 4k: 3900 21000
386 // 16k: 5200
387 // 32k: 4300
388 // 64k: 4000 21000
389 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 +0200390
Lee Thomasond1983222012-02-06 08:41:24 -0800391private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700392 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700393 Chunk* next;
394 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 };
396 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700397 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700398 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700399 DynArray< Block*, 10 > _blockPtrs;
400 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800401
Lee Thomason624d43f2012-10-12 10:58:48 -0700402 int _currentAllocs;
403 int _nAllocs;
404 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800405 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800406};
407
Lee Thomason2c85a712012-01-31 08:24:24 -0800408
Lee Thomason56bdd022012-02-09 18:16:58 -0800409
410/**
411 Implements the interface to the "Visitor pattern" (see the Accept() method.)
412 If you call the Accept() method, it requires being passed a XMLVisitor
413 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200414 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800415 are simply called with Visit().
416
417 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700418 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800419
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700420 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800421 visiting). You need to only override methods that are interesting to you.
422
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600423 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800424
425 You should never change the document from a callback.
426
427 @sa XMLNode::Accept()
428*/
PKEuS16ed47d2013-07-06 12:02:43 +0200429class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800430{
431public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700432 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800433
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700434 /// Visit a document.
435 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
436 return true;
437 }
438 /// Visit a document.
439 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
440 return true;
441 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800442
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700443 /// Visit an element.
444 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
445 return true;
446 }
447 /// Visit an element.
448 virtual bool VisitExit( const XMLElement& /*element*/ ) {
449 return true;
450 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800451
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700452 /// Visit a declaration.
453 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
454 return true;
455 }
456 /// Visit a text node.
457 virtual bool Visit( const XMLText& /*text*/ ) {
458 return true;
459 }
460 /// Visit a comment node.
461 virtual bool Visit( const XMLComment& /*comment*/ ) {
462 return true;
463 }
464 /// Visit an unknown node.
465 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
466 return true;
467 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800468};
469
470
U-Stream\Leeae25a442012-02-17 17:48:16 -0800471/*
472 Utility functionality.
473*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800474class XMLUtil
475{
Lee Thomasond1983222012-02-06 08:41:24 -0800476public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700477 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
478 // correct, but simple, and usually works.
479 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100480 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700481 ++p;
482 }
483 return p;
484 }
485 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100486 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700487 ++p;
488 }
489 return p;
490 }
491 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100492 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700493 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200494
495 inline static bool IsNameStartChar( unsigned char ch ) {
496 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
497 || ch == ':'
498 || ch == '_';
499 }
500
501 inline static bool IsNameChar( unsigned char ch ) {
502 return IsNameStartChar( ch )
503 || isdigit( ch )
504 || ch == '.'
505 || ch == '-';
506 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800507
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700508 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
509 int n = 0;
510 if ( p == q ) {
511 return true;
512 }
513 while( *p && *q && *p == *q && n<nChar ) {
514 ++p;
515 ++q;
516 ++n;
517 }
518 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
519 return true;
520 }
521 return false;
522 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200523
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700524 inline static int IsUTF8Continuation( const char p ) {
525 return p & 0x80;
526 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800527
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700528 static const char* ReadBOM( const char* p, bool* hasBOM );
529 // p is the starting location,
530 // the UTF-8 value of the entity will be placed in value, and length filled in.
531 static const char* GetCharacterRef( const char* p, char* value, int* length );
532 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700533
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 // converts primitive types to strings
535 static void ToStr( int v, char* buffer, int bufferSize );
536 static void ToStr( unsigned v, char* buffer, int bufferSize );
537 static void ToStr( bool v, char* buffer, int bufferSize );
538 static void ToStr( float v, char* buffer, int bufferSize );
539 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700540
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700541 // converts strings to primitive types
542 static bool ToInt( const char* str, int* value );
543 static bool ToUnsigned( const char* str, unsigned* value );
544 static bool ToBool( const char* str, bool* value );
545 static bool ToFloat( const char* str, float* value );
546 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800547};
548
Lee Thomason5cae8972012-01-24 18:03:07 -0800549
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800550/** XMLNode is a base class for every object that is in the
551 XML Document Object Model (DOM), except XMLAttributes.
552 Nodes have siblings, a parent, and children which can
553 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700554 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800555 be cast to its more defined type.
556
Thomas Roß08bdf502012-05-12 14:21:23 +0200557 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800558 When the XMLDocument gets deleted, all its Nodes
559 will also be deleted.
560
561 @verbatim
562 A Document can contain: Element (container or leaf)
563 Comment (leaf)
564 Unknown (leaf)
565 Declaration( leaf )
566
567 An Element can contain: Element (container or leaf)
568 Text (leaf)
569 Attributes (not on tree)
570 Comment (leaf)
571 Unknown (leaf)
572
573 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800574*/
PKEuS16ed47d2013-07-06 12:02:43 +0200575class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800576{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700577 friend class XMLDocument;
578 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800580
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700581 /// Get the XMLDocument that owns this XMLNode.
582 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700583 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 }
585 /// Get the XMLDocument that owns this XMLNode.
586 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700587 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800589
Lee Thomason2fa81722012-11-09 12:37:46 -0800590 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100592 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700593 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800594 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700595 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100596 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700597 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800598 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700599 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100600 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700601 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800602 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700603 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100604 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700605 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800606 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700607 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100608 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700609 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800610 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100612 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700613 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800614
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700615 virtual const XMLElement* ToElement() const {
616 return 0;
617 }
618 virtual const XMLText* ToText() const {
619 return 0;
620 }
621 virtual const XMLComment* ToComment() const {
622 return 0;
623 }
624 virtual const XMLDocument* ToDocument() const {
625 return 0;
626 }
627 virtual const XMLDeclaration* ToDeclaration() const {
628 return 0;
629 }
630 virtual const XMLUnknown* ToUnknown() const {
631 return 0;
632 }
Lee Thomason751da522012-02-10 08:50:51 -0800633
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 /** The meaning of 'value' changes for the specific type.
635 @verbatim
636 Document: empty
637 Element: name of the element
638 Comment: the comment text
639 Unknown: the tag contents
640 Text: the text string
641 @endverbatim
642 */
643 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700644 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700645 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100646
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 /** Set the Value of an XML node.
648 @sa Value()
649 */
650 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800651
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700652 /// Get the parent of this node on the DOM.
653 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700654 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100656
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700657 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700658 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason751da522012-02-10 08:50:51 -0800660
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 /// Returns true if this node has no children.
662 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700663 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 }
Lee Thomason751da522012-02-10 08:50:51 -0800665
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 /// Get the first child node, or null if none exists.
667 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700668 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100670
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700671 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700672 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700673 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100674
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 /** Get the first child element, or optionally the first child
676 element with the specified name.
677 */
678 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700679
680 XMLElement* FirstChildElement( const char* value=0 ) {
681 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 /// Get the last child node, or null if none exists.
685 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700686 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700688
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700689 XMLNode* LastChild() {
690 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
691 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800692
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700693 /** Get the last child element or optionally the last child
694 element with the specified name.
695 */
696 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700697
698 XMLElement* LastChildElement( const char* value=0 ) {
699 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700701
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700702 /// Get the previous (left) sibling node of this node.
703 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700704 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700706
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700708 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700709 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800710
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700711 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700713
714 XMLElement* PreviousSiblingElement( const char* value=0 ) {
715 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700717
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 /// Get the next (right) sibling node of this node.
719 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700720 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700722
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700724 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700725 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700726
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700727 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700728 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700729
730 XMLElement* NextSiblingElement( const char* value=0 ) {
731 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700732 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 /**
735 Add a child node as the last (right) child.
736 */
737 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800738
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700739 XMLNode* LinkEndChild( XMLNode* addThis ) {
740 return InsertEndChild( addThis );
741 }
742 /**
743 Add a child node as the first (left) child.
744 */
745 XMLNode* InsertFirstChild( XMLNode* addThis );
746 /**
747 Add a node after the specified child node.
748 */
749 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700750
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 /**
752 Delete all the children of this node.
753 */
754 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800755
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700756 /**
757 Delete a child of this node.
758 */
759 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800760
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700761 /**
762 Make a copy of this node, but not its children.
763 You may pass in a Document pointer that will be
764 the owner of the new Node. If the 'document' is
765 null, then the node returned will be allocated
766 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800767
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700768 Note: if called on a XMLDocument, this will return null.
769 */
770 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800771
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700772 /**
773 Test if 2 nodes are the same, but don't test children.
774 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800775
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700776 Note: if called on a XMLDocument, this will return false.
777 */
778 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800779
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600780 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700781 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600782 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800783
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600784 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
785 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700786 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800787
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700788 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800789
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 - http://www.saxproject.org/
791 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800792
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800794
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700795 An example of using Accept():
796 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600797 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700798 tinyxmlDoc.Accept( &printer );
799 const char* xmlcstr = printer.CStr();
800 @endverbatim
801 */
802 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800803
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700804 // internal
805 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800806
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800807protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700808 XMLNode( XMLDocument* );
809 virtual ~XMLNode();
810 XMLNode( const XMLNode& ); // not supported
811 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700812
Lee Thomason624d43f2012-10-12 10:58:48 -0700813 XMLDocument* _document;
814 XMLNode* _parent;
815 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800816
Lee Thomason624d43f2012-10-12 10:58:48 -0700817 XMLNode* _firstChild;
818 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800819
Lee Thomason624d43f2012-10-12 10:58:48 -0700820 XMLNode* _prev;
821 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800822
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800823private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700824 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700825 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800826};
827
828
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800829/** XML text.
830
831 Note that a text node can have child element nodes, for example:
832 @verbatim
833 <root>This is <b>bold</b></root>
834 @endverbatim
835
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700836 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800837 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 -0700838 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600839 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800840*/
PKEuS16ed47d2013-07-06 12:02:43 +0200841class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800842{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700843 friend class XMLBase;
844 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800845public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800847
Lee Thomason624d43f2012-10-12 10:58:48 -0700848 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 return this;
850 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700851 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 return this;
853 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800854
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700856 void SetCData( bool isCData ) {
857 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700858 }
859 /// Returns true if this is a CDATA text element.
860 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700861 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700862 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800863
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700864 char* ParseDeep( char*, StrPair* endTag );
865 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
866 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800867
Lee Thomason5492a1c2012-01-23 15:32:10 -0800868protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700869 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700870 virtual ~XMLText() {}
871 XMLText( const XMLText& ); // not supported
872 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800873
874private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700875 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800876};
877
878
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800879/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200880class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800881{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700882 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800883public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700884 virtual XMLComment* ToComment() {
885 return this;
886 }
887 virtual const XMLComment* ToComment() const {
888 return this;
889 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800890
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700891 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800892
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700893 char* ParseDeep( char*, StrPair* endTag );
894 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
895 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800896
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800897protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700898 XMLComment( XMLDocument* doc );
899 virtual ~XMLComment();
900 XMLComment( const XMLComment& ); // not supported
901 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800902
Lee Thomason3f57d272012-01-11 15:30:03 -0800903private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800904};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800905
906
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800907/** In correct XML the declaration is the first entry in the file.
908 @verbatim
909 <?xml version="1.0" standalone="yes"?>
910 @endverbatim
911
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600912 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800913 however.
914
915 The text of the declaration isn't interpreted. It is parsed
916 and written as a string.
917*/
PKEuS16ed47d2013-07-06 12:02:43 +0200918class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800919{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700920 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800921public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700922 virtual XMLDeclaration* ToDeclaration() {
923 return this;
924 }
925 virtual const XMLDeclaration* ToDeclaration() const {
926 return this;
927 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800928
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700929 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800930
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700931 char* ParseDeep( char*, StrPair* endTag );
932 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
933 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800934
935protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700936 XMLDeclaration( XMLDocument* doc );
937 virtual ~XMLDeclaration();
938 XMLDeclaration( const XMLDeclaration& ); // not supported
939 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800940};
941
942
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600943/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800944 unknown. It is a tag of text, but should not be modified.
945 It will be written back to the XML, unchanged, when the file
946 is saved.
947
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600948 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800949*/
PKEuS16ed47d2013-07-06 12:02:43 +0200950class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800951{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700952 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800953public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700954 virtual XMLUnknown* ToUnknown() {
955 return this;
956 }
957 virtual const XMLUnknown* ToUnknown() const {
958 return this;
959 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800960
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700961 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800962
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700963 char* ParseDeep( char*, StrPair* endTag );
964 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
965 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800966
967protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700968 XMLUnknown( XMLDocument* doc );
969 virtual ~XMLUnknown();
970 XMLUnknown( const XMLUnknown& ); // not supported
971 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800972};
973
974
Lee Thomason2fa81722012-11-09 12:37:46 -0800975enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700976 XML_NO_ERROR = 0,
977 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800978
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700979 XML_NO_ATTRIBUTE,
980 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800981
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700982 XML_ERROR_FILE_NOT_FOUND,
983 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
984 XML_ERROR_FILE_READ_ERROR,
985 XML_ERROR_ELEMENT_MISMATCH,
986 XML_ERROR_PARSING_ELEMENT,
987 XML_ERROR_PARSING_ATTRIBUTE,
988 XML_ERROR_IDENTIFYING_TAG,
989 XML_ERROR_PARSING_TEXT,
990 XML_ERROR_PARSING_CDATA,
991 XML_ERROR_PARSING_COMMENT,
992 XML_ERROR_PARSING_DECLARATION,
993 XML_ERROR_PARSING_UNKNOWN,
994 XML_ERROR_EMPTY_DOCUMENT,
995 XML_ERROR_MISMATCHED_ELEMENT,
996 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700997
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700998 XML_CAN_NOT_CONVERT_TEXT,
999 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001000};
1001
1002
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001003/** An attribute is a name-value pair. Elements have an arbitrary
1004 number of attributes, each with a unique name.
1005
1006 @note The attributes are not XMLNodes. You may only query the
1007 Next() attribute in a list.
1008*/
PKEuS16ed47d2013-07-06 12:02:43 +02001009class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001010{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001011 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001012public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001013 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001015 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001016 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001017 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001018 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001019 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001020 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001021 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001023 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001024 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001025
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001026 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001027 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001028 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001029 */
1030 int IntValue() const {
1031 int i=0;
1032 QueryIntValue( &i );
1033 return i;
1034 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001035 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001036 unsigned UnsignedValue() const {
1037 unsigned i=0;
1038 QueryUnsignedValue( &i );
1039 return i;
1040 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001041 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001042 bool BoolValue() const {
1043 bool b=false;
1044 QueryBoolValue( &b );
1045 return b;
1046 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001047 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001048 double DoubleValue() const {
1049 double d=0;
1050 QueryDoubleValue( &d );
1051 return d;
1052 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001053 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001054 float FloatValue() const {
1055 float f=0;
1056 QueryFloatValue( &f );
1057 return f;
1058 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001059
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001060 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001061 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001062 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1063 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001064 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001065 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001066 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001067 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001068 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001069 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001070 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001071 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001072 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001073
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001074 /// Set the attribute to a string value.
1075 void SetAttribute( const char* value );
1076 /// Set the attribute to value.
1077 void SetAttribute( int value );
1078 /// Set the attribute to value.
1079 void SetAttribute( unsigned value );
1080 /// Set the attribute to value.
1081 void SetAttribute( bool value );
1082 /// Set the attribute to value.
1083 void SetAttribute( double value );
1084 /// Set the attribute to value.
1085 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001086
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001087private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001089
Thomas Roß61892312013-05-12 14:07:38 +02001090 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001091 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001092
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001093 XMLAttribute( const XMLAttribute& ); // not supported
1094 void operator=( const XMLAttribute& ); // not supported
1095 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001096
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001097 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001098
Lee Thomason624d43f2012-10-12 10:58:48 -07001099 mutable StrPair _name;
1100 mutable StrPair _value;
1101 XMLAttribute* _next;
1102 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001103};
1104
1105
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001106/** The element is a container class. It has a value, the element name,
1107 and can contain other elements, text, comments, and unknowns.
1108 Elements also contain an arbitrary number of attributes.
1109*/
PKEuS16ed47d2013-07-06 12:02:43 +02001110class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001111{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001112 friend class XMLBase;
1113 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001114public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001115 /// Get the name of an element (which is the Value() of the node.)
1116 const char* Name() const {
1117 return Value();
1118 }
1119 /// Set the name of the element.
1120 void SetName( const char* str, bool staticMem=false ) {
1121 SetValue( str, staticMem );
1122 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001123
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001124 virtual XMLElement* ToElement() {
1125 return this;
1126 }
1127 virtual const XMLElement* ToElement() const {
1128 return this;
1129 }
1130 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001131
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001132 /** Given an attribute name, Attribute() returns the value
1133 for the attribute of that name, or null if none
1134 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001135
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001136 @verbatim
1137 const char* value = ele->Attribute( "foo" );
1138 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001139
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001140 The 'value' parameter is normally null. However, if specified,
1141 the attribute will only be returned if the 'name' and 'value'
1142 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001143
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001144 @verbatim
1145 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1146 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001147
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001148 rather than:
1149 @verbatim
1150 if ( ele->Attribute( "foo" ) ) {
1151 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1152 }
1153 @endverbatim
1154 */
1155 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001156
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001157 /** Given an attribute name, IntAttribute() returns the value
1158 of the attribute interpreted as an integer. 0 will be
1159 returned if there is an error. For a method with error
1160 checking, see QueryIntAttribute()
1161 */
1162 int IntAttribute( const char* name ) const {
1163 int i=0;
1164 QueryIntAttribute( name, &i );
1165 return i;
1166 }
1167 /// See IntAttribute()
1168 unsigned UnsignedAttribute( const char* name ) const {
1169 unsigned i=0;
1170 QueryUnsignedAttribute( name, &i );
1171 return i;
1172 }
1173 /// See IntAttribute()
1174 bool BoolAttribute( const char* name ) const {
1175 bool b=false;
1176 QueryBoolAttribute( name, &b );
1177 return b;
1178 }
1179 /// See IntAttribute()
1180 double DoubleAttribute( const char* name ) const {
1181 double d=0;
1182 QueryDoubleAttribute( name, &d );
1183 return d;
1184 }
1185 /// See IntAttribute()
1186 float FloatAttribute( const char* name ) const {
1187 float f=0;
1188 QueryFloatAttribute( name, &f );
1189 return f;
1190 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001191
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001192 /** Given an attribute name, QueryIntAttribute() returns
1193 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1194 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1195 doesn't exist. If successful, the result of the conversion
1196 will be written to 'value'. If not successful, nothing will
1197 be written to 'value'. This allows you to provide default
1198 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001199
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001200 @verbatim
1201 int value = 10;
1202 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1203 @endverbatim
1204 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001205 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001206 const XMLAttribute* a = FindAttribute( name );
1207 if ( !a ) {
1208 return XML_NO_ATTRIBUTE;
1209 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001210 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001211 }
1212 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001213 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 const XMLAttribute* a = FindAttribute( name );
1215 if ( !a ) {
1216 return XML_NO_ATTRIBUTE;
1217 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001218 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001219 }
1220 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001221 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 const XMLAttribute* a = FindAttribute( name );
1223 if ( !a ) {
1224 return XML_NO_ATTRIBUTE;
1225 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001226 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001227 }
1228 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001229 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 const XMLAttribute* a = FindAttribute( name );
1231 if ( !a ) {
1232 return XML_NO_ATTRIBUTE;
1233 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001234 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001235 }
1236 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001237 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 const XMLAttribute* a = FindAttribute( name );
1239 if ( !a ) {
1240 return XML_NO_ATTRIBUTE;
1241 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001242 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001243 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001244
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001245
1246 /** Given an attribute name, QueryAttribute() returns
1247 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1248 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1249 doesn't exist. It is overloaded for the primitive types,
1250 and is a generally more convenient replacement of
1251 QueryIntAttribute() and related functions.
1252
1253 If successful, the result of the conversion
1254 will be written to 'value'. If not successful, nothing will
1255 be written to 'value'. This allows you to provide default
1256 value:
1257
1258 @verbatim
1259 int value = 10;
1260 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1261 @endverbatim
1262 */
1263 int QueryAttribute( const char* name, int* value ) const {
1264 return QueryIntAttribute( name, value );
1265 }
1266
1267 int QueryAttribute( const char* name, unsigned int* value ) const {
1268 return QueryUnsignedAttribute( name, value );
1269 }
1270
1271 int QueryAttribute( const char* name, bool* value ) const {
1272 return QueryBoolAttribute( name, value );
1273 }
1274
1275 int QueryAttribute( const char* name, double* value ) const {
1276 return QueryDoubleAttribute( name, value );
1277 }
1278
1279 int QueryAttribute( const char* name, float* value ) const {
1280 return QueryFloatAttribute( name, value );
1281 }
1282
1283 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001284 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001286 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 }
1288 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001289 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001291 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
1293 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001294 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001296 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001297 }
1298 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001299 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001301 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001302 }
1303 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001304 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001305 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001306 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001307 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001308
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 /**
1310 Delete an attribute.
1311 */
1312 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001313
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001314 /// Return the first attribute in the list.
1315 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001316 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 }
1318 /// Query a specific attribute in the list.
1319 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001320
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001322 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001323 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001324
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001325 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001327
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001328 This is a convenient method for getting the text of simple contained text:
1329 @verbatim
1330 <foo>This is text</foo>
1331 const char* str = fooElement->GetText();
1332 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001333
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001334 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001335
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001336 Note that this function can be misleading. If the element foo was created from
1337 this XML:
1338 @verbatim
1339 <foo><b>This is text</b></foo>
1340 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001341
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001342 then the value of str would be null. The first child node isn't a text node, it is
1343 another element. From this XML:
1344 @verbatim
1345 <foo>This is <b>text</b></foo>
1346 @endverbatim
1347 GetText() will return "This is ".
1348 */
1349 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001350
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001351 /**
1352 Convenience method to query the value of a child text node. This is probably best
1353 shown by example. Given you have a document is this form:
1354 @verbatim
1355 <point>
1356 <x>1</x>
1357 <y>1.4</y>
1358 </point>
1359 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001360
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001361 The QueryIntText() and similar functions provide a safe and easier way to get to the
1362 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001363
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 @verbatim
1365 int x = 0;
1366 float y = 0; // types of x and y are contrived for example
1367 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1368 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1369 xElement->QueryIntText( &x );
1370 yElement->QueryFloatText( &y );
1371 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001372
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1374 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 -07001375
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001376 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001377 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001378 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001379 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001380 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001381 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001382 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001383 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001385 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001386
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001387 // internal:
1388 enum {
1389 OPEN, // <foo>
1390 CLOSED, // <foo/>
1391 CLOSING // </foo>
1392 };
1393 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001394 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001395 }
1396 char* ParseDeep( char* p, StrPair* endTag );
1397 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1398 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001399
Lee Thomason50adb4c2012-02-13 15:07:09 -08001400private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 XMLElement( XMLDocument* doc );
1402 virtual ~XMLElement();
1403 XMLElement( const XMLElement& ); // not supported
1404 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001405
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001406 XMLAttribute* FindAttribute( const char* name );
1407 XMLAttribute* FindOrCreateAttribute( const char* name );
1408 //void LinkAttribute( XMLAttribute* attrib );
1409 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001410
Lee Thomason624d43f2012-10-12 10:58:48 -07001411 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001412 // The attribute list is ordered; there is no 'lastAttribute'
1413 // because the list needs to be scanned for dupes before adding
1414 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001415 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001416};
1417
1418
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001419enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 PRESERVE_WHITESPACE,
1421 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001422};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001423
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001424
1425/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001426 It can be saved, loaded, and printed to the screen.
1427 All Nodes are connected and allocated to a Document.
1428 If the Document is deleted, all its Nodes are also deleted.
1429*/
PKEuS16ed47d2013-07-06 12:02:43 +02001430class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001431{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001432 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001433public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001434 /// constructor
1435 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1436 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001437
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001438 virtual XMLDocument* ToDocument() {
1439 return this;
1440 }
1441 virtual const XMLDocument* ToDocument() const {
1442 return this;
1443 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001444
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001445 /**
1446 Parse an XML file from a character string.
1447 Returns XML_NO_ERROR (0) on success, or
1448 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001449
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001450 You may optionally pass in the 'nBytes', which is
1451 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001452 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 null terminated string.
1454 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001455 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001456
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001457 /**
1458 Load an XML file from disk.
1459 Returns XML_NO_ERROR (0) on success, or
1460 an errorID.
1461 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001462 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001463
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001464 /**
1465 Load an XML file from disk. You are responsible
1466 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001467
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001468 Returns XML_NO_ERROR (0) on success, or
1469 an errorID.
1470 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001471 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001472
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001473 /**
1474 Save the XML file to disk.
1475 Returns XML_NO_ERROR (0) on success, or
1476 an errorID.
1477 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001478 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001479
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001480 /**
1481 Save the XML file to disk. You are responsible
1482 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001483
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001484 Returns XML_NO_ERROR (0) on success, or
1485 an errorID.
1486 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001487 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001488
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001489 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001490 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001491 }
1492 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001493 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001494 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001495
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 /**
1497 Returns true if this document has a leading Byte Order Mark of UTF8.
1498 */
1499 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001500 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001501 }
1502 /** Sets whether to write the BOM when writing the file.
1503 */
1504 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001505 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001506 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001507
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001508 /** Return the root element of DOM. Equivalent to FirstChildElement().
1509 To get the first node, use FirstChild().
1510 */
1511 XMLElement* RootElement() {
1512 return FirstChildElement();
1513 }
1514 const XMLElement* RootElement() const {
1515 return FirstChildElement();
1516 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001517
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001518 /** Print the Document. If the Printer is not provided, it will
1519 print to stdout. If you provide Printer, this can print to a file:
1520 @verbatim
1521 XMLPrinter printer( fp );
1522 doc.Print( &printer );
1523 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001524
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001525 Or you can use a printer to print to memory:
1526 @verbatim
1527 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001528 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001529 // printer.CStr() has a const char* to the XML
1530 @endverbatim
1531 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001532 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001533 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001534
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001535 /**
1536 Create a new Element associated with
1537 this Document. The memory for the Element
1538 is managed by the Document.
1539 */
1540 XMLElement* NewElement( const char* name );
1541 /**
1542 Create a new Comment associated with
1543 this Document. The memory for the Comment
1544 is managed by the Document.
1545 */
1546 XMLComment* NewComment( const char* comment );
1547 /**
1548 Create a new Text associated with
1549 this Document. The memory for the Text
1550 is managed by the Document.
1551 */
1552 XMLText* NewText( const char* text );
1553 /**
1554 Create a new Declaration associated with
1555 this Document. The memory for the object
1556 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001557
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001558 If the 'text' param is null, the standard
1559 declaration is used.:
1560 @verbatim
1561 <?xml version="1.0" encoding="UTF-8"?>
1562 @endverbatim
1563 */
1564 XMLDeclaration* NewDeclaration( const char* text=0 );
1565 /**
1566 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001567 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001568 is managed by the Document.
1569 */
1570 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001571
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001572 /**
1573 Delete a node associated with this document.
1574 It will be unlinked from the DOM.
1575 */
1576 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001577 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001578 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001579
Lee Thomason2fa81722012-11-09 12:37:46 -08001580 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001581
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001582 /// Return true if there was an error parsing the document.
1583 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001584 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001585 }
1586 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001587 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001588 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001589 }
1590 /// Return a possibly helpful diagnostic location or string.
1591 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001592 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001593 }
1594 /// Return a possibly helpful secondary diagnostic location or string.
1595 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001596 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001597 }
1598 /// If there is an error, print it to stdout.
1599 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001600
1601 /// Clear the document, resetting it to the initial state.
1602 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001603
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001604 // internal
1605 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001606
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1608 return 0;
1609 }
1610 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1611 return false;
1612 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001613
Lee Thomason3f57d272012-01-11 15:30:03 -08001614private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001615 XMLDocument( const XMLDocument& ); // not supported
1616 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001617
Lee Thomason2fa81722012-11-09 12:37:46 -08001618 bool _writeBOM;
1619 bool _processEntities;
1620 XMLError _errorID;
1621 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001622 const char* _errorStr1;
1623 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001624 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001625
Lee Thomason624d43f2012-10-12 10:58:48 -07001626 MemPoolT< sizeof(XMLElement) > _elementPool;
1627 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1628 MemPoolT< sizeof(XMLText) > _textPool;
1629 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001630};
1631
Lee Thomason7c913cd2012-01-26 18:32:34 -08001632
Lee Thomason3ffdd392012-03-28 17:27:55 -07001633/**
1634 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001635 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001636 DOM structure. It is a separate utility class.
1637
1638 Take an example:
1639 @verbatim
1640 <Document>
1641 <Element attributeA = "valueA">
1642 <Child attributeB = "value1" />
1643 <Child attributeB = "value2" />
1644 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001645 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001646 @endverbatim
1647
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001648 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001649 easy to write a *lot* of code that looks like:
1650
1651 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001652 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001653 if ( root )
1654 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001655 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001656 if ( element )
1657 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001658 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001659 if ( child )
1660 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001661 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001662 if ( child2 )
1663 {
1664 // Finally do something useful.
1665 @endverbatim
1666
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001667 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001668 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001669 and correct to use:
1670
1671 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001672 XMLHandle docHandle( &document );
1673 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001674 if ( child2 )
1675 {
1676 // do something useful
1677 @endverbatim
1678
1679 Which is MUCH more concise and useful.
1680
1681 It is also safe to copy handles - internally they are nothing more than node pointers.
1682 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001683 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001684 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001685
1686 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001687*/
PKEuS16ed47d2013-07-06 12:02:43 +02001688class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001689{
1690public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001691 /// 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 -07001692 XMLHandle( XMLNode* node ) {
1693 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001694 }
1695 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001696 XMLHandle( XMLNode& node ) {
1697 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001698 }
1699 /// Copy constructor
1700 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001701 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001702 }
1703 /// Assignment
1704 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001705 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001706 return *this;
1707 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001708
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 /// Get the first child of this handle.
1710 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001711 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 }
1713 /// Get the first child element of this handle.
1714 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001715 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001716 }
1717 /// Get the last child of this handle.
1718 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001719 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001720 }
1721 /// Get the last child element of this handle.
1722 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001723 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001724 }
1725 /// Get the previous sibling of this handle.
1726 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001727 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001728 }
1729 /// Get the previous sibling element of this handle.
1730 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001731 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001732 }
1733 /// Get the next sibling of this handle.
1734 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001735 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001736 }
1737 /// Get the next sibling element of this handle.
1738 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001739 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001740 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001741
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001742 /// Safe cast to XMLNode. This can return null.
1743 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001744 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001745 }
1746 /// Safe cast to XMLElement. This can return null.
1747 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001748 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001749 }
1750 /// Safe cast to XMLText. This can return null.
1751 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001752 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001753 }
1754 /// Safe cast to XMLUnknown. This can return null.
1755 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001756 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001757 }
1758 /// Safe cast to XMLDeclaration. This can return null.
1759 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001760 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001761 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001762
1763private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001764 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001765};
1766
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001767
1768/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001769 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1770 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001771*/
PKEuS16ed47d2013-07-06 12:02:43 +02001772class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001773{
1774public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001775 XMLConstHandle( const XMLNode* node ) {
1776 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001777 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001778 XMLConstHandle( const XMLNode& node ) {
1779 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 }
1781 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001782 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 }
Lee Thomason8b899812012-04-04 15:58:16 -07001784
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001785 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001786 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 return *this;
1788 }
Lee Thomason8b899812012-04-04 15:58:16 -07001789
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001790 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001791 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001792 }
1793 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
1796 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001797 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001798 }
1799 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001800 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001801 }
1802 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001803 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001804 }
1805 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001806 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 }
1808 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001809 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001810 }
1811 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001812 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 }
Lee Thomason8b899812012-04-04 15:58:16 -07001814
1815
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001817 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001818 }
1819 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001820 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001821 }
1822 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001823 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001824 }
1825 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001826 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001827 }
1828 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001829 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001830 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001831
Lee Thomason5cae8972012-01-24 18:03:07 -08001832private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001833 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001834};
Lee Thomason6f381b72012-03-02 12:59:39 -08001835
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001836
1837/**
1838 Printing functionality. The XMLPrinter gives you more
1839 options than the XMLDocument::Print() method.
1840
1841 It can:
1842 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001843 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001844 -# Print XML without a XMLDocument.
1845
1846 Print to Memory
1847
1848 @verbatim
1849 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001850 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001851 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001852 @endverbatim
1853
1854 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001855
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001856 You provide the file pointer.
1857 @verbatim
1858 XMLPrinter printer( fp );
1859 doc.Print( &printer );
1860 @endverbatim
1861
1862 Print without a XMLDocument
1863
1864 When loading, an XML parser is very useful. However, sometimes
1865 when saving, it just gets in the way. The code is often set up
1866 for streaming, and constructing the DOM is just overhead.
1867
1868 The Printer supports the streaming case. The following code
1869 prints out a trivially simple XML file without ever creating
1870 an XML document.
1871
1872 @verbatim
1873 XMLPrinter printer( fp );
1874 printer.OpenElement( "foo" );
1875 printer.PushAttribute( "foo", "bar" );
1876 printer.CloseElement();
1877 @endverbatim
1878*/
PKEuS16ed47d2013-07-06 12:02:43 +02001879class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001880{
1881public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001882 /** Construct the printer. If the FILE* is specified,
1883 this will print to the FILE. Else it will print
1884 to memory, and the result is available in CStr().
1885 If 'compact' is set to true, then output is created
1886 with only required whitespace and newlines.
1887 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001888 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001889 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001890
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001891 /** If streaming, write the BOM and declaration. */
1892 void PushHeader( bool writeBOM, bool writeDeclaration );
1893 /** If streaming, start writing an element.
1894 The element must be closed with CloseElement()
1895 */
1896 void OpenElement( const char* name );
1897 /// If streaming, add an attribute to an open element.
1898 void PushAttribute( const char* name, const char* value );
1899 void PushAttribute( const char* name, int value );
1900 void PushAttribute( const char* name, unsigned value );
1901 void PushAttribute( const char* name, bool value );
1902 void PushAttribute( const char* name, double value );
1903 /// If streaming, close the Element.
1904 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001905
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001906 /// Add a text node.
1907 void PushText( const char* text, bool cdata=false );
1908 /// Add a text node from an integer.
1909 void PushText( int value );
1910 /// Add a text node from an unsigned.
1911 void PushText( unsigned value );
1912 /// Add a text node from a bool.
1913 void PushText( bool value );
1914 /// Add a text node from a float.
1915 void PushText( float value );
1916 /// Add a text node from a double.
1917 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001918
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001919 /// Add a comment
1920 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001921
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001922 void PushDeclaration( const char* value );
1923 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001924
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001925 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1926 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1927 return true;
1928 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001929
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001930 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1931 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001932
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 virtual bool Visit( const XMLText& text );
1934 virtual bool Visit( const XMLComment& comment );
1935 virtual bool Visit( const XMLDeclaration& declaration );
1936 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001937
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001938 /**
1939 If in print to memory mode, return a pointer to
1940 the XML file in memory.
1941 */
1942 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001943 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001944 }
1945 /**
1946 If in print to memory mode, return the size
1947 of the XML file in memory. (Note the size returned
1948 includes the terminating null.)
1949 */
1950 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001951 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001952 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001953
1954private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 void SealElement();
1956 void PrintSpace( int depth );
1957 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1958 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001959
Lee Thomason624d43f2012-10-12 10:58:48 -07001960 bool _elementJustOpened;
1961 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001962 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001963 int _depth;
1964 int _textDepth;
1965 bool _processEntities;
1966 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001967
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001968 enum {
1969 ENTITY_RANGE = 64,
1970 BUF_SIZE = 200
1971 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001972 bool _entityFlag[ENTITY_RANGE];
1973 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001974
Lee Thomason624d43f2012-10-12 10:58:48 -07001975 DynArray< const char*, 10 > _stack;
1976 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001977#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001978 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001979#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001980};
1981
1982
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001983} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001984
PKEuS95060352013-07-26 10:42:44 +02001985#if defined(_MSC_VER)
1986# pragma warning(pop)
1987#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001988
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001989#endif // TINYXML2_INCLUDED