blob: 52f9180253af31aab44f157628820b05301b65fa [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
Lee Thomason (grinliz)db304252013-07-31 12:24:52 -070017
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -0800182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080024
Lee Thomason7d00b9a2012-02-27 17:54:22 -080025#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080026#define TINYXML2_INCLUDED
27
Jerome Martinez242c3ea2013-01-06 12:20:04 +010028#if defined(ANDROID_NDK) || defined(__BORLANDC__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070029# include <ctype.h>
30# include <limits.h>
31# include <stdio.h>
32# include <stdlib.h>
33# include <string.h>
34# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070035#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070036# include <cctype>
37# include <climits>
38# include <cstdio>
39# include <cstdlib>
40# include <cstring>
41# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070042#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070043
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070044/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080045 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080046*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080047/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070048 gcc:
Lee Thomason5b0a6772012-11-19 13:54:42 -080049 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
MortenMacFly4ee49f12013-01-14 20:03:14 +010050
Lee Thomasona9cf3f92012-10-11 16:56:51 -070051 Formatting, Artistic Style:
52 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080053*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080054
U-Lama\Lee4cee6112011-12-31 14:58:18 -080055#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070056# ifndef DEBUG
57# define DEBUG
58# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080059#endif
60
PKEuS95060352013-07-26 10:42:44 +020061#ifdef _MSC_VER
62# pragma warning(push)
63# pragma warning(disable: 4251)
64#endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080065
PKEuS16ed47d2013-07-06 12:02:43 +020066#ifdef _WIN32
67# ifdef TINYXML2_EXPORT
68# define TINYXML2_LIB __declspec(dllexport)
69# elif defined(TINYXML2_IMPORT)
70# define TINYXML2_LIB __declspec(dllimport)
71# else
72# define TINYXML2_LIB
73# endif
74#else
75# define TINYXML2_LIB
76#endif
77
78
U-Lama\Lee4cee6112011-12-31 14:58:18 -080079#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070080# if defined(_MSC_VER)
81# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
82# elif defined (ANDROID_NDK)
83# include <android/log.h>
84# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
85# else
86# include <assert.h>
87# define TIXMLASSERT assert
88# endif
89# else
90# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080091#endif
92
U-Lama\Leee13c3e62011-12-28 14:36:55 -080093
Lee Thomason1a1d4a72012-02-15 09:09:25 -080094#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// Microsoft visual studio, version 2005 and higher.
96/*int _snprintf_s(
97 char *buffer,
98 size_t sizeOfBuffer,
99 size_t count,
100 const char *format [,
101 argument] ...
102);*/
103inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
104{
105 va_list va;
106 va_start( va, format );
107 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
108 va_end( va );
109 return result;
110}
111#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -0700112#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700113// GCC version 3 and higher
114//#warning( "Using sn* functions." )
115#define TIXML_SNPRINTF snprintf
116#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800117#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800118
selfpoisede77e1952013-03-13 14:08:29 +0800119static const int TIXML2_MAJOR_VERSION = 1;
120static const int TIXML2_MINOR_VERSION = 0;
121static const int TIXML2_PATCH_VERSION = 11;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800122
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800123namespace tinyxml2
124{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800125class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800126class XMLElement;
127class XMLAttribute;
128class XMLComment;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800129class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800130class XMLDeclaration;
131class XMLUnknown;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800132class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800133
U-Stream\Leeae25a442012-02-17 17:48:16 -0800134/*
135 A class that wraps strings. Normally stores the start and end
136 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800137 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800138 manage) a traditional char[]
139*/
PKEuS95060352013-07-26 10:42:44 +0200140class StrPair
Lee Thomason39ede242012-01-20 11:27:56 -0800141{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800142public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700143 enum {
144 NEEDS_ENTITY_PROCESSING = 0x01,
145 NEEDS_NEWLINE_NORMALIZATION = 0x02,
selfpoisede77e1952013-03-13 14:08:29 +0800146 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800147
selfpoisede77e1952013-03-13 14:08:29 +0800148 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700149 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
selfpoisede77e1952013-03-13 14:08:29 +0800150 ATTRIBUTE_NAME = 0,
151 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
152 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
153 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 };
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomason120b3a62012-10-12 10:06:59 -0700156 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700157 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800158
Lee Thomason120b3a62012-10-12 10:06:59 -0700159 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700160 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700161 _start = start;
162 _end = end;
163 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700164 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700165
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700166 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700167
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700168 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700169 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 }
Lee Thomason39ede242012-01-20 11:27:56 -0800171
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700172 void SetInternedStr( const char* str ) {
173 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700174 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700176
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700177 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800178
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700179 char* ParseText( char* in, const char* endTag, int strFlags );
180 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800181
Lee Thomason39ede242012-01-20 11:27:56 -0800182private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700183 void Reset();
184 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800185
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700186 enum {
187 NEEDS_FLUSH = 0x100,
188 NEEDS_DELETE = 0x200
189 };
Lee Thomasone4422302012-01-20 17:59:50 -0800190
selfpoised4dd59bc2013-03-13 16:54:15 +0800191 // After parsing, if *_end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700192 int _flags;
193 char* _start;
194 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800195};
196
U-Lama\Lee560bd472011-12-28 19:42:49 -0800197
U-Stream\Leeae25a442012-02-17 17:48:16 -0800198/*
199 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
200 Has a small initial memory pool, so that low or no usage will not
201 cause a call to new/delete
202*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800203template <class T, int INIT>
PKEuS95060352013-07-26 10:42:44 +0200204class DynArray
Lee Thomason2c85a712012-01-31 08:24:24 -0800205{
206public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700207 DynArray< T, INIT >() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700208 _mem = _pool;
209 _allocated = INIT;
210 _size = 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700212
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700213 ~DynArray() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700214 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700215 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700216 }
217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void Push( T t ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700220 EnsureCapacity( _size+1 );
221 _mem[_size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 T* PushArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700225 EnsureCapacity( _size+count );
226 T* ret = &_mem[_size];
227 _size += count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 return ret;
229 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700230
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 T Pop() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700232 return _mem[--_size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700234
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700235 void PopArr( int count ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700236 TIXMLASSERT( _size >= count );
237 _size -= count;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800239
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700240 bool Empty() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700241 return _size == 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700243
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700244 T& operator[](int i) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700245 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700246 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700247 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700248
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700249 const T& operator[](int i) const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700250 TIXMLASSERT( i>= 0 && i < _size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700253
Dennis Jenkins59c75d32013-10-08 13:10:07 -0500254 const T& PeekTop() const {
255 TIXMLASSERT( _size > 0 );
256 return _mem[ _size - 1];
257 }
258
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700259 int Size() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700260 return _size;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700261 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700262
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700263 int Capacity() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700264 return _allocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700265 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700266
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700267 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700270
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700271 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700272 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700273 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800274
Lee Thomason2c85a712012-01-31 08:24:24 -0800275private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700276 void EnsureCapacity( int cap ) {
Lee Thomason624d43f2012-10-12 10:58:48 -0700277 if ( cap > _allocated ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700278 int newAllocated = cap * 2;
279 T* newMem = new T[newAllocated];
Lee Thomason624d43f2012-10-12 10:58:48 -0700280 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
281 if ( _mem != _pool ) {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700282 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700283 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700284 _mem = newMem;
Lee Thomason624d43f2012-10-12 10:58:48 -0700285 _allocated = newAllocated;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700286 }
287 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800288
Lee Thomason624d43f2012-10-12 10:58:48 -0700289 T* _mem;
290 T _pool[INIT];
291 int _allocated; // objects allocated
292 int _size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800293};
294
Lee Thomason50adb4c2012-02-13 15:07:09 -0800295
U-Stream\Leeae25a442012-02-17 17:48:16 -0800296/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200297 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800298 and deallocation of objects.
299*/
PKEuS95060352013-07-26 10:42:44 +0200300class MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800301{
302public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700303 MemPool() {}
304 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const = 0;
307 virtual void* Alloc() = 0;
308 virtual void Free( void* ) = 0;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800309 virtual void SetTracked() = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800310};
311
Lee Thomason50adb4c2012-02-13 15:07:09 -0800312
U-Stream\Leeae25a442012-02-17 17:48:16 -0800313/*
314 Template child class to create pools of the correct type.
315*/
Lee Thomasond1983222012-02-06 08:41:24 -0800316template< int SIZE >
PKEuS95060352013-07-26 10:42:44 +0200317class MemPoolT : public MemPool
Lee Thomasond1983222012-02-06 08:41:24 -0800318{
319public:
Lee Thomason5b0a6772012-11-19 13:54:42 -0800320 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700321 ~MemPoolT() {
322 // Delete the blocks.
Lee Thomason624d43f2012-10-12 10:58:48 -0700323 for( int i=0; i<_blockPtrs.Size(); ++i ) {
324 delete _blockPtrs[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700325 }
326 }
Lee Thomasond1983222012-02-06 08:41:24 -0800327
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 virtual int ItemSize() const {
329 return SIZE;
330 }
331 int CurrentAllocs() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700332 return _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700333 }
Lee Thomasond1983222012-02-06 08:41:24 -0800334
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700335 virtual void* Alloc() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700336 if ( !_root ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700337 // Need a new block.
338 Block* block = new Block();
Lee Thomason624d43f2012-10-12 10:58:48 -0700339 _blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800340
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700341 for( int i=0; i<COUNT-1; ++i ) {
342 block->chunk[i].next = &block->chunk[i+1];
343 }
344 block->chunk[COUNT-1].next = 0;
Lee Thomason624d43f2012-10-12 10:58:48 -0700345 _root = block->chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700346 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700347 void* result = _root;
348 _root = _root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800349
Lee Thomason624d43f2012-10-12 10:58:48 -0700350 ++_currentAllocs;
351 if ( _currentAllocs > _maxAllocs ) {
352 _maxAllocs = _currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700354 _nAllocs++;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800355 _nUntracked++;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700356 return result;
357 }
358 virtual void Free( void* mem ) {
359 if ( !mem ) {
360 return;
361 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700362 --_currentAllocs;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700363 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700364#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700365 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700366#endif
Lee Thomason624d43f2012-10-12 10:58:48 -0700367 chunk->next = _root;
368 _root = chunk;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700369 }
370 void Trace( const char* name ) {
371 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
Lee Thomason624d43f2012-10-12 10:58:48 -0700372 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700373 }
Lee Thomasond1983222012-02-06 08:41:24 -0800374
Lee Thomason5b0a6772012-11-19 13:54:42 -0800375 void SetTracked() {
376 _nUntracked--;
377 }
378
379 int Untracked() const {
380 return _nUntracked;
381 }
382
Lee Thomason (grinliz)ac83b4e2013-02-01 09:02:34 -0800383 // This number is perf sensitive. 4k seems like a good tradeoff on my machine.
384 // The test file is large, 170k.
385 // Release: VS2010 gcc(no opt)
386 // 1k: 4000
387 // 2k: 4000
388 // 4k: 3900 21000
389 // 16k: 5200
390 // 32k: 4300
391 // 64k: 4000 21000
392 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
Jerome Martinez7921df12012-10-24 11:45:44 +0200393
Lee Thomasond1983222012-02-06 08:41:24 -0800394private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 union Chunk {
Lee Thomason624d43f2012-10-12 10:58:48 -0700396 Chunk* next;
397 char mem[SIZE];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700398 };
399 struct Block {
Lee Thomason (grinliz)856da212012-10-19 09:08:15 -0700400 Chunk chunk[COUNT];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700401 };
Lee Thomason624d43f2012-10-12 10:58:48 -0700402 DynArray< Block*, 10 > _blockPtrs;
403 Chunk* _root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800404
Lee Thomason624d43f2012-10-12 10:58:48 -0700405 int _currentAllocs;
406 int _nAllocs;
407 int _maxAllocs;
Lee Thomason5b0a6772012-11-19 13:54:42 -0800408 int _nUntracked;
Lee Thomasond1983222012-02-06 08:41:24 -0800409};
410
Lee Thomason2c85a712012-01-31 08:24:24 -0800411
Lee Thomason56bdd022012-02-09 18:16:58 -0800412
413/**
414 Implements the interface to the "Visitor pattern" (see the Accept() method.)
415 If you call the Accept() method, it requires being passed a XMLVisitor
416 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200417 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800418 are simply called with Visit().
419
420 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700421 false, <b>no children of this node or its siblings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800422
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700423 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800424 visiting). You need to only override methods that are interesting to you.
425
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600426 Generally Accept() is called on the XMLDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800427
428 You should never change the document from a callback.
429
430 @sa XMLNode::Accept()
431*/
PKEuS16ed47d2013-07-06 12:02:43 +0200432class TINYXML2_LIB XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800433{
434public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700435 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800436
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700437 /// Visit a document.
438 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
439 return true;
440 }
441 /// Visit a document.
442 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
443 return true;
444 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800445
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700446 /// Visit an element.
447 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
448 return true;
449 }
450 /// Visit an element.
451 virtual bool VisitExit( const XMLElement& /*element*/ ) {
452 return true;
453 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800454
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700455 /// Visit a declaration.
456 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
457 return true;
458 }
459 /// Visit a text node.
460 virtual bool Visit( const XMLText& /*text*/ ) {
461 return true;
462 }
463 /// Visit a comment node.
464 virtual bool Visit( const XMLComment& /*comment*/ ) {
465 return true;
466 }
467 /// Visit an unknown node.
468 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
469 return true;
470 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800471};
472
473
U-Stream\Leeae25a442012-02-17 17:48:16 -0800474/*
475 Utility functionality.
476*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800477class XMLUtil
478{
Lee Thomasond1983222012-02-06 08:41:24 -0800479public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700480 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
481 // correct, but simple, and usually works.
482 static const char* SkipWhiteSpace( const char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100483 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700484 ++p;
485 }
486 return p;
487 }
488 static char* SkipWhiteSpace( char* p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100489 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700490 ++p;
491 }
492 return p;
493 }
494 static bool IsWhiteSpace( char p ) {
Jerome Martinez242c3ea2013-01-06 12:20:04 +0100495 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700496 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200497
498 inline static bool IsNameStartChar( unsigned char ch ) {
499 return ( ( ch < 128 ) ? isalpha( ch ) : 1 )
500 || ch == ':'
501 || ch == '_';
502 }
503
504 inline static bool IsNameChar( unsigned char ch ) {
505 return IsNameStartChar( ch )
506 || isdigit( ch )
507 || ch == '.'
508 || ch == '-';
509 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800510
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700511 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
512 int n = 0;
513 if ( p == q ) {
514 return true;
515 }
516 while( *p && *q && *p == *q && n<nChar ) {
517 ++p;
518 ++q;
519 ++n;
520 }
521 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
522 return true;
523 }
524 return false;
525 }
Martinsh Shaitersc6d02f42013-01-26 21:22:57 +0200526
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700527 inline static int IsUTF8Continuation( const char p ) {
528 return p & 0x80;
529 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800530
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700531 static const char* ReadBOM( const char* p, bool* hasBOM );
532 // p is the starting location,
533 // the UTF-8 value of the entity will be placed in value, and length filled in.
534 static const char* GetCharacterRef( const char* p, char* value, int* length );
535 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700536
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700537 // converts primitive types to strings
538 static void ToStr( int v, char* buffer, int bufferSize );
539 static void ToStr( unsigned v, char* buffer, int bufferSize );
540 static void ToStr( bool v, char* buffer, int bufferSize );
541 static void ToStr( float v, char* buffer, int bufferSize );
542 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700543
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700544 // converts strings to primitive types
545 static bool ToInt( const char* str, int* value );
546 static bool ToUnsigned( const char* str, unsigned* value );
547 static bool ToBool( const char* str, bool* value );
548 static bool ToFloat( const char* str, float* value );
549 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800550};
551
Lee Thomason5cae8972012-01-24 18:03:07 -0800552
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800553/** XMLNode is a base class for every object that is in the
554 XML Document Object Model (DOM), except XMLAttributes.
555 Nodes have siblings, a parent, and children which can
556 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700557 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800558 be cast to its more defined type.
559
Thomas Roß08bdf502012-05-12 14:21:23 +0200560 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800561 When the XMLDocument gets deleted, all its Nodes
562 will also be deleted.
563
564 @verbatim
565 A Document can contain: Element (container or leaf)
566 Comment (leaf)
567 Unknown (leaf)
568 Declaration( leaf )
569
570 An Element can contain: Element (container or leaf)
571 Text (leaf)
572 Attributes (not on tree)
573 Comment (leaf)
574 Unknown (leaf)
575
576 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800577*/
PKEuS16ed47d2013-07-06 12:02:43 +0200578class TINYXML2_LIB XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700580 friend class XMLDocument;
581 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800582public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800583
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700584 /// Get the XMLDocument that owns this XMLNode.
585 const XMLDocument* GetDocument() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700586 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700587 }
588 /// Get the XMLDocument that owns this XMLNode.
589 XMLDocument* GetDocument() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700590 return _document;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700591 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592
Lee Thomason2fa81722012-11-09 12:37:46 -0800593 /// Safely cast to an Element, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700594 virtual XMLElement* ToElement() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100595 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700596 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800597 /// Safely cast to Text, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 virtual XMLText* ToText() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100599 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700600 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800601 /// Safely cast to a Comment, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700602 virtual XMLComment* ToComment() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100603 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700604 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800605 /// Safely cast to a Document, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 virtual XMLDocument* ToDocument() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100607 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700608 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800609 /// Safely cast to a Declaration, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700610 virtual XMLDeclaration* ToDeclaration() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100611 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700612 }
Lee Thomason2fa81722012-11-09 12:37:46 -0800613 /// Safely cast to an Unknown, or null.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700614 virtual XMLUnknown* ToUnknown() {
MortenMacFly4ee49f12013-01-14 20:03:14 +0100615 return 0;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700616 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800617
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700618 virtual const XMLElement* ToElement() const {
619 return 0;
620 }
621 virtual const XMLText* ToText() const {
622 return 0;
623 }
624 virtual const XMLComment* ToComment() const {
625 return 0;
626 }
627 virtual const XMLDocument* ToDocument() const {
628 return 0;
629 }
630 virtual const XMLDeclaration* ToDeclaration() const {
631 return 0;
632 }
633 virtual const XMLUnknown* ToUnknown() const {
634 return 0;
635 }
Lee Thomason751da522012-02-10 08:50:51 -0800636
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700637 /** The meaning of 'value' changes for the specific type.
638 @verbatim
639 Document: empty
640 Element: name of the element
641 Comment: the comment text
642 Unknown: the tag contents
643 Text: the text string
644 @endverbatim
645 */
Michael Daumling21626882013-10-22 17:03:37 +0200646 const char* Value() const;
MortenMacFly4ee49f12013-01-14 20:03:14 +0100647
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700648 /** Set the Value of an XML node.
649 @sa Value()
650 */
651 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800652
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700653 /// Get the parent of this node on the DOM.
654 const XMLNode* Parent() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700655 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100657
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700658 XMLNode* Parent() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700659 return _parent;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700660 }
Lee Thomason751da522012-02-10 08:50:51 -0800661
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700662 /// Returns true if this node has no children.
663 bool NoChildren() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700664 return !_firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700665 }
Lee Thomason751da522012-02-10 08:50:51 -0800666
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700667 /// Get the first child node, or null if none exists.
668 const XMLNode* FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700669 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100671
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700672 XMLNode* FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700673 return _firstChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700674 }
MortenMacFly4ee49f12013-01-14 20:03:14 +0100675
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700676 /** Get the first child element, or optionally the first child
677 element with the specified name.
678 */
679 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700680
681 XMLElement* FirstChildElement( const char* value=0 ) {
682 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700683 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800684
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700685 /// Get the last child node, or null if none exists.
686 const XMLNode* LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700687 return _lastChild;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700688 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700689
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700690 XMLNode* LastChild() {
691 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
692 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800693
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700694 /** Get the last child element or optionally the last child
695 element with the specified name.
696 */
697 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700698
699 XMLElement* LastChildElement( const char* value=0 ) {
700 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700701 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700702
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700703 /// Get the previous (left) sibling node of this node.
704 const XMLNode* PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700705 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700706 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700707
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 XMLNode* PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700709 return _prev;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700710 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800711
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700712 /// Get the previous (left) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700713 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason624d43f2012-10-12 10:58:48 -0700714
715 XMLElement* PreviousSiblingElement( const char* value=0 ) {
716 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700717 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700718
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700719 /// Get the next (right) sibling node of this node.
720 const XMLNode* NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700721 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700722 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 XMLNode* NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -0700725 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700727
Andrew C. Martin0fd87462013-03-09 20:09:45 -0700728 /// Get the next (right) sibling element of this node, with an optionally supplied name.
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason624d43f2012-10-12 10:58:48 -0700730
731 XMLElement* NextSiblingElement( const char* value=0 ) {
732 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700733 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800734
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700735 /**
736 Add a child node as the last (right) child.
737 */
738 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800739
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700740 XMLNode* LinkEndChild( XMLNode* addThis ) {
741 return InsertEndChild( addThis );
742 }
743 /**
744 Add a child node as the first (left) child.
745 */
746 XMLNode* InsertFirstChild( XMLNode* addThis );
747 /**
748 Add a node after the specified child node.
749 */
750 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700751
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700752 /**
753 Delete all the children of this node.
754 */
755 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800756
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700757 /**
758 Delete a child of this node.
759 */
760 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800761
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700762 /**
763 Make a copy of this node, but not its children.
764 You may pass in a Document pointer that will be
765 the owner of the new Node. If the 'document' is
766 null, then the node returned will be allocated
767 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800768
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700769 Note: if called on a XMLDocument, this will return null.
770 */
771 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800772
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700773 /**
774 Test if 2 nodes are the same, but don't test children.
775 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800776
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700777 Note: if called on a XMLDocument, this will return false.
778 */
779 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800780
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600781 /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 XML tree will be conditionally visited and the host will be called back
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600783 via the XMLVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800784
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600785 This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse
786 the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700787 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800788
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700789 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800790
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 - http://www.saxproject.org/
792 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800793
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700794 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800795
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700796 An example of using Accept():
797 @verbatim
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600798 XMLPrinter printer;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700799 tinyxmlDoc.Accept( &printer );
800 const char* xmlcstr = printer.CStr();
801 @endverbatim
802 */
803 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800804
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700805 // internal
806 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800807
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800808protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700809 XMLNode( XMLDocument* );
810 virtual ~XMLNode();
811 XMLNode( const XMLNode& ); // not supported
812 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700813
Lee Thomason624d43f2012-10-12 10:58:48 -0700814 XMLDocument* _document;
815 XMLNode* _parent;
816 mutable StrPair _value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800817
Lee Thomason624d43f2012-10-12 10:58:48 -0700818 XMLNode* _firstChild;
819 XMLNode* _lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800820
Lee Thomason624d43f2012-10-12 10:58:48 -0700821 XMLNode* _prev;
822 XMLNode* _next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800823
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800824private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700825 MemPool* _memPool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700826 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800827};
828
829
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800830/** XML text.
831
832 Note that a text node can have child element nodes, for example:
833 @verbatim
834 <root>This is <b>bold</b></root>
835 @endverbatim
836
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700837 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800838 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 -0700839 you generally want to leave it alone, but you can change the output mode with
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600840 SetCData() and query it with CData().
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800841*/
PKEuS16ed47d2013-07-06 12:02:43 +0200842class TINYXML2_LIB XMLText : public XMLNode
Lee Thomason5492a1c2012-01-23 15:32:10 -0800843{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700844 friend class XMLBase;
845 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800846public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700847 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800848
Lee Thomason624d43f2012-10-12 10:58:48 -0700849 virtual XMLText* ToText() {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700850 return this;
851 }
Lee Thomason624d43f2012-10-12 10:58:48 -0700852 virtual const XMLText* ToText() const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700853 return this;
854 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800855
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700856 /// Declare whether this should be CDATA or standard text.
Lee Thomason624d43f2012-10-12 10:58:48 -0700857 void SetCData( bool isCData ) {
858 _isCData = isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700859 }
860 /// Returns true if this is a CDATA text element.
861 bool CData() const {
Lee Thomason624d43f2012-10-12 10:58:48 -0700862 return _isCData;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700863 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800864
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700865 char* ParseDeep( char*, StrPair* endTag );
866 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
867 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800868
Lee Thomason5492a1c2012-01-23 15:32:10 -0800869protected:
Lee Thomason624d43f2012-10-12 10:58:48 -0700870 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700871 virtual ~XMLText() {}
872 XMLText( const XMLText& ); // not supported
873 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800874
875private:
Lee Thomason624d43f2012-10-12 10:58:48 -0700876 bool _isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800877};
878
879
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800880/** An XML Comment. */
PKEuS16ed47d2013-07-06 12:02:43 +0200881class TINYXML2_LIB XMLComment : public XMLNode
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800882{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700883 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800884public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700885 virtual XMLComment* ToComment() {
886 return this;
887 }
888 virtual const XMLComment* ToComment() const {
889 return this;
890 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800891
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700892 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800893
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700894 char* ParseDeep( char*, StrPair* endTag );
895 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
896 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800897
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800898protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700899 XMLComment( XMLDocument* doc );
900 virtual ~XMLComment();
901 XMLComment( const XMLComment& ); // not supported
902 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800903
Lee Thomason3f57d272012-01-11 15:30:03 -0800904private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800905};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800906
907
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800908/** In correct XML the declaration is the first entry in the file.
909 @verbatim
910 <?xml version="1.0" standalone="yes"?>
911 @endverbatim
912
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600913 TinyXML-2 will happily read or write files without a declaration,
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800914 however.
915
916 The text of the declaration isn't interpreted. It is parsed
917 and written as a string.
918*/
PKEuS16ed47d2013-07-06 12:02:43 +0200919class TINYXML2_LIB XMLDeclaration : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800920{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700921 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800922public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700923 virtual XMLDeclaration* ToDeclaration() {
924 return this;
925 }
926 virtual const XMLDeclaration* ToDeclaration() const {
927 return this;
928 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800929
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700930 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800931
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700932 char* ParseDeep( char*, StrPair* endTag );
933 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
934 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800935
936protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700937 XMLDeclaration( XMLDocument* doc );
938 virtual ~XMLDeclaration();
939 XMLDeclaration( const XMLDeclaration& ); // not supported
940 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800941};
942
943
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600944/** Any tag that TinyXML-2 doesn't recognize is saved as an
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800945 unknown. It is a tag of text, but should not be modified.
946 It will be written back to the XML, unchanged, when the file
947 is saved.
948
Vasily Biryukov9a975b72013-05-11 21:41:42 +0600949 DTD tags get thrown into XMLUnknowns.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800950*/
PKEuS16ed47d2013-07-06 12:02:43 +0200951class TINYXML2_LIB XMLUnknown : public XMLNode
Lee Thomason50f97b22012-02-11 16:33:40 -0800952{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700953 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800954public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700955 virtual XMLUnknown* ToUnknown() {
956 return this;
957 }
958 virtual const XMLUnknown* ToUnknown() const {
959 return this;
960 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800961
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700962 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800963
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700964 char* ParseDeep( char*, StrPair* endTag );
965 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
966 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800967
968protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700969 XMLUnknown( XMLDocument* doc );
970 virtual ~XMLUnknown();
971 XMLUnknown( const XMLUnknown& ); // not supported
972 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800973};
974
975
Lee Thomason2fa81722012-11-09 12:37:46 -0800976enum XMLError {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700977 XML_NO_ERROR = 0,
978 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800979
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700980 XML_NO_ATTRIBUTE,
981 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800982
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700983 XML_ERROR_FILE_NOT_FOUND,
984 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
985 XML_ERROR_FILE_READ_ERROR,
986 XML_ERROR_ELEMENT_MISMATCH,
987 XML_ERROR_PARSING_ELEMENT,
988 XML_ERROR_PARSING_ATTRIBUTE,
989 XML_ERROR_IDENTIFYING_TAG,
990 XML_ERROR_PARSING_TEXT,
991 XML_ERROR_PARSING_CDATA,
992 XML_ERROR_PARSING_COMMENT,
993 XML_ERROR_PARSING_DECLARATION,
994 XML_ERROR_PARSING_UNKNOWN,
995 XML_ERROR_EMPTY_DOCUMENT,
996 XML_ERROR_MISMATCHED_ELEMENT,
997 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700998
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700999 XML_CAN_NOT_CONVERT_TEXT,
1000 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -08001001};
1002
1003
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001004/** An attribute is a name-value pair. Elements have an arbitrary
1005 number of attributes, each with a unique name.
1006
1007 @note The attributes are not XMLNodes. You may only query the
1008 Next() attribute in a list.
1009*/
PKEuS16ed47d2013-07-06 12:02:43 +02001010class TINYXML2_LIB XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001011{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001012 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001013public:
Lee Thomason2fa81722012-11-09 12:37:46 -08001014 /// The name of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001015 const char* Name() const;
1016
Lee Thomason2fa81722012-11-09 12:37:46 -08001017 /// The value of the attribute.
Michael Daumling21626882013-10-22 17:03:37 +02001018 const char* Value() const;
1019
Lee Thomason2fa81722012-11-09 12:37:46 -08001020 /// The next attribute in the list.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001021 const XMLAttribute* Next() const {
MortenMacFly4ee49f12013-01-14 20:03:14 +01001022 return _next;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001023 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001024
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001025 /** IntValue interprets the attribute as an integer, and returns the value.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001026 If the value isn't an integer, 0 will be returned. There is no error checking;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001027 use QueryIntValue() if you need error checking.
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001028 */
1029 int IntValue() const {
1030 int i=0;
1031 QueryIntValue( &i );
1032 return i;
1033 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001034 /// Query as an unsigned integer. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001035 unsigned UnsignedValue() const {
1036 unsigned i=0;
1037 QueryUnsignedValue( &i );
1038 return i;
1039 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001040 /// Query as a boolean. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001041 bool BoolValue() const {
1042 bool b=false;
1043 QueryBoolValue( &b );
1044 return b;
1045 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001046 /// Query as a double. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001047 double DoubleValue() const {
1048 double d=0;
1049 QueryDoubleValue( &d );
1050 return d;
1051 }
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001052 /// Query as a float. See IntValue()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001053 float FloatValue() const {
1054 float f=0;
1055 QueryFloatValue( &f );
1056 return f;
1057 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001058
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001059 /** QueryIntValue interprets the attribute as an integer, and returns the value
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001060 in the provided parameter. The function will return XML_NO_ERROR on success,
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001061 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
1062 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001063 XMLError QueryIntValue( int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001064 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001065 XMLError QueryUnsignedValue( unsigned int* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001066 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001067 XMLError QueryBoolValue( bool* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001068 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001069 XMLError QueryDoubleValue( double* value ) const;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001070 /// See QueryIntValue
Lee Thomason2fa81722012-11-09 12:37:46 -08001071 XMLError QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001072
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 /// Set the attribute to a string value.
1074 void SetAttribute( const char* value );
1075 /// Set the attribute to value.
1076 void SetAttribute( int value );
1077 /// Set the attribute to value.
1078 void SetAttribute( unsigned value );
1079 /// Set the attribute to value.
1080 void SetAttribute( bool value );
1081 /// Set the attribute to value.
1082 void SetAttribute( double value );
1083 /// Set the attribute to value.
1084 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001085
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001086private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001087 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001088
Thomas Roß61892312013-05-12 14:07:38 +02001089 XMLAttribute() : _next( 0 ), _memPool( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001090 virtual ~XMLAttribute() {}
Lee Thomason624d43f2012-10-12 10:58:48 -07001091
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001092 XMLAttribute( const XMLAttribute& ); // not supported
1093 void operator=( const XMLAttribute& ); // not supported
1094 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001095
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001096 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001097
Lee Thomason624d43f2012-10-12 10:58:48 -07001098 mutable StrPair _name;
1099 mutable StrPair _value;
1100 XMLAttribute* _next;
1101 MemPool* _memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001102};
1103
1104
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001105/** The element is a container class. It has a value, the element name,
1106 and can contain other elements, text, comments, and unknowns.
1107 Elements also contain an arbitrary number of attributes.
1108*/
PKEuS16ed47d2013-07-06 12:02:43 +02001109class TINYXML2_LIB XMLElement : public XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001110{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001111 friend class XMLBase;
1112 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001113public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001114 /// Get the name of an element (which is the Value() of the node.)
1115 const char* Name() const {
1116 return Value();
1117 }
1118 /// Set the name of the element.
1119 void SetName( const char* str, bool staticMem=false ) {
1120 SetValue( str, staticMem );
1121 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001122
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001123 virtual XMLElement* ToElement() {
1124 return this;
1125 }
1126 virtual const XMLElement* ToElement() const {
1127 return this;
1128 }
1129 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001130
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001131 /** Given an attribute name, Attribute() returns the value
1132 for the attribute of that name, or null if none
1133 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001134
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001135 @verbatim
1136 const char* value = ele->Attribute( "foo" );
1137 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001138
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001139 The 'value' parameter is normally null. However, if specified,
1140 the attribute will only be returned if the 'name' and 'value'
1141 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001142
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001143 @verbatim
1144 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1145 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001146
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001147 rather than:
1148 @verbatim
1149 if ( ele->Attribute( "foo" ) ) {
1150 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1151 }
1152 @endverbatim
1153 */
1154 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001155
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001156 /** Given an attribute name, IntAttribute() returns the value
1157 of the attribute interpreted as an integer. 0 will be
1158 returned if there is an error. For a method with error
1159 checking, see QueryIntAttribute()
1160 */
1161 int IntAttribute( const char* name ) const {
1162 int i=0;
1163 QueryIntAttribute( name, &i );
1164 return i;
1165 }
1166 /// See IntAttribute()
1167 unsigned UnsignedAttribute( const char* name ) const {
1168 unsigned i=0;
1169 QueryUnsignedAttribute( name, &i );
1170 return i;
1171 }
1172 /// See IntAttribute()
1173 bool BoolAttribute( const char* name ) const {
1174 bool b=false;
1175 QueryBoolAttribute( name, &b );
1176 return b;
1177 }
1178 /// See IntAttribute()
1179 double DoubleAttribute( const char* name ) const {
1180 double d=0;
1181 QueryDoubleAttribute( name, &d );
1182 return d;
1183 }
1184 /// See IntAttribute()
1185 float FloatAttribute( const char* name ) const {
1186 float f=0;
1187 QueryFloatAttribute( name, &f );
1188 return f;
1189 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001190
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001191 /** Given an attribute name, QueryIntAttribute() returns
1192 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1193 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1194 doesn't exist. If successful, the result of the conversion
1195 will be written to 'value'. If not successful, nothing will
1196 be written to 'value'. This allows you to provide default
1197 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001198
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001199 @verbatim
1200 int value = 10;
1201 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1202 @endverbatim
1203 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001204 XMLError QueryIntAttribute( const char* name, int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001205 const XMLAttribute* a = FindAttribute( name );
1206 if ( !a ) {
1207 return XML_NO_ATTRIBUTE;
1208 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001209 return a->QueryIntValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001210 }
1211 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001212 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001213 const XMLAttribute* a = FindAttribute( name );
1214 if ( !a ) {
1215 return XML_NO_ATTRIBUTE;
1216 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001217 return a->QueryUnsignedValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001218 }
1219 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001220 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001221 const XMLAttribute* a = FindAttribute( name );
1222 if ( !a ) {
1223 return XML_NO_ATTRIBUTE;
1224 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001225 return a->QueryBoolValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001226 }
1227 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001228 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 const XMLAttribute* a = FindAttribute( name );
1230 if ( !a ) {
1231 return XML_NO_ATTRIBUTE;
1232 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001233 return a->QueryDoubleValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001234 }
1235 /// See QueryIntAttribute()
Lee Thomason2fa81722012-11-09 12:37:46 -08001236 XMLError QueryFloatAttribute( const char* name, float* value ) const {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 const XMLAttribute* a = FindAttribute( name );
1238 if ( !a ) {
1239 return XML_NO_ATTRIBUTE;
1240 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001241 return a->QueryFloatValue( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001242 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001243
Lee Thomason (grinliz)5efaa5f2013-02-01 19:26:30 -08001244
1245 /** Given an attribute name, QueryAttribute() returns
1246 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1247 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1248 doesn't exist. It is overloaded for the primitive types,
1249 and is a generally more convenient replacement of
1250 QueryIntAttribute() and related functions.
1251
1252 If successful, the result of the conversion
1253 will be written to 'value'. If not successful, nothing will
1254 be written to 'value'. This allows you to provide default
1255 value:
1256
1257 @verbatim
1258 int value = 10;
1259 QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1260 @endverbatim
1261 */
1262 int QueryAttribute( const char* name, int* value ) const {
1263 return QueryIntAttribute( name, value );
1264 }
1265
1266 int QueryAttribute( const char* name, unsigned int* value ) const {
1267 return QueryUnsignedAttribute( name, value );
1268 }
1269
1270 int QueryAttribute( const char* name, bool* value ) const {
1271 return QueryBoolAttribute( name, value );
1272 }
1273
1274 int QueryAttribute( const char* name, double* value ) const {
1275 return QueryDoubleAttribute( name, value );
1276 }
1277
1278 int QueryAttribute( const char* name, float* value ) const {
1279 return QueryFloatAttribute( name, value );
1280 }
1281
1282 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001283 void SetAttribute( const char* name, const char* value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001284 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001285 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001286 }
1287 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001288 void SetAttribute( const char* name, int value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001289 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001290 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001291 }
1292 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001293 void SetAttribute( const char* name, unsigned value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001294 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001295 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 }
1297 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001298 void SetAttribute( const char* name, bool value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001299 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001300 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 }
1302 /// Sets the named attribute to value.
Lee Thomason624d43f2012-10-12 10:58:48 -07001303 void SetAttribute( const char* name, double value ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001304 XMLAttribute* a = FindOrCreateAttribute( name );
Lee Thomason624d43f2012-10-12 10:58:48 -07001305 a->SetAttribute( value );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001307
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001308 /**
1309 Delete an attribute.
1310 */
1311 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001312
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001313 /// Return the first attribute in the list.
1314 const XMLAttribute* FirstAttribute() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001315 return _rootAttribute;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001316 }
1317 /// Query a specific attribute in the list.
1318 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001319
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001320 /** Convenience function for easy access to the text inside an element. Although easy
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001321 and concise, GetText() is limited compared to getting the XMLText child
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001322 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001323
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001324 If the first child of 'this' is a XMLText, the GetText()
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001325 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001326
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 This is a convenient method for getting the text of simple contained text:
1328 @verbatim
1329 <foo>This is text</foo>
1330 const char* str = fooElement->GetText();
1331 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001334
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001335 Note that this function can be misleading. If the element foo was created from
1336 this XML:
1337 @verbatim
1338 <foo><b>This is text</b></foo>
1339 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001340
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001341 then the value of str would be null. The first child node isn't a text node, it is
1342 another element. From this XML:
1343 @verbatim
1344 <foo>This is <b>text</b></foo>
1345 @endverbatim
1346 GetText() will return "This is ".
1347 */
1348 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001349
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001350 /**
1351 Convenience method to query the value of a child text node. This is probably best
1352 shown by example. Given you have a document is this form:
1353 @verbatim
1354 <point>
1355 <x>1</x>
1356 <y>1.4</y>
1357 </point>
1358 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001359
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001360 The QueryIntText() and similar functions provide a safe and easier way to get to the
1361 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 @verbatim
1364 int x = 0;
1365 float y = 0; // types of x and y are contrived for example
1366 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1367 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1368 xElement->QueryIntText( &x );
1369 yElement->QueryFloatText( &y );
1370 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001371
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001372 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1373 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001374
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001375 */
MortenMacFly4ee49f12013-01-14 20:03:14 +01001376 XMLError QueryIntText( int* ival ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001377 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001378 XMLError QueryUnsignedText( unsigned* uval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001380 XMLError QueryBoolText( bool* bval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001381 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001382 XMLError QueryDoubleText( double* dval ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001383 /// See QueryIntText()
MortenMacFly4ee49f12013-01-14 20:03:14 +01001384 XMLError QueryFloatText( float* fval ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001385
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001386 // internal:
1387 enum {
1388 OPEN, // <foo>
1389 CLOSED, // <foo/>
1390 CLOSING // </foo>
1391 };
1392 int ClosingType() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001393 return _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001394 }
1395 char* ParseDeep( char* p, StrPair* endTag );
1396 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1397 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001398
Lee Thomason50adb4c2012-02-13 15:07:09 -08001399private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001400 XMLElement( XMLDocument* doc );
1401 virtual ~XMLElement();
1402 XMLElement( const XMLElement& ); // not supported
1403 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001404
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001405 XMLAttribute* FindAttribute( const char* name );
1406 XMLAttribute* FindOrCreateAttribute( const char* name );
1407 //void LinkAttribute( XMLAttribute* attrib );
1408 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001409
Lee Thomason624d43f2012-10-12 10:58:48 -07001410 int _closingType;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001411 // The attribute list is ordered; there is no 'lastAttribute'
1412 // because the list needs to be scanned for dupes before adding
1413 // a new attribute.
Lee Thomason624d43f2012-10-12 10:58:48 -07001414 XMLAttribute* _rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001415};
1416
1417
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001418enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001419 PRESERVE_WHITESPACE,
1420 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001421};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001422
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001423
1424/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001425 It can be saved, loaded, and printed to the screen.
1426 All Nodes are connected and allocated to a Document.
1427 If the Document is deleted, all its Nodes are also deleted.
1428*/
PKEuS16ed47d2013-07-06 12:02:43 +02001429class TINYXML2_LIB XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001430{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001431 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001432public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001433 /// constructor
1434 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1435 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001436
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001437 virtual XMLDocument* ToDocument() {
1438 return this;
1439 }
1440 virtual const XMLDocument* ToDocument() const {
1441 return this;
1442 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001443
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001444 /**
1445 Parse an XML file from a character string.
1446 Returns XML_NO_ERROR (0) on success, or
1447 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001448
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001449 You may optionally pass in the 'nBytes', which is
1450 the number of bytes which will be parsed. If not
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001451 specified, TinyXML-2 will assume 'xml' points to a
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001452 null terminated string.
1453 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001454 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001455
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001456 /**
1457 Load an XML file from disk.
1458 Returns XML_NO_ERROR (0) on success, or
1459 an errorID.
1460 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001461 XMLError LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001462
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001463 /**
1464 Load an XML file from disk. You are responsible
1465 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001466
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001467 Returns XML_NO_ERROR (0) on success, or
1468 an errorID.
1469 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001470 XMLError LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001471
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001472 /**
1473 Save the XML file to disk.
1474 Returns XML_NO_ERROR (0) on success, or
1475 an errorID.
1476 */
Lee Thomason2fa81722012-11-09 12:37:46 -08001477 XMLError SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001478
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001479 /**
1480 Save the XML file to disk. You are responsible
1481 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001482
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001483 Returns XML_NO_ERROR (0) on success, or
1484 an errorID.
1485 */
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001486 XMLError SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001487
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001488 bool ProcessEntities() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001489 return _processEntities;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001490 }
1491 Whitespace WhitespaceMode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001492 return _whitespace;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001493 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001494
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001495 /**
1496 Returns true if this document has a leading Byte Order Mark of UTF8.
1497 */
1498 bool HasBOM() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001499 return _writeBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001500 }
1501 /** Sets whether to write the BOM when writing the file.
1502 */
1503 void SetBOM( bool useBOM ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001504 _writeBOM = useBOM;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001505 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001506
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 /** Return the root element of DOM. Equivalent to FirstChildElement().
1508 To get the first node, use FirstChild().
1509 */
1510 XMLElement* RootElement() {
1511 return FirstChildElement();
1512 }
1513 const XMLElement* RootElement() const {
1514 return FirstChildElement();
1515 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001516
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001517 /** Print the Document. If the Printer is not provided, it will
1518 print to stdout. If you provide Printer, this can print to a file:
1519 @verbatim
1520 XMLPrinter printer( fp );
1521 doc.Print( &printer );
1522 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001523
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001524 Or you can use a printer to print to memory:
1525 @verbatim
1526 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001527 doc.Print( &printer );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001528 // printer.CStr() has a const char* to the XML
1529 @endverbatim
1530 */
PKEuS1c5f99e2013-07-06 11:28:39 +02001531 void Print( XMLPrinter* streamer=0 ) const;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001532 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001533
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001534 /**
1535 Create a new Element associated with
1536 this Document. The memory for the Element
1537 is managed by the Document.
1538 */
1539 XMLElement* NewElement( const char* name );
1540 /**
1541 Create a new Comment associated with
1542 this Document. The memory for the Comment
1543 is managed by the Document.
1544 */
1545 XMLComment* NewComment( const char* comment );
1546 /**
1547 Create a new Text associated with
1548 this Document. The memory for the Text
1549 is managed by the Document.
1550 */
1551 XMLText* NewText( const char* text );
1552 /**
1553 Create a new Declaration associated with
1554 this Document. The memory for the object
1555 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001556
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001557 If the 'text' param is null, the standard
1558 declaration is used.:
1559 @verbatim
1560 <?xml version="1.0" encoding="UTF-8"?>
1561 @endverbatim
1562 */
1563 XMLDeclaration* NewDeclaration( const char* text=0 );
1564 /**
1565 Create a new Unknown associated with
Andrew C. Martin0fd87462013-03-09 20:09:45 -07001566 this Document. The memory for the object
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001567 is managed by the Document.
1568 */
1569 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001570
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001571 /**
1572 Delete a node associated with this document.
1573 It will be unlinked from the DOM.
1574 */
1575 void DeleteNode( XMLNode* node ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001576 node->_parent->DeleteChild( node );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001577 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001578
Lee Thomason2fa81722012-11-09 12:37:46 -08001579 void SetError( XMLError error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001580
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001581 /// Return true if there was an error parsing the document.
1582 bool Error() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001583 return _errorID != XML_NO_ERROR;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 }
1585 /// Return the errorID.
Lee Thomason2fa81722012-11-09 12:37:46 -08001586 XMLError ErrorID() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001587 return _errorID;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001588 }
1589 /// Return a possibly helpful diagnostic location or string.
1590 const char* GetErrorStr1() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001591 return _errorStr1;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001592 }
1593 /// Return a possibly helpful secondary diagnostic location or string.
1594 const char* GetErrorStr2() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001595 return _errorStr2;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001596 }
1597 /// If there is an error, print it to stdout.
1598 void PrintError() const;
Martinsh Shaitersa9d42b02013-01-30 11:14:27 +02001599
1600 /// Clear the document, resetting it to the initial state.
1601 void Clear();
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001602
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001603 // internal
1604 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001605
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001606 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1607 return 0;
1608 }
1609 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1610 return false;
1611 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001612
Lee Thomason3f57d272012-01-11 15:30:03 -08001613private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001614 XMLDocument( const XMLDocument& ); // not supported
1615 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001616
Lee Thomason2fa81722012-11-09 12:37:46 -08001617 bool _writeBOM;
1618 bool _processEntities;
1619 XMLError _errorID;
1620 Whitespace _whitespace;
Lee Thomason624d43f2012-10-12 10:58:48 -07001621 const char* _errorStr1;
1622 const char* _errorStr2;
Lee Thomason2fa81722012-11-09 12:37:46 -08001623 char* _charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001624
Lee Thomason624d43f2012-10-12 10:58:48 -07001625 MemPoolT< sizeof(XMLElement) > _elementPool;
1626 MemPoolT< sizeof(XMLAttribute) > _attributePool;
1627 MemPoolT< sizeof(XMLText) > _textPool;
1628 MemPoolT< sizeof(XMLComment) > _commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001629};
1630
Lee Thomason7c913cd2012-01-26 18:32:34 -08001631
Lee Thomason3ffdd392012-03-28 17:27:55 -07001632/**
1633 A XMLHandle is a class that wraps a node pointer with null checks; this is
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001634 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2
Lee Thomason3ffdd392012-03-28 17:27:55 -07001635 DOM structure. It is a separate utility class.
1636
1637 Take an example:
1638 @verbatim
1639 <Document>
1640 <Element attributeA = "valueA">
1641 <Child attributeB = "value1" />
1642 <Child attributeB = "value2" />
1643 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001644 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001645 @endverbatim
1646
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001647 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001648 easy to write a *lot* of code that looks like:
1649
1650 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001651 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001652 if ( root )
1653 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001654 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001655 if ( element )
1656 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001657 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001658 if ( child )
1659 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001660 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001661 if ( child2 )
1662 {
1663 // Finally do something useful.
1664 @endverbatim
1665
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001666 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001667 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001668 and correct to use:
1669
1670 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001671 XMLHandle docHandle( &document );
1672 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001673 if ( child2 )
1674 {
1675 // do something useful
1676 @endverbatim
1677
1678 Which is MUCH more concise and useful.
1679
1680 It is also safe to copy handles - internally they are nothing more than node pointers.
1681 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001682 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001683 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001684
1685 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001686*/
PKEuS16ed47d2013-07-06 12:02:43 +02001687class TINYXML2_LIB XMLHandle
Lee Thomason3ffdd392012-03-28 17:27:55 -07001688{
1689public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001690 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Lee Thomason624d43f2012-10-12 10:58:48 -07001691 XMLHandle( XMLNode* node ) {
1692 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001693 }
1694 /// Create a handle from a node.
Lee Thomason624d43f2012-10-12 10:58:48 -07001695 XMLHandle( XMLNode& node ) {
1696 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001697 }
1698 /// Copy constructor
1699 XMLHandle( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001700 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001701 }
1702 /// Assignment
1703 XMLHandle& operator=( const XMLHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001704 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001705 return *this;
1706 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001707
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001708 /// Get the first child of this handle.
1709 XMLHandle FirstChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001710 return XMLHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001711 }
1712 /// Get the first child element of this handle.
1713 XMLHandle FirstChildElement( const char* value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001714 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001715 }
1716 /// Get the last child of this handle.
1717 XMLHandle LastChild() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001718 return XMLHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001719 }
1720 /// Get the last child element of this handle.
1721 XMLHandle LastChildElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001722 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001723 }
1724 /// Get the previous sibling of this handle.
1725 XMLHandle PreviousSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001726 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001727 }
1728 /// Get the previous sibling element of this handle.
1729 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001730 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001731 }
1732 /// Get the next sibling of this handle.
1733 XMLHandle NextSibling() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001734 return XMLHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001735 }
1736 /// Get the next sibling element of this handle.
1737 XMLHandle NextSiblingElement( const char* _value=0 ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001738 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001739 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001740
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001741 /// Safe cast to XMLNode. This can return null.
1742 XMLNode* ToNode() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001743 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001744 }
1745 /// Safe cast to XMLElement. This can return null.
1746 XMLElement* ToElement() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001747 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001748 }
1749 /// Safe cast to XMLText. This can return null.
1750 XMLText* ToText() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001751 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001752 }
1753 /// Safe cast to XMLUnknown. This can return null.
1754 XMLUnknown* ToUnknown() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001755 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001756 }
1757 /// Safe cast to XMLDeclaration. This can return null.
1758 XMLDeclaration* ToDeclaration() {
Lee Thomason624d43f2012-10-12 10:58:48 -07001759 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001760 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001761
1762private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001763 XMLNode* _node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001764};
1765
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001766
1767/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001768 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1769 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001770*/
PKEuS16ed47d2013-07-06 12:02:43 +02001771class TINYXML2_LIB XMLConstHandle
Lee Thomason8b899812012-04-04 15:58:16 -07001772{
1773public:
Lee Thomason624d43f2012-10-12 10:58:48 -07001774 XMLConstHandle( const XMLNode* node ) {
1775 _node = node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001776 }
Lee Thomason624d43f2012-10-12 10:58:48 -07001777 XMLConstHandle( const XMLNode& node ) {
1778 _node = &node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001779 }
1780 XMLConstHandle( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001781 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001782 }
Lee Thomason8b899812012-04-04 15:58:16 -07001783
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001784 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
Lee Thomason624d43f2012-10-12 10:58:48 -07001785 _node = ref._node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001786 return *this;
1787 }
Lee Thomason8b899812012-04-04 15:58:16 -07001788
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001789 const XMLConstHandle FirstChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001790 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001791 }
1792 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001793 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001794 }
1795 const XMLConstHandle LastChild() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001796 return XMLConstHandle( _node ? _node->LastChild() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001797 }
1798 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001799 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001800 }
1801 const XMLConstHandle PreviousSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001802 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001803 }
1804 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001805 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001806 }
1807 const XMLConstHandle NextSibling() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001808 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001809 }
1810 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001811 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001812 }
Lee Thomason8b899812012-04-04 15:58:16 -07001813
1814
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001815 const XMLNode* ToNode() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001816 return _node;
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001817 }
1818 const XMLElement* ToElement() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001819 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001820 }
1821 const XMLText* ToText() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001822 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001823 }
1824 const XMLUnknown* ToUnknown() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001825 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001826 }
1827 const XMLDeclaration* ToDeclaration() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001828 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001829 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001830
Lee Thomason5cae8972012-01-24 18:03:07 -08001831private:
Lee Thomason624d43f2012-10-12 10:58:48 -07001832 const XMLNode* _node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001833};
Lee Thomason6f381b72012-03-02 12:59:39 -08001834
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001835
1836/**
1837 Printing functionality. The XMLPrinter gives you more
1838 options than the XMLDocument::Print() method.
1839
1840 It can:
1841 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001842 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001843 -# Print XML without a XMLDocument.
1844
1845 Print to Memory
1846
1847 @verbatim
1848 XMLPrinter printer;
Vasily Biryukov9a975b72013-05-11 21:41:42 +06001849 doc.Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001850 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001851 @endverbatim
1852
1853 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001854
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001855 You provide the file pointer.
1856 @verbatim
1857 XMLPrinter printer( fp );
1858 doc.Print( &printer );
1859 @endverbatim
1860
1861 Print without a XMLDocument
1862
1863 When loading, an XML parser is very useful. However, sometimes
1864 when saving, it just gets in the way. The code is often set up
1865 for streaming, and constructing the DOM is just overhead.
1866
1867 The Printer supports the streaming case. The following code
1868 prints out a trivially simple XML file without ever creating
1869 an XML document.
1870
1871 @verbatim
1872 XMLPrinter printer( fp );
1873 printer.OpenElement( "foo" );
1874 printer.PushAttribute( "foo", "bar" );
1875 printer.CloseElement();
1876 @endverbatim
1877*/
PKEuS16ed47d2013-07-06 12:02:43 +02001878class TINYXML2_LIB XMLPrinter : public XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001879{
1880public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001881 /** Construct the printer. If the FILE* is specified,
1882 this will print to the FILE. Else it will print
1883 to memory, and the result is available in CStr().
1884 If 'compact' is set to true, then output is created
1885 with only required whitespace and newlines.
1886 */
PKEuS1bfb9542013-08-04 13:51:17 +02001887 XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 );
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001888 virtual ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001889
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001890 /** If streaming, write the BOM and declaration. */
1891 void PushHeader( bool writeBOM, bool writeDeclaration );
1892 /** If streaming, start writing an element.
1893 The element must be closed with CloseElement()
1894 */
1895 void OpenElement( const char* name );
1896 /// If streaming, add an attribute to an open element.
1897 void PushAttribute( const char* name, const char* value );
1898 void PushAttribute( const char* name, int value );
1899 void PushAttribute( const char* name, unsigned value );
1900 void PushAttribute( const char* name, bool value );
1901 void PushAttribute( const char* name, double value );
1902 /// If streaming, close the Element.
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001903 virtual void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001904
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001905 /// Add a text node.
1906 void PushText( const char* text, bool cdata=false );
1907 /// Add a text node from an integer.
1908 void PushText( int value );
1909 /// Add a text node from an unsigned.
1910 void PushText( unsigned value );
1911 /// Add a text node from a bool.
1912 void PushText( bool value );
1913 /// Add a text node from a float.
1914 void PushText( float value );
1915 /// Add a text node from a double.
1916 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001917
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001918 /// Add a comment
1919 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001920
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001921 void PushDeclaration( const char* value );
1922 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001923
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001924 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1925 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1926 return true;
1927 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001928
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001929 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1930 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001931
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001932 virtual bool Visit( const XMLText& text );
1933 virtual bool Visit( const XMLComment& comment );
1934 virtual bool Visit( const XMLDeclaration& declaration );
1935 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001936
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001937 /**
1938 If in print to memory mode, return a pointer to
1939 the XML file in memory.
1940 */
1941 const char* CStr() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001942 return _buffer.Mem();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001943 }
1944 /**
1945 If in print to memory mode, return the size
1946 of the XML file in memory. (Note the size returned
1947 includes the terminating null.)
1948 */
1949 int CStrSize() const {
Lee Thomason624d43f2012-10-12 10:58:48 -07001950 return _buffer.Size();
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001951 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001952
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001953protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001954 void SealElement();
Dennis Jenkins59c75d32013-10-08 13:10:07 -05001955 bool _elementJustOpened;
1956 DynArray< const char*, 10 > _stack;
1957
1958private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001959 void PrintSpace( int depth );
1960 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1961 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001962
Lee Thomason624d43f2012-10-12 10:58:48 -07001963 bool _firstElement;
Jerome Martinez242c3ea2013-01-06 12:20:04 +01001964 FILE* _fp;
Lee Thomason624d43f2012-10-12 10:58:48 -07001965 int _depth;
1966 int _textDepth;
1967 bool _processEntities;
1968 bool _compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001969
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001970 enum {
1971 ENTITY_RANGE = 64,
1972 BUF_SIZE = 200
1973 };
Lee Thomason624d43f2012-10-12 10:58:48 -07001974 bool _entityFlag[ENTITY_RANGE];
1975 bool _restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001976
Lee Thomason624d43f2012-10-12 10:58:48 -07001977 DynArray< char, 20 > _buffer;
PKEuSe736f292012-07-16 03:27:55 -07001978#ifdef _MSC_VER
Lee Thomason624d43f2012-10-12 10:58:48 -07001979 DynArray< char, 20 > _accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001980#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001981};
1982
1983
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001984} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001985
PKEuS95060352013-07-26 10:42:44 +02001986#if defined(_MSC_VER)
1987# pragma warning(pop)
1988#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001989
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001990#endif // TINYXML2_INCLUDED