blob: 975ab8ca1607d5207c74c696c40826a68ed8b573 [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 Thomason5e3803c2012-04-16 08:57:05 -070027#include <cctype>
28#include <climits>
29#include <cstdio>
30#include <cstring>
31#include <cstdarg>
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070032
Lee Thomason7d00b9a2012-02-27 17:54:22 -080033/*
Lee Thomason7d00b9a2012-02-27 17:54:22 -080034 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080035*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080036/*
37 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
38*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080039
U-Lama\Lee4cee6112011-12-31 14:58:18 -080040#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
41 #ifndef DEBUG
42 #define DEBUG
43 #endif
44#endif
45
46
47#if defined(DEBUG)
48 #if defined(_MSC_VER)
Guillermo A. Amaral68b0c872012-03-24 11:07:19 -070049 #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
U-Lama\Lee4cee6112011-12-31 14:58:18 -080050 #elif defined (ANDROID_NDK)
51 #include <android/log.h>
52 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
53 #else
54 #include <assert.h>
55 #define TIXMLASSERT assert
56 #endif
57#else
58 #define TIXMLASSERT( x ) {}
59#endif
60
U-Lama\Leee13c3e62011-12-28 14:36:55 -080061
Lee Thomason1a1d4a72012-02-15 09:09:25 -080062#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
63 // Microsoft visual studio, version 2005 and higher.
Lee Thomason (grinliz)598c13e2012-04-06 21:18:23 -070064 /*int _snprintf_s(
65 char *buffer,
66 size_t sizeOfBuffer,
67 size_t count,
68 const char *format [,
69 argument] ...
70 );*/
71 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
72 va_list va;
73 va_start( va, format );
74 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
75 va_end( va );
76 return result;
77 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -080078 #define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070079#else
U-Stream\Leeae25a442012-02-17 17:48:16 -080080 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080081 //#warning( "Using sn* functions." )
82 #define TIXML_SNPRINTF snprintf
83 #define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080084#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080085
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -070086static const int TIXML2_MAJOR_VERSION = 1;
87static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason21be8822012-07-15 17:27:22 -070088static const int TIXML2_PATCH_VERSION = 6;
Lee Thomason1ff38e02012-02-14 18:18:16 -080089
U-Lama\Leee13c3e62011-12-28 14:36:55 -080090namespace tinyxml2
91{
Lee Thomasonce0763e2012-01-11 15:43:54 -080092class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080093class XMLElement;
94class XMLAttribute;
95class XMLComment;
96class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080097class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080098class XMLDeclaration;
99class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800100
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800101class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800102
U-Stream\Leeae25a442012-02-17 17:48:16 -0800103/*
104 A class that wraps strings. Normally stores the start and end
105 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800106 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800107 manage) a traditional char[]
108*/
Lee Thomason39ede242012-01-20 11:27:56 -0800109class StrPair
110{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800111public:
Lee Thomason39ede242012-01-20 11:27:56 -0800112 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800113 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800114 NEEDS_NEWLINE_NORMALIZATION = 0x02,
115
116 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800117 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800118 ATTRIBUTE_NAME = 0,
119 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800120 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700121 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomason39ede242012-01-20 11:27:56 -0800122 };
123
124 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800125 ~StrPair();
126
Lee Thomason5ce89412012-03-20 13:23:44 -0700127 void Set( char* _start, char* _end, int _flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800128 Reset();
Lee Thomason5ce89412012-03-20 13:23:44 -0700129 this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
Lee Thomason39ede242012-01-20 11:27:56 -0800130 }
131 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800132 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800133
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700134 void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800135 void SetStr( const char* str, int flags=0 );
136
Lee Thomason78a773d2012-07-02 10:10:19 -0700137 char* ParseText( char* in, const char* endTag, int strFlags );
Lee Thomason56bdd022012-02-09 18:16:58 -0800138 char* ParseName( char* in );
139
Lee Thomason2c85a712012-01-31 08:24:24 -0800140
Lee Thomason39ede242012-01-20 11:27:56 -0800141private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800142 void Reset();
143
Lee Thomasone4422302012-01-20 17:59:50 -0800144 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800145 NEEDS_FLUSH = 0x100,
146 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800147 };
148
Lee Thomason39ede242012-01-20 11:27:56 -0800149 // After parsing, if *end != 0, it can be set to zero.
150 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800151 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800152 char* end;
153};
154
U-Lama\Lee560bd472011-12-28 19:42:49 -0800155
U-Stream\Leeae25a442012-02-17 17:48:16 -0800156/*
157 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
158 Has a small initial memory pool, so that low or no usage will not
159 cause a call to new/delete
160*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800161template <class T, int INIT>
162class DynArray
163{
164public:
165 DynArray< T, INIT >()
166 {
167 mem = pool;
168 allocated = INIT;
169 size = 0;
170 }
171 ~DynArray()
172 {
173 if ( mem != pool ) {
Lee Thomasona2ae54e2012-05-18 13:47:48 -0700174 delete [] mem;
Lee Thomason2c85a712012-01-31 08:24:24 -0800175 }
176 }
177 void Push( T t )
178 {
179 EnsureCapacity( size+1 );
180 mem[size++] = t;
181 }
182
183 T* PushArr( int count )
184 {
185 EnsureCapacity( size+count );
186 T* ret = &mem[size];
187 size += count;
188 return ret;
189 }
190 T Pop() {
191 return mem[--size];
192 }
193 void PopArr( int count )
194 {
195 TIXMLASSERT( size >= count );
196 size -= count;
197 }
198
U-Stream\Leeae25a442012-02-17 17:48:16 -0800199 bool Empty() const { return size == 0; }
200 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
201 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
202 int Size() const { return size; }
203 int Capacity() const { return allocated; }
204 const T* Mem() const { return mem; }
205 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800206
207
208private:
209 void EnsureCapacity( int cap ) {
210 if ( cap > allocated ) {
211 int newAllocated = cap * 2;
212 T* newMem = new T[newAllocated];
213 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
214 if ( mem != pool ) delete [] mem;
215 mem = newMem;
216 allocated = newAllocated;
217 }
218 }
219
220 T* mem;
221 T pool[INIT];
222 int allocated; // objects allocated
223 int size; // number objects in use
224};
225
Lee Thomason50adb4c2012-02-13 15:07:09 -0800226
U-Stream\Leeae25a442012-02-17 17:48:16 -0800227/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200228 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800229 and deallocation of objects.
230*/
Lee Thomasond1983222012-02-06 08:41:24 -0800231class MemPool
232{
233public:
234 MemPool() {}
235 virtual ~MemPool() {}
236
237 virtual int ItemSize() const = 0;
238 virtual void* Alloc() = 0;
239 virtual void Free( void* ) = 0;
240};
241
Lee Thomason50adb4c2012-02-13 15:07:09 -0800242
U-Stream\Leeae25a442012-02-17 17:48:16 -0800243/*
244 Template child class to create pools of the correct type.
245*/
Lee Thomasond1983222012-02-06 08:41:24 -0800246template< int SIZE >
247class MemPoolT : public MemPool
248{
249public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800250 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800251 ~MemPoolT() {
252 // Delete the blocks.
253 for( int i=0; i<blockPtrs.Size(); ++i ) {
254 delete blockPtrs[i];
255 }
256 }
257
258 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800259 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800260
261 virtual void* Alloc() {
262 if ( !root ) {
263 // Need a new block.
264 Block* block = new Block();
265 blockPtrs.Push( block );
266
267 for( int i=0; i<COUNT-1; ++i ) {
268 block->chunk[i].next = &block->chunk[i+1];
269 }
270 block->chunk[COUNT-1].next = 0;
271 root = block->chunk;
272 }
273 void* result = root;
274 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800275
276 ++currentAllocs;
277 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
278 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800279 return result;
280 }
281 virtual void Free( void* mem ) {
282 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800283 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800284 Chunk* chunk = (Chunk*)mem;
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700285#ifdef DEBUG
Lee Thomasond1983222012-02-06 08:41:24 -0800286 memset( chunk, 0xfe, sizeof(Chunk) );
Lee Thomason (grinliz)6020a012012-09-08 21:15:09 -0700287#endif
Lee Thomasond1983222012-02-06 08:41:24 -0800288 chunk->next = root;
289 root = chunk;
290 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800291 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800292 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
293 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800294 }
Lee Thomasond1983222012-02-06 08:41:24 -0800295
296private:
297 enum { COUNT = 1024/SIZE };
298 union Chunk {
299 Chunk* next;
300 char mem[SIZE];
301 };
302 struct Block {
303 Chunk chunk[COUNT];
304 };
305 DynArray< Block*, 10 > blockPtrs;
306 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800307
308 int currentAllocs;
309 int nAllocs;
310 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800311};
312
Lee Thomason2c85a712012-01-31 08:24:24 -0800313
Lee Thomason56bdd022012-02-09 18:16:58 -0800314
315/**
316 Implements the interface to the "Visitor pattern" (see the Accept() method.)
317 If you call the Accept() method, it requires being passed a XMLVisitor
318 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200319 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800320 are simply called with Visit().
321
322 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200323 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800324
325 All flavors of Visit methods have a default implementation that returns 'true' (continue
326 visiting). You need to only override methods that are interesting to you.
327
Thomas Roß08bdf502012-05-12 14:21:23 +0200328 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800329
330 You should never change the document from a callback.
331
332 @sa XMLNode::Accept()
333*/
334class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800335{
336public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800337 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800338
Lee Thomason56bdd022012-02-09 18:16:58 -0800339 /// Visit a document.
340 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
341 /// Visit a document.
342 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
343
344 /// Visit an element.
345 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
346 /// Visit an element.
347 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
348
Thomas Roß08bdf502012-05-12 14:21:23 +0200349 /// Visit a declaration.
Lee Thomason50f97b22012-02-11 16:33:40 -0800350 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200351 /// Visit a text node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800352 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200353 /// Visit a comment node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800354 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200355 /// Visit an unknown node.
Lee Thomason50f97b22012-02-11 16:33:40 -0800356 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800357};
358
359
U-Stream\Leeae25a442012-02-17 17:48:16 -0800360/*
361 Utility functionality.
362*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800363class XMLUtil
364{
Lee Thomasond1983222012-02-06 08:41:24 -0800365public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800366 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
367 // correct, but simple, and usually works.
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700368 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { ++p; } return p; }
369 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800370
371 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
372 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800373 if ( p == q ) {
374 return true;
375 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800376 while( *p && *q && *p == *q && n<nChar ) {
377 ++p; ++q; ++n;
378 }
379 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
380 return true;
381 }
382 return false;
383 }
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700384 inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800385 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
386 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800387
388 static const char* ReadBOM( const char* p, bool* hasBOM );
389 // p is the starting location,
390 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800391 static const char* GetCharacterRef( const char* p, char* value, int* length );
392 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700393
394 // converts primitive types to strings
395 static void ToStr( int v, char* buffer, int bufferSize );
396 static void ToStr( unsigned v, char* buffer, int bufferSize );
397 static void ToStr( bool v, char* buffer, int bufferSize );
398 static void ToStr( float v, char* buffer, int bufferSize );
399 static void ToStr( double v, char* buffer, int bufferSize );
400
401 // converts strings to primitive types
402 static bool ToInt( const char* str, int* value );
403 static bool ToUnsigned( const char* str, unsigned* value );
404 static bool ToBool( const char* str, bool* value );
405 static bool ToFloat( const char* str, float* value );
406 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800407};
408
Lee Thomason5cae8972012-01-24 18:03:07 -0800409
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800410/** XMLNode is a base class for every object that is in the
411 XML Document Object Model (DOM), except XMLAttributes.
412 Nodes have siblings, a parent, and children which can
413 be navigated. A node is always in a XMLDocument.
Lee Thomason3a682622012-03-25 13:19:40 -0700414 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800415 be cast to its more defined type.
416
Thomas Roß08bdf502012-05-12 14:21:23 +0200417 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800418 When the XMLDocument gets deleted, all its Nodes
419 will also be deleted.
420
421 @verbatim
422 A Document can contain: Element (container or leaf)
423 Comment (leaf)
424 Unknown (leaf)
425 Declaration( leaf )
426
427 An Element can contain: Element (container or leaf)
428 Text (leaf)
429 Attributes (not on tree)
430 Comment (leaf)
431 Unknown (leaf)
432
433 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800434*/
Lee Thomasond1983222012-02-06 08:41:24 -0800435class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800436{
437 friend class XMLDocument;
438 friend class XMLElement;
439public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800440
441 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800442 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800443 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800444 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800445
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800446 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
447 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
448 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
449 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
450 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
451 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800452
Lee Thomason50f97b22012-02-11 16:33:40 -0800453 virtual const XMLElement* ToElement() const { return 0; }
454 virtual const XMLText* ToText() const { return 0; }
455 virtual const XMLComment* ToComment() const { return 0; }
456 virtual const XMLDocument* ToDocument() const { return 0; }
457 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
458 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800459
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800460 /** The meaning of 'value' changes for the specific type.
461 @verbatim
Thomas Roß08bdf502012-05-12 14:21:23 +0200462 Document: empty
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800463 Element: name of the element
464 Comment: the comment text
465 Unknown: the tag contents
466 Text: the text string
467 @endverbatim
468 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800469 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800470 /** Set the Value of an XML node.
471 @sa Value()
472 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800473 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800474
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800475 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800476 const XMLNode* Parent() const { return parent; }
477 XMLNode* Parent() { return parent; }
478
Lee Thomason50f97b22012-02-11 16:33:40 -0800479 /// Returns true if this node has no children.
480 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800481
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800482 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800483 const XMLNode* FirstChild() const { return firstChild; }
484 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800485 /** Get the first child element, or optionally the first child
486 element with the specified name.
487 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800488 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700489 XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800490
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800491 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800492 const XMLNode* LastChild() const { return lastChild; }
493 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800494
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800495 /** Get the last child element or optionally the last child
496 element with the specified name.
497 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800498 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700499 XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800500
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800501 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800502 const XMLNode* PreviousSibling() const { return prev; }
503 XMLNode* PreviousSibling() { return prev; }
504
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800505 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800506 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason5ce89412012-03-20 13:23:44 -0700507 XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800508
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800509 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800510 const XMLNode* NextSibling() const { return next; }
511 XMLNode* NextSibling() { return next; }
512
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800513 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800514 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700515 XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800516
Lee Thomason1ff38e02012-02-14 18:18:16 -0800517 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800518 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800519 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800520 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800521
522 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800523 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800524 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800525 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800526 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800527 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800528 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800529 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800530 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
531
U-Stream\Leeae25a442012-02-17 17:48:16 -0800532 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800533 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800534 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800535 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800536
537 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800538 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800539 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800540 void DeleteChild( XMLNode* node );
541
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800542 /**
543 Make a copy of this node, but not its children.
544 You may pass in a Document pointer that will be
545 the owner of the new Node. If the 'document' is
546 null, then the node returned will be allocated
547 from the current Document. (this->GetDocument())
548
549 Note: if called on a XMLDocument, this will return null.
550 */
551 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
552
553 /**
554 Test if 2 nodes are the same, but don't test children.
555 The 2 nodes do not need to be in the same Document.
556
557 Note: if called on a XMLDocument, this will return false.
558 */
559 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
560
Thomas Roß08bdf502012-05-12 14:21:23 +0200561 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800562 XML tree will be conditionally visited and the host will be called back
563 via the TiXmlVisitor interface.
564
565 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
566 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
567 interface versus any other.)
568
569 The interface has been based on ideas from:
570
571 - http://www.saxproject.org/
572 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
573
574 Which are both good references for "visiting".
575
576 An example of using Accept():
577 @verbatim
578 TiXmlPrinter printer;
579 tinyxmlDoc.Accept( &printer );
580 const char* xmlcstr = printer.CStr();
581 @endverbatim
582 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800583 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800584
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800585 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800586 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800587
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800588protected:
589 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800590 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800591 XMLNode( const XMLNode& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700592 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800593
Lee Thomason3f57d272012-01-11 15:30:03 -0800594 XMLDocument* document;
595 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800596 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800597
598 XMLNode* firstChild;
599 XMLNode* lastChild;
600
601 XMLNode* prev;
602 XMLNode* next;
603
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800604private:
Lee Thomasond1983222012-02-06 08:41:24 -0800605 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800606 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800607};
608
609
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800610/** XML text.
611
612 Note that a text node can have child element nodes, for example:
613 @verbatim
614 <root>This is <b>bold</b></root>
615 @endverbatim
616
617 A text node can have 2 ways to output the next. "normal" output
618 and CDATA. It will default to the mode it was parsed from the XML file and
619 you generally want to leave it alone, but you can change the output mode with
620 SetCDATA() and query it with CDATA().
621*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800622class XMLText : public XMLNode
623{
Lee Thomason2c85a712012-01-31 08:24:24 -0800624 friend class XMLBase;
625 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800626public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800627 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800628
Lee Thomason751da522012-02-10 08:50:51 -0800629 virtual XMLText* ToText() { return this; }
630 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800631
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800632 /// Declare whether this should be CDATA or standard text.
Lee Thomason5ce89412012-03-20 13:23:44 -0700633 void SetCData( bool _isCData ) { this->isCData = _isCData; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800634 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800635 bool CData() const { return isCData; }
636
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800637 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800638 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
639 virtual bool ShallowEqual( const XMLNode* compare ) const;
640
Lee Thomason5492a1c2012-01-23 15:32:10 -0800641
642protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800643 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
644 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800645 XMLText( const XMLText& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700646 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800647
648private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800649 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800650};
651
652
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800653/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800654class XMLComment : public XMLNode
655{
Lee Thomason2c85a712012-01-31 08:24:24 -0800656 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800657public:
Lee Thomason751da522012-02-10 08:50:51 -0800658 virtual XMLComment* ToComment() { return this; }
659 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800660
Lee Thomason56bdd022012-02-09 18:16:58 -0800661 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800662
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800663 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800664 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
665 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800666
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800667protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800668 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800669 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800670 XMLComment( const XMLComment& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700671 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800672
Lee Thomason3f57d272012-01-11 15:30:03 -0800673private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800674};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800675
676
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800677/** In correct XML the declaration is the first entry in the file.
678 @verbatim
679 <?xml version="1.0" standalone="yes"?>
680 @endverbatim
681
682 TinyXML2 will happily read or write files without a declaration,
683 however.
684
685 The text of the declaration isn't interpreted. It is parsed
686 and written as a string.
687*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800688class XMLDeclaration : public XMLNode
689{
690 friend class XMLDocument;
691public:
692 virtual XMLDeclaration* ToDeclaration() { return this; }
693 virtual const XMLDeclaration* ToDeclaration() const { return this; }
694
695 virtual bool Accept( XMLVisitor* visitor ) const;
696
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800697 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800698 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
699 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800700
701protected:
702 XMLDeclaration( XMLDocument* doc );
703 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800704 XMLDeclaration( const XMLDeclaration& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700705 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800706};
707
708
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800709/** Any tag that tinyXml doesn't recognize is saved as an
710 unknown. It is a tag of text, but should not be modified.
711 It will be written back to the XML, unchanged, when the file
712 is saved.
713
714 DTD tags get thrown into TiXmlUnknowns.
715*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800716class XMLUnknown : public XMLNode
717{
718 friend class XMLDocument;
719public:
720 virtual XMLUnknown* ToUnknown() { return this; }
721 virtual const XMLUnknown* ToUnknown() const { return this; }
722
723 virtual bool Accept( XMLVisitor* visitor ) const;
724
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800725 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800726 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
727 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800728
729protected:
730 XMLUnknown( XMLDocument* doc );
731 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800732 XMLUnknown( const XMLUnknown& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700733 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800734};
735
736
Lee Thomason1ff38e02012-02-14 18:18:16 -0800737enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800738 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800739 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800740
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700741 XML_NO_ATTRIBUTE,
742 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800743
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700744 XML_ERROR_FILE_NOT_FOUND,
Lee Thomason7f7b1622012-03-24 12:49:03 -0700745 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
Lee Thomasona3efec02012-06-15 14:30:44 -0700746 XML_ERROR_FILE_READ_ERROR,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700747 XML_ERROR_ELEMENT_MISMATCH,
748 XML_ERROR_PARSING_ELEMENT,
749 XML_ERROR_PARSING_ATTRIBUTE,
750 XML_ERROR_IDENTIFYING_TAG,
751 XML_ERROR_PARSING_TEXT,
752 XML_ERROR_PARSING_CDATA,
753 XML_ERROR_PARSING_COMMENT,
754 XML_ERROR_PARSING_DECLARATION,
755 XML_ERROR_PARSING_UNKNOWN,
756 XML_ERROR_EMPTY_DOCUMENT,
757 XML_ERROR_MISMATCHED_ELEMENT,
Lee Thomason21be8822012-07-15 17:27:22 -0700758 XML_ERROR_PARSING,
759
760 XML_CAN_NOT_CONVERT_TEXT,
761 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800762};
763
764
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800765/** An attribute is a name-value pair. Elements have an arbitrary
766 number of attributes, each with a unique name.
767
768 @note The attributes are not XMLNodes. You may only query the
769 Next() attribute in a list.
770*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800771class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800772{
773 friend class XMLElement;
774public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800775 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
776 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
777 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800778
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800779 /** IntAttribute interprets the attribute as an integer, and returns the value.
780 If the value isn't an integer, 0 will be returned. There is no error checking;
781 use QueryIntAttribute() if you need error checking.
782 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800783 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800784 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800785 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800786 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800787 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800788 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800789 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800790 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800791 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800792
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800793 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
794 in the provided paremeter. The function will return XML_NO_ERROR on success,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700795 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800796 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800797 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800798 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800799 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800800 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800801 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800802 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800803 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800804 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800805 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800806
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800807 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800808 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800809 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800810 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800811 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800812 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800813 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800814 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800815 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800816 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800817 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800818 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800819
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800820private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800821 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800822
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800823 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800824 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800825 XMLAttribute( const XMLAttribute& ); // not supported
826 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800827 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800828
Lee Thomason6f381b72012-03-02 12:59:39 -0800829 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800830
Lee Thomason751da522012-02-10 08:50:51 -0800831 mutable StrPair name;
832 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800833 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800834 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800835};
836
837
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800838/** The element is a container class. It has a value, the element name,
839 and can contain other elements, text, comments, and unknowns.
840 Elements also contain an arbitrary number of attributes.
841*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800842class XMLElement : public XMLNode
843{
Lee Thomason2c85a712012-01-31 08:24:24 -0800844 friend class XMLBase;
845 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800846public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800847 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800848 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800849 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800850 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800851
Lee Thomason751da522012-02-10 08:50:51 -0800852 virtual XMLElement* ToElement() { return this; }
853 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800854 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800855
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800856 /** Given an attribute name, Attribute() returns the value
Lee Thomason92258152012-03-24 13:05:39 -0700857 for the attribute of that name, or null if none
858 exists. For example:
859
860 @verbatim
861 const char* value = ele->Attribute( "foo" );
862 @endverbatim
863
864 The 'value' parameter is normally null. However, if specified,
865 the attribute will only be returned if the 'name' and 'value'
866 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700867
868 @verbatim
869 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
870 @endverbatim
871
872 rather than:
873 @verbatim
874 if ( ele->Attribute( "foo" ) ) {
875 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
876 }
877 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800878 */
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700879 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800880
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800881 /** Given an attribute name, IntAttribute() returns the value
882 of the attribute interpreted as an integer. 0 will be
883 returned if there is an error. For a method with error
884 checking, see QueryIntAttribute()
885 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800886 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800887 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800888 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800889 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800890 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800891 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200892 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800893 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200894 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800895
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800896 /** Given an attribute name, QueryIntAttribute() returns
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700897 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
898 can't be performed, or XML_NO_ATTRIBUTE if the attribute
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800899 doesn't exist. If successful, the result of the conversion
900 will be written to 'value'. If not successful, nothing will
901 be written to 'value'. This allows you to provide default
902 value:
903
904 @verbatim
905 int value = 10;
906 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
907 @endverbatim
908 */
Thomas Roß08bdf502012-05-12 14:21:23 +0200909 int QueryIntAttribute( const char* name, int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800910 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700911 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800912 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700913 int QueryBoolAttribute( const char* name, bool* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800914 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700915 int QueryDoubleAttribute( const char* name, double* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800916 /// See QueryIntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200917 int QueryFloatAttribute( const char* name, float* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800918
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800919 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700920 void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800921 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700922 void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800923 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700924 void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800925 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700926 void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800927 /// Sets the named attribute to value.
Thomas Roß08bdf502012-05-12 14:21:23 +0200928 void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800929
U-Stream\Leeae25a442012-02-17 17:48:16 -0800930 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800931 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800932 */
933 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800934
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800935 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800936 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800937 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800938 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800939
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800940 /** Convenience function for easy access to the text inside an element. Although easy
941 and concise, GetText() is limited compared to getting the TiXmlText child
942 and accessing it directly.
943
944 If the first child of 'this' is a TiXmlText, the GetText()
945 returns the character string of the Text node, else null is returned.
946
947 This is a convenient method for getting the text of simple contained text:
948 @verbatim
949 <foo>This is text</foo>
Lee Thomason21be8822012-07-15 17:27:22 -0700950 const char* str = fooElement->GetText();
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800951 @endverbatim
952
953 'str' will be a pointer to "This is text".
954
955 Note that this function can be misleading. If the element foo was created from
956 this XML:
957 @verbatim
Lee Thomason21be8822012-07-15 17:27:22 -0700958 <foo><b>This is text</b></foo>
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800959 @endverbatim
960
961 then the value of str would be null. The first child node isn't a text node, it is
962 another element. From this XML:
963 @verbatim
Lee Thomason21be8822012-07-15 17:27:22 -0700964 <foo>This is <b>text</b></foo>
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800965 @endverbatim
966 GetText() will return "This is ".
967 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800968 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800969
Lee Thomason21be8822012-07-15 17:27:22 -0700970 /**
971 Convenience method to query the value of a child text node. This is probably best
972 shown by example. Given you have a document is this form:
973 @verbatim
974 <point>
975 <x>1</x>
976 <y>1.4</y>
977 </point>
978 @endverbatim
979
980 The QueryIntText() and similar functions provide a safe and easier way to get to the
981 "value" of x and y.
982
983 @verbatim
984 int x = 0;
985 float y = 0; // types of x and y are contrived for example
986 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
987 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
988 xElement->QueryIntText( &x );
989 yElement->QueryFloatText( &y );
990 @endverbatim
991
992 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
993 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
994
995 */
996 int QueryIntText( int* _value ) const;
997 /// See QueryIntText()
998 int QueryUnsignedText( unsigned* _value ) const;
999 /// See QueryIntText()
1000 int QueryBoolText( bool* _value ) const;
1001 /// See QueryIntText()
1002 int QueryDoubleText( double* _value ) const;
1003 /// See QueryIntText()
1004 int QueryFloatText( float* _value ) const;
1005
Lee Thomason2c85a712012-01-31 08:24:24 -08001006 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001007 enum {
1008 OPEN, // <foo>
1009 CLOSED, // <foo/>
1010 CLOSING // </foo>
1011 };
1012 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -08001013 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001014 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1015 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001016
Lee Thomason50adb4c2012-02-13 15:07:09 -08001017private:
Lee Thomason2c85a712012-01-31 08:24:24 -08001018 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -08001019 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -08001020 XMLElement( const XMLElement& ); // not supported
1021 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001022
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001023 XMLAttribute* FindAttribute( const char* name );
1024 XMLAttribute* FindOrCreateAttribute( const char* name );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001025 //void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001026 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001027
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001028 int closingType;
Lee Thomason5e3803c2012-04-16 08:57:05 -07001029 // The attribute list is ordered; there is no 'lastAttribute'
1030 // because the list needs to be scanned for dupes before adding
1031 // a new attribute.
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001032 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001033};
1034
1035
Thomas Roß08bdf502012-05-12 14:21:23 +02001036/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001037 It can be saved, loaded, and printed to the screen.
1038 All Nodes are connected and allocated to a Document.
1039 If the Document is deleted, all its Nodes are also deleted.
1040*/
Lee Thomason67d61312012-01-24 16:01:51 -08001041class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001042{
Lee Thomasond1983222012-02-06 08:41:24 -08001043 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001044public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001045 /// constructor
Lee Thomason6f381b72012-03-02 12:59:39 -08001046 XMLDocument( bool processEntities = true );
Lee Thomason3f57d272012-01-11 15:30:03 -08001047 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001048
Lee Thomason751da522012-02-10 08:50:51 -08001049 virtual XMLDocument* ToDocument() { return this; }
1050 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -08001051
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001052 /**
1053 Parse an XML file from a character string.
1054 Returns XML_NO_ERROR (0) on success, or
1055 an errorID.
1056 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001057 int Parse( const char* xml );
Lee Thomasond11cd162012-04-12 08:35:36 -07001058
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001059 /**
1060 Load an XML file from disk.
1061 Returns XML_NO_ERROR (0) on success, or
1062 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001063 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001064 int LoadFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001065
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001066 /**
1067 Load an XML file from disk. You are responsible
1068 for providing and closing the FILE*.
1069
1070 Returns XML_NO_ERROR (0) on success, or
1071 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001072 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001073 int LoadFile( FILE* );
Lee Thomasond11cd162012-04-12 08:35:36 -07001074
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001075 /**
1076 Save the XML file to disk.
Ken Miller81da1fb2012-04-09 23:32:26 -05001077 Returns XML_NO_ERROR (0) on success, or
1078 an errorID.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001079 */
Ken Miller81da1fb2012-04-09 23:32:26 -05001080 int SaveFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001081
Ken Miller81da1fb2012-04-09 23:32:26 -05001082 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001083 Save the XML file to disk. You are responsible
Ken Miller81da1fb2012-04-09 23:32:26 -05001084 for providing and closing the FILE*.
1085
1086 Returns XML_NO_ERROR (0) on success, or
1087 an errorID.
1088 */
1089 int SaveFile( FILE* );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001090
Lee Thomason6f381b72012-03-02 12:59:39 -08001091 bool ProcessEntities() const { return processEntities; }
1092
1093 /**
1094 Returns true if this document has a leading Byte Order Mark of UTF8.
1095 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001096 bool HasBOM() const { return writeBOM; }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001097 /** Sets whether to write the BOM when writing the file.
1098 */
1099 void SetBOM( bool useBOM ) { writeBOM = useBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001100
1101 /** Return the root element of DOM. Equivalent to FirstChildElement().
1102 To get the first node, use FirstChild().
1103 */
Lee Thomasond6277762012-02-22 16:00:12 -08001104 XMLElement* RootElement() { return FirstChildElement(); }
1105 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001106
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001107 /** Print the Document. If the Printer is not provided, it will
1108 print to stdout. If you provide Printer, this can print to a file:
1109 @verbatim
1110 XMLPrinter printer( fp );
1111 doc.Print( &printer );
1112 @endverbatim
1113
1114 Or you can use a printer to print to memory:
1115 @verbatim
1116 XMLPrinter printer;
1117 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001118 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001119 @endverbatim
1120 */
1121 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001122 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001123
Lee Thomason1ff38e02012-02-14 18:18:16 -08001124 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001125 Create a new Element associated with
1126 this Document. The memory for the Element
1127 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001128 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001129 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001130 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001131 Create a new Comment associated with
1132 this Document. The memory for the Comment
1133 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001134 */
1135 XMLComment* NewComment( const char* comment );
1136 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001137 Create a new Text associated with
1138 this Document. The memory for the Text
1139 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001140 */
1141 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001142 /**
1143 Create a new Declaration associated with
1144 this Document. The memory for the object
1145 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001146
1147 If the 'text' param is null, the standard
1148 declaration is used.:
1149 @verbatim
1150 <?xml version="1.0" encoding="UTF-8"?>
1151 @endverbatim
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001152 */
Lee Thomasonf68c4382012-04-28 14:37:11 -07001153 XMLDeclaration* NewDeclaration( const char* text=0 );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001154 /**
1155 Create a new Unknown associated with
1156 this Document. The memory for the object
1157 is managed by the Document.
1158 */
1159 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001160
U-Stream\Leeae25a442012-02-17 17:48:16 -08001161 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001162 Delete a node associated with this document.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001163 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001164 */
1165 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1166
Lee Thomason67d61312012-01-24 16:01:51 -08001167 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001168
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001169 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001170 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001171 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001172 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001173 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001174 const char* GetErrorStr1() const { return errorStr1; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001175 /// Return a possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001176 const char* GetErrorStr2() const { return errorStr2; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001177 /// If there is an error, print it to stdout.
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001178 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001179
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001180 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001181 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001182
Lee Thomason6f381b72012-03-02 12:59:39 -08001183 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
1184 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001185
Lee Thomason3f57d272012-01-11 15:30:03 -08001186private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001187 XMLDocument( const XMLDocument& ); // not supported
1188 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001189 void InitDocument();
1190
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001191 bool writeBOM;
Lee Thomason6f381b72012-03-02 12:59:39 -08001192 bool processEntities;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001193 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001194 const char* errorStr1;
1195 const char* errorStr2;
1196 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001197
1198 MemPoolT< sizeof(XMLElement) > elementPool;
1199 MemPoolT< sizeof(XMLAttribute) > attributePool;
1200 MemPoolT< sizeof(XMLText) > textPool;
1201 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001202};
1203
Lee Thomason7c913cd2012-01-26 18:32:34 -08001204
Lee Thomason3ffdd392012-03-28 17:27:55 -07001205/**
1206 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001207 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001208 DOM structure. It is a separate utility class.
1209
1210 Take an example:
1211 @verbatim
1212 <Document>
1213 <Element attributeA = "valueA">
1214 <Child attributeB = "value1" />
1215 <Child attributeB = "value2" />
1216 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001217 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001218 @endverbatim
1219
1220 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1221 easy to write a *lot* of code that looks like:
1222
1223 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001224 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001225 if ( root )
1226 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001227 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001228 if ( element )
1229 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001230 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001231 if ( child )
1232 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001233 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001234 if ( child2 )
1235 {
1236 // Finally do something useful.
1237 @endverbatim
1238
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001239 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1240 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001241 and correct to use:
1242
1243 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001244 XMLHandle docHandle( &document );
1245 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001246 if ( child2 )
1247 {
1248 // do something useful
1249 @endverbatim
1250
1251 Which is MUCH more concise and useful.
1252
1253 It is also safe to copy handles - internally they are nothing more than node pointers.
1254 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001255 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001256 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001257
1258 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001259*/
1260class XMLHandle
1261{
1262public:
1263 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Lee Thomason8b899812012-04-04 15:58:16 -07001264 XMLHandle( XMLNode* _node ) { node = _node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001265 /// Create a handle from a node.
Lee Thomason8b899812012-04-04 15:58:16 -07001266 XMLHandle( XMLNode& _node ) { node = &_node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001267 /// Copy constructor
Lee Thomason8b899812012-04-04 15:58:16 -07001268 XMLHandle( const XMLHandle& ref ) { node = ref.node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001269 /// Assignment
PKEuSc28ba3a2012-07-16 03:08:47 -07001270 XMLHandle& operator=( const XMLHandle& ref ) { node = ref.node; return *this; }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001271
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001272 /// Get the first child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001273 XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001274 /// Get the first child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001275 XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001276 /// Get the last child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001277 XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001278 /// Get the last child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001279 XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001280 /// Get the previous sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001281 XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001282 /// Get the previous sibling element of this handle.
Lee Thomason5708f812012-03-28 17:46:41 -07001283 XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001284 /// Get the next sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001285 XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001286 /// Get the next sibling element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001287 XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001288
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001289 /// Safe cast to XMLNode. This can return null.
Lee Thomason8b899812012-04-04 15:58:16 -07001290 XMLNode* ToNode() { return node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001291 /// Safe cast to XMLElement. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001292 XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001293 /// Safe cast to XMLText. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001294 XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001295 /// Safe cast to XMLUnknown. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001296 XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001297 /// Safe cast to XMLDeclaration. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001298 XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001299
1300private:
1301 XMLNode* node;
1302};
1303
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001304
1305/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001306 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1307 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001308*/
1309class XMLConstHandle
1310{
1311public:
1312 XMLConstHandle( const XMLNode* _node ) { node = _node; }
1313 XMLConstHandle( const XMLNode& _node ) { node = &_node; }
1314 XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; }
1315
PKEuSc28ba3a2012-07-16 03:08:47 -07001316 XMLConstHandle& operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; }
Lee Thomason8b899812012-04-04 15:58:16 -07001317
1318 const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1319 const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
1320 const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); }
1321 const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
1322 const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1323 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1324 const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1325 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1326
1327
1328 const XMLNode* ToNode() const { return node; }
1329 const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1330 const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1331 const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001332 const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1333
Lee Thomason5cae8972012-01-24 18:03:07 -08001334private:
Lee Thomason8b899812012-04-04 15:58:16 -07001335 const XMLNode* node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001336};
Lee Thomason6f381b72012-03-02 12:59:39 -08001337
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001338
1339/**
1340 Printing functionality. The XMLPrinter gives you more
1341 options than the XMLDocument::Print() method.
1342
1343 It can:
1344 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001345 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001346 -# Print XML without a XMLDocument.
1347
1348 Print to Memory
1349
1350 @verbatim
1351 XMLPrinter printer;
1352 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001353 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001354 @endverbatim
1355
1356 Print to a File
1357
1358 You provide the file pointer.
1359 @verbatim
1360 XMLPrinter printer( fp );
1361 doc.Print( &printer );
1362 @endverbatim
1363
1364 Print without a XMLDocument
1365
1366 When loading, an XML parser is very useful. However, sometimes
1367 when saving, it just gets in the way. The code is often set up
1368 for streaming, and constructing the DOM is just overhead.
1369
1370 The Printer supports the streaming case. The following code
1371 prints out a trivially simple XML file without ever creating
1372 an XML document.
1373
1374 @verbatim
1375 XMLPrinter printer( fp );
1376 printer.OpenElement( "foo" );
1377 printer.PushAttribute( "foo", "bar" );
1378 printer.CloseElement();
1379 @endverbatim
1380*/
1381class XMLPrinter : public XMLVisitor
1382{
1383public:
1384 /** Construct the printer. If the FILE* is specified,
1385 this will print to the FILE. Else it will print
Lee Thomason4cd85342012-06-04 17:02:37 -07001386 to memory, and the result is available in CStr().
1387 If 'compact' is set to true, then output is created
1388 with only required whitespace and newlines.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001389 */
sniperbat25900882012-05-28 17:22:07 +08001390 XMLPrinter( FILE* file=0, bool compact = false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001391 ~XMLPrinter() {}
1392
1393 /** If streaming, write the BOM and declaration. */
1394 void PushHeader( bool writeBOM, bool writeDeclaration );
1395 /** If streaming, start writing an element.
1396 The element must be closed with CloseElement()
1397 */
1398 void OpenElement( const char* name );
1399 /// If streaming, add an attribute to an open element.
1400 void PushAttribute( const char* name, const char* value );
1401 void PushAttribute( const char* name, int value );
1402 void PushAttribute( const char* name, unsigned value );
1403 void PushAttribute( const char* name, bool value );
1404 void PushAttribute( const char* name, double value );
1405 /// If streaming, close the Element.
1406 void CloseElement();
1407
1408 /// Add a text node.
1409 void PushText( const char* text, bool cdata=false );
Lee Thomason21be8822012-07-15 17:27:22 -07001410 /// Add a text node from an integer.
1411 void PushText( int value );
1412 /// Add a text node from an unsigned.
1413 void PushText( unsigned value );
1414 /// Add a text node from a bool.
1415 void PushText( bool value );
1416 /// Add a text node from a float.
1417 void PushText( float value );
1418 /// Add a text node from a double.
1419 void PushText( double value );
1420
1421 /// Add a comment
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001422 void PushComment( const char* comment );
1423
1424 void PushDeclaration( const char* value );
1425 void PushUnknown( const char* value );
1426
1427 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1428 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1429
1430 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1431 virtual bool VisitExit( const XMLElement& element );
1432
1433 virtual bool Visit( const XMLText& text );
1434 virtual bool Visit( const XMLComment& comment );
1435 virtual bool Visit( const XMLDeclaration& declaration );
1436 virtual bool Visit( const XMLUnknown& unknown );
1437
1438 /**
1439 If in print to memory mode, return a pointer to
1440 the XML file in memory.
1441 */
1442 const char* CStr() const { return buffer.Mem(); }
sniperbate01e7862012-05-21 12:45:36 +08001443 /**
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001444 If in print to memory mode, return the size
1445 of the XML file in memory. (Note the size returned
1446 includes the terminating null.)
sniperbate01e7862012-05-21 12:45:36 +08001447 */
Lee Thomasonc78dc012012-06-12 13:12:15 -07001448 int CStrSize() const { return buffer.Size(); }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001449
1450private:
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001451 void SealElement();
1452 void PrintSpace( int depth );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001453 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1454 void Print( const char* format, ... );
1455
1456 bool elementJustOpened;
1457 bool firstElement;
1458 FILE* fp;
1459 int depth;
1460 int textDepth;
1461 bool processEntities;
sniperbat25900882012-05-28 17:22:07 +08001462 bool compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001463
1464 enum {
1465 ENTITY_RANGE = 64,
1466 BUF_SIZE = 200
1467 };
1468 bool entityFlag[ENTITY_RANGE];
1469 bool restrictedEntityFlag[ENTITY_RANGE];
1470
1471 DynArray< const char*, 10 > stack;
PKEuSe736f292012-07-16 03:27:55 -07001472 DynArray< char, 20 > buffer;
1473#ifdef _MSC_VER
1474 DynArray< char, 20 > accumulator;
1475#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001476};
1477
1478
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001479} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001480
1481
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001482#endif // TINYXML2_INCLUDED