blob: 72dc801ea01d9b7d68d6de6421d9ac96c70d5893 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Jerome Martinez242c3ea2013-01-06 12:20:04 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080048 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010049
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
PKEuS95060352013-07-26 10:42:44 +020060#ifdef _MSC_VER
61# pragma warning(push)
62# pragma warning(disable: 4251)
63#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080064
PKEuS16ed47d2013-07-06 12:02:43 +020065#ifdef _WIN32
66# ifdef TINYXML2_EXPORT
67# define TINYXML2_LIB __declspec(dllexport)
68# elif defined(TINYXML2_IMPORT)
69# define TINYXML2_LIB __declspec(dllimport)
70# else
71# define TINYXML2_LIB
72# endif
73#else
74# define TINYXML2_LIB
75#endif
76
77
U-Lama\Lee4cee6112011-12-31 14:58:18 -080078#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070079# if defined(_MSC_VER)
80# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
81# elif defined (ANDROID_NDK)
82# include <android/log.h>
83# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
84# else
85# include <assert.h>
86# define TIXMLASSERT assert
87# endif
88# else
89# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080090#endif
91
U-Lama\Leee13c3e62011-12-28 14:36:55 -080092
Lee Thomason1a1d4a72012-02-15 09:09:25 -080093#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070094// Microsoft visual studio, version 2005 and higher.
95/*int _snprintf_s(
96 char *buffer,
97 size_t sizeOfBuffer,
98 size_t count,
99 const char *format [,
100 argument] ...
101);*/
102inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
103{
104 va_list va;
105 va_start( va, format );
106 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
107 va_end( va );
108 return result;
109}
110#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700111#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700112// GCC version 3 and higher
113//#warning( "Using sn* functions." )
114#define TIXML_SNPRINTF snprintf
115#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800116#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800117
selfpoisede77e1952013-03-13 14:08:29 +0800118static const int TIXML2_MAJOR_VERSION = 1;
119static const int TIXML2_MINOR_VERSION = 0;
120static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800121
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800122namespace tinyxml2
123{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800124class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800125class XMLElement;
126class XMLAttribute;
127class XMLComment;
128class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800129class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800130class XMLDeclaration;
131class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800132
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800133class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800134
U-Stream\Leeae25a442012-02-17 17:48:16 -0800135/*
136 A class that wraps strings. Normally stores the start and end
137 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800138 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800139 manage) a traditional char[]
140*/
PKEuS95060352013-07-26 10:42:44 +0200141class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800142{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800143public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 enum {
145 NEEDS_ENTITY_PROCESSING = 0x01,
146 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800147 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800148
selfpoisede77e1952013-03-13 14:08:29 +0800149 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800151 ATTRIBUTE_NAME = 0,
152 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
153 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
154 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700155 };
Lee Thomason39ede242012-01-20 11:27:56 -0800156
Lee Thomason120b3a62012-10-12 10:06:59 -0700157 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700158 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800159
Lee Thomason120b3a62012-10-12 10:06:59 -0700160 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700162 _start = start;
163 _end = end;
164 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700165 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700166
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700168
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700169 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700170 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700171 }
Lee Thomason39ede242012-01-20 11:27:56 -0800172
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700173 void SetInternedStr( const char* str ) {
174 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700175 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700176 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700177
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700178 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800179
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700180 char* ParseText( char* in, const char* endTag, int strFlags );
181 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800182
Lee Thomason39ede242012-01-20 11:27:56 -0800183private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700184 void Reset();
185 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800186
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700187 enum {
188 NEEDS_FLUSH = 0x100,
189 NEEDS_DELETE = 0x200
190 };
Lee Thomasone4422302012-01-20 17:59:50 -0800191
selfpoised4dd59bc2013-03-13 16:54:15 +0800192 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700193 int _flags;
194 char* _start;
195 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800196};
197
U-Lama\Lee560bd472011-12-28 19:42:49 -0800198
U-Stream\Leeae25a442012-02-17 17:48:16 -0800199/*
200 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
201 Has a small initial memory pool, so that low or no usage will not
202 cause a call to new/delete
203*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800204template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200205class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800206{
207public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700209 _mem = _pool;
210 _allocated = INIT;
211 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700212 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700213
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700214 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700215 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700216 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
218 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700219
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700220 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700221 EnsureCapacity( _size+1 );
222 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700223 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800224
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700225 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700226 EnsureCapacity( _size+count );
227 T* ret = &_mem[_size];
228 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700229 return ret;
230 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700231
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700233 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700234 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700235
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700237 TIXMLASSERT( _size >= count );
238 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700239 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800240
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700241 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700242 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700243 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700244
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700245 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700246 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700251 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700252 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700253 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700254
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700264 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700267 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800270
Lee Thomason2c85a712012-01-31 08:24:24 -0800271private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700272 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700273 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700274 int newAllocated = cap * 2;
275 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700276 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
277 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700278 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700279 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700280 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700281 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 }
283 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800284
Lee Thomason624d43f2012-10-12 10:58:48 -0700285 T* _mem;
286 T _pool[INIT];
287 int _allocated; // objects allocated
288 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800289};
290
Lee Thomason50adb4c2012-02-13 15:07:09 -0800291
U-Stream\Leeae25a442012-02-17 17:48:16 -0800292/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200293 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800294 and deallocation of objects.
295*/
PKEuS95060352013-07-26 10:42:44 +0200296class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800297{
298public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700299 MemPool() {}
300 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800301
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700302 virtual int ItemSize() const = 0;
303 virtual void* Alloc() = 0;
304 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800305 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800306};
307
Lee Thomason50adb4c2012-02-13 15:07:09 -0800308
U-Stream\Leeae25a442012-02-17 17:48:16 -0800309/*
310 Template child class to create pools of the correct type.
311*/
Lee Thomasond1983222012-02-06 08:41:24 -0800312template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200313class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800314{
315public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800316 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700317 ~MemPoolT() {
318 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700319 for( int i=0; i<_blockPtrs.Size(); ++i ) {
320 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700321 }
322 }
Lee Thomasond1983222012-02-06 08:41:24 -0800323
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700324 virtual int ItemSize() const {
325 return SIZE;
326 }
327 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700328 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700329 }
Lee Thomasond1983222012-02-06 08:41:24 -0800330
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700331 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 // Need a new block.
334 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700335 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800336
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700337 for( int i=0; i<COUNT-1; ++i ) {
338 block->chunk[i].next = &block->chunk[i+1];
339 }
340 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700341 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700343 void* result = _root;
344 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800345
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 ++_currentAllocs;
347 if ( _currentAllocs > _maxAllocs ) {
348 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700349 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800351 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700352 return result;
353 }
354 virtual void Free( void* mem ) {
355 if ( !mem ) {
356 return;
357 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700358 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700359 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700360#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700362#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700363 chunk->next = _root;
364 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 }
366 void Trace( const char* name ) {
367 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700368 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
Lee Thomasond1983222012-02-06 08:41:24 -0800370
Lee Thomason5b0a6772012-11-19 13:54:42 -0800371 void SetTracked() {
372 _nUntracked--;
373 }
374
375 int Untracked() const {
376 return _nUntracked;
377 }
378
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800379 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
380 // The test file is large, 170k.
381 // Release: VS2010 gcc(no opt)
382 // 1k: 4000
383 // 2k: 4000
384 // 4k: 3900 21000
385 // 16k: 5200
386 // 32k: 4300
387 // 64k: 4000 21000
388 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 +0200389
Lee Thomasond1983222012-02-06 08:41:24 -0800390private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700391 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700392 Chunk* next;
393 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700394 };
395 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700396 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700397 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700398 DynArray< Block*, 10 > _blockPtrs;
399 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800400
Lee Thomason624d43f2012-10-12 10:58:48 -0700401 int _currentAllocs;
402 int _nAllocs;
403 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800404 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800405};
406
Lee Thomason2c85a712012-01-31 08:24:24 -0800407
Lee Thomason56bdd022012-02-09 18:16:58 -0800408
409/**
410 Implements the interface to the "Visitor pattern" (see the Accept() method.)
411 If you call the Accept() method, it requires being passed a XMLVisitor
412 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200413 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800414 are simply called with Visit().
415
416 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700417 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800418
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700419 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800420 visiting). You need to only override methods that are interesting to you.
421
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600422 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800423
424 You should never change the document from a callback.
425
426 @sa XMLNode::Accept()
427*/
PKEuS16ed47d2013-07-06 12:02:43 +0200428class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800429{
430public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700431 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800432
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700433 /// Visit a document.
434 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
435 return true;
436 }
437 /// Visit a document.
438 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
439 return true;
440 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800441
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700442 /// Visit an element.
443 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
444 return true;
445 }
446 /// Visit an element.
447 virtual bool VisitExit( const XMLElement& /*element*/ ) {
448 return true;
449 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800450
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700451 /// Visit a declaration.
452 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
453 return true;
454 }
455 /// Visit a text node.
456 virtual bool Visit( const XMLText& /*text*/ ) {
457 return true;
458 }
459 /// Visit a comment node.
460 virtual bool Visit( const XMLComment& /*comment*/ ) {
461 return true;
462 }
463 /// Visit an unknown node.
464 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
465 return true;
466 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800467};
468
469
U-Stream\Leeae25a442012-02-17 17:48:16 -0800470/*
471 Utility functionality.
472*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800473class XMLUtil
474{
Lee Thomasond1983222012-02-06 08:41:24 -0800475public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700476 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
477 // correct, but simple, and usually works.
478 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100479 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 ++p;
481 }
482 return p;
483 }
484 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100485 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700486 ++p;
487 }
488 return p;
489 }
490 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100491 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700492 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200493
494 inline static bool IsNameStartChar( unsigned char ch ) {
495 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
496 || ch == ':'
497 || ch == '_';
498 }
499
500 inline static bool IsNameChar( unsigned char ch ) {
501 return IsNameStartChar( ch )
502 || isdigit( ch )
503 || ch == '.'
504 || ch == '-';
505 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800506
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700507 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
508 int n = 0;
509 if ( p == q ) {
510 return true;
511 }
512 while( *p && *q && *p == *q && n<nChar ) {
513 ++p;
514 ++q;
515 ++n;
516 }
517 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
518 return true;
519 }
520 return false;
521 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200522
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700523 inline static int IsUTF8Continuation( const char p ) {
524 return p & 0x80;
525 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800526
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 static const char* ReadBOM( const char* p, bool* hasBOM );
528 // p is the starting location,
529 // the UTF-8 value of the entity will be placed in value, and length filled in.
530 static const char* GetCharacterRef( const char* p, char* value, int* length );
531 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700532
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700533 // converts primitive types to strings
534 static void ToStr( int v, char* buffer, int bufferSize );
535 static void ToStr( unsigned v, char* buffer, int bufferSize );
536 static void ToStr( bool v, char* buffer, int bufferSize );
537 static void ToStr( float v, char* buffer, int bufferSize );
538 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700539
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700540 // converts strings to primitive types
541 static bool ToInt( const char* str, int* value );
542 static bool ToUnsigned( const char* str, unsigned* value );
543 static bool ToBool( const char* str, bool* value );
544 static bool ToFloat( const char* str, float* value );
545 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800546};
547
Lee Thomason5cae8972012-01-24 18:03:07 -0800548
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800549/** XMLNode is a base class for every object that is in the
550 XML Document Object Model (DOM), except XMLAttributes.
551 Nodes have siblings, a parent, and children which can
552 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700553 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800554 be cast to its more defined type.
555
Thomas Roß08bdf502012-05-12 14:21:23 +0200556 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800557 When the XMLDocument gets deleted, all its Nodes
558 will also be deleted.
559
560 @verbatim
561 A Document can contain: Element (container or leaf)
562 Comment (leaf)
563 Unknown (leaf)
564 Declaration( leaf )
565
566 An Element can contain: Element (container or leaf)
567 Text (leaf)
568 Attributes (not on tree)
569 Comment (leaf)
570 Unknown (leaf)
571
572 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800573*/
PKEuS16ed47d2013-07-06 12:02:43 +0200574class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800575{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 friend class XMLDocument;
577 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800578public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800579
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 /// Get the XMLDocument that owns this XMLNode.
581 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700582 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700583 }
584 /// Get the XMLDocument that owns this XMLNode.
585 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700586 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800588
Lee Thomason2fa81722012-11-09 12:37:46 -0800589 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700590 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100591 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800593 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100595 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700596 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800597 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100599 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800601 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100603 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800605 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100607 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800609 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100611 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800613
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 virtual const XMLElement* ToElement() const {
615 return 0;
616 }
617 virtual const XMLText* ToText() const {
618 return 0;
619 }
620 virtual const XMLComment* ToComment() const {
621 return 0;
622 }
623 virtual const XMLDocument* ToDocument() const {
624 return 0;
625 }
626 virtual const XMLDeclaration* ToDeclaration() const {
627 return 0;
628 }
629 virtual const XMLUnknown* ToUnknown() const {
630 return 0;
631 }
Lee Thomason751da522012-02-10 08:50:51 -0800632
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700633 /** The meaning of 'value' changes for the specific type.
634 @verbatim
635 Document: empty
636 Element: name of the element
637 Comment: the comment text
638 Unknown: the tag contents
639 Text: the text string
640 @endverbatim
641 */
642 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700643 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700644 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100645
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700646 /** Set the Value of an XML node.
647 @sa Value()
648 */
649 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800650
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700651 /// Get the parent of this node on the DOM.
652 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700653 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100655
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700657 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 }
Lee Thomason751da522012-02-10 08:50:51 -0800659
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 /// Returns true if this node has no children.
661 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700662 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700663 }
Lee Thomason751da522012-02-10 08:50:51 -0800664
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 /// Get the first child node, or null if none exists.
666 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700667 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700668 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100669
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700671 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100673
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 /** Get the first child element, or optionally the first child
675 element with the specified name.
676 */
677 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700678
679 XMLElement* FirstChildElement( const char* value=0 ) {
680 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700681 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800682
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 /// Get the last child node, or null if none exists.
684 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700685 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700686 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700687
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 XMLNode* LastChild() {
689 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
690 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800691
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 /** Get the last child element or optionally the last child
693 element with the specified name.
694 */
695 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700696
697 XMLElement* LastChildElement( const char* value=0 ) {
698 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700699 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700700
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 /// Get the previous (left) sibling node of this node.
702 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700703 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700705
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700706 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700707 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800709
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700710 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700711 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700712
713 XMLElement* PreviousSiblingElement( const char* value=0 ) {
714 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700716
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 /// Get the next (right) sibling node of this node.
718 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700719 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700721
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700722 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700723 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700725
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700726 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700728
729 XMLElement* NextSiblingElement( const char* value=0 ) {
730 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800732
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 /**
734 Add a child node as the last (right) child.
735 */
736 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800737
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700738 XMLNode* LinkEndChild( XMLNode* addThis ) {
739 return InsertEndChild( addThis );
740 }
741 /**
742 Add a child node as the first (left) child.
743 */
744 XMLNode* InsertFirstChild( XMLNode* addThis );
745 /**
746 Add a node after the specified child node.
747 */
748 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700749
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700750 /**
751 Delete all the children of this node.
752 */
753 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800754
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700755 /**
756 Delete a child of this node.
757 */
758 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800759
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 /**
761 Make a copy of this node, but not its children.
762 You may pass in a Document pointer that will be
763 the owner of the new Node. If the 'document' is
764 null, then the node returned will be allocated
765 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800766
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700767 Note: if called on a XMLDocument, this will return null.
768 */
769 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800770
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 /**
772 Test if 2 nodes are the same, but don't test children.
773 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 Note: if called on a XMLDocument, this will return false.
776 */
777 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800778
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600779 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700780 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600781 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800782
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600783 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
784 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700785 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800786
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700787 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800788
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 - http://www.saxproject.org/
790 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800791
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700792 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800793
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700794 An example of using Accept():
795 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600796 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700797 tinyxmlDoc.Accept( &printer );
798 const char* xmlcstr = printer.CStr();
799 @endverbatim
800 */
801 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800802
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 // internal
804 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800805
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800806protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 XMLNode( XMLDocument* );
808 virtual ~XMLNode();
809 XMLNode( const XMLNode& ); // not supported
810 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700811
Lee Thomason624d43f2012-10-12 10:58:48 -0700812 XMLDocument* _document;
813 XMLNode* _parent;
814 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800815
Lee Thomason624d43f2012-10-12 10:58:48 -0700816 XMLNode* _firstChild;
817 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800818
Lee Thomason624d43f2012-10-12 10:58:48 -0700819 XMLNode* _prev;
820 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800821
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800822private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700823 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700824 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800825};
826
827
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800828/** XML text.
829
830 Note that a text node can have child element nodes, for example:
831 @verbatim
832 <root>This is <b>bold</b></root>
833 @endverbatim
834
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700835 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800836 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 -0700837 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600838 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800839*/
PKEuS16ed47d2013-07-06 12:02:43 +0200840class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800841{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700842 friend class XMLBase;
843 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800844public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700845 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800846
Lee Thomason624d43f2012-10-12 10:58:48 -0700847 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700848 return this;
849 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700850 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700851 return this;
852 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800853
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700854 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700855 void SetCData( bool isCData ) {
856 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 }
858 /// Returns true if this is a CDATA text element.
859 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700860 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700861 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800862
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 char* ParseDeep( char*, StrPair* endTag );
864 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
865 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800866
Lee Thomason5492a1c2012-01-23 15:32:10 -0800867protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700868 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700869 virtual ~XMLText() {}
870 XMLText( const XMLText& ); // not supported
871 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800872
873private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700874 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800875};
876
877
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800878/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200879class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800880{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700881 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800882public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 virtual XMLComment* ToComment() {
884 return this;
885 }
886 virtual const XMLComment* ToComment() const {
887 return this;
888 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800889
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700890 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800891
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700892 char* ParseDeep( char*, StrPair* endTag );
893 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
894 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800895
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800896protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700897 XMLComment( XMLDocument* doc );
898 virtual ~XMLComment();
899 XMLComment( const XMLComment& ); // not supported
900 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800901
Lee Thomason3f57d272012-01-11 15:30:03 -0800902private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800903};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800904
905
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800906/** In correct XML the declaration is the first entry in the file.
907 @verbatim
908 <?xml version="1.0" standalone="yes"?>
909 @endverbatim
910
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600911 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800912 however.
913
914 The text of the declaration isn't interpreted. It is parsed
915 and written as a string.
916*/
PKEuS16ed47d2013-07-06 12:02:43 +0200917class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800918{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700919 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800920public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700921 virtual XMLDeclaration* ToDeclaration() {
922 return this;
923 }
924 virtual const XMLDeclaration* ToDeclaration() const {
925 return this;
926 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800927
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700928 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800929
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700930 char* ParseDeep( char*, StrPair* endTag );
931 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
932 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800933
934protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700935 XMLDeclaration( XMLDocument* doc );
936 virtual ~XMLDeclaration();
937 XMLDeclaration( const XMLDeclaration& ); // not supported
938 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800939};
940
941
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600942/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800943 unknown. It is a tag of text, but should not be modified.
944 It will be written back to the XML, unchanged, when the file
945 is saved.
946
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600947 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800948*/
PKEuS16ed47d2013-07-06 12:02:43 +0200949class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800950{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700951 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800952public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700953 virtual XMLUnknown* ToUnknown() {
954 return this;
955 }
956 virtual const XMLUnknown* ToUnknown() const {
957 return this;
958 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800959
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700960 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800961
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700962 char* ParseDeep( char*, StrPair* endTag );
963 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
964 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800965
966protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700967 XMLUnknown( XMLDocument* doc );
968 virtual ~XMLUnknown();
969 XMLUnknown( const XMLUnknown& ); // not supported
970 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800971};
972
973
Lee Thomason2fa81722012-11-09 12:37:46 -0800974enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700975 XML_NO_ERROR = 0,
976 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800977
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700978 XML_NO_ATTRIBUTE,
979 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800980
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700981 XML_ERROR_FILE_NOT_FOUND,
982 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
983 XML_ERROR_FILE_READ_ERROR,
984 XML_ERROR_ELEMENT_MISMATCH,
985 XML_ERROR_PARSING_ELEMENT,
986 XML_ERROR_PARSING_ATTRIBUTE,
987 XML_ERROR_IDENTIFYING_TAG,
988 XML_ERROR_PARSING_TEXT,
989 XML_ERROR_PARSING_CDATA,
990 XML_ERROR_PARSING_COMMENT,
991 XML_ERROR_PARSING_DECLARATION,
992 XML_ERROR_PARSING_UNKNOWN,
993 XML_ERROR_EMPTY_DOCUMENT,
994 XML_ERROR_MISMATCHED_ELEMENT,
995 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700996
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700997 XML_CAN_NOT_CONVERT_TEXT,
998 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800999};
1000
1001
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001002/** An attribute is a name-value pair. Elements have an arbitrary
1003 number of attributes, each with a unique name.
1004
1005 @note The attributes are not XMLNodes. You may only query the
1006 Next() attribute in a list.
1007*/
PKEuS16ed47d2013-07-06 12:02:43 +02001008class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001009{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001010 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001011public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001012 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001013 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001014 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001015 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001016 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001017 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001018 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001020 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001021 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001022 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001023 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001024
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001025 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001026 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001027 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001028 */
1029 int IntValue() const {
1030 int i=0;
1031 QueryIntValue( &i );
1032 return i;
1033 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001034 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001035 unsigned UnsignedValue() const {
1036 unsigned i=0;
1037 QueryUnsignedValue( &i );
1038 return i;
1039 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001040 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001041 bool BoolValue() const {
1042 bool b=false;
1043 QueryBoolValue( &b );
1044 return b;
1045 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001046 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 double DoubleValue() const {
1048 double d=0;
1049 QueryDoubleValue( &d );
1050 return d;
1051 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001052 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 float FloatValue() const {
1054 float f=0;
1055 QueryFloatValue( &f );
1056 return f;
1057 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001058
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001059 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001060 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001061 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1062 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001063 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001064 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001065 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001067 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001068 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001069 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001070 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001071 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001072
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 /// Set the attribute to a string value.
1074 void SetAttribute( const char* value );
1075 /// Set the attribute to value.
1076 void SetAttribute( int value );
1077 /// Set the attribute to value.
1078 void SetAttribute( unsigned value );
1079 /// Set the attribute to value.
1080 void SetAttribute( bool value );
1081 /// Set the attribute to value.
1082 void SetAttribute( double value );
1083 /// Set the attribute to value.
1084 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001085
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001086private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001088
Thomas Roß61892312013-05-12 14:07:38 +02001089 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001090 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001091
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001092 XMLAttribute( const XMLAttribute& ); // not supported
1093 void operator=( const XMLAttribute& ); // not supported
1094 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001096 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001097
Lee Thomason624d43f2012-10-12 10:58:48 -07001098 mutable StrPair _name;
1099 mutable StrPair _value;
1100 XMLAttribute* _next;
1101 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001102};
1103
1104
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001105/** The element is a container class. It has a value, the element name,
1106 and can contain other elements, text, comments, and unknowns.
1107 Elements also contain an arbitrary number of attributes.
1108*/
PKEuS16ed47d2013-07-06 12:02:43 +02001109class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001110{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001111 friend class XMLBase;
1112 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001113public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001114 /// Get the name of an element (which is the Value() of the node.)
1115 const char* Name() const {
1116 return Value();
1117 }
1118 /// Set the name of the element.
1119 void SetName( const char* str, bool staticMem=false ) {
1120 SetValue( str, staticMem );
1121 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001122
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001123 virtual XMLElement* ToElement() {
1124 return this;
1125 }
1126 virtual const XMLElement* ToElement() const {
1127 return this;
1128 }
1129 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001130
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001131 /** Given an attribute name, Attribute() returns the value
1132 for the attribute of that name, or null if none
1133 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001134
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001135 @verbatim
1136 const char* value = ele->Attribute( "foo" );
1137 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001138
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 The 'value' parameter is normally null. However, if specified,
1140 the attribute will only be returned if the 'name' and 'value'
1141 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 @verbatim
1144 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1145 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001146
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001147 rather than:
1148 @verbatim
1149 if ( ele->Attribute( "foo" ) ) {
1150 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1151 }
1152 @endverbatim
1153 */
1154 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001155
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001156 /** Given an attribute name, IntAttribute() returns the value
1157 of the attribute interpreted as an integer. 0 will be
1158 returned if there is an error. For a method with error
1159 checking, see QueryIntAttribute()
1160 */
1161 int IntAttribute( const char* name ) const {
1162 int i=0;
1163 QueryIntAttribute( name, &i );
1164 return i;
1165 }
1166 /// See IntAttribute()
1167 unsigned UnsignedAttribute( const char* name ) const {
1168 unsigned i=0;
1169 QueryUnsignedAttribute( name, &i );
1170 return i;
1171 }
1172 /// See IntAttribute()
1173 bool BoolAttribute( const char* name ) const {
1174 bool b=false;
1175 QueryBoolAttribute( name, &b );
1176 return b;
1177 }
1178 /// See IntAttribute()
1179 double DoubleAttribute( const char* name ) const {
1180 double d=0;
1181 QueryDoubleAttribute( name, &d );
1182 return d;
1183 }
1184 /// See IntAttribute()
1185 float FloatAttribute( const char* name ) const {
1186 float f=0;
1187 QueryFloatAttribute( name, &f );
1188 return f;
1189 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001190
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001191 /** Given an attribute name, QueryIntAttribute() returns
1192 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1193 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1194 doesn't exist. If successful, the result of the conversion
1195 will be written to 'value'. If not successful, nothing will
1196 be written to 'value'. This allows you to provide default
1197 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001198
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001199 @verbatim
1200 int value = 10;
1201 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1202 @endverbatim
1203 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001204 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001205 const XMLAttribute* a = FindAttribute( name );
1206 if ( !a ) {
1207 return XML_NO_ATTRIBUTE;
1208 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001209 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001210 }
1211 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001212 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001213 const XMLAttribute* a = FindAttribute( name );
1214 if ( !a ) {
1215 return XML_NO_ATTRIBUTE;
1216 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001217 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 }
1219 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001220 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 const XMLAttribute* a = FindAttribute( name );
1222 if ( !a ) {
1223 return XML_NO_ATTRIBUTE;
1224 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001225 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001226 }
1227 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001228 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 const XMLAttribute* a = FindAttribute( name );
1230 if ( !a ) {
1231 return XML_NO_ATTRIBUTE;
1232 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001233 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001234 }
1235 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001236 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 const XMLAttribute* a = FindAttribute( name );
1238 if ( !a ) {
1239 return XML_NO_ATTRIBUTE;
1240 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001241 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001242 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001243
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001244
1245 /** Given an attribute name, QueryAttribute() returns
1246 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1247 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1248 doesn't exist. It is overloaded for the primitive types,
1249 and is a generally more convenient replacement of
1250 QueryIntAttribute() and related functions.
1251
1252 If successful, the result of the conversion
1253 will be written to 'value'. If not successful, nothing will
1254 be written to 'value'. This allows you to provide default
1255 value:
1256
1257 @verbatim
1258 int value = 10;
1259 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1260 @endverbatim
1261 */
1262 int QueryAttribute( const char* name, int* value ) const {
1263 return QueryIntAttribute( name, value );
1264 }
1265
1266 int QueryAttribute( const char* name, unsigned int* value ) const {
1267 return QueryUnsignedAttribute( name, value );
1268 }
1269
1270 int QueryAttribute( const char* name, bool* value ) const {
1271 return QueryBoolAttribute( name, value );
1272 }
1273
1274 int QueryAttribute( const char* name, double* value ) const {
1275 return QueryDoubleAttribute( name, value );
1276 }
1277
1278 int QueryAttribute( const char* name, float* value ) const {
1279 return QueryFloatAttribute( name, value );
1280 }
1281
1282 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001283 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001284 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001285 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001286 }
1287 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001288 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001289 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001290 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001291 }
1292 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001293 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001294 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001295 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 }
1297 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001298 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 }
1302 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001303 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001305 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001307
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 /**
1309 Delete an attribute.
1310 */
1311 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001312
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001313 /// Return the first attribute in the list.
1314 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001315 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 }
1317 /// Query a specific attribute in the list.
1318 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001319
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001320 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001321 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001323
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001324 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001325 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001326
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 This is a convenient method for getting the text of simple contained text:
1328 @verbatim
1329 <foo>This is text</foo>
1330 const char* str = fooElement->GetText();
1331 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001334
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 Note that this function can be misleading. If the element foo was created from
1336 this XML:
1337 @verbatim
1338 <foo><b>This is text</b></foo>
1339 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001340
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 then the value of str would be null. The first child node isn't a text node, it is
1342 another element. From this XML:
1343 @verbatim
1344 <foo>This is <b>text</b></foo>
1345 @endverbatim
1346 GetText() will return "This is ".
1347 */
1348 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001349
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001350 /**
1351 Convenience method to query the value of a child text node. This is probably best
1352 shown by example. Given you have a document is this form:
1353 @verbatim
1354 <point>
1355 <x>1</x>
1356 <y>1.4</y>
1357 </point>
1358 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001359
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001360 The QueryIntText() and similar functions provide a safe and easier way to get to the
1361 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 @verbatim
1364 int x = 0;
1365 float y = 0; // types of x and y are contrived for example
1366 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1367 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1368 xElement->QueryIntText( &x );
1369 yElement->QueryFloatText( &y );
1370 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001371
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001372 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1373 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 -07001374
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001375 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001376 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001378 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001380 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001382 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001384 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001385
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 // internal:
1387 enum {
1388 OPEN, // <foo>
1389 CLOSED, // <foo/>
1390 CLOSING // </foo>
1391 };
1392 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001393 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001394 }
1395 char* ParseDeep( char* p, StrPair* endTag );
1396 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1397 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001398
Lee Thomason50adb4c2012-02-13 15:07:09 -08001399private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001400 XMLElement( XMLDocument* doc );
1401 virtual ~XMLElement();
1402 XMLElement( const XMLElement& ); // not supported
1403 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001404
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 XMLAttribute* FindAttribute( const char* name );
1406 XMLAttribute* FindOrCreateAttribute( const char* name );
1407 //void LinkAttribute( XMLAttribute* attrib );
1408 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001409
Lee Thomason624d43f2012-10-12 10:58:48 -07001410 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001411 // The attribute list is ordered; there is no 'lastAttribute'
1412 // because the list needs to be scanned for dupes before adding
1413 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001414 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001415};
1416
1417
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001418enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001419 PRESERVE_WHITESPACE,
1420 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001421};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001422
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001423
1424/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001425 It can be saved, loaded, and printed to the screen.
1426 All Nodes are connected and allocated to a Document.
1427 If the Document is deleted, all its Nodes are also deleted.
1428*/
PKEuS16ed47d2013-07-06 12:02:43 +02001429class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001430{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001432public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001433 /// constructor
1434 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1435 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001436
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001437 virtual XMLDocument* ToDocument() {
1438 return this;
1439 }
1440 virtual const XMLDocument* ToDocument() const {
1441 return this;
1442 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001443
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 /**
1445 Parse an XML file from a character string.
1446 Returns XML_NO_ERROR (0) on success, or
1447 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001448
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001449 You may optionally pass in the 'nBytes', which is
1450 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001451 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 null terminated string.
1453 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001454 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001455
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001456 /**
1457 Load an XML file from disk.
1458 Returns XML_NO_ERROR (0) on success, or
1459 an errorID.
1460 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001461 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001462
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001463 /**
1464 Load an XML file from disk. You are responsible
1465 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001466
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001467 Returns XML_NO_ERROR (0) on success, or
1468 an errorID.
1469 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001470 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001471
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001472 /**
1473 Save the XML file to disk.
1474 Returns XML_NO_ERROR (0) on success, or
1475 an errorID.
1476 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001477 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001478
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001479 /**
1480 Save the XML file to disk. You are responsible
1481 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001482
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 Returns XML_NO_ERROR (0) on success, or
1484 an errorID.
1485 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001486 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001487
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001489 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001490 }
1491 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001492 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001493 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001494
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001495 /**
1496 Returns true if this document has a leading Byte Order Mark of UTF8.
1497 */
1498 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001499 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001500 }
1501 /** Sets whether to write the BOM when writing the file.
1502 */
1503 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001504 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /** Return the root element of DOM. Equivalent to FirstChildElement().
1508 To get the first node, use FirstChild().
1509 */
1510 XMLElement* RootElement() {
1511 return FirstChildElement();
1512 }
1513 const XMLElement* RootElement() const {
1514 return FirstChildElement();
1515 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 /** Print the Document. If the Printer is not provided, it will
1518 print to stdout. If you provide Printer, this can print to a file:
1519 @verbatim
1520 XMLPrinter printer( fp );
1521 doc.Print( &printer );
1522 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001523
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 Or you can use a printer to print to memory:
1525 @verbatim
1526 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001527 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 // printer.CStr() has a const char* to the XML
1529 @endverbatim
1530 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001531 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001533
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001534 /**
1535 Create a new Element associated with
1536 this Document. The memory for the Element
1537 is managed by the Document.
1538 */
1539 XMLElement* NewElement( const char* name );
1540 /**
1541 Create a new Comment associated with
1542 this Document. The memory for the Comment
1543 is managed by the Document.
1544 */
1545 XMLComment* NewComment( const char* comment );
1546 /**
1547 Create a new Text associated with
1548 this Document. The memory for the Text
1549 is managed by the Document.
1550 */
1551 XMLText* NewText( const char* text );
1552 /**
1553 Create a new Declaration associated with
1554 this Document. The memory for the object
1555 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001556
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001557 If the 'text' param is null, the standard
1558 declaration is used.:
1559 @verbatim
1560 <?xml version="1.0" encoding="UTF-8"?>
1561 @endverbatim
1562 */
1563 XMLDeclaration* NewDeclaration( const char* text=0 );
1564 /**
1565 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001566 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 is managed by the Document.
1568 */
1569 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001570
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001571 /**
1572 Delete a node associated with this document.
1573 It will be unlinked from the DOM.
1574 */
1575 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001576 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001578
Lee Thomason2fa81722012-11-09 12:37:46 -08001579 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001580
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001581 /// Return true if there was an error parsing the document.
1582 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001583 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 }
1585 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001586 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001587 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 }
1589 /// Return a possibly helpful diagnostic location or string.
1590 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001591 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 }
1593 /// Return a possibly helpful secondary diagnostic location or string.
1594 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001595 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 }
1597 /// If there is an error, print it to stdout.
1598 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001599
1600 /// Clear the document, resetting it to the initial state.
1601 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001602
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 // internal
1604 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001605
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1607 return 0;
1608 }
1609 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1610 return false;
1611 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001612
Lee Thomason3f57d272012-01-11 15:30:03 -08001613private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 XMLDocument( const XMLDocument& ); // not supported
1615 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001616
Lee Thomason2fa81722012-11-09 12:37:46 -08001617 bool _writeBOM;
1618 bool _processEntities;
1619 XMLError _errorID;
1620 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001621 const char* _errorStr1;
1622 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001623 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001624
Lee Thomason624d43f2012-10-12 10:58:48 -07001625 MemPoolT< sizeof(XMLElement) > _elementPool;
1626 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1627 MemPoolT< sizeof(XMLText) > _textPool;
1628 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001629};
1630
Lee Thomason7c913cd2012-01-26 18:32:34 -08001631
Lee Thomason3ffdd392012-03-28 17:27:55 -07001632/**
1633 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001634 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001635 DOM structure. It is a separate utility class.
1636
1637 Take an example:
1638 @verbatim
1639 <Document>
1640 <Element attributeA = "valueA">
1641 <Child attributeB = "value1" />
1642 <Child attributeB = "value2" />
1643 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001644 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001645 @endverbatim
1646
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001647 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001648 easy to write a *lot* of code that looks like:
1649
1650 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001651 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001652 if ( root )
1653 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001654 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001655 if ( element )
1656 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001657 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001658 if ( child )
1659 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001660 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001661 if ( child2 )
1662 {
1663 // Finally do something useful.
1664 @endverbatim
1665
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001666 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001667 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001668 and correct to use:
1669
1670 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001671 XMLHandle docHandle( &document );
1672 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001673 if ( child2 )
1674 {
1675 // do something useful
1676 @endverbatim
1677
1678 Which is MUCH more concise and useful.
1679
1680 It is also safe to copy handles - internally they are nothing more than node pointers.
1681 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001682 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001683 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001684
1685 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001686*/
PKEuS16ed47d2013-07-06 12:02:43 +02001687class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001688{
1689public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001690 /// 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 -07001691 XMLHandle( XMLNode* node ) {
1692 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001693 }
1694 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001695 XMLHandle( XMLNode& node ) {
1696 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
1698 /// Copy constructor
1699 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 }
1702 /// Assignment
1703 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001704 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 return *this;
1706 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001707
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 /// Get the first child of this handle.
1709 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001710 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001711 }
1712 /// Get the first child element of this handle.
1713 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 /// Get the last child of this handle.
1717 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001718 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001719 }
1720 /// Get the last child element of this handle.
1721 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 /// Get the previous sibling of this handle.
1725 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 /// Get the previous sibling element of this handle.
1729 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 /// Get the next sibling of this handle.
1733 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 /// Get the next sibling element of this handle.
1737 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001740
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 /// Safe cast to XMLNode. This can return null.
1742 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001743 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
1745 /// Safe cast to XMLElement. This can return null.
1746 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
1749 /// Safe cast to XMLText. This can return null.
1750 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
1753 /// Safe cast to XMLUnknown. This can return null.
1754 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001755 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 }
1757 /// Safe cast to XMLDeclaration. This can return null.
1758 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001759 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001760 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001761
1762private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001763 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001764};
1765
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001766
1767/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001768 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1769 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001770*/
PKEuS16ed47d2013-07-06 12:02:43 +02001771class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001772{
1773public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001774 XMLConstHandle( const XMLNode* node ) {
1775 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001776 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001777 XMLConstHandle( const XMLNode& node ) {
1778 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001779 }
1780 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001781 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001782 }
Lee Thomason8b899812012-04-04 15:58:16 -07001783
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001784 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001785 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 return *this;
1787 }
Lee Thomason8b899812012-04-04 15:58:16 -07001788
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001790 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001791 }
1792 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001793 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001794 }
1795 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001796 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001797 }
1798 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001799 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001800 }
1801 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001802 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 }
1804 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001805 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001806 }
1807 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 }
1810 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001811 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001812 }
Lee Thomason8b899812012-04-04 15:58:16 -07001813
1814
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001815 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001816 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001817 }
1818 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001819 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001820 }
1821 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001822 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001823 }
1824 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001825 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001826 }
1827 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001828 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001829 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001830
Lee Thomason5cae8972012-01-24 18:03:07 -08001831private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001832 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001833};
Lee Thomason6f381b72012-03-02 12:59:39 -08001834
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001835
1836/**
1837 Printing functionality. The XMLPrinter gives you more
1838 options than the XMLDocument::Print() method.
1839
1840 It can:
1841 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001842 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001843 -# Print XML without a XMLDocument.
1844
1845 Print to Memory
1846
1847 @verbatim
1848 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001849 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001850 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001851 @endverbatim
1852
1853 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001854
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001855 You provide the file pointer.
1856 @verbatim
1857 XMLPrinter printer( fp );
1858 doc.Print( &printer );
1859 @endverbatim
1860
1861 Print without a XMLDocument
1862
1863 When loading, an XML parser is very useful. However, sometimes
1864 when saving, it just gets in the way. The code is often set up
1865 for streaming, and constructing the DOM is just overhead.
1866
1867 The Printer supports the streaming case. The following code
1868 prints out a trivially simple XML file without ever creating
1869 an XML document.
1870
1871 @verbatim
1872 XMLPrinter printer( fp );
1873 printer.OpenElement( "foo" );
1874 printer.PushAttribute( "foo", "bar" );
1875 printer.CloseElement();
1876 @endverbatim
1877*/
PKEuS16ed47d2013-07-06 12:02:43 +02001878class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001879{
1880public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001881 /** Construct the printer. If the FILE* is specified,
1882 this will print to the FILE. Else it will print
1883 to memory, and the result is available in CStr().
1884 If 'compact' is set to true, then output is created
1885 with only required whitespace and newlines.
1886 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001887 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001888 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001889
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 /** If streaming, write the BOM and declaration. */
1891 void PushHeader( bool writeBOM, bool writeDeclaration );
1892 /** If streaming, start writing an element.
1893 The element must be closed with CloseElement()
1894 */
1895 void OpenElement( const char* name );
1896 /// If streaming, add an attribute to an open element.
1897 void PushAttribute( const char* name, const char* value );
1898 void PushAttribute( const char* name, int value );
1899 void PushAttribute( const char* name, unsigned value );
1900 void PushAttribute( const char* name, bool value );
1901 void PushAttribute( const char* name, double value );
1902 /// If streaming, close the Element.
1903 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001904
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001905 /// Add a text node.
1906 void PushText( const char* text, bool cdata=false );
1907 /// Add a text node from an integer.
1908 void PushText( int value );
1909 /// Add a text node from an unsigned.
1910 void PushText( unsigned value );
1911 /// Add a text node from a bool.
1912 void PushText( bool value );
1913 /// Add a text node from a float.
1914 void PushText( float value );
1915 /// Add a text node from a double.
1916 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001917
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 /// Add a comment
1919 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001920
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001921 void PushDeclaration( const char* value );
1922 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001923
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001924 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1925 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1926 return true;
1927 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001928
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001929 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1930 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001931
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001932 virtual bool Visit( const XMLText& text );
1933 virtual bool Visit( const XMLComment& comment );
1934 virtual bool Visit( const XMLDeclaration& declaration );
1935 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001936
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 /**
1938 If in print to memory mode, return a pointer to
1939 the XML file in memory.
1940 */
1941 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001942 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001943 }
1944 /**
1945 If in print to memory mode, return the size
1946 of the XML file in memory. (Note the size returned
1947 includes the terminating null.)
1948 */
1949 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001950 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001951 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001952
1953private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001954 void SealElement();
1955 void PrintSpace( int depth );
1956 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1957 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001958
Lee Thomason624d43f2012-10-12 10:58:48 -07001959 bool _elementJustOpened;
1960 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001961 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001962 int _depth;
1963 int _textDepth;
1964 bool _processEntities;
1965 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001966
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001967 enum {
1968 ENTITY_RANGE = 64,
1969 BUF_SIZE = 200
1970 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001971 bool _entityFlag[ENTITY_RANGE];
1972 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001973
Lee Thomason624d43f2012-10-12 10:58:48 -07001974 DynArray< const char*, 10 > _stack;
1975 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001976#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001978#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001979};
1980
1981
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001982} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001983
PKEuS95060352013-07-26 10:42:44 +02001984#if defined(_MSC_VER)
1985# pragma warning(pop)
1986#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001987
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001988#endif // TINYXML2_INCLUDED