blob: aa86d0d3f41a53687c9225a41f3550ed23d556a8 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Jerome Martinez242c3ea2013-01-06 12:20:04 +010027#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080048 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010049
Lee Thomasona9cf3f92012-10-11 16:56:51 -070050 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
PKEuS16ed47d2013-07-06 12:02:43 +020061#ifdef _WIN32
62# ifdef TINYXML2_EXPORT
63# define TINYXML2_LIB __declspec(dllexport)
64# elif defined(TINYXML2_IMPORT)
65# define TINYXML2_LIB __declspec(dllimport)
66# else
67# define TINYXML2_LIB
68# endif
69#else
70# define TINYXML2_LIB
71#endif
72
73
U-Lama\Lee4cee6112011-12-31 14:58:18 -080074#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070075# if defined(_MSC_VER)
76# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
77# elif defined (ANDROID_NDK)
78# include <android/log.h>
79# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
80# else
81# include <assert.h>
82# define TIXMLASSERT assert
83# endif
84# else
85# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080086#endif
87
U-Lama\Leee13c3e62011-12-28 14:36:55 -080088
Lee Thomason1a1d4a72012-02-15 09:09:25 -080089#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070090// Microsoft visual studio, version 2005 and higher.
91/*int _snprintf_s(
92 char *buffer,
93 size_t sizeOfBuffer,
94 size_t count,
95 const char *format [,
96 argument] ...
97);*/
98inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
99{
100 va_list va;
101 va_start( va, format );
102 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
103 va_end( va );
104 return result;
105}
106#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700107#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700108// GCC version 3 and higher
109//#warning( "Using sn* functions." )
110#define TIXML_SNPRINTF snprintf
111#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800112#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800113
selfpoisede77e1952013-03-13 14:08:29 +0800114static const int TIXML2_MAJOR_VERSION = 1;
115static const int TIXML2_MINOR_VERSION = 0;
116static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800117
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800118namespace tinyxml2
119{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800120class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800121class XMLElement;
122class XMLAttribute;
123class XMLComment;
124class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800125class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800126class XMLDeclaration;
127class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800128
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800129class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800130
U-Stream\Leeae25a442012-02-17 17:48:16 -0800131/*
132 A class that wraps strings. Normally stores the start and end
133 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800134 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800135 manage) a traditional char[]
136*/
PKEuS16ed47d2013-07-06 12:02:43 +0200137class TINYXML2_LIB StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800138{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800139public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700140 enum {
141 NEEDS_ENTITY_PROCESSING = 0x01,
142 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800143 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800144
selfpoisede77e1952013-03-13 14:08:29 +0800145 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700146 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800147 ATTRIBUTE_NAME = 0,
148 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
149 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
150 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700151 };
Lee Thomason39ede242012-01-20 11:27:56 -0800152
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = start;
159 _end = end;
160 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700164
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700165 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700166 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 }
Lee Thomason39ede242012-01-20 11:27:56 -0800168
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700169 void SetInternedStr( const char* str ) {
170 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700171 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700173
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700174 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800175
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700176 char* ParseText( char* in, const char* endTag, int strFlags );
177 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800178
Lee Thomason39ede242012-01-20 11:27:56 -0800179private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700180 void Reset();
181 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800182
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 enum {
184 NEEDS_FLUSH = 0x100,
185 NEEDS_DELETE = 0x200
186 };
Lee Thomasone4422302012-01-20 17:59:50 -0800187
selfpoised4dd59bc2013-03-13 16:54:15 +0800188 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700189 int _flags;
190 char* _start;
191 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800192};
193
U-Lama\Lee560bd472011-12-28 19:42:49 -0800194
U-Stream\Leeae25a442012-02-17 17:48:16 -0800195/*
196 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
197 Has a small initial memory pool, so that low or no usage will not
198 cause a call to new/delete
199*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800200template <class T, int INIT>
PKEuS16ed47d2013-07-06 12:02:43 +0200201class TINYXML2_LIB DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800202{
203public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700204 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700205 _mem = _pool;
206 _allocated = INIT;
207 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700209
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700210 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700211 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700212 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 }
214 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700215
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700217 EnsureCapacity( _size+1 );
218 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800220
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700221 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700222 EnsureCapacity( _size+count );
223 T* ret = &_mem[_size];
224 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700225 return ret;
226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700229 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700230 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700231
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700232 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700233 TIXMLASSERT( _size >= count );
234 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800236
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700237 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700238 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700239 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700240
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700241 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700242 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700243 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700247 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700248 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700250
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700251 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700252 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700253 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700254
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700256 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700257 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700260 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700264 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800266
Lee Thomason2c85a712012-01-31 08:24:24 -0800267private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700268 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700269 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700270 int newAllocated = cap * 2;
271 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700272 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
273 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700274 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700275 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700276 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 }
279 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800280
Lee Thomason624d43f2012-10-12 10:58:48 -0700281 T* _mem;
282 T _pool[INIT];
283 int _allocated; // objects allocated
284 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800285};
286
Lee Thomason50adb4c2012-02-13 15:07:09 -0800287
U-Stream\Leeae25a442012-02-17 17:48:16 -0800288/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200289 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800290 and deallocation of objects.
291*/
PKEuS16ed47d2013-07-06 12:02:43 +0200292class TINYXML2_LIB MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800293{
294public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700295 MemPool() {}
296 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800297
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700298 virtual int ItemSize() const = 0;
299 virtual void* Alloc() = 0;
300 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800301 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800302};
303
Lee Thomason50adb4c2012-02-13 15:07:09 -0800304
U-Stream\Leeae25a442012-02-17 17:48:16 -0800305/*
306 Template child class to create pools of the correct type.
307*/
Lee Thomasond1983222012-02-06 08:41:24 -0800308template< int SIZE >
PKEuS16ed47d2013-07-06 12:02:43 +0200309class TINYXML2_LIB MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800310{
311public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800312 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 ~MemPoolT() {
314 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700315 for( int i=0; i<_blockPtrs.Size(); ++i ) {
316 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700317 }
318 }
Lee Thomasond1983222012-02-06 08:41:24 -0800319
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700320 virtual int ItemSize() const {
321 return SIZE;
322 }
323 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700324 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
Lee Thomasond1983222012-02-06 08:41:24 -0800326
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700327 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700328 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700329 // Need a new block.
330 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700331 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800332
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 for( int i=0; i<COUNT-1; ++i ) {
334 block->chunk[i].next = &block->chunk[i+1];
335 }
336 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700337 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700338 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 void* result = _root;
340 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800341
Lee Thomason624d43f2012-10-12 10:58:48 -0700342 ++_currentAllocs;
343 if ( _currentAllocs > _maxAllocs ) {
344 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700345 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700346 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800347 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700348 return result;
349 }
350 virtual void Free( void* mem ) {
351 if ( !mem ) {
352 return;
353 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700355 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700356#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700357 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700358#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700359 chunk->next = _root;
360 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700361 }
362 void Trace( const char* name ) {
363 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700364 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 }
Lee Thomasond1983222012-02-06 08:41:24 -0800366
Lee Thomason5b0a6772012-11-19 13:54:42 -0800367 void SetTracked() {
368 _nUntracked--;
369 }
370
371 int Untracked() const {
372 return _nUntracked;
373 }
374
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800375 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
376 // The test file is large, 170k.
377 // Release: VS2010 gcc(no opt)
378 // 1k: 4000
379 // 2k: 4000
380 // 4k: 3900 21000
381 // 16k: 5200
382 // 32k: 4300
383 // 64k: 4000 21000
384 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 +0200385
Lee Thomasond1983222012-02-06 08:41:24 -0800386private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700387 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700388 Chunk* next;
389 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700390 };
391 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700392 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700394 DynArray< Block*, 10 > _blockPtrs;
395 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800396
Lee Thomason624d43f2012-10-12 10:58:48 -0700397 int _currentAllocs;
398 int _nAllocs;
399 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800400 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800401};
402
Lee Thomason2c85a712012-01-31 08:24:24 -0800403
Lee Thomason56bdd022012-02-09 18:16:58 -0800404
405/**
406 Implements the interface to the "Visitor pattern" (see the Accept() method.)
407 If you call the Accept() method, it requires being passed a XMLVisitor
408 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200409 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800410 are simply called with Visit().
411
412 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700413 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800414
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700415 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800416 visiting). You need to only override methods that are interesting to you.
417
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600418 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800419
420 You should never change the document from a callback.
421
422 @sa XMLNode::Accept()
423*/
PKEuS16ed47d2013-07-06 12:02:43 +0200424class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800425{
426public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700427 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800428
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700429 /// Visit a document.
430 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
431 return true;
432 }
433 /// Visit a document.
434 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
435 return true;
436 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800437
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700438 /// Visit an element.
439 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
440 return true;
441 }
442 /// Visit an element.
443 virtual bool VisitExit( const XMLElement& /*element*/ ) {
444 return true;
445 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800446
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700447 /// Visit a declaration.
448 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
449 return true;
450 }
451 /// Visit a text node.
452 virtual bool Visit( const XMLText& /*text*/ ) {
453 return true;
454 }
455 /// Visit a comment node.
456 virtual bool Visit( const XMLComment& /*comment*/ ) {
457 return true;
458 }
459 /// Visit an unknown node.
460 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
461 return true;
462 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800463};
464
465
U-Stream\Leeae25a442012-02-17 17:48:16 -0800466/*
467 Utility functionality.
468*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800469class XMLUtil
470{
Lee Thomasond1983222012-02-06 08:41:24 -0800471public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700472 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
473 // correct, but simple, and usually works.
474 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100475 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700476 ++p;
477 }
478 return p;
479 }
480 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100481 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700482 ++p;
483 }
484 return p;
485 }
486 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100487 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700488 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200489
490 inline static bool IsNameStartChar( unsigned char ch ) {
491 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
492 || ch == ':'
493 || ch == '_';
494 }
495
496 inline static bool IsNameChar( unsigned char ch ) {
497 return IsNameStartChar( ch )
498 || isdigit( ch )
499 || ch == '.'
500 || ch == '-';
501 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800502
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700503 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
504 int n = 0;
505 if ( p == q ) {
506 return true;
507 }
508 while( *p && *q && *p == *q && n<nChar ) {
509 ++p;
510 ++q;
511 ++n;
512 }
513 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
514 return true;
515 }
516 return false;
517 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200518
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700519 inline static int IsUTF8Continuation( const char p ) {
520 return p & 0x80;
521 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800522
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700523 static const char* ReadBOM( const char* p, bool* hasBOM );
524 // p is the starting location,
525 // the UTF-8 value of the entity will be placed in value, and length filled in.
526 static const char* GetCharacterRef( const char* p, char* value, int* length );
527 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700528
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700529 // converts primitive types to strings
530 static void ToStr( int v, char* buffer, int bufferSize );
531 static void ToStr( unsigned v, char* buffer, int bufferSize );
532 static void ToStr( bool v, char* buffer, int bufferSize );
533 static void ToStr( float v, char* buffer, int bufferSize );
534 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700535
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700536 // converts strings to primitive types
537 static bool ToInt( const char* str, int* value );
538 static bool ToUnsigned( const char* str, unsigned* value );
539 static bool ToBool( const char* str, bool* value );
540 static bool ToFloat( const char* str, float* value );
541 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800542};
543
Lee Thomason5cae8972012-01-24 18:03:07 -0800544
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800545/** XMLNode is a base class for every object that is in the
546 XML Document Object Model (DOM), except XMLAttributes.
547 Nodes have siblings, a parent, and children which can
548 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700549 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800550 be cast to its more defined type.
551
Thomas Roß08bdf502012-05-12 14:21:23 +0200552 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800553 When the XMLDocument gets deleted, all its Nodes
554 will also be deleted.
555
556 @verbatim
557 A Document can contain: Element (container or leaf)
558 Comment (leaf)
559 Unknown (leaf)
560 Declaration( leaf )
561
562 An Element can contain: Element (container or leaf)
563 Text (leaf)
564 Attributes (not on tree)
565 Comment (leaf)
566 Unknown (leaf)
567
568 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800569*/
PKEuS16ed47d2013-07-06 12:02:43 +0200570class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800571{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700572 friend class XMLDocument;
573 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800574public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800575
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700576 /// Get the XMLDocument that owns this XMLNode.
577 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700578 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700579 }
580 /// Get the XMLDocument that owns this XMLNode.
581 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700582 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700583 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800584
Lee Thomason2fa81722012-11-09 12:37:46 -0800585 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700586 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100587 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700588 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800589 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700590 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100591 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700592 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800593 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100595 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700596 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800597 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 virtual XMLDocument* ToDocument() {
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 Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 virtual XMLDeclaration* ToDeclaration() {
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 an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100607 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800609
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 virtual const XMLElement* ToElement() const {
611 return 0;
612 }
613 virtual const XMLText* ToText() const {
614 return 0;
615 }
616 virtual const XMLComment* ToComment() const {
617 return 0;
618 }
619 virtual const XMLDocument* ToDocument() const {
620 return 0;
621 }
622 virtual const XMLDeclaration* ToDeclaration() const {
623 return 0;
624 }
625 virtual const XMLUnknown* ToUnknown() const {
626 return 0;
627 }
Lee Thomason751da522012-02-10 08:50:51 -0800628
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700629 /** The meaning of 'value' changes for the specific type.
630 @verbatim
631 Document: empty
632 Element: name of the element
633 Comment: the comment text
634 Unknown: the tag contents
635 Text: the text string
636 @endverbatim
637 */
638 const char* Value() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700639 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700640 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100641
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700642 /** Set the Value of an XML node.
643 @sa Value()
644 */
645 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800646
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700647 /// Get the parent of this node on the DOM.
648 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700649 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100651
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700652 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700653 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700654 }
Lee Thomason751da522012-02-10 08:50:51 -0800655
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 /// Returns true if this node has no children.
657 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700658 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700659 }
Lee Thomason751da522012-02-10 08:50:51 -0800660
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700661 /// Get the first child node, or null if none exists.
662 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700663 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100665
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700666 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700667 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700668 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100669
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 /** Get the first child element, or optionally the first child
671 element with the specified name.
672 */
673 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700674
675 XMLElement* FirstChildElement( const char* value=0 ) {
676 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700677 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800678
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700679 /// Get the last child node, or null if none exists.
680 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700681 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700682 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700683
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700684 XMLNode* LastChild() {
685 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
686 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800687
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 /** Get the last child element or optionally the last child
689 element with the specified name.
690 */
691 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700692
693 XMLElement* LastChildElement( const char* value=0 ) {
694 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700695 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700696
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 /// Get the previous (left) sibling node of this node.
698 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700699 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700700 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700701
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700702 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700703 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800705
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700706 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700707 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700708
709 XMLElement* PreviousSiblingElement( const char* value=0 ) {
710 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700711 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700712
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 /// Get the next (right) sibling node of this node.
714 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700715 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700717
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700718 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700719 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700721
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700722 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700723 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700724
725 XMLElement* NextSiblingElement( const char* value=0 ) {
726 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700727 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 /**
730 Add a child node as the last (right) child.
731 */
732 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800733
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700734 XMLNode* LinkEndChild( XMLNode* addThis ) {
735 return InsertEndChild( addThis );
736 }
737 /**
738 Add a child node as the first (left) child.
739 */
740 XMLNode* InsertFirstChild( XMLNode* addThis );
741 /**
742 Add a node after the specified child node.
743 */
744 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700745
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700746 /**
747 Delete all the children of this node.
748 */
749 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800750
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700751 /**
752 Delete a child of this node.
753 */
754 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800755
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700756 /**
757 Make a copy of this node, but not its children.
758 You may pass in a Document pointer that will be
759 the owner of the new Node. If the 'document' is
760 null, then the node returned will be allocated
761 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800762
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700763 Note: if called on a XMLDocument, this will return null.
764 */
765 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800766
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700767 /**
768 Test if 2 nodes are the same, but don't test children.
769 The 2 nodes do not need to be in the same Document.
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 false.
772 */
773 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800774
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600775 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700776 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600777 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800778
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600779 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
780 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700781 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800782
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700783 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800784
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700785 - http://www.saxproject.org/
786 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800787
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700788 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800789
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700790 An example of using Accept():
791 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600792 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700793 tinyxmlDoc.Accept( &printer );
794 const char* xmlcstr = printer.CStr();
795 @endverbatim
796 */
797 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800798
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700799 // internal
800 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800801
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800802protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700803 XMLNode( XMLDocument* );
804 virtual ~XMLNode();
805 XMLNode( const XMLNode& ); // not supported
806 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700807
Lee Thomason624d43f2012-10-12 10:58:48 -0700808 XMLDocument* _document;
809 XMLNode* _parent;
810 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800811
Lee Thomason624d43f2012-10-12 10:58:48 -0700812 XMLNode* _firstChild;
813 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800814
Lee Thomason624d43f2012-10-12 10:58:48 -0700815 XMLNode* _prev;
816 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800817
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800818private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700819 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700820 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800821};
822
823
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800824/** XML text.
825
826 Note that a text node can have child element nodes, for example:
827 @verbatim
828 <root>This is <b>bold</b></root>
829 @endverbatim
830
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700831 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800832 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 -0700833 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600834 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800835*/
PKEuS16ed47d2013-07-06 12:02:43 +0200836class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800837{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700838 friend class XMLBase;
839 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800840public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700841 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800842
Lee Thomason624d43f2012-10-12 10:58:48 -0700843 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 return this;
845 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700846 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 return this;
848 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800849
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700850 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700851 void SetCData( bool isCData ) {
852 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700853 }
854 /// Returns true if this is a CDATA text element.
855 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700856 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800858
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700859 char* ParseDeep( char*, StrPair* endTag );
860 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
861 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800862
Lee Thomason5492a1c2012-01-23 15:32:10 -0800863protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700864 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700865 virtual ~XMLText() {}
866 XMLText( const XMLText& ); // not supported
867 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800868
869private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700870 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800871};
872
873
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800874/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200875class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800876{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700877 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800878public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700879 virtual XMLComment* ToComment() {
880 return this;
881 }
882 virtual const XMLComment* ToComment() const {
883 return this;
884 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800885
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700886 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800887
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700888 char* ParseDeep( char*, StrPair* endTag );
889 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
890 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800891
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800892protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700893 XMLComment( XMLDocument* doc );
894 virtual ~XMLComment();
895 XMLComment( const XMLComment& ); // not supported
896 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800897
Lee Thomason3f57d272012-01-11 15:30:03 -0800898private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800899};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800900
901
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800902/** In correct XML the declaration is the first entry in the file.
903 @verbatim
904 <?xml version="1.0" standalone="yes"?>
905 @endverbatim
906
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600907 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800908 however.
909
910 The text of the declaration isn't interpreted. It is parsed
911 and written as a string.
912*/
PKEuS16ed47d2013-07-06 12:02:43 +0200913class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800914{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700915 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800916public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700917 virtual XMLDeclaration* ToDeclaration() {
918 return this;
919 }
920 virtual const XMLDeclaration* ToDeclaration() const {
921 return this;
922 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800923
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700924 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800925
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700926 char* ParseDeep( char*, StrPair* endTag );
927 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
928 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800929
930protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700931 XMLDeclaration( XMLDocument* doc );
932 virtual ~XMLDeclaration();
933 XMLDeclaration( const XMLDeclaration& ); // not supported
934 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800935};
936
937
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600938/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800939 unknown. It is a tag of text, but should not be modified.
940 It will be written back to the XML, unchanged, when the file
941 is saved.
942
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600943 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800944*/
PKEuS16ed47d2013-07-06 12:02:43 +0200945class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800946{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700947 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800948public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700949 virtual XMLUnknown* ToUnknown() {
950 return this;
951 }
952 virtual const XMLUnknown* ToUnknown() const {
953 return this;
954 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800955
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700956 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800957
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700958 char* ParseDeep( char*, StrPair* endTag );
959 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
960 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800961
962protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700963 XMLUnknown( XMLDocument* doc );
964 virtual ~XMLUnknown();
965 XMLUnknown( const XMLUnknown& ); // not supported
966 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800967};
968
969
Lee Thomason2fa81722012-11-09 12:37:46 -0800970enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700971 XML_NO_ERROR = 0,
972 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800973
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700974 XML_NO_ATTRIBUTE,
975 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800976
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 XML_ERROR_FILE_NOT_FOUND,
978 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
979 XML_ERROR_FILE_READ_ERROR,
980 XML_ERROR_ELEMENT_MISMATCH,
981 XML_ERROR_PARSING_ELEMENT,
982 XML_ERROR_PARSING_ATTRIBUTE,
983 XML_ERROR_IDENTIFYING_TAG,
984 XML_ERROR_PARSING_TEXT,
985 XML_ERROR_PARSING_CDATA,
986 XML_ERROR_PARSING_COMMENT,
987 XML_ERROR_PARSING_DECLARATION,
988 XML_ERROR_PARSING_UNKNOWN,
989 XML_ERROR_EMPTY_DOCUMENT,
990 XML_ERROR_MISMATCHED_ELEMENT,
991 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700992
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700993 XML_CAN_NOT_CONVERT_TEXT,
994 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800995};
996
997
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800998/** An attribute is a name-value pair. Elements have an arbitrary
999 number of attributes, each with a unique name.
1000
1001 @note The attributes are not XMLNodes. You may only query the
1002 Next() attribute in a list.
1003*/
PKEuS16ed47d2013-07-06 12:02:43 +02001004class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001005{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001006 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001007public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001008 /// The name of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001009 const char* Name() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001010 return _name.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001011 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001012 /// The value of the attribute.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001013 const char* Value() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001014 return _value.GetStr();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001015 }
Lee Thomason2fa81722012-11-09 12:37:46 -08001016 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001017 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001018 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001019 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001020
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001021 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001023 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001024 */
1025 int IntValue() const {
1026 int i=0;
1027 QueryIntValue( &i );
1028 return i;
1029 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001030 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001031 unsigned UnsignedValue() const {
1032 unsigned i=0;
1033 QueryUnsignedValue( &i );
1034 return i;
1035 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001036 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001037 bool BoolValue() const {
1038 bool b=false;
1039 QueryBoolValue( &b );
1040 return b;
1041 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001042 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001043 double DoubleValue() const {
1044 double d=0;
1045 QueryDoubleValue( &d );
1046 return d;
1047 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001048 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001049 float FloatValue() const {
1050 float f=0;
1051 QueryFloatValue( &f );
1052 return f;
1053 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001054
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001055 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001056 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1058 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001059 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001060 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001061 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001062 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001063 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001064 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001065 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001067 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001068
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001069 /// Set the attribute to a string value.
1070 void SetAttribute( const char* value );
1071 /// Set the attribute to value.
1072 void SetAttribute( int value );
1073 /// Set the attribute to value.
1074 void SetAttribute( unsigned value );
1075 /// Set the attribute to value.
1076 void SetAttribute( bool value );
1077 /// Set the attribute to value.
1078 void SetAttribute( double value );
1079 /// Set the attribute to value.
1080 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001081
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001082private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001083 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001084
Thomas Roß61892312013-05-12 14:07:38 +02001085 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001086 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001087
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001088 XMLAttribute( const XMLAttribute& ); // not supported
1089 void operator=( const XMLAttribute& ); // not supported
1090 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001091
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001092 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001093
Lee Thomason624d43f2012-10-12 10:58:48 -07001094 mutable StrPair _name;
1095 mutable StrPair _value;
1096 XMLAttribute* _next;
1097 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001098};
1099
1100
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001101/** The element is a container class. It has a value, the element name,
1102 and can contain other elements, text, comments, and unknowns.
1103 Elements also contain an arbitrary number of attributes.
1104*/
PKEuS16ed47d2013-07-06 12:02:43 +02001105class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001106{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001107 friend class XMLBase;
1108 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001109public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001110 /// Get the name of an element (which is the Value() of the node.)
1111 const char* Name() const {
1112 return Value();
1113 }
1114 /// Set the name of the element.
1115 void SetName( const char* str, bool staticMem=false ) {
1116 SetValue( str, staticMem );
1117 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001118
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001119 virtual XMLElement* ToElement() {
1120 return this;
1121 }
1122 virtual const XMLElement* ToElement() const {
1123 return this;
1124 }
1125 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001126
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001127 /** Given an attribute name, Attribute() returns the value
1128 for the attribute of that name, or null if none
1129 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001130
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001131 @verbatim
1132 const char* value = ele->Attribute( "foo" );
1133 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001134
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001135 The 'value' parameter is normally null. However, if specified,
1136 the attribute will only be returned if the 'name' and 'value'
1137 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001138
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 @verbatim
1140 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1141 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 rather than:
1144 @verbatim
1145 if ( ele->Attribute( "foo" ) ) {
1146 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1147 }
1148 @endverbatim
1149 */
1150 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001151
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001152 /** Given an attribute name, IntAttribute() returns the value
1153 of the attribute interpreted as an integer. 0 will be
1154 returned if there is an error. For a method with error
1155 checking, see QueryIntAttribute()
1156 */
1157 int IntAttribute( const char* name ) const {
1158 int i=0;
1159 QueryIntAttribute( name, &i );
1160 return i;
1161 }
1162 /// See IntAttribute()
1163 unsigned UnsignedAttribute( const char* name ) const {
1164 unsigned i=0;
1165 QueryUnsignedAttribute( name, &i );
1166 return i;
1167 }
1168 /// See IntAttribute()
1169 bool BoolAttribute( const char* name ) const {
1170 bool b=false;
1171 QueryBoolAttribute( name, &b );
1172 return b;
1173 }
1174 /// See IntAttribute()
1175 double DoubleAttribute( const char* name ) const {
1176 double d=0;
1177 QueryDoubleAttribute( name, &d );
1178 return d;
1179 }
1180 /// See IntAttribute()
1181 float FloatAttribute( const char* name ) const {
1182 float f=0;
1183 QueryFloatAttribute( name, &f );
1184 return f;
1185 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001186
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001187 /** Given an attribute name, QueryIntAttribute() returns
1188 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1189 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1190 doesn't exist. If successful, the result of the conversion
1191 will be written to 'value'. If not successful, nothing will
1192 be written to 'value'. This allows you to provide default
1193 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001194
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001195 @verbatim
1196 int value = 10;
1197 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1198 @endverbatim
1199 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001200 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001201 const XMLAttribute* a = FindAttribute( name );
1202 if ( !a ) {
1203 return XML_NO_ATTRIBUTE;
1204 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001205 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001206 }
1207 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001208 XMLError QueryUnsignedAttribute( const char* name, unsigned 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->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001214 }
1215 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001216 XMLError QueryBoolAttribute( const char* name, bool* 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->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001222 }
1223 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001224 XMLError QueryDoubleAttribute( const char* name, double* 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->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001230 }
1231 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001232 XMLError QueryFloatAttribute( const char* name, float* 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->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001238 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001239
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001240
1241 /** Given an attribute name, QueryAttribute() returns
1242 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1243 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1244 doesn't exist. It is overloaded for the primitive types,
1245 and is a generally more convenient replacement of
1246 QueryIntAttribute() and related functions.
1247
1248 If successful, the result of the conversion
1249 will be written to 'value'. If not successful, nothing will
1250 be written to 'value'. This allows you to provide default
1251 value:
1252
1253 @verbatim
1254 int value = 10;
1255 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1256 @endverbatim
1257 */
1258 int QueryAttribute( const char* name, int* value ) const {
1259 return QueryIntAttribute( name, value );
1260 }
1261
1262 int QueryAttribute( const char* name, unsigned int* value ) const {
1263 return QueryUnsignedAttribute( name, value );
1264 }
1265
1266 int QueryAttribute( const char* name, bool* value ) const {
1267 return QueryBoolAttribute( name, value );
1268 }
1269
1270 int QueryAttribute( const char* name, double* value ) const {
1271 return QueryDoubleAttribute( name, value );
1272 }
1273
1274 int QueryAttribute( const char* name, float* value ) const {
1275 return QueryFloatAttribute( name, value );
1276 }
1277
1278 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001279 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001280 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001281 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001282 }
1283 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001284 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001285 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001286 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001287 }
1288 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001289 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001290 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001291 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001292 }
1293 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001294 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001295 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001296 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001297 }
1298 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001299 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001300 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001301 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001302 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001303
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 /**
1305 Delete an attribute.
1306 */
1307 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001308
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001309 /// Return the first attribute in the list.
1310 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001311 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001312 }
1313 /// Query a specific attribute in the list.
1314 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001315
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001317 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001318 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001319
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001320 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001321 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001322
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001323 This is a convenient method for getting the text of simple contained text:
1324 @verbatim
1325 <foo>This is text</foo>
1326 const char* str = fooElement->GetText();
1327 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001328
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001330
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001331 Note that this function can be misleading. If the element foo was created from
1332 this XML:
1333 @verbatim
1334 <foo><b>This is text</b></foo>
1335 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001336
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001337 then the value of str would be null. The first child node isn't a text node, it is
1338 another element. From this XML:
1339 @verbatim
1340 <foo>This is <b>text</b></foo>
1341 @endverbatim
1342 GetText() will return "This is ".
1343 */
1344 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001345
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001346 /**
1347 Convenience method to query the value of a child text node. This is probably best
1348 shown by example. Given you have a document is this form:
1349 @verbatim
1350 <point>
1351 <x>1</x>
1352 <y>1.4</y>
1353 </point>
1354 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001355
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001356 The QueryIntText() and similar functions provide a safe and easier way to get to the
1357 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001358
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 @verbatim
1360 int x = 0;
1361 float y = 0; // types of x and y are contrived for example
1362 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1363 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1364 xElement->QueryIntText( &x );
1365 yElement->QueryFloatText( &y );
1366 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001367
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001368 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1369 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 -07001370
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001371 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001372 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001373 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001374 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001375 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001376 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001378 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001380 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001381
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001382 // internal:
1383 enum {
1384 OPEN, // <foo>
1385 CLOSED, // <foo/>
1386 CLOSING // </foo>
1387 };
1388 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001389 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001390 }
1391 char* ParseDeep( char* p, StrPair* endTag );
1392 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1393 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001394
Lee Thomason50adb4c2012-02-13 15:07:09 -08001395private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001396 XMLElement( XMLDocument* doc );
1397 virtual ~XMLElement();
1398 XMLElement( const XMLElement& ); // not supported
1399 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001400
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001401 XMLAttribute* FindAttribute( const char* name );
1402 XMLAttribute* FindOrCreateAttribute( const char* name );
1403 //void LinkAttribute( XMLAttribute* attrib );
1404 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001405
Lee Thomason624d43f2012-10-12 10:58:48 -07001406 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001407 // The attribute list is ordered; there is no 'lastAttribute'
1408 // because the list needs to be scanned for dupes before adding
1409 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001410 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001411};
1412
1413
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001414enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001415 PRESERVE_WHITESPACE,
1416 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001417};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001418
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001419
1420/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001421 It can be saved, loaded, and printed to the screen.
1422 All Nodes are connected and allocated to a Document.
1423 If the Document is deleted, all its Nodes are also deleted.
1424*/
PKEuS16ed47d2013-07-06 12:02:43 +02001425class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001426{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001427 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001428public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001429 /// constructor
1430 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1431 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001432
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001433 virtual XMLDocument* ToDocument() {
1434 return this;
1435 }
1436 virtual const XMLDocument* ToDocument() const {
1437 return this;
1438 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001439
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001440 /**
1441 Parse an XML file from a character string.
1442 Returns XML_NO_ERROR (0) on success, or
1443 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001444
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001445 You may optionally pass in the 'nBytes', which is
1446 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001447 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001448 null terminated string.
1449 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001450 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001451
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 /**
1453 Load an XML file from disk.
1454 Returns XML_NO_ERROR (0) on success, or
1455 an errorID.
1456 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001457 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001458
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001459 /**
1460 Load an XML file from disk. You are responsible
1461 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001462
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001463 Returns XML_NO_ERROR (0) on success, or
1464 an errorID.
1465 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001466 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001467
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001468 /**
1469 Save the XML file to disk.
1470 Returns XML_NO_ERROR (0) on success, or
1471 an errorID.
1472 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001473 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001474
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001475 /**
1476 Save the XML file to disk. You are responsible
1477 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001478
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001479 Returns XML_NO_ERROR (0) on success, or
1480 an errorID.
1481 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001482 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001483
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001484 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001485 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001486 }
1487 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001488 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001489 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001490
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001491 /**
1492 Returns true if this document has a leading Byte Order Mark of UTF8.
1493 */
1494 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001495 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 }
1497 /** Sets whether to write the BOM when writing the file.
1498 */
1499 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001500 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001501 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001502
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001503 /** Return the root element of DOM. Equivalent to FirstChildElement().
1504 To get the first node, use FirstChild().
1505 */
1506 XMLElement* RootElement() {
1507 return FirstChildElement();
1508 }
1509 const XMLElement* RootElement() const {
1510 return FirstChildElement();
1511 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001512
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001513 /** Print the Document. If the Printer is not provided, it will
1514 print to stdout. If you provide Printer, this can print to a file:
1515 @verbatim
1516 XMLPrinter printer( fp );
1517 doc.Print( &printer );
1518 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001519
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001520 Or you can use a printer to print to memory:
1521 @verbatim
1522 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001523 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 // printer.CStr() has a const char* to the XML
1525 @endverbatim
1526 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001527 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001529
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001530 /**
1531 Create a new Element associated with
1532 this Document. The memory for the Element
1533 is managed by the Document.
1534 */
1535 XMLElement* NewElement( const char* name );
1536 /**
1537 Create a new Comment associated with
1538 this Document. The memory for the Comment
1539 is managed by the Document.
1540 */
1541 XMLComment* NewComment( const char* comment );
1542 /**
1543 Create a new Text associated with
1544 this Document. The memory for the Text
1545 is managed by the Document.
1546 */
1547 XMLText* NewText( const char* text );
1548 /**
1549 Create a new Declaration associated with
1550 this Document. The memory for the object
1551 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001552
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001553 If the 'text' param is null, the standard
1554 declaration is used.:
1555 @verbatim
1556 <?xml version="1.0" encoding="UTF-8"?>
1557 @endverbatim
1558 */
1559 XMLDeclaration* NewDeclaration( const char* text=0 );
1560 /**
1561 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001562 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001563 is managed by the Document.
1564 */
1565 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001566
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 /**
1568 Delete a node associated with this document.
1569 It will be unlinked from the DOM.
1570 */
1571 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001572 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001573 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001574
Lee Thomason2fa81722012-11-09 12:37:46 -08001575 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001576
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 /// Return true if there was an error parsing the document.
1578 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001579 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001580 }
1581 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001582 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001583 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 }
1585 /// Return a possibly helpful diagnostic location or string.
1586 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001587 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 }
1589 /// Return a possibly helpful secondary diagnostic location or string.
1590 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001591 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 }
1593 /// If there is an error, print it to stdout.
1594 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001595
1596 /// Clear the document, resetting it to the initial state.
1597 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001598
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001599 // internal
1600 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001601
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1603 return 0;
1604 }
1605 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1606 return false;
1607 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001608
Lee Thomason3f57d272012-01-11 15:30:03 -08001609private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001610 XMLDocument( const XMLDocument& ); // not supported
1611 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001612
Lee Thomason2fa81722012-11-09 12:37:46 -08001613 bool _writeBOM;
1614 bool _processEntities;
1615 XMLError _errorID;
1616 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001617 const char* _errorStr1;
1618 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001619 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001620
Lee Thomason624d43f2012-10-12 10:58:48 -07001621 MemPoolT< sizeof(XMLElement) > _elementPool;
1622 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1623 MemPoolT< sizeof(XMLText) > _textPool;
1624 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001625};
1626
Lee Thomason7c913cd2012-01-26 18:32:34 -08001627
Lee Thomason3ffdd392012-03-28 17:27:55 -07001628/**
1629 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001630 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001631 DOM structure. It is a separate utility class.
1632
1633 Take an example:
1634 @verbatim
1635 <Document>
1636 <Element attributeA = "valueA">
1637 <Child attributeB = "value1" />
1638 <Child attributeB = "value2" />
1639 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001640 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001641 @endverbatim
1642
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001643 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001644 easy to write a *lot* of code that looks like:
1645
1646 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001647 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001648 if ( root )
1649 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001650 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001651 if ( element )
1652 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001653 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001654 if ( child )
1655 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001656 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001657 if ( child2 )
1658 {
1659 // Finally do something useful.
1660 @endverbatim
1661
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001662 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001663 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001664 and correct to use:
1665
1666 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001667 XMLHandle docHandle( &document );
1668 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001669 if ( child2 )
1670 {
1671 // do something useful
1672 @endverbatim
1673
1674 Which is MUCH more concise and useful.
1675
1676 It is also safe to copy handles - internally they are nothing more than node pointers.
1677 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001678 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001679 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001680
1681 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001682*/
PKEuS16ed47d2013-07-06 12:02:43 +02001683class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001684{
1685public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001686 /// 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 -07001687 XMLHandle( XMLNode* node ) {
1688 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001689 }
1690 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001691 XMLHandle( XMLNode& node ) {
1692 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001693 }
1694 /// Copy constructor
1695 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001696 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
1698 /// Assignment
1699 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 return *this;
1702 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001703
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001704 /// Get the first child of this handle.
1705 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001706 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001707 }
1708 /// Get the first child element of this handle.
1709 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001710 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001711 }
1712 /// Get the last child of this handle.
1713 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 /// Get the last child element of this handle.
1717 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001718 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001719 }
1720 /// Get the previous sibling of this handle.
1721 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 /// Get the previous sibling element of this handle.
1725 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 /// Get the next sibling of this handle.
1729 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 /// Get the next sibling element of this handle.
1733 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001736
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001737 /// Safe cast to XMLNode. This can return null.
1738 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001739 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001740 }
1741 /// Safe cast to XMLElement. This can return null.
1742 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001743 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
1745 /// Safe cast to XMLText. This can return null.
1746 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
1749 /// Safe cast to XMLUnknown. This can return null.
1750 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
1753 /// Safe cast to XMLDeclaration. This can return null.
1754 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001755 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001757
1758private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001759 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001760};
1761
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001762
1763/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001764 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1765 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001766*/
PKEuS16ed47d2013-07-06 12:02:43 +02001767class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001768{
1769public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001770 XMLConstHandle( const XMLNode* node ) {
1771 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001772 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001773 XMLConstHandle( const XMLNode& node ) {
1774 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001775 }
1776 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001777 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001778 }
Lee Thomason8b899812012-04-04 15:58:16 -07001779
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001780 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001781 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001782 return *this;
1783 }
Lee Thomason8b899812012-04-04 15:58:16 -07001784
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001785 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001786 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001787 }
1788 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001789 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001790 }
1791 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001792 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001793 }
1794 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001795 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001796 }
1797 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001798 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 }
1800 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001801 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001802 }
1803 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001804 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001805 }
1806 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001807 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001808 }
Lee Thomason8b899812012-04-04 15:58:16 -07001809
1810
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001811 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001812 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001813 }
1814 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001815 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001816 }
1817 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001818 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001819 }
1820 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001821 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001822 }
1823 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001824 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001825 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001826
Lee Thomason5cae8972012-01-24 18:03:07 -08001827private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001828 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001829};
Lee Thomason6f381b72012-03-02 12:59:39 -08001830
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001831
1832/**
1833 Printing functionality. The XMLPrinter gives you more
1834 options than the XMLDocument::Print() method.
1835
1836 It can:
1837 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001838 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001839 -# Print XML without a XMLDocument.
1840
1841 Print to Memory
1842
1843 @verbatim
1844 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001845 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001846 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001847 @endverbatim
1848
1849 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001850
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001851 You provide the file pointer.
1852 @verbatim
1853 XMLPrinter printer( fp );
1854 doc.Print( &printer );
1855 @endverbatim
1856
1857 Print without a XMLDocument
1858
1859 When loading, an XML parser is very useful. However, sometimes
1860 when saving, it just gets in the way. The code is often set up
1861 for streaming, and constructing the DOM is just overhead.
1862
1863 The Printer supports the streaming case. The following code
1864 prints out a trivially simple XML file without ever creating
1865 an XML document.
1866
1867 @verbatim
1868 XMLPrinter printer( fp );
1869 printer.OpenElement( "foo" );
1870 printer.PushAttribute( "foo", "bar" );
1871 printer.CloseElement();
1872 @endverbatim
1873*/
PKEuS16ed47d2013-07-06 12:02:43 +02001874class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001875{
1876public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001877 /** Construct the printer. If the FILE* is specified,
1878 this will print to the FILE. Else it will print
1879 to memory, and the result is available in CStr().
1880 If 'compact' is set to true, then output is created
1881 with only required whitespace and newlines.
1882 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001883 XMLPrinter( FILE* file=0, bool compact = false );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001884 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001885
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001886 /** If streaming, write the BOM and declaration. */
1887 void PushHeader( bool writeBOM, bool writeDeclaration );
1888 /** If streaming, start writing an element.
1889 The element must be closed with CloseElement()
1890 */
1891 void OpenElement( const char* name );
1892 /// If streaming, add an attribute to an open element.
1893 void PushAttribute( const char* name, const char* value );
1894 void PushAttribute( const char* name, int value );
1895 void PushAttribute( const char* name, unsigned value );
1896 void PushAttribute( const char* name, bool value );
1897 void PushAttribute( const char* name, double value );
1898 /// If streaming, close the Element.
1899 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001900
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001901 /// Add a text node.
1902 void PushText( const char* text, bool cdata=false );
1903 /// Add a text node from an integer.
1904 void PushText( int value );
1905 /// Add a text node from an unsigned.
1906 void PushText( unsigned value );
1907 /// Add a text node from a bool.
1908 void PushText( bool value );
1909 /// Add a text node from a float.
1910 void PushText( float value );
1911 /// Add a text node from a double.
1912 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001913
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001914 /// Add a comment
1915 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001916
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001917 void PushDeclaration( const char* value );
1918 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001919
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001920 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1921 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1922 return true;
1923 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001924
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001925 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1926 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001927
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001928 virtual bool Visit( const XMLText& text );
1929 virtual bool Visit( const XMLComment& comment );
1930 virtual bool Visit( const XMLDeclaration& declaration );
1931 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001932
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001933 /**
1934 If in print to memory mode, return a pointer to
1935 the XML file in memory.
1936 */
1937 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001938 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001939 }
1940 /**
1941 If in print to memory mode, return the size
1942 of the XML file in memory. (Note the size returned
1943 includes the terminating null.)
1944 */
1945 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001946 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001947 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001948
1949private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001950 void SealElement();
1951 void PrintSpace( int depth );
1952 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1953 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001954
Lee Thomason624d43f2012-10-12 10:58:48 -07001955 bool _elementJustOpened;
1956 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001957 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001958 int _depth;
1959 int _textDepth;
1960 bool _processEntities;
1961 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001962
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001963 enum {
1964 ENTITY_RANGE = 64,
1965 BUF_SIZE = 200
1966 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001967 bool _entityFlag[ENTITY_RANGE];
1968 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001969
Lee Thomason624d43f2012-10-12 10:58:48 -07001970 DynArray< const char*, 10 > _stack;
1971 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001972#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001973 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001974#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001975};
1976
1977
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001978} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001979
1980
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001981#endif // TINYXML2_INCLUDED