blob: ca80039c06441db0be11d34f3ac08d6c74b797a2 [file] [log] [blame]
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001/*
2Original code by Lee Thomason (www.grinninglizard.com)
3
4This software is provided 'as-is', without any express or implied
5warranty. In no event will the authors be held liable for any
6damages arising from the use of this software.
7
8Permission is granted to anyone to use this software for any
9purpose, including commercial applications, and to alter it and
10redistribute it freely, subject to the following restrictions:
11
121. The origin of this software must not be misrepresented; you must
13not claim that you wrote the original software. If you use this
14software in a product, an acknowledgment in the product documentation
15would be appreciated but is not required.
16
172. Altered source versions must be plainly marked as such, and
18must not be misrepresented as being the original software.
19
203. This notice may not be removed or altered from any source
21distribution.
22*/
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -080023
Lee Thomason7d00b9a2012-02-27 17:54:22 -080024#ifndef TINYXML2_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -080025#define TINYXML2_INCLUDED
26
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070027#ifdef ANDROID_NDK
Lee Thomasona9cf3f92012-10-11 16:56:51 -070028# include <ctype.h>
29# include <limits.h>
30# include <stdio.h>
31# include <stdlib.h>
32# include <string.h>
33# include <stdarg.h>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070034#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070035# include <cctype>
36# include <climits>
37# include <cstdio>
38# include <cstdlib>
39# include <cstring>
40# include <cstdarg>
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -070041#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -070043/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080044 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080045*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080046/*
Lee Thomasona9cf3f92012-10-11 16:56:51 -070047 gcc:
48 g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
49
50 Formatting, Artistic Style:
51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080052*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080053
U-Lama\Lee4cee6112011-12-31 14:58:18 -080054#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070055# ifndef DEBUG
56# define DEBUG
57# endif
U-Lama\Lee4cee6112011-12-31 14:58:18 -080058#endif
59
60
61#if defined(DEBUG)
Lee Thomasona9cf3f92012-10-11 16:56:51 -070062# if defined(_MSC_VER)
63# define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
64# elif defined (ANDROID_NDK)
65# include <android/log.h>
66# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
67# else
68# include <assert.h>
69# define TIXMLASSERT assert
70# endif
71# else
72# define TIXMLASSERT( x ) {}
U-Lama\Lee4cee6112011-12-31 14:58:18 -080073#endif
74
U-Lama\Leee13c3e62011-12-28 14:36:55 -080075
Lee Thomason1a1d4a72012-02-15 09:09:25 -080076#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
Lee Thomasona9cf3f92012-10-11 16:56:51 -070077// Microsoft visual studio, version 2005 and higher.
78/*int _snprintf_s(
79 char *buffer,
80 size_t sizeOfBuffer,
81 size_t count,
82 const char *format [,
83 argument] ...
84);*/
85inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
86{
87 va_list va;
88 va_start( va, format );
89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
90 va_end( va );
91 return result;
92}
93#define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070094#else
Lee Thomasona9cf3f92012-10-11 16:56:51 -070095// GCC version 3 and higher
96//#warning( "Using sn* functions." )
97#define TIXML_SNPRINTF snprintf
98#define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080099#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -0800100
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700101static const int TIXML2_MAJOR_VERSION = 1;
102static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason (grinliz)fc6320e2012-09-23 20:25:50 -0700103static const int TIXML2_PATCH_VERSION = 8;
Lee Thomason1ff38e02012-02-14 18:18:16 -0800104
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800105namespace tinyxml2
106{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800107class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800108class XMLElement;
109class XMLAttribute;
110class XMLComment;
111class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800112class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800113class XMLDeclaration;
114class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800115
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800117
U-Stream\Leeae25a442012-02-17 17:48:16 -0800118/*
119 A class that wraps strings. Normally stores the start and end
120 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800121 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800122 manage) a traditional char[]
123*/
Lee Thomason39ede242012-01-20 11:27:56 -0800124class StrPair
125{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800126public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700127 enum {
128 NEEDS_ENTITY_PROCESSING = 0x01,
129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
130 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800131
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
134 ATTRIBUTE_NAME = 0,
135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
138 };
Lee Thomason39ede242012-01-20 11:27:56 -0800139
Lee Thomason120b3a62012-10-12 10:06:59 -0700140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700141 ~StrPair();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142
Lee Thomason120b3a62012-10-12 10:06:59 -0700143 void Set( char* start, char* end, int flags ) {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700144 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700145 _start = start;
146 _end = end;
147 _flags = flags | NEEDS_FLUSH;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700148 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700149
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700150 const char* GetStr();
Lee Thomason120b3a62012-10-12 10:06:59 -0700151
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700152 bool Empty() const {
Lee Thomason120b3a62012-10-12 10:06:59 -0700153 return _start == _end;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700154 }
Lee Thomason39ede242012-01-20 11:27:56 -0800155
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700156 void SetInternedStr( const char* str ) {
157 Reset();
Lee Thomason120b3a62012-10-12 10:06:59 -0700158 _start = const_cast<char*>(str);
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700159 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700160
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700161 void SetStr( const char* str, int flags=0 );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800162
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700163 char* ParseText( char* in, const char* endTag, int strFlags );
164 char* ParseName( char* in );
Lee Thomason56bdd022012-02-09 18:16:58 -0800165
Lee Thomason39ede242012-01-20 11:27:56 -0800166private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700167 void Reset();
168 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800169
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700170 enum {
171 NEEDS_FLUSH = 0x100,
172 NEEDS_DELETE = 0x200
173 };
Lee Thomasone4422302012-01-20 17:59:50 -0800174
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700175 // After parsing, if *end != 0, it can be set to zero.
Lee Thomason120b3a62012-10-12 10:06:59 -0700176 int _flags;
177 char* _start;
178 char* _end;
Lee Thomason39ede242012-01-20 11:27:56 -0800179};
180
U-Lama\Lee560bd472011-12-28 19:42:49 -0800181
U-Stream\Leeae25a442012-02-17 17:48:16 -0800182/*
183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
184 Has a small initial memory pool, so that low or no usage will not
185 cause a call to new/delete
186*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800187template <class T, int INIT>
188class DynArray
189{
190public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700191 DynArray< T, INIT >() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700192 _mem = pool;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700193 allocated = INIT;
194 size = 0;
195 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700196
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700197 ~DynArray() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700198 if ( _mem != pool ) {
199 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700200 }
201 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700202
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700203 void Push( T t ) {
204 EnsureCapacity( size+1 );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700205 _mem[size++] = t;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700206 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800207
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700208 T* PushArr( int count ) {
209 EnsureCapacity( size+count );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700210 T* ret = &_mem[size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700211 size += count;
212 return ret;
213 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700214
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700215 T Pop() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700216 return _mem[--size];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700217 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700218
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700219 void PopArr( int count ) {
220 TIXMLASSERT( size >= count );
221 size -= count;
222 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800223
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700224 bool Empty() const {
225 return size == 0;
226 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700227
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700228 T& operator[](int i) {
229 TIXMLASSERT( i>= 0 && i < size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700230 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700231 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700232
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700233 const T& operator[](int i) const {
234 TIXMLASSERT( i>= 0 && i < size );
Lee Thomasoned5c8792012-10-12 10:09:48 -0700235 return _mem[i];
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700236 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700237
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700238 int Size() const {
239 return size;
240 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700241
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700242 int Capacity() const {
243 return allocated;
244 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700245
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700246 const T* Mem() const {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700247 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700248 }
Lee Thomason120b3a62012-10-12 10:06:59 -0700249
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700250 T* Mem() {
Lee Thomasoned5c8792012-10-12 10:09:48 -0700251 return _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700252 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800253
Lee Thomason2c85a712012-01-31 08:24:24 -0800254private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700255 void EnsureCapacity( int cap ) {
256 if ( cap > allocated ) {
257 int newAllocated = cap * 2;
258 T* newMem = new T[newAllocated];
Lee Thomasoned5c8792012-10-12 10:09:48 -0700259 memcpy( newMem, _mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
260 if ( _mem != pool ) {
261 delete [] _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700262 }
Lee Thomasoned5c8792012-10-12 10:09:48 -0700263 _mem = newMem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700264 allocated = newAllocated;
265 }
266 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800267
Lee Thomasoned5c8792012-10-12 10:09:48 -0700268 T* _mem;
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700269 T pool[INIT];
270 int allocated; // objects allocated
271 int size; // number objects in use
Lee Thomason2c85a712012-01-31 08:24:24 -0800272};
273
Lee Thomason50adb4c2012-02-13 15:07:09 -0800274
U-Stream\Leeae25a442012-02-17 17:48:16 -0800275/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200276 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800277 and deallocation of objects.
278*/
Lee Thomasond1983222012-02-06 08:41:24 -0800279class MemPool
280{
281public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700282 MemPool() {}
283 virtual ~MemPool() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800284
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700285 virtual int ItemSize() const = 0;
286 virtual void* Alloc() = 0;
287 virtual void Free( void* ) = 0;
Lee Thomasond1983222012-02-06 08:41:24 -0800288};
289
Lee Thomason50adb4c2012-02-13 15:07:09 -0800290
U-Stream\Leeae25a442012-02-17 17:48:16 -0800291/*
292 Template child class to create pools of the correct type.
293*/
Lee Thomasond1983222012-02-06 08:41:24 -0800294template< int SIZE >
295class MemPoolT : public MemPool
296{
297public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700298 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
299 ~MemPoolT() {
300 // Delete the blocks.
301 for( int i=0; i<blockPtrs.Size(); ++i ) {
302 delete blockPtrs[i];
303 }
304 }
Lee Thomasond1983222012-02-06 08:41:24 -0800305
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700306 virtual int ItemSize() const {
307 return SIZE;
308 }
309 int CurrentAllocs() const {
310 return currentAllocs;
311 }
Lee Thomasond1983222012-02-06 08:41:24 -0800312
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700313 virtual void* Alloc() {
314 if ( !root ) {
315 // Need a new block.
316 Block* block = new Block();
317 blockPtrs.Push( block );
Lee Thomasond1983222012-02-06 08:41:24 -0800318
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700319 for( int i=0; i<COUNT-1; ++i ) {
320 block->chunk[i].next = &block->chunk[i+1];
321 }
322 block->chunk[COUNT-1].next = 0;
323 root = block->chunk;
324 }
325 void* result = root;
326 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800327
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700328 ++currentAllocs;
329 if ( currentAllocs > maxAllocs ) {
330 maxAllocs = currentAllocs;
331 }
332 nAllocs++;
333 return result;
334 }
335 virtual void Free( void* mem ) {
336 if ( !mem ) {
337 return;
338 }
339 --currentAllocs;
340 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700341#ifdef DEBUG
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700342 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700343#endif
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700344 chunk->next = root;
345 root = chunk;
346 }
347 void Trace( const char* name ) {
348 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
349 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
350 }
Lee Thomasond1983222012-02-06 08:41:24 -0800351
352private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700353 enum { COUNT = 1024/SIZE };
354 union Chunk {
355 Chunk* next;
356 char mem[SIZE];
357 };
358 struct Block {
359 Chunk chunk[COUNT];
360 };
361 DynArray< Block*, 10 > blockPtrs;
362 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800363
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700364 int currentAllocs;
365 int nAllocs;
366 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800367};
368
Lee Thomason2c85a712012-01-31 08:24:24 -0800369
Lee Thomason56bdd022012-02-09 18:16:58 -0800370
371/**
372 Implements the interface to the "Visitor pattern" (see the Accept() method.)
373 If you call the Accept() method, it requires being passed a XMLVisitor
374 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200375 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800376 are simply called with Visit().
377
378 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200379 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800380
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700381 All flavors of Visit methods have a default implementation that returns 'true' (continue
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 visiting). You need to only override methods that are interesting to you.
383
Thomas Roß08bdf502012-05-12 14:21:23 +0200384 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800385
386 You should never change the document from a callback.
387
388 @sa XMLNode::Accept()
389*/
390class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800391{
392public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700393 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800394
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700395 /// Visit a document.
396 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
397 return true;
398 }
399 /// Visit a document.
400 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
401 return true;
402 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800403
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700404 /// Visit an element.
405 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
406 return true;
407 }
408 /// Visit an element.
409 virtual bool VisitExit( const XMLElement& /*element*/ ) {
410 return true;
411 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800412
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700413 /// Visit a declaration.
414 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
415 return true;
416 }
417 /// Visit a text node.
418 virtual bool Visit( const XMLText& /*text*/ ) {
419 return true;
420 }
421 /// Visit a comment node.
422 virtual bool Visit( const XMLComment& /*comment*/ ) {
423 return true;
424 }
425 /// Visit an unknown node.
426 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
427 return true;
428 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800429};
430
431
U-Stream\Leeae25a442012-02-17 17:48:16 -0800432/*
433 Utility functionality.
434*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800435class XMLUtil
436{
Lee Thomasond1983222012-02-06 08:41:24 -0800437public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700438 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
439 // correct, but simple, and usually works.
440 static const char* SkipWhiteSpace( const char* p ) {
441 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
442 ++p;
443 }
444 return p;
445 }
446 static char* SkipWhiteSpace( char* p ) {
447 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
448 ++p;
449 }
450 return p;
451 }
452 static bool IsWhiteSpace( char p ) {
453 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
454 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800455
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700456 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
457 int n = 0;
458 if ( p == q ) {
459 return true;
460 }
461 while( *p && *q && *p == *q && n<nChar ) {
462 ++p;
463 ++q;
464 ++n;
465 }
466 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
467 return true;
468 }
469 return false;
470 }
471 inline static int IsUTF8Continuation( const char p ) {
472 return p & 0x80;
473 }
474 inline static int IsAlphaNum( unsigned char anyByte ) {
475 return ( anyByte < 128 ) ? isalnum( anyByte ) : 1;
476 }
477 inline static int IsAlpha( unsigned char anyByte ) {
478 return ( anyByte < 128 ) ? isalpha( anyByte ) : 1;
479 }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800480
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700481 static const char* ReadBOM( const char* p, bool* hasBOM );
482 // p is the starting location,
483 // the UTF-8 value of the entity will be placed in value, and length filled in.
484 static const char* GetCharacterRef( const char* p, char* value, int* length );
485 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700486
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700487 // converts primitive types to strings
488 static void ToStr( int v, char* buffer, int bufferSize );
489 static void ToStr( unsigned v, char* buffer, int bufferSize );
490 static void ToStr( bool v, char* buffer, int bufferSize );
491 static void ToStr( float v, char* buffer, int bufferSize );
492 static void ToStr( double v, char* buffer, int bufferSize );
Lee Thomason21be8822012-07-15 17:27:22 -0700493
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700494 // converts strings to primitive types
495 static bool ToInt( const char* str, int* value );
496 static bool ToUnsigned( const char* str, unsigned* value );
497 static bool ToBool( const char* str, bool* value );
498 static bool ToFloat( const char* str, float* value );
499 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800500};
501
Lee Thomason5cae8972012-01-24 18:03:07 -0800502
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800503/** XMLNode is a base class for every object that is in the
504 XML Document Object Model (DOM), except XMLAttributes.
505 Nodes have siblings, a parent, and children which can
506 be navigated. A node is always in a XMLDocument.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700507 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800508 be cast to its more defined type.
509
Thomas Roß08bdf502012-05-12 14:21:23 +0200510 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800511 When the XMLDocument gets deleted, all its Nodes
512 will also be deleted.
513
514 @verbatim
515 A Document can contain: Element (container or leaf)
516 Comment (leaf)
517 Unknown (leaf)
518 Declaration( leaf )
519
520 An Element can contain: Element (container or leaf)
521 Text (leaf)
522 Attributes (not on tree)
523 Comment (leaf)
524 Unknown (leaf)
525
526 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800527*/
Lee Thomasond1983222012-02-06 08:41:24 -0800528class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800529{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700530 friend class XMLDocument;
531 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800532public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800533
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700534 /// Get the XMLDocument that owns this XMLNode.
535 const XMLDocument* GetDocument() const {
536 return document;
537 }
538 /// Get the XMLDocument that owns this XMLNode.
539 XMLDocument* GetDocument() {
540 return document;
541 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800542
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700543 virtual XMLElement* ToElement() {
544 return 0; ///< Safely cast to an Element, or null.
545 }
546 virtual XMLText* ToText() {
547 return 0; ///< Safely cast to Text, or null.
548 }
549 virtual XMLComment* ToComment() {
550 return 0; ///< Safely cast to a Comment, or null.
551 }
552 virtual XMLDocument* ToDocument() {
553 return 0; ///< Safely cast to a Document, or null.
554 }
555 virtual XMLDeclaration* ToDeclaration() {
556 return 0; ///< Safely cast to a Declaration, or null.
557 }
558 virtual XMLUnknown* ToUnknown() {
559 return 0; ///< Safely cast to an Unknown, or null.
560 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800561
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700562 virtual const XMLElement* ToElement() const {
563 return 0;
564 }
565 virtual const XMLText* ToText() const {
566 return 0;
567 }
568 virtual const XMLComment* ToComment() const {
569 return 0;
570 }
571 virtual const XMLDocument* ToDocument() const {
572 return 0;
573 }
574 virtual const XMLDeclaration* ToDeclaration() const {
575 return 0;
576 }
577 virtual const XMLUnknown* ToUnknown() const {
578 return 0;
579 }
Lee Thomason751da522012-02-10 08:50:51 -0800580
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700581 /** The meaning of 'value' changes for the specific type.
582 @verbatim
583 Document: empty
584 Element: name of the element
585 Comment: the comment text
586 Unknown: the tag contents
587 Text: the text string
588 @endverbatim
589 */
590 const char* Value() const {
591 return value.GetStr();
592 }
593 /** Set the Value of an XML node.
594 @sa Value()
595 */
596 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800597
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700598 /// Get the parent of this node on the DOM.
599 const XMLNode* Parent() const {
600 return parent;
601 }
602 XMLNode* Parent() {
603 return parent;
604 }
Lee Thomason751da522012-02-10 08:50:51 -0800605
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700606 /// Returns true if this node has no children.
607 bool NoChildren() const {
608 return !firstChild;
609 }
Lee Thomason751da522012-02-10 08:50:51 -0800610
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700611 /// Get the first child node, or null if none exists.
612 const XMLNode* FirstChild() const {
613 return firstChild;
614 }
615 XMLNode* FirstChild() {
616 return firstChild;
617 }
618 /** Get the first child element, or optionally the first child
619 element with the specified name.
620 */
621 const XMLElement* FirstChildElement( const char* value=0 ) const;
622 XMLElement* FirstChildElement( const char* _value=0 ) {
623 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value ));
624 }
Lee Thomason3f57d272012-01-11 15:30:03 -0800625
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700626 /// Get the last child node, or null if none exists.
627 const XMLNode* LastChild() const {
628 return lastChild;
629 }
630 XMLNode* LastChild() {
631 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
632 }
Lee Thomason2c85a712012-01-31 08:24:24 -0800633
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700634 /** Get the last child element or optionally the last child
635 element with the specified name.
636 */
637 const XMLElement* LastChildElement( const char* value=0 ) const;
638 XMLElement* LastChildElement( const char* _value=0 ) {
639 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) );
640 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700641
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700642 /// Get the previous (left) sibling node of this node.
643 const XMLNode* PreviousSibling() const {
644 return prev;
645 }
646 XMLNode* PreviousSibling() {
647 return prev;
648 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800649
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700650 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
651 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
652 XMLElement* PreviousSiblingElement( const char* _value=0 ) {
653 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) );
654 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700655
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700656 /// Get the next (right) sibling node of this node.
657 const XMLNode* NextSibling() const {
658 return next;
659 }
660 XMLNode* NextSibling() {
661 return next;
662 }
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700663
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700664 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
665 const XMLElement* NextSiblingElement( const char* value=0 ) const;
666 XMLElement* NextSiblingElement( const char* _value=0 ) {
667 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) );
668 }
Lee Thomason56bdd022012-02-09 18:16:58 -0800669
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700670 /**
671 Add a child node as the last (right) child.
672 */
673 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800674
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700675 XMLNode* LinkEndChild( XMLNode* addThis ) {
676 return InsertEndChild( addThis );
677 }
678 /**
679 Add a child node as the first (left) child.
680 */
681 XMLNode* InsertFirstChild( XMLNode* addThis );
682 /**
683 Add a node after the specified child node.
684 */
685 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700686
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700687 /**
688 Delete all the children of this node.
689 */
690 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800691
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700692 /**
693 Delete a child of this node.
694 */
695 void DeleteChild( XMLNode* node );
Lee Thomason56bdd022012-02-09 18:16:58 -0800696
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700697 /**
698 Make a copy of this node, but not its children.
699 You may pass in a Document pointer that will be
700 the owner of the new Node. If the 'document' is
701 null, then the node returned will be allocated
702 from the current Document. (this->GetDocument())
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800703
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700704 Note: if called on a XMLDocument, this will return null.
705 */
706 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800707
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700708 /**
709 Test if 2 nodes are the same, but don't test children.
710 The 2 nodes do not need to be in the same Document.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800711
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700712 Note: if called on a XMLDocument, this will return false.
713 */
714 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800715
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700716 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
717 XML tree will be conditionally visited and the host will be called back
718 via the TiXmlVisitor interface.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800719
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700720 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
721 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
722 interface versus any other.)
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800723
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700724 The interface has been based on ideas from:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800725
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700726 - http://www.saxproject.org/
727 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800728
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700729 Which are both good references for "visiting".
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800730
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700731 An example of using Accept():
732 @verbatim
733 TiXmlPrinter printer;
734 tinyxmlDoc.Accept( &printer );
735 const char* xmlcstr = printer.CStr();
736 @endverbatim
737 */
738 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800739
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700740 // internal
741 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800742
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800743protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700744 XMLNode( XMLDocument* );
745 virtual ~XMLNode();
746 XMLNode( const XMLNode& ); // not supported
747 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700748
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700749 XMLDocument* document;
750 XMLNode* parent;
751 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800752
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700753 XMLNode* firstChild;
754 XMLNode* lastChild;
Lee Thomason3f57d272012-01-11 15:30:03 -0800755
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700756 XMLNode* prev;
757 XMLNode* next;
Lee Thomason3f57d272012-01-11 15:30:03 -0800758
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800759private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700760 MemPool* memPool;
761 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800762};
763
764
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800765/** XML text.
766
767 Note that a text node can have child element nodes, for example:
768 @verbatim
769 <root>This is <b>bold</b></root>
770 @endverbatim
771
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -0700772 A text node can have 2 ways to output the next. "normal" output
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800773 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 -0700774 you generally want to leave it alone, but you can change the output mode with
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800775 SetCDATA() and query it with CDATA().
776*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800777class XMLText : public XMLNode
778{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700779 friend class XMLBase;
780 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800781public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700782 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800783
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700784 virtual XMLText* ToText() {
785 return this;
786 }
787 virtual const XMLText* ToText() const {
788 return this;
789 }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800790
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700791 /// Declare whether this should be CDATA or standard text.
792 void SetCData( bool _isCData ) {
793 this->isCData = _isCData;
794 }
795 /// Returns true if this is a CDATA text element.
796 bool CData() const {
797 return isCData;
798 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800799
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700800 char* ParseDeep( char*, StrPair* endTag );
801 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
802 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800803
Lee Thomason5492a1c2012-01-23 15:32:10 -0800804
805protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700806 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
807 virtual ~XMLText() {}
808 XMLText( const XMLText& ); // not supported
809 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800810
811private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700812 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800813};
814
815
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800816/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800817class XMLComment : public XMLNode
818{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700819 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800820public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700821 virtual XMLComment* ToComment() {
822 return this;
823 }
824 virtual const XMLComment* ToComment() const {
825 return this;
826 }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800827
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700828 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800829
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700830 char* ParseDeep( char*, StrPair* endTag );
831 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
832 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800833
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800834protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700835 XMLComment( XMLDocument* doc );
836 virtual ~XMLComment();
837 XMLComment( const XMLComment& ); // not supported
838 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800839
Lee Thomason3f57d272012-01-11 15:30:03 -0800840private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800841};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800842
843
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800844/** In correct XML the declaration is the first entry in the file.
845 @verbatim
846 <?xml version="1.0" standalone="yes"?>
847 @endverbatim
848
849 TinyXML2 will happily read or write files without a declaration,
850 however.
851
852 The text of the declaration isn't interpreted. It is parsed
853 and written as a string.
854*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800855class XMLDeclaration : public XMLNode
856{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700857 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800858public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700859 virtual XMLDeclaration* ToDeclaration() {
860 return this;
861 }
862 virtual const XMLDeclaration* ToDeclaration() const {
863 return this;
864 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800865
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700866 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800867
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700868 char* ParseDeep( char*, StrPair* endTag );
869 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
870 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800871
872protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700873 XMLDeclaration( XMLDocument* doc );
874 virtual ~XMLDeclaration();
875 XMLDeclaration( const XMLDeclaration& ); // not supported
876 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800877};
878
879
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800880/** Any tag that tinyXml doesn't recognize is saved as an
881 unknown. It is a tag of text, but should not be modified.
882 It will be written back to the XML, unchanged, when the file
883 is saved.
884
885 DTD tags get thrown into TiXmlUnknowns.
886*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800887class XMLUnknown : public XMLNode
888{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700889 friend class XMLDocument;
Lee Thomason50f97b22012-02-11 16:33:40 -0800890public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700891 virtual XMLUnknown* ToUnknown() {
892 return this;
893 }
894 virtual const XMLUnknown* ToUnknown() const {
895 return this;
896 }
Lee Thomason50f97b22012-02-11 16:33:40 -0800897
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700898 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800899
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700900 char* ParseDeep( char*, StrPair* endTag );
901 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
902 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800903
904protected:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700905 XMLUnknown( XMLDocument* doc );
906 virtual ~XMLUnknown();
907 XMLUnknown( const XMLUnknown& ); // not supported
908 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800909};
910
911
Lee Thomason1ff38e02012-02-14 18:18:16 -0800912enum {
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700913 XML_NO_ERROR = 0,
914 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800915
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700916 XML_NO_ATTRIBUTE,
917 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800918
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700919 XML_ERROR_FILE_NOT_FOUND,
920 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
921 XML_ERROR_FILE_READ_ERROR,
922 XML_ERROR_ELEMENT_MISMATCH,
923 XML_ERROR_PARSING_ELEMENT,
924 XML_ERROR_PARSING_ATTRIBUTE,
925 XML_ERROR_IDENTIFYING_TAG,
926 XML_ERROR_PARSING_TEXT,
927 XML_ERROR_PARSING_CDATA,
928 XML_ERROR_PARSING_COMMENT,
929 XML_ERROR_PARSING_DECLARATION,
930 XML_ERROR_PARSING_UNKNOWN,
931 XML_ERROR_EMPTY_DOCUMENT,
932 XML_ERROR_MISMATCHED_ELEMENT,
933 XML_ERROR_PARSING,
Lee Thomason21be8822012-07-15 17:27:22 -0700934
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700935 XML_CAN_NOT_CONVERT_TEXT,
936 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800937};
938
939
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800940/** An attribute is a name-value pair. Elements have an arbitrary
941 number of attributes, each with a unique name.
942
943 @note The attributes are not XMLNodes. You may only query the
944 Next() attribute in a list.
945*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800946class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800947{
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700948 friend class XMLElement;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800949public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700950 const char* Name() const {
951 return name.GetStr(); ///< The name of the attribute.
952 }
953 const char* Value() const {
954 return value.GetStr(); ///< The value of the attribute.
955 }
956 const XMLAttribute* Next() const {
957 return next; ///< The next attribute in the list.
958 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800959
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700960 /** IntAttribute interprets the attribute as an integer, and returns the value.
961 If the value isn't an integer, 0 will be returned. There is no error checking;
962 use QueryIntAttribute() if you need error checking.
963 */
964 int IntValue() const {
965 int i=0;
966 QueryIntValue( &i );
967 return i;
968 }
969 /// Query as an unsigned integer. See IntAttribute()
970 unsigned UnsignedValue() const {
971 unsigned i=0;
972 QueryUnsignedValue( &i );
973 return i;
974 }
975 /// Query as a boolean. See IntAttribute()
976 bool BoolValue() const {
977 bool b=false;
978 QueryBoolValue( &b );
979 return b;
980 }
981 /// Query as a double. See IntAttribute()
982 double DoubleValue() const {
983 double d=0;
984 QueryDoubleValue( &d );
985 return d;
986 }
987 /// Query as a float. See IntAttribute()
988 float FloatValue() const {
989 float f=0;
990 QueryFloatValue( &f );
991 return f;
992 }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800993
Lee Thomasona9cf3f92012-10-11 16:56:51 -0700994 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
995 in the provided paremeter. The function will return XML_NO_ERROR on success,
996 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
997 */
998 int QueryIntValue( int* value ) const;
999 /// See QueryIntAttribute
1000 int QueryUnsignedValue( unsigned int* value ) const;
1001 /// See QueryIntAttribute
1002 int QueryBoolValue( bool* value ) const;
1003 /// See QueryIntAttribute
1004 int QueryDoubleValue( double* value ) const;
1005 /// See QueryIntAttribute
1006 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -08001007
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001008 /// Set the attribute to a string value.
1009 void SetAttribute( const char* value );
1010 /// Set the attribute to value.
1011 void SetAttribute( int value );
1012 /// Set the attribute to value.
1013 void SetAttribute( unsigned value );
1014 /// Set the attribute to value.
1015 void SetAttribute( bool value );
1016 /// Set the attribute to value.
1017 void SetAttribute( double value );
1018 /// Set the attribute to value.
1019 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001020
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001021private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001022 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001023
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001024 XMLAttribute() : next( 0 ) {}
1025 virtual ~XMLAttribute() {}
1026 XMLAttribute( const XMLAttribute& ); // not supported
1027 void operator=( const XMLAttribute& ); // not supported
1028 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -08001029
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001030 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001031
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001032 mutable StrPair name;
1033 mutable StrPair value;
1034 XMLAttribute* next;
1035 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001036};
1037
1038
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001039/** The element is a container class. It has a value, the element name,
1040 and can contain other elements, text, comments, and unknowns.
1041 Elements also contain an arbitrary number of attributes.
1042*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001043class XMLElement : public XMLNode
1044{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001045 friend class XMLBase;
1046 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001047public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001048 /// Get the name of an element (which is the Value() of the node.)
1049 const char* Name() const {
1050 return Value();
1051 }
1052 /// Set the name of the element.
1053 void SetName( const char* str, bool staticMem=false ) {
1054 SetValue( str, staticMem );
1055 }
Lee Thomason2c85a712012-01-31 08:24:24 -08001056
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001057 virtual XMLElement* ToElement() {
1058 return this;
1059 }
1060 virtual const XMLElement* ToElement() const {
1061 return this;
1062 }
1063 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001064
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001065 /** Given an attribute name, Attribute() returns the value
1066 for the attribute of that name, or null if none
1067 exists. For example:
Lee Thomason92258152012-03-24 13:05:39 -07001068
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001069 @verbatim
1070 const char* value = ele->Attribute( "foo" );
1071 @endverbatim
Lee Thomason92258152012-03-24 13:05:39 -07001072
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001073 The 'value' parameter is normally null. However, if specified,
1074 the attribute will only be returned if the 'name' and 'value'
1075 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001076
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001077 @verbatim
1078 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
1079 @endverbatim
Lee Thomason8ba7f7d2012-03-24 13:04:04 -07001080
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001081 rather than:
1082 @verbatim
1083 if ( ele->Attribute( "foo" ) ) {
1084 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
1085 }
1086 @endverbatim
1087 */
1088 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001089
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001090 /** Given an attribute name, IntAttribute() returns the value
1091 of the attribute interpreted as an integer. 0 will be
1092 returned if there is an error. For a method with error
1093 checking, see QueryIntAttribute()
1094 */
1095 int IntAttribute( const char* name ) const {
1096 int i=0;
1097 QueryIntAttribute( name, &i );
1098 return i;
1099 }
1100 /// See IntAttribute()
1101 unsigned UnsignedAttribute( const char* name ) const {
1102 unsigned i=0;
1103 QueryUnsignedAttribute( name, &i );
1104 return i;
1105 }
1106 /// See IntAttribute()
1107 bool BoolAttribute( const char* name ) const {
1108 bool b=false;
1109 QueryBoolAttribute( name, &b );
1110 return b;
1111 }
1112 /// See IntAttribute()
1113 double DoubleAttribute( const char* name ) const {
1114 double d=0;
1115 QueryDoubleAttribute( name, &d );
1116 return d;
1117 }
1118 /// See IntAttribute()
1119 float FloatAttribute( const char* name ) const {
1120 float f=0;
1121 QueryFloatAttribute( name, &f );
1122 return f;
1123 }
U-Stream\Lee09a11c52012-02-17 08:31:16 -08001124
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001125 /** Given an attribute name, QueryIntAttribute() returns
1126 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
1127 can't be performed, or XML_NO_ATTRIBUTE if the attribute
1128 doesn't exist. If successful, the result of the conversion
1129 will be written to 'value'. If not successful, nothing will
1130 be written to 'value'. This allows you to provide default
1131 value:
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001132
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001133 @verbatim
1134 int value = 10;
1135 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
1136 @endverbatim
1137 */
1138 int QueryIntAttribute( const char* name, int* _value ) const {
1139 const XMLAttribute* a = FindAttribute( name );
1140 if ( !a ) {
1141 return XML_NO_ATTRIBUTE;
1142 }
1143 return a->QueryIntValue( _value );
1144 }
1145 /// See QueryIntAttribute()
1146 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const {
1147 const XMLAttribute* a = FindAttribute( name );
1148 if ( !a ) {
1149 return XML_NO_ATTRIBUTE;
1150 }
1151 return a->QueryUnsignedValue( _value );
1152 }
1153 /// See QueryIntAttribute()
1154 int QueryBoolAttribute( const char* name, bool* _value ) const {
1155 const XMLAttribute* a = FindAttribute( name );
1156 if ( !a ) {
1157 return XML_NO_ATTRIBUTE;
1158 }
1159 return a->QueryBoolValue( _value );
1160 }
1161 /// See QueryIntAttribute()
1162 int QueryDoubleAttribute( const char* name, double* _value ) const {
1163 const XMLAttribute* a = FindAttribute( name );
1164 if ( !a ) {
1165 return XML_NO_ATTRIBUTE;
1166 }
1167 return a->QueryDoubleValue( _value );
1168 }
1169 /// See QueryIntAttribute()
1170 int QueryFloatAttribute( const char* name, float* _value ) const {
1171 const XMLAttribute* a = FindAttribute( name );
1172 if ( !a ) {
1173 return XML_NO_ATTRIBUTE;
1174 }
1175 return a->QueryFloatValue( _value );
1176 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001177
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001178 /// Sets the named attribute to value.
1179 void SetAttribute( const char* name, const char* _value ) {
1180 XMLAttribute* a = FindOrCreateAttribute( name );
1181 a->SetAttribute( _value );
1182 }
1183 /// Sets the named attribute to value.
1184 void SetAttribute( const char* name, int _value ) {
1185 XMLAttribute* a = FindOrCreateAttribute( name );
1186 a->SetAttribute( _value );
1187 }
1188 /// Sets the named attribute to value.
1189 void SetAttribute( const char* name, unsigned _value ) {
1190 XMLAttribute* a = FindOrCreateAttribute( name );
1191 a->SetAttribute( _value );
1192 }
1193 /// Sets the named attribute to value.
1194 void SetAttribute( const char* name, bool _value ) {
1195 XMLAttribute* a = FindOrCreateAttribute( name );
1196 a->SetAttribute( _value );
1197 }
1198 /// Sets the named attribute to value.
1199 void SetAttribute( const char* name, double _value ) {
1200 XMLAttribute* a = FindOrCreateAttribute( name );
1201 a->SetAttribute( _value );
1202 }
Lee Thomason50f97b22012-02-11 16:33:40 -08001203
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001204 /**
1205 Delete an attribute.
1206 */
1207 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -08001208
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001209 /// Return the first attribute in the list.
1210 const XMLAttribute* FirstAttribute() const {
1211 return rootAttribute;
1212 }
1213 /// Query a specific attribute in the list.
1214 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -08001215
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001216 /** Convenience function for easy access to the text inside an element. Although easy
1217 and concise, GetText() is limited compared to getting the TiXmlText child
1218 and accessing it directly.
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001219
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001220 If the first child of 'this' is a TiXmlText, the GetText()
1221 returns the character string of the Text node, else null is returned.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001222
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001223 This is a convenient method for getting the text of simple contained text:
1224 @verbatim
1225 <foo>This is text</foo>
1226 const char* str = fooElement->GetText();
1227 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001228
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001229 'str' will be a pointer to "This is text".
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001230
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001231 Note that this function can be misleading. If the element foo was created from
1232 this XML:
1233 @verbatim
1234 <foo><b>This is text</b></foo>
1235 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001236
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001237 then the value of str would be null. The first child node isn't a text node, it is
1238 another element. From this XML:
1239 @verbatim
1240 <foo>This is <b>text</b></foo>
1241 @endverbatim
1242 GetText() will return "This is ".
1243 */
1244 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -08001245
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001246 /**
1247 Convenience method to query the value of a child text node. This is probably best
1248 shown by example. Given you have a document is this form:
1249 @verbatim
1250 <point>
1251 <x>1</x>
1252 <y>1.4</y>
1253 </point>
1254 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001255
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001256 The QueryIntText() and similar functions provide a safe and easier way to get to the
1257 "value" of x and y.
Lee Thomason21be8822012-07-15 17:27:22 -07001258
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001259 @verbatim
1260 int x = 0;
1261 float y = 0; // types of x and y are contrived for example
1262 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
1263 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
1264 xElement->QueryIntText( &x );
1265 yElement->QueryFloatText( &y );
1266 @endverbatim
Lee Thomason21be8822012-07-15 17:27:22 -07001267
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001268 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1269 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 -07001270
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001271 */
1272 int QueryIntText( int* _value ) const;
1273 /// See QueryIntText()
1274 int QueryUnsignedText( unsigned* _value ) const;
1275 /// See QueryIntText()
1276 int QueryBoolText( bool* _value ) const;
1277 /// See QueryIntText()
1278 int QueryDoubleText( double* _value ) const;
1279 /// See QueryIntText()
1280 int QueryFloatText( float* _value ) const;
Lee Thomason21be8822012-07-15 17:27:22 -07001281
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001282 // internal:
1283 enum {
1284 OPEN, // <foo>
1285 CLOSED, // <foo/>
1286 CLOSING // </foo>
1287 };
1288 int ClosingType() const {
1289 return closingType;
1290 }
1291 char* ParseDeep( char* p, StrPair* endTag );
1292 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1293 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001294
Lee Thomason50adb4c2012-02-13 15:07:09 -08001295private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001296 XMLElement( XMLDocument* doc );
1297 virtual ~XMLElement();
1298 XMLElement( const XMLElement& ); // not supported
1299 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001300
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001301 XMLAttribute* FindAttribute( const char* name );
1302 XMLAttribute* FindOrCreateAttribute( const char* name );
1303 //void LinkAttribute( XMLAttribute* attrib );
1304 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001305
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001306 int closingType;
1307 // The attribute list is ordered; there is no 'lastAttribute'
1308 // because the list needs to be scanned for dupes before adding
1309 // a new attribute.
1310 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001311};
1312
1313
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001314enum Whitespace {
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001315 PRESERVE_WHITESPACE,
1316 COLLAPSE_WHITESPACE
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001317};
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001318
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001319
1320/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001321 It can be saved, loaded, and printed to the screen.
1322 All Nodes are connected and allocated to a Document.
1323 If the Document is deleted, all its Nodes are also deleted.
1324*/
Lee Thomason67d61312012-01-24 16:01:51 -08001325class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001326{
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001327 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001328public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001329 /// constructor
1330 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
1331 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001332
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001333 virtual XMLDocument* ToDocument() {
1334 return this;
1335 }
1336 virtual const XMLDocument* ToDocument() const {
1337 return this;
1338 }
Lee Thomason56bdd022012-02-09 18:16:58 -08001339
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001340 /**
1341 Parse an XML file from a character string.
1342 Returns XML_NO_ERROR (0) on success, or
1343 an errorID.
Lee Thomason (grinliz)e2bcb322012-09-17 17:58:25 -07001344
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001345 You may optionally pass in the 'nBytes', which is
1346 the number of bytes which will be parsed. If not
1347 specified, TinyXML will assume 'xml' points to a
1348 null terminated string.
1349 */
1350 int Parse( const char* xml, size_t nBytes=(size_t)(-1) );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001351
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001352 /**
1353 Load an XML file from disk.
1354 Returns XML_NO_ERROR (0) on success, or
1355 an errorID.
1356 */
1357 int LoadFile( const char* filename );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001358
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001359 /**
1360 Load an XML file from disk. You are responsible
1361 for providing and closing the FILE*.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001362
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001363 Returns XML_NO_ERROR (0) on success, or
1364 an errorID.
1365 */
1366 int LoadFile( FILE* );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001367
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001368 /**
1369 Save the XML file to disk.
1370 Returns XML_NO_ERROR (0) on success, or
1371 an errorID.
1372 */
1373 int SaveFile( const char* filename, bool compact = false );
Lee Thomasond11cd162012-04-12 08:35:36 -07001374
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001375 /**
1376 Save the XML file to disk. You are responsible
1377 for providing and closing the FILE*.
Ken Miller81da1fb2012-04-09 23:32:26 -05001378
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001379 Returns XML_NO_ERROR (0) on success, or
1380 an errorID.
1381 */
1382 int SaveFile( FILE* fp, bool compact = false );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001383
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001384 bool ProcessEntities() const {
1385 return processEntities;
1386 }
1387 Whitespace WhitespaceMode() const {
1388 return whitespace;
1389 }
Lee Thomason6f381b72012-03-02 12:59:39 -08001390
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001391 /**
1392 Returns true if this document has a leading Byte Order Mark of UTF8.
1393 */
1394 bool HasBOM() const {
1395 return writeBOM;
1396 }
1397 /** Sets whether to write the BOM when writing the file.
1398 */
1399 void SetBOM( bool useBOM ) {
1400 writeBOM = useBOM;
1401 }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001402
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001403 /** Return the root element of DOM. Equivalent to FirstChildElement().
1404 To get the first node, use FirstChild().
1405 */
1406 XMLElement* RootElement() {
1407 return FirstChildElement();
1408 }
1409 const XMLElement* RootElement() const {
1410 return FirstChildElement();
1411 }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001412
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001413 /** Print the Document. If the Printer is not provided, it will
1414 print to stdout. If you provide Printer, this can print to a file:
1415 @verbatim
1416 XMLPrinter printer( fp );
1417 doc.Print( &printer );
1418 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001419
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001420 Or you can use a printer to print to memory:
1421 @verbatim
1422 XMLPrinter printer;
1423 doc->Print( &printer );
1424 // printer.CStr() has a const char* to the XML
1425 @endverbatim
1426 */
1427 void Print( XMLPrinter* streamer=0 );
1428 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001429
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001430 /**
1431 Create a new Element associated with
1432 this Document. The memory for the Element
1433 is managed by the Document.
1434 */
1435 XMLElement* NewElement( const char* name );
1436 /**
1437 Create a new Comment associated with
1438 this Document. The memory for the Comment
1439 is managed by the Document.
1440 */
1441 XMLComment* NewComment( const char* comment );
1442 /**
1443 Create a new Text associated with
1444 this Document. The memory for the Text
1445 is managed by the Document.
1446 */
1447 XMLText* NewText( const char* text );
1448 /**
1449 Create a new Declaration associated with
1450 this Document. The memory for the object
1451 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001452
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001453 If the 'text' param is null, the standard
1454 declaration is used.:
1455 @verbatim
1456 <?xml version="1.0" encoding="UTF-8"?>
1457 @endverbatim
1458 */
1459 XMLDeclaration* NewDeclaration( const char* text=0 );
1460 /**
1461 Create a new Unknown associated with
1462 this Document. The memory for the object
1463 is managed by the Document.
1464 */
1465 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001466
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001467 /**
1468 Delete a node associated with this document.
1469 It will be unlinked from the DOM.
1470 */
1471 void DeleteNode( XMLNode* node ) {
1472 node->parent->DeleteChild( node );
1473 }
U-Stream\Leeae25a442012-02-17 17:48:16 -08001474
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001475 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001476
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001477 /// Return true if there was an error parsing the document.
1478 bool Error() const {
1479 return errorID != XML_NO_ERROR;
1480 }
1481 /// Return the errorID.
1482 int ErrorID() const {
1483 return errorID;
1484 }
1485 /// Return a possibly helpful diagnostic location or string.
1486 const char* GetErrorStr1() const {
1487 return errorStr1;
1488 }
1489 /// Return a possibly helpful secondary diagnostic location or string.
1490 const char* GetErrorStr2() const {
1491 return errorStr2;
1492 }
1493 /// If there is an error, print it to stdout.
1494 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001495
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001496 // internal
1497 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001498
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001499 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
1500 return 0;
1501 }
1502 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
1503 return false;
1504 }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001505
Lee Thomason3f57d272012-01-11 15:30:03 -08001506private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001507 XMLDocument( const XMLDocument& ); // not supported
1508 void operator=( const XMLDocument& ); // not supported
1509 void InitDocument();
Lee Thomason18d68bd2012-01-26 18:17:26 -08001510
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001511 bool writeBOM;
1512 bool processEntities;
1513 int errorID;
1514 Whitespace whitespace;
1515 const char* errorStr1;
1516 const char* errorStr2;
1517 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001518
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001519 MemPoolT< sizeof(XMLElement) > elementPool;
1520 MemPoolT< sizeof(XMLAttribute) > attributePool;
1521 MemPoolT< sizeof(XMLText) > textPool;
1522 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001523};
1524
Lee Thomason7c913cd2012-01-26 18:32:34 -08001525
Lee Thomason3ffdd392012-03-28 17:27:55 -07001526/**
1527 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001528 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001529 DOM structure. It is a separate utility class.
1530
1531 Take an example:
1532 @verbatim
1533 <Document>
1534 <Element attributeA = "valueA">
1535 <Child attributeB = "value1" />
1536 <Child attributeB = "value2" />
1537 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001538 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001539 @endverbatim
1540
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001541 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
Lee Thomason3ffdd392012-03-28 17:27:55 -07001542 easy to write a *lot* of code that looks like:
1543
1544 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001545 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001546 if ( root )
1547 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001548 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001549 if ( element )
1550 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001551 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001552 if ( child )
1553 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001554 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001555 if ( child2 )
1556 {
1557 // Finally do something useful.
1558 @endverbatim
1559
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001560 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001561 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001562 and correct to use:
1563
1564 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001565 XMLHandle docHandle( &document );
1566 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001567 if ( child2 )
1568 {
1569 // do something useful
1570 @endverbatim
1571
1572 Which is MUCH more concise and useful.
1573
1574 It is also safe to copy handles - internally they are nothing more than node pointers.
1575 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001576 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001577 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001578
1579 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001580*/
1581class XMLHandle
1582{
1583public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001584 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1585 XMLHandle( XMLNode* _node ) {
1586 node = _node;
1587 }
1588 /// Create a handle from a node.
1589 XMLHandle( XMLNode& _node ) {
1590 node = &_node;
1591 }
1592 /// Copy constructor
1593 XMLHandle( const XMLHandle& ref ) {
1594 node = ref.node;
1595 }
1596 /// Assignment
1597 XMLHandle& operator=( const XMLHandle& ref ) {
1598 node = ref.node;
1599 return *this;
1600 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001601
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001602 /// Get the first child of this handle.
1603 XMLHandle FirstChild() {
1604 return XMLHandle( node ? node->FirstChild() : 0 );
1605 }
1606 /// Get the first child element of this handle.
1607 XMLHandle FirstChildElement( const char* value=0 ) {
1608 return XMLHandle( node ? node->FirstChildElement( value ) : 0 );
1609 }
1610 /// Get the last child of this handle.
1611 XMLHandle LastChild() {
1612 return XMLHandle( node ? node->LastChild() : 0 );
1613 }
1614 /// Get the last child element of this handle.
1615 XMLHandle LastChildElement( const char* _value=0 ) {
1616 return XMLHandle( node ? node->LastChildElement( _value ) : 0 );
1617 }
1618 /// Get the previous sibling of this handle.
1619 XMLHandle PreviousSibling() {
1620 return XMLHandle( node ? node->PreviousSibling() : 0 );
1621 }
1622 /// Get the previous sibling element of this handle.
1623 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
1624 return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 );
1625 }
1626 /// Get the next sibling of this handle.
1627 XMLHandle NextSibling() {
1628 return XMLHandle( node ? node->NextSibling() : 0 );
1629 }
1630 /// Get the next sibling element of this handle.
1631 XMLHandle NextSiblingElement( const char* _value=0 ) {
1632 return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 );
1633 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001634
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001635 /// Safe cast to XMLNode. This can return null.
1636 XMLNode* ToNode() {
1637 return node;
1638 }
1639 /// Safe cast to XMLElement. This can return null.
1640 XMLElement* ToElement() {
1641 return ( ( node && node->ToElement() ) ? node->ToElement() : 0 );
1642 }
1643 /// Safe cast to XMLText. This can return null.
1644 XMLText* ToText() {
1645 return ( ( node && node->ToText() ) ? node->ToText() : 0 );
1646 }
1647 /// Safe cast to XMLUnknown. This can return null.
1648 XMLUnknown* ToUnknown() {
1649 return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 );
1650 }
1651 /// Safe cast to XMLDeclaration. This can return null.
1652 XMLDeclaration* ToDeclaration() {
1653 return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 );
1654 }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001655
1656private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001657 XMLNode* node;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001658};
1659
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001660
1661/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001662 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1663 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001664*/
1665class XMLConstHandle
1666{
1667public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001668 XMLConstHandle( const XMLNode* _node ) {
1669 node = _node;
1670 }
1671 XMLConstHandle( const XMLNode& _node ) {
1672 node = &_node;
1673 }
1674 XMLConstHandle( const XMLConstHandle& ref ) {
1675 node = ref.node;
1676 }
Lee Thomason8b899812012-04-04 15:58:16 -07001677
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001678 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
1679 node = ref.node;
1680 return *this;
1681 }
Lee Thomason8b899812012-04-04 15:58:16 -07001682
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001683 const XMLConstHandle FirstChild() const {
1684 return XMLConstHandle( node ? node->FirstChild() : 0 );
1685 }
1686 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
1687 return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 );
1688 }
1689 const XMLConstHandle LastChild() const {
1690 return XMLConstHandle( node ? node->LastChild() : 0 );
1691 }
1692 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
1693 return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 );
1694 }
1695 const XMLConstHandle PreviousSibling() const {
1696 return XMLConstHandle( node ? node->PreviousSibling() : 0 );
1697 }
1698 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
1699 return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 );
1700 }
1701 const XMLConstHandle NextSibling() const {
1702 return XMLConstHandle( node ? node->NextSibling() : 0 );
1703 }
1704 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
1705 return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 );
1706 }
Lee Thomason8b899812012-04-04 15:58:16 -07001707
1708
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001709 const XMLNode* ToNode() const {
1710 return node;
1711 }
1712 const XMLElement* ToElement() const {
1713 return ( ( node && node->ToElement() ) ? node->ToElement() : 0 );
1714 }
1715 const XMLText* ToText() const {
1716 return ( ( node && node->ToText() ) ? node->ToText() : 0 );
1717 }
1718 const XMLUnknown* ToUnknown() const {
1719 return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 );
1720 }
1721 const XMLDeclaration* ToDeclaration() const {
1722 return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 );
1723 }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001724
Lee Thomason5cae8972012-01-24 18:03:07 -08001725private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001726 const XMLNode* node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001727};
Lee Thomason6f381b72012-03-02 12:59:39 -08001728
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001729
1730/**
1731 Printing functionality. The XMLPrinter gives you more
1732 options than the XMLDocument::Print() method.
1733
1734 It can:
1735 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001736 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001737 -# Print XML without a XMLDocument.
1738
1739 Print to Memory
1740
1741 @verbatim
1742 XMLPrinter printer;
1743 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001744 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001745 @endverbatim
1746
1747 Print to a File
Lee Thomason (grinliz)2f1f6242012-09-16 11:32:34 -07001748
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001749 You provide the file pointer.
1750 @verbatim
1751 XMLPrinter printer( fp );
1752 doc.Print( &printer );
1753 @endverbatim
1754
1755 Print without a XMLDocument
1756
1757 When loading, an XML parser is very useful. However, sometimes
1758 when saving, it just gets in the way. The code is often set up
1759 for streaming, and constructing the DOM is just overhead.
1760
1761 The Printer supports the streaming case. The following code
1762 prints out a trivially simple XML file without ever creating
1763 an XML document.
1764
1765 @verbatim
1766 XMLPrinter printer( fp );
1767 printer.OpenElement( "foo" );
1768 printer.PushAttribute( "foo", "bar" );
1769 printer.CloseElement();
1770 @endverbatim
1771*/
1772class XMLPrinter : public XMLVisitor
1773{
1774public:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001775 /** Construct the printer. If the FILE* is specified,
1776 this will print to the FILE. Else it will print
1777 to memory, and the result is available in CStr().
1778 If 'compact' is set to true, then output is created
1779 with only required whitespace and newlines.
1780 */
1781 XMLPrinter( FILE* file=0, bool compact = false );
1782 ~XMLPrinter() {}
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001783
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001784 /** If streaming, write the BOM and declaration. */
1785 void PushHeader( bool writeBOM, bool writeDeclaration );
1786 /** If streaming, start writing an element.
1787 The element must be closed with CloseElement()
1788 */
1789 void OpenElement( const char* name );
1790 /// If streaming, add an attribute to an open element.
1791 void PushAttribute( const char* name, const char* value );
1792 void PushAttribute( const char* name, int value );
1793 void PushAttribute( const char* name, unsigned value );
1794 void PushAttribute( const char* name, bool value );
1795 void PushAttribute( const char* name, double value );
1796 /// If streaming, close the Element.
1797 void CloseElement();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001798
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001799 /// Add a text node.
1800 void PushText( const char* text, bool cdata=false );
1801 /// Add a text node from an integer.
1802 void PushText( int value );
1803 /// Add a text node from an unsigned.
1804 void PushText( unsigned value );
1805 /// Add a text node from a bool.
1806 void PushText( bool value );
1807 /// Add a text node from a float.
1808 void PushText( float value );
1809 /// Add a text node from a double.
1810 void PushText( double value );
Lee Thomason21be8822012-07-15 17:27:22 -07001811
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001812 /// Add a comment
1813 void PushComment( const char* comment );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001814
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001815 void PushDeclaration( const char* value );
1816 void PushUnknown( const char* value );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001817
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001818 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1819 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
1820 return true;
1821 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001822
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001823 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1824 virtual bool VisitExit( const XMLElement& element );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001825
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001826 virtual bool Visit( const XMLText& text );
1827 virtual bool Visit( const XMLComment& comment );
1828 virtual bool Visit( const XMLDeclaration& declaration );
1829 virtual bool Visit( const XMLUnknown& unknown );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001830
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001831 /**
1832 If in print to memory mode, return a pointer to
1833 the XML file in memory.
1834 */
1835 const char* CStr() const {
1836 return buffer.Mem();
1837 }
1838 /**
1839 If in print to memory mode, return the size
1840 of the XML file in memory. (Note the size returned
1841 includes the terminating null.)
1842 */
1843 int CStrSize() const {
1844 return buffer.Size();
1845 }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001846
1847private:
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001848 void SealElement();
1849 void PrintSpace( int depth );
1850 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1851 void Print( const char* format, ... );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001852
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001853 bool elementJustOpened;
1854 bool firstElement;
1855 FILE* fp;
1856 int depth;
1857 int textDepth;
1858 bool processEntities;
1859 bool compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001860
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001861 enum {
1862 ENTITY_RANGE = 64,
1863 BUF_SIZE = 200
1864 };
1865 bool entityFlag[ENTITY_RANGE];
1866 bool restrictedEntityFlag[ENTITY_RANGE];
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001867
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001868 DynArray< const char*, 10 > stack;
1869 DynArray< char, 20 > buffer;
PKEuSe736f292012-07-16 03:27:55 -07001870#ifdef _MSC_VER
Lee Thomasona9cf3f92012-10-11 16:56:51 -07001871 DynArray< char, 20 > accumulator;
PKEuSe736f292012-07-16 03:27:55 -07001872#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001873};
1874
1875
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001876} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001877
1878
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001879#endif // TINYXML2_INCLUDED