blob: 6b293247b40e70b730eacd2687621e4d00af1df7 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -070017
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -0800182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080024
Lee Thomason7d00b9a2012-02-27 17:54:22 -080025#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080026#define TINYXML2_INCLUDED
27
Jerome Martinez242c3ea2013-01-06 12:20:04 +010028#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070029# include <ctype.h>
30# include <limits.h>
31# include <stdio.h>
32# include <stdlib.h>
33# include <string.h>
34# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070035#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070036# include <cctype>
37# include <climits>
38# include <cstdio>
39# include <cstdlib>
40# include <cstring>
41# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070043
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070044/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080045 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080046*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080047/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070048 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080049 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010050
Lee Thomasona9cf3f92012-10-11 16:56:51 -070051 Formatting, Artistic Style:
52 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080053*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080054
U-Lama\Lee4cee6112011-12-31 14:58:18 -080055#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070056# ifndef DEBUG
57# define DEBUG
58# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080059#endif
60
PKEuS95060352013-07-26 10:42:44 +020061#ifdef _MSC_VER
62# pragma warning(push)
63# pragma warning(disable: 4251)
64#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080065
PKEuS16ed47d2013-07-06 12:02:43 +020066#ifdef _WIN32
67# ifdef TINYXML2_EXPORT
68# define TINYXML2_LIB __declspec(dllexport)
69# elif defined(TINYXML2_IMPORT)
70# define TINYXML2_LIB __declspec(dllimport)
71# else
72# define TINYXML2_LIB
73# endif
74#else
75# define TINYXML2_LIB
76#endif
77
78
U-Lama\Lee4cee6112011-12-31 14:58:18 -080079#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070080# if defined(_MSC_VER)
81# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
82# elif defined (ANDROID_NDK)
83# include <android/log.h>
84# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85# else
86# include <assert.h>
87# define TIXMLASSERT assert
88# endif
89# else
90# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080091#endif
92
U-Lama\Leee13c3e62011-12-28 14:36:55 -080093
Lee Thomason1a1d4a72012-02-15 09:09:25 -080094#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// Microsoft visual studio, version 2005 and higher.
96/*int _snprintf_s(
97 char *buffer,
98 size_t sizeOfBuffer,
99 size_t count,
100 const char *format [,
101 argument] ...
102);*/
103inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
104{
105 va_list va;
106 va_start( va, format );
107 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
108 va_end( va );
109 return result;
110}
111#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700112#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700113// GCC version 3 and higher
114//#warning( "Using sn* functions." )
115#define TIXML_SNPRINTF snprintf
116#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800117#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800118
selfpoisede77e1952013-03-13 14:08:29 +0800119static const int TIXML2_MAJOR_VERSION = 1;
120static const int TIXML2_MINOR_VERSION = 0;
121static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800122
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800123namespace tinyxml2
124{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800125class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800126class XMLElement;
127class XMLAttribute;
128class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800129class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800130class XMLDeclaration;
131class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800132class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800133
U-Stream\Leeae25a442012-02-17 17:48:16 -0800134/*
135 A class that wraps strings. Normally stores the start and end
136 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800137 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800138 manage) a traditional char[]
139*/
PKEuS95060352013-07-26 10:42:44 +0200140class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800141{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800142public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 enum {
144 NEEDS_ENTITY_PROCESSING = 0x01,
145 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800146 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800147
selfpoisede77e1952013-03-13 14:08:29 +0800148 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800150 ATTRIBUTE_NAME = 0,
151 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
152 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
153 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 };
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800158
Lee Thomason120b3a62012-10-12 10:06:59 -0700159 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700161 _start = start;
162 _end = end;
163 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700165
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700169 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 }
Lee Thomason39ede242012-01-20 11:27:56 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 void SetInternedStr( const char* str ) {
173 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700174 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700176
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700177 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800178
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700179 char* ParseText( char* in, const char* endTag, int strFlags );
180 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800181
Lee Thomason39ede242012-01-20 11:27:56 -0800182private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 void Reset();
184 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800185
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700186 enum {
187 NEEDS_FLUSH = 0x100,
188 NEEDS_DELETE = 0x200
189 };
Lee Thomasone4422302012-01-20 17:59:50 -0800190
selfpoised4dd59bc2013-03-13 16:54:15 +0800191 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700192 int _flags;
193 char* _start;
194 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800195};
196
U-Lama\Lee560bd472011-12-28 19:42:49 -0800197
U-Stream\Leeae25a442012-02-17 17:48:16 -0800198/*
199 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
200 Has a small initial memory pool, so that low or no usage will not
201 cause a call to new/delete
202*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800203template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200204class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800205{
206public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700208 _mem = _pool;
209 _allocated = INIT;
210 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700212
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700214 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700215 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 EnsureCapacity( _size+1 );
221 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 EnsureCapacity( _size+count );
226 T* ret = &_mem[_size];
227 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 return ret;
229 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700234
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700236 TIXMLASSERT( _size >= count );
237 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800239
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700241 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700243
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700245 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700246 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700248
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700250 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700253
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500254 const T& PeekTop() const {
255 TIXMLASSERT( _size > 0 );
256 return _mem[ _size - 1];
257 }
258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700267 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700270
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700272 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800274
Lee Thomason2c85a712012-01-31 08:24:24 -0800275private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 int newAllocated = cap * 2;
279 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700280 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
281 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700282 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700284 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700285 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700286 }
287 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800288
Lee Thomason624d43f2012-10-12 10:58:48 -0700289 T* _mem;
290 T _pool[INIT];
291 int _allocated; // objects allocated
292 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800293};
294
Lee Thomason50adb4c2012-02-13 15:07:09 -0800295
U-Stream\Leeae25a442012-02-17 17:48:16 -0800296/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200297 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800298 and deallocation of objects.
299*/
PKEuS95060352013-07-26 10:42:44 +0200300class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800301{
302public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 MemPool() {}
304 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const = 0;
307 virtual void* Alloc() = 0;
308 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800309 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800310};
311
Lee Thomason50adb4c2012-02-13 15:07:09 -0800312
U-Stream\Leeae25a442012-02-17 17:48:16 -0800313/*
314 Template child class to create pools of the correct type.
315*/
Lee Thomasond1983222012-02-06 08:41:24 -0800316template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200317class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800318{
319public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800320 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700321 ~MemPoolT() {
322 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 for( int i=0; i<_blockPtrs.Size(); ++i ) {
324 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
326 }
Lee Thomasond1983222012-02-06 08:41:24 -0800327
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 virtual int ItemSize() const {
329 return SIZE;
330 }
331 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 }
Lee Thomasond1983222012-02-06 08:41:24 -0800334
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700336 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700337 // Need a new block.
338 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800340
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 for( int i=0; i<COUNT-1; ++i ) {
342 block->chunk[i].next = &block->chunk[i+1];
343 }
344 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700345 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700347 void* result = _root;
348 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800349
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 ++_currentAllocs;
351 if ( _currentAllocs > _maxAllocs ) {
352 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800355 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 return result;
357 }
358 virtual void Free( void* mem ) {
359 if ( !mem ) {
360 return;
361 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700364#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700366#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700367 chunk->next = _root;
368 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
370 void Trace( const char* name ) {
371 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 }
Lee Thomasond1983222012-02-06 08:41:24 -0800374
Lee Thomason5b0a6772012-11-19 13:54:42 -0800375 void SetTracked() {
376 _nUntracked--;
377 }
378
379 int Untracked() const {
380 return _nUntracked;
381 }
382
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800383 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
384 // The test file is large, 170k.
385 // Release: VS2010 gcc(no opt)
386 // 1k: 4000
387 // 2k: 4000
388 // 4k: 3900 21000
389 // 16k: 5200
390 // 32k: 4300
391 // 64k: 4000 21000
392 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
Jerome Martinez7921df12012-10-24 11:45:44 +0200393
Lee Thomasond1983222012-02-06 08:41:24 -0800394private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700396 Chunk* next;
397 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700398 };
399 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700400 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700401 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700402 DynArray< Block*, 10 > _blockPtrs;
403 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800404
Lee Thomason624d43f2012-10-12 10:58:48 -0700405 int _currentAllocs;
406 int _nAllocs;
407 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800408 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800409};
410
Lee Thomason2c85a712012-01-31 08:24:24 -0800411
Lee Thomason56bdd022012-02-09 18:16:58 -0800412
413/**
414 Implements the interface to the "Visitor pattern" (see the Accept() method.)
415 If you call the Accept() method, it requires being passed a XMLVisitor
416 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200417 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800418 are simply called with Visit().
419
420 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700421 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800422
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700423 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800424 visiting). You need to only override methods that are interesting to you.
425
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600426 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800427
428 You should never change the document from a callback.
429
430 @sa XMLNode::Accept()
431*/
PKEuS16ed47d2013-07-06 12:02:43 +0200432class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800433{
434public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700435 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800436
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700437 /// Visit a document.
438 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
439 return true;
440 }
441 /// Visit a document.
442 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
443 return true;
444 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800445
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700446 /// Visit an element.
447 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
448 return true;
449 }
450 /// Visit an element.
451 virtual bool VisitExit( const XMLElement& /*element*/ ) {
452 return true;
453 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800454
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700455 /// Visit a declaration.
456 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
457 return true;
458 }
459 /// Visit a text node.
460 virtual bool Visit( const XMLText& /*text*/ ) {
461 return true;
462 }
463 /// Visit a comment node.
464 virtual bool Visit( const XMLComment& /*comment*/ ) {
465 return true;
466 }
467 /// Visit an unknown node.
468 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
469 return true;
470 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800471};
472
473
U-Stream\Leeae25a442012-02-17 17:48:16 -0800474/*
475 Utility functionality.
476*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800477class XMLUtil
478{
Lee Thomasond1983222012-02-06 08:41:24 -0800479public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
481 // correct, but simple, and usually works.
482 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100483 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700484 ++p;
485 }
486 return p;
487 }
488 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100489 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700490 ++p;
491 }
492 return p;
493 }
494 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100495 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700496 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200497
498 inline static bool IsNameStartChar( unsigned char ch ) {
499 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
500 || ch == ':'
501 || ch == '_';
502 }
503
504 inline static bool IsNameChar( unsigned char ch ) {
505 return IsNameStartChar( ch )
506 || isdigit( ch )
507 || ch == '.'
508 || ch == '-';
509 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800510
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700511 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
512 int n = 0;
513 if ( p == q ) {
514 return true;
515 }
516 while( *p && *q && *p == *q && n<nChar ) {
517 ++p;
518 ++q;
519 ++n;
520 }
521 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
522 return true;
523 }
524 return false;
525 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200526
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 inline static int IsUTF8Continuation( const char p ) {
528 return p & 0x80;
529 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 static const char* ReadBOM( const char* p, bool* hasBOM );
532 // p is the starting location,
533 // the UTF-8 value of the entity will be placed in value, and length filled in.
534 static const char* GetCharacterRef( const char* p, char* value, int* length );
535 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700536
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 // converts primitive types to strings
538 static void ToStr( int v, char* buffer, int bufferSize );
539 static void ToStr( unsigned v, char* buffer, int bufferSize );
540 static void ToStr( bool v, char* buffer, int bufferSize );
541 static void ToStr( float v, char* buffer, int bufferSize );
542 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700543
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700544 // converts strings to primitive types
545 static bool ToInt( const char* str, int* value );
546 static bool ToUnsigned( const char* str, unsigned* value );
547 static bool ToBool( const char* str, bool* value );
548 static bool ToFloat( const char* str, float* value );
549 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800550};
551
Lee Thomason5cae8972012-01-24 18:03:07 -0800552
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800553/** XMLNode is a base class for every object that is in the
554 XML Document Object Model (DOM), except XMLAttributes.
555 Nodes have siblings, a parent, and children which can
556 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700557 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800558 be cast to its more defined type.
559
Thomas Roß08bdf502012-05-12 14:21:23 +0200560 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800561 When the XMLDocument gets deleted, all its Nodes
562 will also be deleted.
563
564 @verbatim
565 A Document can contain: Element (container or leaf)
566 Comment (leaf)
567 Unknown (leaf)
568 Declaration( leaf )
569
570 An Element can contain: Element (container or leaf)
571 Text (leaf)
572 Attributes (not on tree)
573 Comment (leaf)
574 Unknown (leaf)
575
576 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800577*/
PKEuS16ed47d2013-07-06 12:02:43 +0200578class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 friend class XMLDocument;
581 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800582public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800583
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 /// Get the XMLDocument that owns this XMLNode.
585 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700586 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 }
588 /// Get the XMLDocument that owns this XMLNode.
589 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700590 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592
Lee Thomason2fa81722012-11-09 12:37:46 -0800593 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100595 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700596 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800597 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100599 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800601 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100603 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800605 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100607 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800609 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100611 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800613 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100615 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800617
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 virtual const XMLElement* ToElement() const {
619 return 0;
620 }
621 virtual const XMLText* ToText() const {
622 return 0;
623 }
624 virtual const XMLComment* ToComment() const {
625 return 0;
626 }
627 virtual const XMLDocument* ToDocument() const {
628 return 0;
629 }
630 virtual const XMLDeclaration* ToDeclaration() const {
631 return 0;
632 }
633 virtual const XMLUnknown* ToUnknown() const {
634 return 0;
635 }
Lee Thomason751da522012-02-10 08:50:51 -0800636
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 /** The meaning of 'value' changes for the specific type.
638 @verbatim
639 Document: empty
640 Element: name of the element
641 Comment: the comment text
642 Unknown: the tag contents
643 Text: the text string
644 @endverbatim
645 */
646 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700647 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100649
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 /** Set the Value of an XML node.
651 @sa Value()
652 */
653 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800654
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700655 /// Get the parent of this node on the DOM.
656 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700657 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100659
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700661 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700662 }
Lee Thomason751da522012-02-10 08:50:51 -0800663
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 /// Returns true if this node has no children.
665 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700666 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 }
Lee Thomason751da522012-02-10 08:50:51 -0800668
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700669 /// Get the first child node, or null if none exists.
670 const XMLNode* FirstChild() const {
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 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700675 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100677
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700678 /** Get the first child element, or optionally the first child
679 element with the specified name.
680 */
681 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700682
683 XMLElement* FirstChildElement( const char* value=0 ) {
684 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700685 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800686
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 /// Get the last child node, or null if none exists.
688 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700689 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700691
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 XMLNode* LastChild() {
693 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
694 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800695
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700696 /** Get the last child element or optionally the last child
697 element with the specified name.
698 */
699 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700700
701 XMLElement* LastChildElement( const char* value=0 ) {
702 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700704
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700705 /// Get the previous (left) sibling node of this node.
706 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700707 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700709
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700711 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800713
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700714 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700715 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700716
717 XMLElement* PreviousSiblingElement( const char* value=0 ) {
718 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700720
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700721 /// Get the next (right) sibling node of this node.
722 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700723 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700727 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700728 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700729
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700730 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700732
733 XMLElement* NextSiblingElement( const char* value=0 ) {
734 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800736
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700737 /**
738 Add a child node as the last (right) child.
739 */
740 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800741
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700742 XMLNode* LinkEndChild( XMLNode* addThis ) {
743 return InsertEndChild( addThis );
744 }
745 /**
746 Add a child node as the first (left) child.
747 */
748 XMLNode* InsertFirstChild( XMLNode* addThis );
749 /**
750 Add a node after the specified child node.
751 */
752 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700753
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700754 /**
755 Delete all the children of this node.
756 */
757 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800758
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700759 /**
760 Delete a child of this node.
761 */
762 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800763
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700764 /**
765 Make a copy of this node, but not its children.
766 You may pass in a Document pointer that will be
767 the owner of the new Node. If the 'document' is
768 null, then the node returned will be allocated
769 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800770
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700771 Note: if called on a XMLDocument, this will return null.
772 */
773 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800774
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700775 /**
776 Test if 2 nodes are the same, but don't test children.
777 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800778
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700779 Note: if called on a XMLDocument, this will return false.
780 */
781 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800782
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600783 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600785 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800786
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600787 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
788 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800790
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800792
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 - http://www.saxproject.org/
794 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800795
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800797
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700798 An example of using Accept():
799 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600800 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700801 tinyxmlDoc.Accept( &printer );
802 const char* xmlcstr = printer.CStr();
803 @endverbatim
804 */
805 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800806
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700807 // internal
808 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800809
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800810protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700811 XMLNode( XMLDocument* );
812 virtual ~XMLNode();
813 XMLNode( const XMLNode& ); // not supported
814 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700815
Lee Thomason624d43f2012-10-12 10:58:48 -0700816 XMLDocument* _document;
817 XMLNode* _parent;
818 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800819
Lee Thomason624d43f2012-10-12 10:58:48 -0700820 XMLNode* _firstChild;
821 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800822
Lee Thomason624d43f2012-10-12 10:58:48 -0700823 XMLNode* _prev;
824 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800825
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800826private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700827 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700828 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800829};
830
831
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800832/** XML text.
833
834 Note that a text node can have child element nodes, for example:
835 @verbatim
836 <root>This is <b>bold</b></root>
837 @endverbatim
838
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700839 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800840 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 -0700841 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600842 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800843*/
PKEuS16ed47d2013-07-06 12:02:43 +0200844class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800845{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700846 friend class XMLBase;
847 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800848public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700849 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800850
Lee Thomason624d43f2012-10-12 10:58:48 -0700851 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700852 return this;
853 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700854 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700855 return this;
856 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800857
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700858 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700859 void SetCData( bool isCData ) {
860 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700861 }
862 /// Returns true if this is a CDATA text element.
863 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700864 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700865 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800866
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700867 char* ParseDeep( char*, StrPair* endTag );
868 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
869 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800870
Lee Thomason5492a1c2012-01-23 15:32:10 -0800871protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700872 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700873 virtual ~XMLText() {}
874 XMLText( const XMLText& ); // not supported
875 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800876
877private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700878 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800879};
880
881
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800882/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200883class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800884{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800886public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700887 virtual XMLComment* ToComment() {
888 return this;
889 }
890 virtual const XMLComment* ToComment() const {
891 return this;
892 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800893
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700894 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800895
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700896 char* ParseDeep( char*, StrPair* endTag );
897 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
898 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800899
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800900protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700901 XMLComment( XMLDocument* doc );
902 virtual ~XMLComment();
903 XMLComment( const XMLComment& ); // not supported
904 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800905
Lee Thomason3f57d272012-01-11 15:30:03 -0800906private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800907};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800908
909
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800910/** In correct XML the declaration is the first entry in the file.
911 @verbatim
912 <?xml version="1.0" standalone="yes"?>
913 @endverbatim
914
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600915 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800916 however.
917
918 The text of the declaration isn't interpreted. It is parsed
919 and written as a string.
920*/
PKEuS16ed47d2013-07-06 12:02:43 +0200921class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800922{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700923 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800924public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700925 virtual XMLDeclaration* ToDeclaration() {
926 return this;
927 }
928 virtual const XMLDeclaration* ToDeclaration() const {
929 return this;
930 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800931
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700932 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800933
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700934 char* ParseDeep( char*, StrPair* endTag );
935 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
936 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800937
938protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700939 XMLDeclaration( XMLDocument* doc );
940 virtual ~XMLDeclaration();
941 XMLDeclaration( const XMLDeclaration& ); // not supported
942 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800943};
944
945
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600946/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800947 unknown. It is a tag of text, but should not be modified.
948 It will be written back to the XML, unchanged, when the file
949 is saved.
950
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600951 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800952*/
PKEuS16ed47d2013-07-06 12:02:43 +0200953class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800954{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700955 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800956public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700957 virtual XMLUnknown* ToUnknown() {
958 return this;
959 }
960 virtual const XMLUnknown* ToUnknown() const {
961 return this;
962 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800963
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800965
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700966 char* ParseDeep( char*, StrPair* endTag );
967 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
968 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800969
970protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700971 XMLUnknown( XMLDocument* doc );
972 virtual ~XMLUnknown();
973 XMLUnknown( const XMLUnknown& ); // not supported
974 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800975};
976
977
Lee Thomason2fa81722012-11-09 12:37:46 -0800978enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700979 XML_NO_ERROR = 0,
980 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800981
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700982 XML_NO_ATTRIBUTE,
983 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800984
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700985 XML_ERROR_FILE_NOT_FOUND,
986 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
987 XML_ERROR_FILE_READ_ERROR,
988 XML_ERROR_ELEMENT_MISMATCH,
989 XML_ERROR_PARSING_ELEMENT,
990 XML_ERROR_PARSING_ATTRIBUTE,
991 XML_ERROR_IDENTIFYING_TAG,
992 XML_ERROR_PARSING_TEXT,
993 XML_ERROR_PARSING_CDATA,
994 XML_ERROR_PARSING_COMMENT,
995 XML_ERROR_PARSING_DECLARATION,
996 XML_ERROR_PARSING_UNKNOWN,
997 XML_ERROR_EMPTY_DOCUMENT,
998 XML_ERROR_MISMATCHED_ELEMENT,
999 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -07001000
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001001 XML_CAN_NOT_CONVERT_TEXT,
1002 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001003};
1004
1005
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001006/** An attribute is a name-value pair. Elements have an arbitrary
1007 number of attributes, each with a unique name.
1008
1009 @note The attributes are not XMLNodes. You may only query the
1010 Next() attribute in a list.
1011*/
PKEuS16ed47d2013-07-06 12:02:43 +02001012class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001013{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001014 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001015public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001016 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001017 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001018 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001020 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001021 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001022 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001023 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001024 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001025 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001026 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001027 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001028
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001029 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001030 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001031 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001032 */
1033 int IntValue() const {
1034 int i=0;
1035 QueryIntValue( &i );
1036 return i;
1037 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001038 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001039 unsigned UnsignedValue() const {
1040 unsigned i=0;
1041 QueryUnsignedValue( &i );
1042 return i;
1043 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001044 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001045 bool BoolValue() const {
1046 bool b=false;
1047 QueryBoolValue( &b );
1048 return b;
1049 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001050 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001051 double DoubleValue() const {
1052 double d=0;
1053 QueryDoubleValue( &d );
1054 return d;
1055 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001056 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 float FloatValue() const {
1058 float f=0;
1059 QueryFloatValue( &f );
1060 return f;
1061 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001062
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001063 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001064 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001065 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1066 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001067 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001068 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001069 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001070 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001071 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001072 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001073 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001074 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001075 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001076
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001077 /// Set the attribute to a string value.
1078 void SetAttribute( const char* value );
1079 /// Set the attribute to value.
1080 void SetAttribute( int value );
1081 /// Set the attribute to value.
1082 void SetAttribute( unsigned value );
1083 /// Set the attribute to value.
1084 void SetAttribute( bool value );
1085 /// Set the attribute to value.
1086 void SetAttribute( double value );
1087 /// Set the attribute to value.
1088 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001089
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001090private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001091 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001092
Thomas Roß61892312013-05-12 14:07:38 +02001093 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001094 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001096 XMLAttribute( const XMLAttribute& ); // not supported
1097 void operator=( const XMLAttribute& ); // not supported
1098 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001099
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001100 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001101
Lee Thomason624d43f2012-10-12 10:58:48 -07001102 mutable StrPair _name;
1103 mutable StrPair _value;
1104 XMLAttribute* _next;
1105 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001106};
1107
1108
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001109/** The element is a container class. It has a value, the element name,
1110 and can contain other elements, text, comments, and unknowns.
1111 Elements also contain an arbitrary number of attributes.
1112*/
PKEuS16ed47d2013-07-06 12:02:43 +02001113class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001114{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001115 friend class XMLBase;
1116 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001117public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001118 /// Get the name of an element (which is the Value() of the node.)
1119 const char* Name() const {
1120 return Value();
1121 }
1122 /// Set the name of the element.
1123 void SetName( const char* str, bool staticMem=false ) {
1124 SetValue( str, staticMem );
1125 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001126
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001127 virtual XMLElement* ToElement() {
1128 return this;
1129 }
1130 virtual const XMLElement* ToElement() const {
1131 return this;
1132 }
1133 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001134
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001135 /** Given an attribute name, Attribute() returns the value
1136 for the attribute of that name, or null if none
1137 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001138
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 @verbatim
1140 const char* value = ele->Attribute( "foo" );
1141 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 The 'value' parameter is normally null. However, if specified,
1144 the attribute will only be returned if the 'name' and 'value'
1145 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001146
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001147 @verbatim
1148 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1149 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001150
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001151 rather than:
1152 @verbatim
1153 if ( ele->Attribute( "foo" ) ) {
1154 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1155 }
1156 @endverbatim
1157 */
1158 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001159
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001160 /** Given an attribute name, IntAttribute() returns the value
1161 of the attribute interpreted as an integer. 0 will be
1162 returned if there is an error. For a method with error
1163 checking, see QueryIntAttribute()
1164 */
1165 int IntAttribute( const char* name ) const {
1166 int i=0;
1167 QueryIntAttribute( name, &i );
1168 return i;
1169 }
1170 /// See IntAttribute()
1171 unsigned UnsignedAttribute( const char* name ) const {
1172 unsigned i=0;
1173 QueryUnsignedAttribute( name, &i );
1174 return i;
1175 }
1176 /// See IntAttribute()
1177 bool BoolAttribute( const char* name ) const {
1178 bool b=false;
1179 QueryBoolAttribute( name, &b );
1180 return b;
1181 }
1182 /// See IntAttribute()
1183 double DoubleAttribute( const char* name ) const {
1184 double d=0;
1185 QueryDoubleAttribute( name, &d );
1186 return d;
1187 }
1188 /// See IntAttribute()
1189 float FloatAttribute( const char* name ) const {
1190 float f=0;
1191 QueryFloatAttribute( name, &f );
1192 return f;
1193 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001194
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001195 /** Given an attribute name, QueryIntAttribute() returns
1196 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1197 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1198 doesn't exist. If successful, the result of the conversion
1199 will be written to 'value'. If not successful, nothing will
1200 be written to 'value'. This allows you to provide default
1201 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001202
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001203 @verbatim
1204 int value = 10;
1205 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1206 @endverbatim
1207 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001208 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 const XMLAttribute* a = FindAttribute( name );
1210 if ( !a ) {
1211 return XML_NO_ATTRIBUTE;
1212 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001213 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 }
1215 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001216 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001217 const XMLAttribute* a = FindAttribute( name );
1218 if ( !a ) {
1219 return XML_NO_ATTRIBUTE;
1220 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001221 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 }
1223 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001224 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001225 const XMLAttribute* a = FindAttribute( name );
1226 if ( !a ) {
1227 return XML_NO_ATTRIBUTE;
1228 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001229 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 }
1231 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001232 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001233 const XMLAttribute* a = FindAttribute( name );
1234 if ( !a ) {
1235 return XML_NO_ATTRIBUTE;
1236 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001237 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 }
1239 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001240 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001241 const XMLAttribute* a = FindAttribute( name );
1242 if ( !a ) {
1243 return XML_NO_ATTRIBUTE;
1244 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001245 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001246 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001247
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001248
1249 /** Given an attribute name, QueryAttribute() returns
1250 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1251 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1252 doesn't exist. It is overloaded for the primitive types,
1253 and is a generally more convenient replacement of
1254 QueryIntAttribute() and related functions.
1255
1256 If successful, the result of the conversion
1257 will be written to 'value'. If not successful, nothing will
1258 be written to 'value'. This allows you to provide default
1259 value:
1260
1261 @verbatim
1262 int value = 10;
1263 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1264 @endverbatim
1265 */
1266 int QueryAttribute( const char* name, int* value ) const {
1267 return QueryIntAttribute( name, value );
1268 }
1269
1270 int QueryAttribute( const char* name, unsigned int* value ) const {
1271 return QueryUnsignedAttribute( name, value );
1272 }
1273
1274 int QueryAttribute( const char* name, bool* value ) const {
1275 return QueryBoolAttribute( name, value );
1276 }
1277
1278 int QueryAttribute( const char* name, double* value ) const {
1279 return QueryDoubleAttribute( name, value );
1280 }
1281
1282 int QueryAttribute( const char* name, float* value ) const {
1283 return QueryFloatAttribute( name, value );
1284 }
1285
1286 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001287 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001288 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001289 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 }
1291 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001292 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001293 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001294 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 }
1296 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001297 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001298 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001299 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 }
1301 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001302 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001303 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001304 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001305 }
1306 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001307 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001309 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001310 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001311
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 /**
1313 Delete an attribute.
1314 */
1315 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001316
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001317 /// Return the first attribute in the list.
1318 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001319 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001320 }
1321 /// Query a specific attribute in the list.
1322 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001323
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001324 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001325 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001326 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001327
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001328 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001330
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001331 This is a convenient method for getting the text of simple contained text:
1332 @verbatim
1333 <foo>This is text</foo>
1334 const char* str = fooElement->GetText();
1335 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001336
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001337 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001338
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001339 Note that this function can be misleading. If the element foo was created from
1340 this XML:
1341 @verbatim
1342 <foo><b>This is text</b></foo>
1343 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001344
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001345 then the value of str would be null. The first child node isn't a text node, it is
1346 another element. From this XML:
1347 @verbatim
1348 <foo>This is <b>text</b></foo>
1349 @endverbatim
1350 GetText() will return "This is ".
1351 */
1352 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001353
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001354 /**
1355 Convenience method to query the value of a child text node. This is probably best
1356 shown by example. Given you have a document is this form:
1357 @verbatim
1358 <point>
1359 <x>1</x>
1360 <y>1.4</y>
1361 </point>
1362 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001363
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001364 The QueryIntText() and similar functions provide a safe and easier way to get to the
1365 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001366
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001367 @verbatim
1368 int x = 0;
1369 float y = 0; // types of x and y are contrived for example
1370 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1371 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1372 xElement->QueryIntText( &x );
1373 yElement->QueryFloatText( &y );
1374 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001375
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001376 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1377 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 -07001378
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001380 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001382 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001384 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001385 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001386 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001387 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001388 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001389
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001390 // internal:
1391 enum {
1392 OPEN, // <foo>
1393 CLOSED, // <foo/>
1394 CLOSING // </foo>
1395 };
1396 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001397 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001398 }
1399 char* ParseDeep( char* p, StrPair* endTag );
1400 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1401 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001402
Lee Thomason50adb4c2012-02-13 15:07:09 -08001403private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001404 XMLElement( XMLDocument* doc );
1405 virtual ~XMLElement();
1406 XMLElement( const XMLElement& ); // not supported
1407 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001408
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001409 XMLAttribute* FindAttribute( const char* name );
1410 XMLAttribute* FindOrCreateAttribute( const char* name );
1411 //void LinkAttribute( XMLAttribute* attrib );
1412 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001413
Lee Thomason624d43f2012-10-12 10:58:48 -07001414 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 // The attribute list is ordered; there is no 'lastAttribute'
1416 // because the list needs to be scanned for dupes before adding
1417 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001418 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001419};
1420
1421
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001422enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001423 PRESERVE_WHITESPACE,
1424 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001425};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001426
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001427
1428/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001429 It can be saved, loaded, and printed to the screen.
1430 All Nodes are connected and allocated to a Document.
1431 If the Document is deleted, all its Nodes are also deleted.
1432*/
PKEuS16ed47d2013-07-06 12:02:43 +02001433class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001434{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001435 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001436public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001437 /// constructor
1438 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1439 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001440
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001441 virtual XMLDocument* ToDocument() {
1442 return this;
1443 }
1444 virtual const XMLDocument* ToDocument() const {
1445 return this;
1446 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001447
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001448 /**
1449 Parse an XML file from a character string.
1450 Returns XML_NO_ERROR (0) on success, or
1451 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001452
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 You may optionally pass in the 'nBytes', which is
1454 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001455 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001456 null terminated string.
1457 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001458 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001459
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001460 /**
1461 Load an XML file from disk.
1462 Returns XML_NO_ERROR (0) on success, or
1463 an errorID.
1464 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001465 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001466
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001467 /**
1468 Load an XML file from disk. You are responsible
1469 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001470
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001471 Returns XML_NO_ERROR (0) on success, or
1472 an errorID.
1473 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001474 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001475
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001476 /**
1477 Save the XML file to disk.
1478 Returns XML_NO_ERROR (0) on success, or
1479 an errorID.
1480 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001481 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001482
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 /**
1484 Save the XML file to disk. You are responsible
1485 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001486
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001487 Returns XML_NO_ERROR (0) on success, or
1488 an errorID.
1489 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001490 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001491
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001492 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001493 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001494 }
1495 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001496 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001497 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001498
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 /**
1500 Returns true if this document has a leading Byte Order Mark of UTF8.
1501 */
1502 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001503 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001504 }
1505 /** Sets whether to write the BOM when writing the file.
1506 */
1507 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001508 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001509 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001510
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001511 /** Return the root element of DOM. Equivalent to FirstChildElement().
1512 To get the first node, use FirstChild().
1513 */
1514 XMLElement* RootElement() {
1515 return FirstChildElement();
1516 }
1517 const XMLElement* RootElement() const {
1518 return FirstChildElement();
1519 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001520
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001521 /** Print the Document. If the Printer is not provided, it will
1522 print to stdout. If you provide Printer, this can print to a file:
1523 @verbatim
1524 XMLPrinter printer( fp );
1525 doc.Print( &printer );
1526 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001527
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 Or you can use a printer to print to memory:
1529 @verbatim
1530 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001531 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 // printer.CStr() has a const char* to the XML
1533 @endverbatim
1534 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001535 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001536 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001537
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001538 /**
1539 Create a new Element associated with
1540 this Document. The memory for the Element
1541 is managed by the Document.
1542 */
1543 XMLElement* NewElement( const char* name );
1544 /**
1545 Create a new Comment associated with
1546 this Document. The memory for the Comment
1547 is managed by the Document.
1548 */
1549 XMLComment* NewComment( const char* comment );
1550 /**
1551 Create a new Text associated with
1552 this Document. The memory for the Text
1553 is managed by the Document.
1554 */
1555 XMLText* NewText( const char* text );
1556 /**
1557 Create a new Declaration associated with
1558 this Document. The memory for the object
1559 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001560
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001561 If the 'text' param is null, the standard
1562 declaration is used.:
1563 @verbatim
1564 <?xml version="1.0" encoding="UTF-8"?>
1565 @endverbatim
1566 */
1567 XMLDeclaration* NewDeclaration( const char* text=0 );
1568 /**
1569 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001570 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001571 is managed by the Document.
1572 */
1573 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001574
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001575 /**
1576 Delete a node associated with this document.
1577 It will be unlinked from the DOM.
1578 */
1579 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001580 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001581 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001582
Lee Thomason2fa81722012-11-09 12:37:46 -08001583 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001584
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001585 /// Return true if there was an error parsing the document.
1586 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001587 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 }
1589 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001590 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001591 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 }
1593 /// Return a possibly helpful diagnostic location or string.
1594 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001595 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 }
1597 /// Return a possibly helpful secondary diagnostic location or string.
1598 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001599 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001600 }
1601 /// If there is an error, print it to stdout.
1602 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001603
1604 /// Clear the document, resetting it to the initial state.
1605 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001606
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001607 // internal
1608 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001609
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001610 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1611 return 0;
1612 }
1613 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1614 return false;
1615 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001616
Lee Thomason3f57d272012-01-11 15:30:03 -08001617private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001618 XMLDocument( const XMLDocument& ); // not supported
1619 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001620
Lee Thomason2fa81722012-11-09 12:37:46 -08001621 bool _writeBOM;
1622 bool _processEntities;
1623 XMLError _errorID;
1624 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001625 const char* _errorStr1;
1626 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001627 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001628
Lee Thomason624d43f2012-10-12 10:58:48 -07001629 MemPoolT< sizeof(XMLElement) > _elementPool;
1630 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1631 MemPoolT< sizeof(XMLText) > _textPool;
1632 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001633};
1634
Lee Thomason7c913cd2012-01-26 18:32:34 -08001635
Lee Thomason3ffdd392012-03-28 17:27:55 -07001636/**
1637 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001638 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001639 DOM structure. It is a separate utility class.
1640
1641 Take an example:
1642 @verbatim
1643 <Document>
1644 <Element attributeA = "valueA">
1645 <Child attributeB = "value1" />
1646 <Child attributeB = "value2" />
1647 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001648 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001649 @endverbatim
1650
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001651 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001652 easy to write a *lot* of code that looks like:
1653
1654 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001655 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001656 if ( root )
1657 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001658 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001659 if ( element )
1660 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001661 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001662 if ( child )
1663 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001664 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001665 if ( child2 )
1666 {
1667 // Finally do something useful.
1668 @endverbatim
1669
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001670 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001671 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001672 and correct to use:
1673
1674 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001675 XMLHandle docHandle( &document );
1676 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001677 if ( child2 )
1678 {
1679 // do something useful
1680 @endverbatim
1681
1682 Which is MUCH more concise and useful.
1683
1684 It is also safe to copy handles - internally they are nothing more than node pointers.
1685 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001686 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001687 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001688
1689 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001690*/
PKEuS16ed47d2013-07-06 12:02:43 +02001691class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001692{
1693public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001694 /// 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 -07001695 XMLHandle( XMLNode* node ) {
1696 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
1698 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001699 XMLHandle( XMLNode& node ) {
1700 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 }
1702 /// Copy constructor
1703 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001704 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 }
1706 /// Assignment
1707 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001708 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 return *this;
1710 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001711
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001712 /// Get the first child of this handle.
1713 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 /// Get the first child element of this handle.
1717 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001718 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001719 }
1720 /// Get the last child of this handle.
1721 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 /// Get the last child element of this handle.
1725 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 /// Get the previous sibling of this handle.
1729 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 /// Get the previous sibling element of this handle.
1733 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 /// Get the next sibling of this handle.
1737 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
1740 /// Get the next sibling element of this handle.
1741 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001742 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001743 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001744
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001745 /// Safe cast to XMLNode. This can return null.
1746 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
1749 /// Safe cast to XMLElement. This can return null.
1750 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
1753 /// Safe cast to XMLText. This can return null.
1754 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001755 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 }
1757 /// Safe cast to XMLUnknown. This can return null.
1758 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001759 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001760 }
1761 /// Safe cast to XMLDeclaration. This can return null.
1762 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001763 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001764 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001765
1766private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001767 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001768};
1769
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001770
1771/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001772 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1773 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001774*/
PKEuS16ed47d2013-07-06 12:02:43 +02001775class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001776{
1777public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001778 XMLConstHandle( const XMLNode* node ) {
1779 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001781 XMLConstHandle( const XMLNode& node ) {
1782 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001783 }
1784 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001785 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 }
Lee Thomason8b899812012-04-04 15:58:16 -07001787
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001788 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001789 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001790 return *this;
1791 }
Lee Thomason8b899812012-04-04 15:58:16 -07001792
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001793 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001794 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001795 }
1796 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001797 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001798 }
1799 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001800 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001801 }
1802 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001803 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001804 }
1805 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001806 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001807 }
1808 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001809 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001810 }
1811 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001812 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 }
1814 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 }
Lee Thomason8b899812012-04-04 15:58:16 -07001817
1818
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001820 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001821 }
1822 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001823 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001824 }
1825 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001826 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001827 }
1828 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001829 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001830 }
1831 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001832 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001833 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001834
Lee Thomason5cae8972012-01-24 18:03:07 -08001835private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001836 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001837};
Lee Thomason6f381b72012-03-02 12:59:39 -08001838
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001839
1840/**
1841 Printing functionality. The XMLPrinter gives you more
1842 options than the XMLDocument::Print() method.
1843
1844 It can:
1845 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001846 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001847 -# Print XML without a XMLDocument.
1848
1849 Print to Memory
1850
1851 @verbatim
1852 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001853 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001854 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001855 @endverbatim
1856
1857 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001858
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001859 You provide the file pointer.
1860 @verbatim
1861 XMLPrinter printer( fp );
1862 doc.Print( &printer );
1863 @endverbatim
1864
1865 Print without a XMLDocument
1866
1867 When loading, an XML parser is very useful. However, sometimes
1868 when saving, it just gets in the way. The code is often set up
1869 for streaming, and constructing the DOM is just overhead.
1870
1871 The Printer supports the streaming case. The following code
1872 prints out a trivially simple XML file without ever creating
1873 an XML document.
1874
1875 @verbatim
1876 XMLPrinter printer( fp );
1877 printer.OpenElement( "foo" );
1878 printer.PushAttribute( "foo", "bar" );
1879 printer.CloseElement();
1880 @endverbatim
1881*/
PKEuS16ed47d2013-07-06 12:02:43 +02001882class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001883{
1884public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001885 /** Construct the printer. If the FILE* is specified,
1886 this will print to the FILE. Else it will print
1887 to memory, and the result is available in CStr().
1888 If 'compact' is set to true, then output is created
1889 with only required whitespace and newlines.
1890 */
PKEuS1bfb9542013-08-04 13:51:17 +02001891 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001892 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001893
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001894 /** If streaming, write the BOM and declaration. */
1895 void PushHeader( bool writeBOM, bool writeDeclaration );
1896 /** If streaming, start writing an element.
1897 The element must be closed with CloseElement()
1898 */
1899 void OpenElement( const char* name );
1900 /// If streaming, add an attribute to an open element.
1901 void PushAttribute( const char* name, const char* value );
1902 void PushAttribute( const char* name, int value );
1903 void PushAttribute( const char* name, unsigned value );
1904 void PushAttribute( const char* name, bool value );
1905 void PushAttribute( const char* name, double value );
1906 /// If streaming, close the Element.
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001907 virtual void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001908
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001909 /// Add a text node.
1910 void PushText( const char* text, bool cdata=false );
1911 /// Add a text node from an integer.
1912 void PushText( int value );
1913 /// Add a text node from an unsigned.
1914 void PushText( unsigned value );
1915 /// Add a text node from a bool.
1916 void PushText( bool value );
1917 /// Add a text node from a float.
1918 void PushText( float value );
1919 /// Add a text node from a double.
1920 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001921
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001922 /// Add a comment
1923 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001924
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001925 void PushDeclaration( const char* value );
1926 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001927
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001928 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1929 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1930 return true;
1931 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001932
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1934 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001935
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001936 virtual bool Visit( const XMLText& text );
1937 virtual bool Visit( const XMLComment& comment );
1938 virtual bool Visit( const XMLDeclaration& declaration );
1939 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001940
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001941 /**
1942 If in print to memory mode, return a pointer to
1943 the XML file in memory.
1944 */
1945 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001946 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 }
1948 /**
1949 If in print to memory mode, return the size
1950 of the XML file in memory. (Note the size returned
1951 includes the terminating null.)
1952 */
1953 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001954 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001955 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001956
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001957protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001958 void SealElement();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001959 bool _elementJustOpened;
1960 DynArray< const char*, 10 > _stack;
1961
1962private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001963 void PrintSpace( int depth );
1964 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1965 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001966
Lee Thomason624d43f2012-10-12 10:58:48 -07001967 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001968 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001969 int _depth;
1970 int _textDepth;
1971 bool _processEntities;
1972 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001973
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001974 enum {
1975 ENTITY_RANGE = 64,
1976 BUF_SIZE = 200
1977 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001978 bool _entityFlag[ENTITY_RANGE];
1979 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001980
Lee Thomason624d43f2012-10-12 10:58:48 -07001981 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001982#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001983 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001984#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001985};
1986
1987
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001988} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001989
PKEuS95060352013-07-26 10:42:44 +02001990#if defined(_MSC_VER)
1991# pragma warning(pop)
1992#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001993
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001994#endif // TINYXML2_INCLUDED