blob: b766d3509eb0b6b847e9541c48a89c2b4c065203 [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
28 #include <ctype.h>
29 #include <limits.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34#else
35 #include <cctype>
36 #include <climits>
37 #include <cstdio>
38 #include <cstdlib>
39 #include <cstring>
40 #include <cstdarg>
41#endif
Lee Thomason (grinliz)6a22be22012-04-04 12:39:05 -070042
Lee Thomason7d00b9a2012-02-27 17:54:22 -080043/*
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/*
47 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
48*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080049
U-Lama\Lee4cee6112011-12-31 14:58:18 -080050#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
51 #ifndef DEBUG
52 #define DEBUG
53 #endif
54#endif
55
56
57#if defined(DEBUG)
58 #if defined(_MSC_VER)
Guillermo A. Amaral68b0c872012-03-24 11:07:19 -070059 #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
U-Lama\Lee4cee6112011-12-31 14:58:18 -080060 #elif defined (ANDROID_NDK)
61 #include <android/log.h>
62 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
63 #else
64 #include <assert.h>
65 #define TIXMLASSERT assert
66 #endif
67#else
68 #define TIXMLASSERT( x ) {}
69#endif
70
U-Lama\Leee13c3e62011-12-28 14:36:55 -080071
Lee Thomason1a1d4a72012-02-15 09:09:25 -080072#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
73 // Microsoft visual studio, version 2005 and higher.
Lee Thomason (grinliz)598c13e2012-04-06 21:18:23 -070074 /*int _snprintf_s(
75 char *buffer,
76 size_t sizeOfBuffer,
77 size_t count,
78 const char *format [,
79 argument] ...
80 );*/
81 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
82 va_list va;
83 va_start( va, format );
84 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
85 va_end( va );
86 return result;
87 }
Lee Thomason1a1d4a72012-02-15 09:09:25 -080088 #define TIXML_SSCANF sscanf_s
Lee Thomason (grinliz)b9e791f2012-04-06 21:27:10 -070089#else
U-Stream\Leeae25a442012-02-17 17:48:16 -080090 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080091 //#warning( "Using sn* functions." )
92 #define TIXML_SNPRINTF snprintf
93 #define TIXML_SSCANF sscanf
Lee Thomason1a1d4a72012-02-15 09:09:25 -080094#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080095
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -070096static const int TIXML2_MAJOR_VERSION = 1;
97static const int TIXML2_MINOR_VERSION = 0;
Lee Thomason21be8822012-07-15 17:27:22 -070098static const int TIXML2_PATCH_VERSION = 6;
Lee Thomason1ff38e02012-02-14 18:18:16 -080099
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800100namespace tinyxml2
101{
Lee Thomasonce0763e2012-01-11 15:43:54 -0800102class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800103class XMLElement;
104class XMLAttribute;
105class XMLComment;
106class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800107class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -0800108class XMLDeclaration;
109class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800110
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800111class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800112
U-Stream\Leeae25a442012-02-17 17:48:16 -0800113/*
114 A class that wraps strings. Normally stores the start and end
115 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800116 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800117 manage) a traditional char[]
118*/
Lee Thomason39ede242012-01-20 11:27:56 -0800119class StrPair
120{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800121public:
Lee Thomason39ede242012-01-20 11:27:56 -0800122 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800123 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800124 NEEDS_NEWLINE_NORMALIZATION = 0x02,
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700125 COLLAPSE_WHITESPACE = 0x04,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800126
127 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800128 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800129 ATTRIBUTE_NAME = 0,
130 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason6f381b72012-03-02 12:59:39 -0800131 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700132 COMMENT = NEEDS_NEWLINE_NORMALIZATION
Lee Thomason39ede242012-01-20 11:27:56 -0800133 };
134
135 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800136 ~StrPair();
137
Lee Thomason5ce89412012-03-20 13:23:44 -0700138 void Set( char* _start, char* _end, int _flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800139 Reset();
Lee Thomason5ce89412012-03-20 13:23:44 -0700140 this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
Lee Thomason39ede242012-01-20 11:27:56 -0800141 }
142 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800143 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800144
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700145 void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800146 void SetStr( const char* str, int flags=0 );
147
Lee Thomason78a773d2012-07-02 10:10:19 -0700148 char* ParseText( char* in, const char* endTag, int strFlags );
Lee Thomason56bdd022012-02-09 18:16:58 -0800149 char* ParseName( char* in );
150
Lee Thomason2c85a712012-01-31 08:24:24 -0800151
Lee Thomason39ede242012-01-20 11:27:56 -0800152private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800153 void Reset();
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700154 void CollapseWhitespace();
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800155
Lee Thomasone4422302012-01-20 17:59:50 -0800156 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800157 NEEDS_FLUSH = 0x100,
158 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800159 };
160
Lee Thomason39ede242012-01-20 11:27:56 -0800161 // After parsing, if *end != 0, it can be set to zero.
162 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800163 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800164 char* end;
165};
166
U-Lama\Lee560bd472011-12-28 19:42:49 -0800167
U-Stream\Leeae25a442012-02-17 17:48:16 -0800168/*
169 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
170 Has a small initial memory pool, so that low or no usage will not
171 cause a call to new/delete
172*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800173template <class T, int INIT>
174class DynArray
175{
176public:
177 DynArray< T, INIT >()
178 {
179 mem = pool;
180 allocated = INIT;
181 size = 0;
182 }
183 ~DynArray()
184 {
185 if ( mem != pool ) {
Lee Thomasona2ae54e2012-05-18 13:47:48 -0700186 delete [] mem;
Lee Thomason2c85a712012-01-31 08:24:24 -0800187 }
188 }
189 void Push( T t )
190 {
191 EnsureCapacity( size+1 );
192 mem[size++] = t;
193 }
194
195 T* PushArr( int count )
196 {
197 EnsureCapacity( size+count );
198 T* ret = &mem[size];
199 size += count;
200 return ret;
201 }
202 T Pop() {
203 return mem[--size];
204 }
205 void PopArr( int count )
206 {
207 TIXMLASSERT( size >= count );
208 size -= count;
209 }
210
U-Stream\Leeae25a442012-02-17 17:48:16 -0800211 bool Empty() const { return size == 0; }
212 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
213 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
214 int Size() const { return size; }
215 int Capacity() const { return allocated; }
216 const T* Mem() const { return mem; }
217 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800218
219
220private:
221 void EnsureCapacity( int cap ) {
222 if ( cap > allocated ) {
223 int newAllocated = cap * 2;
224 T* newMem = new T[newAllocated];
225 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
226 if ( mem != pool ) delete [] mem;
227 mem = newMem;
228 allocated = newAllocated;
229 }
230 }
231
232 T* mem;
233 T pool[INIT];
234 int allocated; // objects allocated
235 int size; // number objects in use
236};
237
Lee Thomason50adb4c2012-02-13 15:07:09 -0800238
U-Stream\Leeae25a442012-02-17 17:48:16 -0800239/*
Thomas Roß08bdf502012-05-12 14:21:23 +0200240 Parent virtual class of a pool for fast allocation
U-Stream\Leeae25a442012-02-17 17:48:16 -0800241 and deallocation of objects.
242*/
Lee Thomasond1983222012-02-06 08:41:24 -0800243class MemPool
244{
245public:
246 MemPool() {}
247 virtual ~MemPool() {}
248
249 virtual int ItemSize() const = 0;
250 virtual void* Alloc() = 0;
251 virtual void Free( void* ) = 0;
252};
253
Lee Thomason50adb4c2012-02-13 15:07:09 -0800254
U-Stream\Leeae25a442012-02-17 17:48:16 -0800255/*
256 Template child class to create pools of the correct type.
257*/
Lee Thomasond1983222012-02-06 08:41:24 -0800258template< int SIZE >
259class MemPoolT : public MemPool
260{
261public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800262 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800263 ~MemPoolT() {
264 // Delete the blocks.
265 for( int i=0; i<blockPtrs.Size(); ++i ) {
266 delete blockPtrs[i];
267 }
268 }
269
270 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800271 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800272
273 virtual void* Alloc() {
274 if ( !root ) {
275 // Need a new block.
276 Block* block = new Block();
277 blockPtrs.Push( block );
278
279 for( int i=0; i<COUNT-1; ++i ) {
280 block->chunk[i].next = &block->chunk[i+1];
281 }
282 block->chunk[COUNT-1].next = 0;
283 root = block->chunk;
284 }
285 void* result = root;
286 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800287
288 ++currentAllocs;
289 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
290 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800291 return result;
292 }
293 virtual void Free( void* mem ) {
294 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800295 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800296 Chunk* chunk = (Chunk*)mem;
297 memset( chunk, 0xfe, sizeof(Chunk) );
298 chunk->next = root;
299 root = chunk;
300 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800301 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800302 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
303 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800304 }
Lee Thomasond1983222012-02-06 08:41:24 -0800305
306private:
307 enum { COUNT = 1024/SIZE };
308 union Chunk {
309 Chunk* next;
310 char mem[SIZE];
311 };
312 struct Block {
313 Chunk chunk[COUNT];
314 };
315 DynArray< Block*, 10 > blockPtrs;
316 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800317
318 int currentAllocs;
319 int nAllocs;
320 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800321};
322
Lee Thomason2c85a712012-01-31 08:24:24 -0800323
Lee Thomason56bdd022012-02-09 18:16:58 -0800324
325/**
326 Implements the interface to the "Visitor pattern" (see the Accept() method.)
327 If you call the Accept() method, it requires being passed a XMLVisitor
328 class to handle callbacks. For nodes that contain other nodes (Document, Element)
Thomas Roß08bdf502012-05-12 14:21:23 +0200329 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
Lee Thomason56bdd022012-02-09 18:16:58 -0800330 are simply called with Visit().
331
332 If you return 'true' from a Visit method, recursive parsing will continue. If you return
Thomas Roß08bdf502012-05-12 14:21:23 +0200333 false, <b>no children of this node or its sibilings</b> will be visited.
Lee Thomason56bdd022012-02-09 18:16:58 -0800334
335 All flavors of Visit methods have a default implementation that returns 'true' (continue
336 visiting). You need to only override methods that are interesting to you.
337
Thomas Roß08bdf502012-05-12 14:21:23 +0200338 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
Lee Thomason56bdd022012-02-09 18:16:58 -0800339
340 You should never change the document from a callback.
341
342 @sa XMLNode::Accept()
343*/
344class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800345{
346public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800347 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800348
Lee Thomason56bdd022012-02-09 18:16:58 -0800349 /// Visit a document.
350 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
351 /// Visit a document.
352 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
353
354 /// Visit an element.
355 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
356 /// Visit an element.
357 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
358
Thomas Roß08bdf502012-05-12 14:21:23 +0200359 /// Visit a declaration.
Lee Thomason50f97b22012-02-11 16:33:40 -0800360 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200361 /// Visit a text node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800362 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200363 /// Visit a comment node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800364 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
Thomas Roß08bdf502012-05-12 14:21:23 +0200365 /// Visit an unknown node.
Lee Thomason50f97b22012-02-11 16:33:40 -0800366 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800367};
368
369
U-Stream\Leeae25a442012-02-17 17:48:16 -0800370/*
371 Utility functionality.
372*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800373class XMLUtil
374{
Lee Thomasond1983222012-02-06 08:41:24 -0800375public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800376 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
377 // correct, but simple, and usually works.
Lee Thomason (grinliz)390e9782012-07-01 21:22:53 -0700378 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) { ++p; } return p; }
379 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) { ++p; } return p; }
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -0700380 static bool IsWhiteSpace( char p ) { return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) ); }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800381
382 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
383 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800384 if ( p == q ) {
385 return true;
386 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800387 while( *p && *q && *p == *q && n<nChar ) {
388 ++p; ++q; ++n;
389 }
390 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
391 return true;
392 }
393 return false;
394 }
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -0700395 inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800396 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
397 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800398
399 static const char* ReadBOM( const char* p, bool* hasBOM );
400 // p is the starting location,
401 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800402 static const char* GetCharacterRef( const char* p, char* value, int* length );
403 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason21be8822012-07-15 17:27:22 -0700404
405 // converts primitive types to strings
406 static void ToStr( int v, char* buffer, int bufferSize );
407 static void ToStr( unsigned v, char* buffer, int bufferSize );
408 static void ToStr( bool v, char* buffer, int bufferSize );
409 static void ToStr( float v, char* buffer, int bufferSize );
410 static void ToStr( double v, char* buffer, int bufferSize );
411
412 // converts strings to primitive types
413 static bool ToInt( const char* str, int* value );
414 static bool ToUnsigned( const char* str, unsigned* value );
415 static bool ToBool( const char* str, bool* value );
416 static bool ToFloat( const char* str, float* value );
417 static bool ToDouble( const char* str, double* value );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800418};
419
Lee Thomason5cae8972012-01-24 18:03:07 -0800420
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800421/** XMLNode is a base class for every object that is in the
422 XML Document Object Model (DOM), except XMLAttributes.
423 Nodes have siblings, a parent, and children which can
424 be navigated. A node is always in a XMLDocument.
Lee Thomason3a682622012-03-25 13:19:40 -0700425 The type of a XMLNode can be queried, and it can
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800426 be cast to its more defined type.
427
Thomas Roß08bdf502012-05-12 14:21:23 +0200428 A XMLDocument allocates memory for all its Nodes.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800429 When the XMLDocument gets deleted, all its Nodes
430 will also be deleted.
431
432 @verbatim
433 A Document can contain: Element (container or leaf)
434 Comment (leaf)
435 Unknown (leaf)
436 Declaration( leaf )
437
438 An Element can contain: Element (container or leaf)
439 Text (leaf)
440 Attributes (not on tree)
441 Comment (leaf)
442 Unknown (leaf)
443
444 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800445*/
Lee Thomasond1983222012-02-06 08:41:24 -0800446class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800447{
448 friend class XMLDocument;
449 friend class XMLElement;
450public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800451
452 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800453 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800454 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800455 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800456
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800457 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
458 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
459 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
460 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
461 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
462 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800463
Lee Thomason50f97b22012-02-11 16:33:40 -0800464 virtual const XMLElement* ToElement() const { return 0; }
465 virtual const XMLText* ToText() const { return 0; }
466 virtual const XMLComment* ToComment() const { return 0; }
467 virtual const XMLDocument* ToDocument() const { return 0; }
468 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
469 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800470
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800471 /** The meaning of 'value' changes for the specific type.
472 @verbatim
Thomas Roß08bdf502012-05-12 14:21:23 +0200473 Document: empty
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800474 Element: name of the element
475 Comment: the comment text
476 Unknown: the tag contents
477 Text: the text string
478 @endverbatim
479 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800480 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800481 /** Set the Value of an XML node.
482 @sa Value()
483 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800484 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800485
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800486 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800487 const XMLNode* Parent() const { return parent; }
488 XMLNode* Parent() { return parent; }
489
Lee Thomason50f97b22012-02-11 16:33:40 -0800490 /// Returns true if this node has no children.
491 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800492
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800493 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800494 const XMLNode* FirstChild() const { return firstChild; }
495 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800496 /** Get the first child element, or optionally the first child
497 element with the specified name.
498 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800499 const XMLElement* FirstChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700500 XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800501
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800502 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800503 const XMLNode* LastChild() const { return lastChild; }
504 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800505
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800506 /** Get the last child element or optionally the last child
507 element with the specified name.
508 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800509 const XMLElement* LastChildElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700510 XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800511
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800512 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800513 const XMLNode* PreviousSibling() const { return prev; }
514 XMLNode* PreviousSibling() { return prev; }
515
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800516 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800517 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
Lee Thomason5ce89412012-03-20 13:23:44 -0700518 XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800519
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800520 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800521 const XMLNode* NextSibling() const { return next; }
522 XMLNode* NextSibling() { return next; }
523
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800524 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800525 const XMLElement* NextSiblingElement( const char* value=0 ) const;
Lee Thomason5ce89412012-03-20 13:23:44 -0700526 XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800527
Lee Thomason1ff38e02012-02-14 18:18:16 -0800528 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800529 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800530 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800531 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800532
533 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800534 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800535 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800536 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800537 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800538 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800539 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800540 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800541 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
542
U-Stream\Leeae25a442012-02-17 17:48:16 -0800543 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800544 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800545 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800546 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800547
548 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800549 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800550 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800551 void DeleteChild( XMLNode* node );
552
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800553 /**
554 Make a copy of this node, but not its children.
555 You may pass in a Document pointer that will be
556 the owner of the new Node. If the 'document' is
557 null, then the node returned will be allocated
558 from the current Document. (this->GetDocument())
559
560 Note: if called on a XMLDocument, this will return null.
561 */
562 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
563
564 /**
565 Test if 2 nodes are the same, but don't test children.
566 The 2 nodes do not need to be in the same Document.
567
568 Note: if called on a XMLDocument, this will return false.
569 */
570 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
571
Thomas Roß08bdf502012-05-12 14:21:23 +0200572 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800573 XML tree will be conditionally visited and the host will be called back
574 via the TiXmlVisitor interface.
575
576 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
577 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
578 interface versus any other.)
579
580 The interface has been based on ideas from:
581
582 - http://www.saxproject.org/
583 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
584
585 Which are both good references for "visiting".
586
587 An example of using Accept():
588 @verbatim
589 TiXmlPrinter printer;
590 tinyxmlDoc.Accept( &printer );
591 const char* xmlcstr = printer.CStr();
592 @endverbatim
593 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800594 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800595
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800596 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800597 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800598
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800599protected:
600 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800601 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800602 XMLNode( const XMLNode& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700603 XMLNode& operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800604
Lee Thomason3f57d272012-01-11 15:30:03 -0800605 XMLDocument* document;
606 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800607 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800608
609 XMLNode* firstChild;
610 XMLNode* lastChild;
611
612 XMLNode* prev;
613 XMLNode* next;
614
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800615private:
Lee Thomasond1983222012-02-06 08:41:24 -0800616 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800617 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800618};
619
620
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800621/** XML text.
622
623 Note that a text node can have child element nodes, for example:
624 @verbatim
625 <root>This is <b>bold</b></root>
626 @endverbatim
627
628 A text node can have 2 ways to output the next. "normal" output
629 and CDATA. It will default to the mode it was parsed from the XML file and
630 you generally want to leave it alone, but you can change the output mode with
631 SetCDATA() and query it with CDATA().
632*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800633class XMLText : public XMLNode
634{
Lee Thomason2c85a712012-01-31 08:24:24 -0800635 friend class XMLBase;
636 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800637public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800638 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800639
Lee Thomason751da522012-02-10 08:50:51 -0800640 virtual XMLText* ToText() { return this; }
641 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800642
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800643 /// Declare whether this should be CDATA or standard text.
Lee Thomason5ce89412012-03-20 13:23:44 -0700644 void SetCData( bool _isCData ) { this->isCData = _isCData; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800645 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800646 bool CData() const { return isCData; }
647
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800648 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800649 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
650 virtual bool ShallowEqual( const XMLNode* compare ) const;
651
Lee Thomason5492a1c2012-01-23 15:32:10 -0800652
653protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800654 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
655 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800656 XMLText( const XMLText& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700657 XMLText& operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800658
659private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800660 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800661};
662
663
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800664/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800665class XMLComment : public XMLNode
666{
Lee Thomason2c85a712012-01-31 08:24:24 -0800667 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800668public:
Lee Thomason751da522012-02-10 08:50:51 -0800669 virtual XMLComment* ToComment() { return this; }
670 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800671
Lee Thomason56bdd022012-02-09 18:16:58 -0800672 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800673
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800674 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800675 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
676 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800677
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800678protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800679 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800680 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800681 XMLComment( const XMLComment& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700682 XMLComment& operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800683
Lee Thomason3f57d272012-01-11 15:30:03 -0800684private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800685};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800686
687
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800688/** In correct XML the declaration is the first entry in the file.
689 @verbatim
690 <?xml version="1.0" standalone="yes"?>
691 @endverbatim
692
693 TinyXML2 will happily read or write files without a declaration,
694 however.
695
696 The text of the declaration isn't interpreted. It is parsed
697 and written as a string.
698*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800699class XMLDeclaration : public XMLNode
700{
701 friend class XMLDocument;
702public:
703 virtual XMLDeclaration* ToDeclaration() { return this; }
704 virtual const XMLDeclaration* ToDeclaration() const { return this; }
705
706 virtual bool Accept( XMLVisitor* visitor ) const;
707
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800708 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800709 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
710 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800711
712protected:
713 XMLDeclaration( XMLDocument* doc );
714 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800715 XMLDeclaration( const XMLDeclaration& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700716 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800717};
718
719
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800720/** Any tag that tinyXml doesn't recognize is saved as an
721 unknown. It is a tag of text, but should not be modified.
722 It will be written back to the XML, unchanged, when the file
723 is saved.
724
725 DTD tags get thrown into TiXmlUnknowns.
726*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800727class XMLUnknown : public XMLNode
728{
729 friend class XMLDocument;
730public:
731 virtual XMLUnknown* ToUnknown() { return this; }
732 virtual const XMLUnknown* ToUnknown() const { return this; }
733
734 virtual bool Accept( XMLVisitor* visitor ) const;
735
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800736 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800737 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
738 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800739
740protected:
741 XMLUnknown( XMLDocument* doc );
742 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800743 XMLUnknown( const XMLUnknown& ); // not supported
PKEuSc28ba3a2012-07-16 03:08:47 -0700744 XMLUnknown& operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800745};
746
747
Lee Thomason1ff38e02012-02-14 18:18:16 -0800748enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800749 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800750 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800751
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700752 XML_NO_ATTRIBUTE,
753 XML_WRONG_ATTRIBUTE_TYPE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800754
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700755 XML_ERROR_FILE_NOT_FOUND,
Lee Thomason7f7b1622012-03-24 12:49:03 -0700756 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
Lee Thomasona3efec02012-06-15 14:30:44 -0700757 XML_ERROR_FILE_READ_ERROR,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700758 XML_ERROR_ELEMENT_MISMATCH,
759 XML_ERROR_PARSING_ELEMENT,
760 XML_ERROR_PARSING_ATTRIBUTE,
761 XML_ERROR_IDENTIFYING_TAG,
762 XML_ERROR_PARSING_TEXT,
763 XML_ERROR_PARSING_CDATA,
764 XML_ERROR_PARSING_COMMENT,
765 XML_ERROR_PARSING_DECLARATION,
766 XML_ERROR_PARSING_UNKNOWN,
767 XML_ERROR_EMPTY_DOCUMENT,
768 XML_ERROR_MISMATCHED_ELEMENT,
Lee Thomason21be8822012-07-15 17:27:22 -0700769 XML_ERROR_PARSING,
770
771 XML_CAN_NOT_CONVERT_TEXT,
772 XML_NO_TEXT_NODE
Lee Thomason1ff38e02012-02-14 18:18:16 -0800773};
774
775
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800776/** An attribute is a name-value pair. Elements have an arbitrary
777 number of attributes, each with a unique name.
778
779 @note The attributes are not XMLNodes. You may only query the
780 Next() attribute in a list.
781*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800782class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800783{
784 friend class XMLElement;
785public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800786 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
787 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
788 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800789
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800790 /** IntAttribute interprets the attribute as an integer, and returns the value.
791 If the value isn't an integer, 0 will be returned. There is no error checking;
792 use QueryIntAttribute() if you need error checking.
793 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800794 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800795 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800796 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800797 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800798 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800799 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800800 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800801 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800802 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800803
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800804 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
805 in the provided paremeter. The function will return XML_NO_ERROR on success,
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700806 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800807 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800808 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800809 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800810 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800811 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800812 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800813 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800814 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800815 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800816 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800817
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800818 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800819 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800820 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800821 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800822 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800823 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800824 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800825 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800826 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800827 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800828 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800829 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800830
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800831private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800832 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800833
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800834 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800835 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800836 XMLAttribute( const XMLAttribute& ); // not supported
837 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800838 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800839
Lee Thomason6f381b72012-03-02 12:59:39 -0800840 char* ParseDeep( char* p, bool processEntities );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800841
Lee Thomason751da522012-02-10 08:50:51 -0800842 mutable StrPair name;
843 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800844 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800845 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800846};
847
848
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800849/** The element is a container class. It has a value, the element name,
850 and can contain other elements, text, comments, and unknowns.
851 Elements also contain an arbitrary number of attributes.
852*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800853class XMLElement : public XMLNode
854{
Lee Thomason2c85a712012-01-31 08:24:24 -0800855 friend class XMLBase;
856 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800857public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800858 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800859 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800860 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800861 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800862
Lee Thomason751da522012-02-10 08:50:51 -0800863 virtual XMLElement* ToElement() { return this; }
864 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800865 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800866
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800867 /** Given an attribute name, Attribute() returns the value
Lee Thomason92258152012-03-24 13:05:39 -0700868 for the attribute of that name, or null if none
869 exists. For example:
870
871 @verbatim
872 const char* value = ele->Attribute( "foo" );
873 @endverbatim
874
875 The 'value' parameter is normally null. However, if specified,
876 the attribute will only be returned if the 'name' and 'value'
877 match. This allow you to write code:
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700878
879 @verbatim
880 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
881 @endverbatim
882
883 rather than:
884 @verbatim
885 if ( ele->Attribute( "foo" ) ) {
886 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
887 }
888 @endverbatim
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800889 */
Lee Thomason8ba7f7d2012-03-24 13:04:04 -0700890 const char* Attribute( const char* name, const char* value=0 ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800891
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800892 /** Given an attribute name, IntAttribute() returns the value
893 of the attribute interpreted as an integer. 0 will be
894 returned if there is an error. For a method with error
895 checking, see QueryIntAttribute()
896 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800897 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800898 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800899 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800900 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800901 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800902 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200903 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800904 /// See IntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200905 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800906
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800907 /** Given an attribute name, QueryIntAttribute() returns
Guillermo A. Amaral2eb70032012-03-20 11:26:57 -0700908 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
909 can't be performed, or XML_NO_ATTRIBUTE if the attribute
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800910 doesn't exist. If successful, the result of the conversion
911 will be written to 'value'. If not successful, nothing will
912 be written to 'value'. This allows you to provide default
913 value:
914
915 @verbatim
916 int value = 10;
917 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
918 @endverbatim
919 */
Thomas Roß08bdf502012-05-12 14:21:23 +0200920 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 -0800921 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700922 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 -0800923 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700924 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 -0800925 /// See QueryIntAttribute()
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700926 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 -0800927 /// See QueryIntAttribute()
Thomas Roß08bdf502012-05-12 14:21:23 +0200928 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 -0800929
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800930 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700931 void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800932 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700933 void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800934 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700935 void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800936 /// Sets the named attribute to value.
Guillermo A. Amaral9a6c6b82012-03-24 17:13:25 -0700937 void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800938 /// Sets the named attribute to value.
Thomas Roß08bdf502012-05-12 14:21:23 +0200939 void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800940
U-Stream\Leeae25a442012-02-17 17:48:16 -0800941 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800942 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800943 */
944 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800945
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800946 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800947 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800948 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800949 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800950
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800951 /** Convenience function for easy access to the text inside an element. Although easy
952 and concise, GetText() is limited compared to getting the TiXmlText child
953 and accessing it directly.
954
955 If the first child of 'this' is a TiXmlText, the GetText()
956 returns the character string of the Text node, else null is returned.
957
958 This is a convenient method for getting the text of simple contained text:
959 @verbatim
960 <foo>This is text</foo>
Lee Thomason21be8822012-07-15 17:27:22 -0700961 const char* str = fooElement->GetText();
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800962 @endverbatim
963
964 'str' will be a pointer to "This is text".
965
966 Note that this function can be misleading. If the element foo was created from
967 this XML:
968 @verbatim
Lee Thomason21be8822012-07-15 17:27:22 -0700969 <foo><b>This is text</b></foo>
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800970 @endverbatim
971
972 then the value of str would be null. The first child node isn't a text node, it is
973 another element. From this XML:
974 @verbatim
Lee Thomason21be8822012-07-15 17:27:22 -0700975 <foo>This is <b>text</b></foo>
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800976 @endverbatim
977 GetText() will return "This is ".
978 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800979 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800980
Lee Thomason21be8822012-07-15 17:27:22 -0700981 /**
982 Convenience method to query the value of a child text node. This is probably best
983 shown by example. Given you have a document is this form:
984 @verbatim
985 <point>
986 <x>1</x>
987 <y>1.4</y>
988 </point>
989 @endverbatim
990
991 The QueryIntText() and similar functions provide a safe and easier way to get to the
992 "value" of x and y.
993
994 @verbatim
995 int x = 0;
996 float y = 0; // types of x and y are contrived for example
997 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
998 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
999 xElement->QueryIntText( &x );
1000 yElement->QueryFloatText( &y );
1001 @endverbatim
1002
1003 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
1004 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
1005
1006 */
1007 int QueryIntText( int* _value ) const;
1008 /// See QueryIntText()
1009 int QueryUnsignedText( unsigned* _value ) const;
1010 /// See QueryIntText()
1011 int QueryBoolText( bool* _value ) const;
1012 /// See QueryIntText()
1013 int QueryDoubleText( double* _value ) const;
1014 /// See QueryIntText()
1015 int QueryFloatText( float* _value ) const;
1016
Lee Thomason2c85a712012-01-31 08:24:24 -08001017 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001018 enum {
1019 OPEN, // <foo>
1020 CLOSED, // <foo/>
1021 CLOSING // </foo>
1022 };
1023 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -08001024 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001025 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
1026 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001027
Lee Thomason50adb4c2012-02-13 15:07:09 -08001028private:
Lee Thomason2c85a712012-01-31 08:24:24 -08001029 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -08001030 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -08001031 XMLElement( const XMLElement& ); // not supported
1032 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001033
Lee Thomason1a1d4a72012-02-15 09:09:25 -08001034 XMLAttribute* FindAttribute( const char* name );
1035 XMLAttribute* FindOrCreateAttribute( const char* name );
Lee Thomason5e3803c2012-04-16 08:57:05 -07001036 //void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001037 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -08001038
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -08001039 int closingType;
Lee Thomason5e3803c2012-04-16 08:57:05 -07001040 // The attribute list is ordered; there is no 'lastAttribute'
1041 // because the list needs to be scanned for dupes before adding
1042 // a new attribute.
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001043 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001044};
1045
1046
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001047enum Whitespace {
1048 PRESERVE_WHITESPACE,
1049 COLLAPSE_WHITESPACE
1050};
1051
1052
Thomas Roß08bdf502012-05-12 14:21:23 +02001053/** A Document binds together all the functionality.
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -08001054 It can be saved, loaded, and printed to the screen.
1055 All Nodes are connected and allocated to a Document.
1056 If the Document is deleted, all its Nodes are also deleted.
1057*/
Lee Thomason67d61312012-01-24 16:01:51 -08001058class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001059{
Lee Thomasond1983222012-02-06 08:41:24 -08001060 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001061public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001062 /// constructor
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001063 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
Lee Thomason3f57d272012-01-11 15:30:03 -08001064 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001065
Lee Thomason751da522012-02-10 08:50:51 -08001066 virtual XMLDocument* ToDocument() { return this; }
1067 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -08001068
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001069 /**
1070 Parse an XML file from a character string.
1071 Returns XML_NO_ERROR (0) on success, or
1072 an errorID.
1073 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001074 int Parse( const char* xml );
Lee Thomasond11cd162012-04-12 08:35:36 -07001075
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001076 /**
1077 Load an XML file from disk.
1078 Returns XML_NO_ERROR (0) on success, or
1079 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001080 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001081 int LoadFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001082
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001083 /**
1084 Load an XML file from disk. You are responsible
1085 for providing and closing the FILE*.
1086
1087 Returns XML_NO_ERROR (0) on success, or
1088 an errorID.
Lee Thomasond11cd162012-04-12 08:35:36 -07001089 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001090 int LoadFile( FILE* );
Lee Thomasond11cd162012-04-12 08:35:36 -07001091
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001092 /**
1093 Save the XML file to disk.
Ken Miller81da1fb2012-04-09 23:32:26 -05001094 Returns XML_NO_ERROR (0) on success, or
1095 an errorID.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001096 */
Ken Miller81da1fb2012-04-09 23:32:26 -05001097 int SaveFile( const char* filename );
Lee Thomasond11cd162012-04-12 08:35:36 -07001098
Ken Miller81da1fb2012-04-09 23:32:26 -05001099 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001100 Save the XML file to disk. You are responsible
Ken Miller81da1fb2012-04-09 23:32:26 -05001101 for providing and closing the FILE*.
1102
1103 Returns XML_NO_ERROR (0) on success, or
1104 an errorID.
1105 */
1106 int SaveFile( FILE* );
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001107
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001108 bool ProcessEntities() const { return processEntities; }
1109 Whitespace WhitespaceMode() const { return whitespace; }
Lee Thomason6f381b72012-03-02 12:59:39 -08001110
1111 /**
1112 Returns true if this document has a leading Byte Order Mark of UTF8.
1113 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001114 bool HasBOM() const { return writeBOM; }
Lee Thomasonf68c4382012-04-28 14:37:11 -07001115 /** Sets whether to write the BOM when writing the file.
1116 */
1117 void SetBOM( bool useBOM ) { writeBOM = useBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001118
1119 /** Return the root element of DOM. Equivalent to FirstChildElement().
1120 To get the first node, use FirstChild().
1121 */
Lee Thomasond6277762012-02-22 16:00:12 -08001122 XMLElement* RootElement() { return FirstChildElement(); }
1123 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001124
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001125 /** Print the Document. If the Printer is not provided, it will
1126 print to stdout. If you provide Printer, this can print to a file:
1127 @verbatim
1128 XMLPrinter printer( fp );
1129 doc.Print( &printer );
1130 @endverbatim
1131
1132 Or you can use a printer to print to memory:
1133 @verbatim
1134 XMLPrinter printer;
1135 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001136 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001137 @endverbatim
1138 */
1139 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001140 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001141
Lee Thomason1ff38e02012-02-14 18:18:16 -08001142 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001143 Create a new Element associated with
1144 this Document. The memory for the Element
1145 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001146 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001147 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001148 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001149 Create a new Comment associated with
1150 this Document. The memory for the Comment
1151 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001152 */
1153 XMLComment* NewComment( const char* comment );
1154 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001155 Create a new Text associated with
1156 this Document. The memory for the Text
1157 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001158 */
1159 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001160 /**
1161 Create a new Declaration associated with
1162 this Document. The memory for the object
1163 is managed by the Document.
Lee Thomasonf68c4382012-04-28 14:37:11 -07001164
1165 If the 'text' param is null, the standard
1166 declaration is used.:
1167 @verbatim
1168 <?xml version="1.0" encoding="UTF-8"?>
1169 @endverbatim
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001170 */
Lee Thomasonf68c4382012-04-28 14:37:11 -07001171 XMLDeclaration* NewDeclaration( const char* text=0 );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001172 /**
1173 Create a new Unknown associated with
1174 this Document. The memory for the object
1175 is managed by the Document.
1176 */
1177 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001178
U-Stream\Leeae25a442012-02-17 17:48:16 -08001179 /**
Thomas Roß08bdf502012-05-12 14:21:23 +02001180 Delete a node associated with this document.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001181 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001182 */
1183 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1184
Lee Thomason67d61312012-01-24 16:01:51 -08001185 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001186
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001187 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001188 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001189 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001190 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001191 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001192 const char* GetErrorStr1() const { return errorStr1; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001193 /// Return a possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001194 const char* GetErrorStr2() const { return errorStr2; }
Thomas Roß08bdf502012-05-12 14:21:23 +02001195 /// If there is an error, print it to stdout.
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001196 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001197
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001198 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001199 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001200
Lee Thomason6f381b72012-03-02 12:59:39 -08001201 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
1202 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001203
Lee Thomason3f57d272012-01-11 15:30:03 -08001204private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001205 XMLDocument( const XMLDocument& ); // not supported
1206 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001207 void InitDocument();
1208
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001209 bool writeBOM;
Lee Thomason6f381b72012-03-02 12:59:39 -08001210 bool processEntities;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001211 int errorID;
Lee Thomason (grinliz)bc1bfb72012-08-20 22:00:38 -07001212 Whitespace whitespace;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001213 const char* errorStr1;
1214 const char* errorStr2;
1215 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001216
1217 MemPoolT< sizeof(XMLElement) > elementPool;
1218 MemPoolT< sizeof(XMLAttribute) > attributePool;
1219 MemPoolT< sizeof(XMLText) > textPool;
1220 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001221};
1222
Lee Thomason7c913cd2012-01-26 18:32:34 -08001223
Lee Thomason3ffdd392012-03-28 17:27:55 -07001224/**
1225 A XMLHandle is a class that wraps a node pointer with null checks; this is
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001226 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
Lee Thomason3ffdd392012-03-28 17:27:55 -07001227 DOM structure. It is a separate utility class.
1228
1229 Take an example:
1230 @verbatim
1231 <Document>
1232 <Element attributeA = "valueA">
1233 <Child attributeB = "value1" />
1234 <Child attributeB = "value2" />
1235 </Element>
Thomas Roß08bdf502012-05-12 14:21:23 +02001236 </Document>
Lee Thomason3ffdd392012-03-28 17:27:55 -07001237 @endverbatim
1238
1239 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1240 easy to write a *lot* of code that looks like:
1241
1242 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001243 XMLElement* root = document.FirstChildElement( "Document" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001244 if ( root )
1245 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001246 XMLElement* element = root->FirstChildElement( "Element" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001247 if ( element )
1248 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001249 XMLElement* child = element->FirstChildElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001250 if ( child )
1251 {
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001252 XMLElement* child2 = child->NextSiblingElement( "Child" );
Lee Thomason3ffdd392012-03-28 17:27:55 -07001253 if ( child2 )
1254 {
1255 // Finally do something useful.
1256 @endverbatim
1257
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001258 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
1259 of such code. A XMLHandle checks for null pointers so it is perfectly safe
Lee Thomason3ffdd392012-03-28 17:27:55 -07001260 and correct to use:
1261
1262 @verbatim
Lee Thomasondb0bbb62012-04-04 15:47:04 -07001263 XMLHandle docHandle( &document );
1264 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
Lee Thomason3ffdd392012-03-28 17:27:55 -07001265 if ( child2 )
1266 {
1267 // do something useful
1268 @endverbatim
1269
1270 Which is MUCH more concise and useful.
1271
1272 It is also safe to copy handles - internally they are nothing more than node pointers.
1273 @verbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001274 XMLHandle handleCopy = handle;
Lee Thomason3ffdd392012-03-28 17:27:55 -07001275 @endverbatim
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001276
1277 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001278*/
1279class XMLHandle
1280{
1281public:
1282 /// 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 -07001283 XMLHandle( XMLNode* _node ) { node = _node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001284 /// Create a handle from a node.
Lee Thomason8b899812012-04-04 15:58:16 -07001285 XMLHandle( XMLNode& _node ) { node = &_node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001286 /// Copy constructor
Lee Thomason8b899812012-04-04 15:58:16 -07001287 XMLHandle( const XMLHandle& ref ) { node = ref.node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001288 /// Assignment
PKEuSc28ba3a2012-07-16 03:08:47 -07001289 XMLHandle& operator=( const XMLHandle& ref ) { node = ref.node; return *this; }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001290
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001291 /// Get the first child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001292 XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001293 /// Get the first child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001294 XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001295 /// Get the last child of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001296 XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001297 /// Get the last child element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001298 XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001299 /// Get the previous sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001300 XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001301 /// Get the previous sibling element of this handle.
Lee Thomason5708f812012-03-28 17:46:41 -07001302 XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001303 /// Get the next sibling of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001304 XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001305 /// Get the next sibling element of this handle.
Lee Thomason8b899812012-04-04 15:58:16 -07001306 XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001307
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001308 /// Safe cast to XMLNode. This can return null.
Lee Thomason8b899812012-04-04 15:58:16 -07001309 XMLNode* ToNode() { return node; }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001310 /// Safe cast to XMLElement. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001311 XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001312 /// Safe cast to XMLText. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001313 XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001314 /// Safe cast to XMLUnknown. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001315 XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001316 /// Safe cast to XMLDeclaration. This can return null.
Lee Thomason3ffdd392012-03-28 17:27:55 -07001317 XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
Lee Thomason3ffdd392012-03-28 17:27:55 -07001318
1319private:
1320 XMLNode* node;
1321};
1322
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001323
1324/**
Lee Thomason (grinliz)ae209f62012-04-04 22:00:07 -07001325 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
1326 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
Lee Thomason8b899812012-04-04 15:58:16 -07001327*/
1328class XMLConstHandle
1329{
1330public:
1331 XMLConstHandle( const XMLNode* _node ) { node = _node; }
1332 XMLConstHandle( const XMLNode& _node ) { node = &_node; }
1333 XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; }
1334
PKEuSc28ba3a2012-07-16 03:08:47 -07001335 XMLConstHandle& operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; }
Lee Thomason8b899812012-04-04 15:58:16 -07001336
1337 const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
1338 const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
1339 const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); }
1340 const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
1341 const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
1342 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
1343 const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
1344 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
1345
1346
1347 const XMLNode* ToNode() const { return node; }
1348 const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1349 const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1350 const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001351 const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
1352
Lee Thomason5cae8972012-01-24 18:03:07 -08001353private:
Lee Thomason8b899812012-04-04 15:58:16 -07001354 const XMLNode* node;
Lee Thomason56bdd022012-02-09 18:16:58 -08001355};
Lee Thomason6f381b72012-03-02 12:59:39 -08001356
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001357
1358/**
1359 Printing functionality. The XMLPrinter gives you more
1360 options than the XMLDocument::Print() method.
1361
1362 It can:
1363 -# Print to memory.
Thomas Roß08bdf502012-05-12 14:21:23 +02001364 -# Print to a file you provide.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001365 -# Print XML without a XMLDocument.
1366
1367 Print to Memory
1368
1369 @verbatim
1370 XMLPrinter printer;
1371 doc->Print( &printer );
Thomas Roß08bdf502012-05-12 14:21:23 +02001372 SomeFunction( printer.CStr() );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001373 @endverbatim
1374
1375 Print to a File
1376
1377 You provide the file pointer.
1378 @verbatim
1379 XMLPrinter printer( fp );
1380 doc.Print( &printer );
1381 @endverbatim
1382
1383 Print without a XMLDocument
1384
1385 When loading, an XML parser is very useful. However, sometimes
1386 when saving, it just gets in the way. The code is often set up
1387 for streaming, and constructing the DOM is just overhead.
1388
1389 The Printer supports the streaming case. The following code
1390 prints out a trivially simple XML file without ever creating
1391 an XML document.
1392
1393 @verbatim
1394 XMLPrinter printer( fp );
1395 printer.OpenElement( "foo" );
1396 printer.PushAttribute( "foo", "bar" );
1397 printer.CloseElement();
1398 @endverbatim
1399*/
1400class XMLPrinter : public XMLVisitor
1401{
1402public:
1403 /** Construct the printer. If the FILE* is specified,
1404 this will print to the FILE. Else it will print
Lee Thomason4cd85342012-06-04 17:02:37 -07001405 to memory, and the result is available in CStr().
1406 If 'compact' is set to true, then output is created
1407 with only required whitespace and newlines.
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001408 */
sniperbat25900882012-05-28 17:22:07 +08001409 XMLPrinter( FILE* file=0, bool compact = false );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001410 ~XMLPrinter() {}
1411
1412 /** If streaming, write the BOM and declaration. */
1413 void PushHeader( bool writeBOM, bool writeDeclaration );
1414 /** If streaming, start writing an element.
1415 The element must be closed with CloseElement()
1416 */
1417 void OpenElement( const char* name );
1418 /// If streaming, add an attribute to an open element.
1419 void PushAttribute( const char* name, const char* value );
1420 void PushAttribute( const char* name, int value );
1421 void PushAttribute( const char* name, unsigned value );
1422 void PushAttribute( const char* name, bool value );
1423 void PushAttribute( const char* name, double value );
1424 /// If streaming, close the Element.
1425 void CloseElement();
1426
1427 /// Add a text node.
1428 void PushText( const char* text, bool cdata=false );
Lee Thomason21be8822012-07-15 17:27:22 -07001429 /// Add a text node from an integer.
1430 void PushText( int value );
1431 /// Add a text node from an unsigned.
1432 void PushText( unsigned value );
1433 /// Add a text node from a bool.
1434 void PushText( bool value );
1435 /// Add a text node from a float.
1436 void PushText( float value );
1437 /// Add a text node from a double.
1438 void PushText( double value );
1439
1440 /// Add a comment
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001441 void PushComment( const char* comment );
1442
1443 void PushDeclaration( const char* value );
1444 void PushUnknown( const char* value );
1445
1446 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
1447 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1448
1449 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1450 virtual bool VisitExit( const XMLElement& element );
1451
1452 virtual bool Visit( const XMLText& text );
1453 virtual bool Visit( const XMLComment& comment );
1454 virtual bool Visit( const XMLDeclaration& declaration );
1455 virtual bool Visit( const XMLUnknown& unknown );
1456
1457 /**
1458 If in print to memory mode, return a pointer to
1459 the XML file in memory.
1460 */
1461 const char* CStr() const { return buffer.Mem(); }
sniperbate01e7862012-05-21 12:45:36 +08001462 /**
Lee Thomason (grinliz)48ea0bc2012-05-26 14:41:14 -07001463 If in print to memory mode, return the size
1464 of the XML file in memory. (Note the size returned
1465 includes the terminating null.)
sniperbate01e7862012-05-21 12:45:36 +08001466 */
Lee Thomasonc78dc012012-06-12 13:12:15 -07001467 int CStrSize() const { return buffer.Size(); }
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001468
1469private:
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001470 void SealElement();
1471 void PrintSpace( int depth );
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001472 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
1473 void Print( const char* format, ... );
1474
1475 bool elementJustOpened;
1476 bool firstElement;
1477 FILE* fp;
1478 int depth;
1479 int textDepth;
1480 bool processEntities;
sniperbat25900882012-05-28 17:22:07 +08001481 bool compactMode;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001482
1483 enum {
1484 ENTITY_RANGE = 64,
1485 BUF_SIZE = 200
1486 };
1487 bool entityFlag[ENTITY_RANGE];
1488 bool restrictedEntityFlag[ENTITY_RANGE];
1489
1490 DynArray< const char*, 10 > stack;
PKEuSe736f292012-07-16 03:27:55 -07001491 DynArray< char, 20 > buffer;
1492#ifdef _MSC_VER
1493 DynArray< char, 20 > accumulator;
1494#endif
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001495};
1496
1497
Guillermo A. Amaralb42ba362012-03-20 00:15:30 -07001498} // tinyxml2
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001499
1500
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001501#endif // TINYXML2_INCLUDED