blob: ac89e36a18825b9f63a26b6b01628a72ee9573a5 [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 Thomason2c85a712012-01-31 08:24:24 -080027
U-Lama\Lee4cee6112011-12-31 14:58:18 -080028#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -080029#include <ctype.h>
30#include <stdio.h>
Lee Thomason2c85a712012-01-31 08:24:24 -080031#include <memory.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -080032
Lee Thomason7d00b9a2012-02-27 17:54:22 -080033/*
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080034 TODO: add 'lastAttribute' for faster parsing.
Lee Thomason7d00b9a2012-02-27 17:54:22 -080035 TODO: intern strings instead of allocation.
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080036*/
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -080037/*
38 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
39*/
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080040
U-Lama\Lee4cee6112011-12-31 14:58:18 -080041#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
42 #ifndef DEBUG
43 #define DEBUG
44 #endif
45#endif
46
47
48#if defined(DEBUG)
49 #if defined(_MSC_VER)
50 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
51 #elif defined (ANDROID_NDK)
52 #include <android/log.h>
53 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
54 #else
55 #include <assert.h>
56 #define TIXMLASSERT assert
57 #endif
58#else
59 #define TIXMLASSERT( x ) {}
60#endif
61
U-Lama\Leee13c3e62011-12-28 14:36:55 -080062
Lee Thomason1a1d4a72012-02-15 09:09:25 -080063// Deprecated library function hell. Compilers want to use the
64// new safe versions. This probably doesn't fully address the problem,
65// but it gets closer. There are too many compilers for me to fully
66// test. If you get compilation troubles, undefine TIXML_SAFE
67
68#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
69 // Microsoft visual studio, version 2005 and higher.
70 #define TIXML_SNPRINTF _snprintf_s
71 #define TIXML_SSCANF sscanf_s
72#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
73 // Microsoft visual studio, version 6 and higher.
74 //#pragma message( "Using _sn* functions." )
75 #define TIXML_SNPRINTF _snprintf
76 #define TIXML_SSCANF sscanf
77#elif defined(__GNUC__) && (__GNUC__ >= 3 )
U-Stream\Leeae25a442012-02-17 17:48:16 -080078 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080079 //#warning( "Using sn* functions." )
80 #define TIXML_SNPRINTF snprintf
81 #define TIXML_SSCANF sscanf
82#else
83 #define TIXML_SNPRINTF snprintf
84 #define TIXML_SSCANF sscanf
85#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080086
87
U-Lama\Leee13c3e62011-12-28 14:36:55 -080088namespace tinyxml2
89{
Lee Thomasonce0763e2012-01-11 15:43:54 -080090class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080091class XMLElement;
92class XMLAttribute;
93class XMLComment;
94class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080095class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080096class XMLDeclaration;
97class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080098
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -080099class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800100
U-Stream\Leeae25a442012-02-17 17:48:16 -0800101/*
102 A class that wraps strings. Normally stores the start and end
103 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800104 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800105 manage) a traditional char[]
106*/
Lee Thomason39ede242012-01-20 11:27:56 -0800107class StrPair
108{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800109public:
Lee Thomason39ede242012-01-20 11:27:56 -0800110 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800111 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800112 NEEDS_NEWLINE_NORMALIZATION = 0x02,
113
114 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
115 ATTRIBUTE_NAME = 0,
116 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
117 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -0800118 };
119
120 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800121 ~StrPair();
122
Lee Thomasone4422302012-01-20 17:59:50 -0800123 void Set( char* start, char* end, int flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800124 Reset();
Lee Thomason39ede242012-01-20 11:27:56 -0800125 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
126 }
127 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800128 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800129
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800130 void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; }
131 void SetStr( const char* str, int flags=0 );
132
Lee Thomason56bdd022012-02-09 18:16:58 -0800133 char* ParseText( char* in, const char* endTag, int strFlags );
134 char* ParseName( char* in );
135
Lee Thomason2c85a712012-01-31 08:24:24 -0800136
Lee Thomason39ede242012-01-20 11:27:56 -0800137private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800138 void Reset();
139
Lee Thomasone4422302012-01-20 17:59:50 -0800140 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800141 NEEDS_FLUSH = 0x100,
142 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800143 };
144
Lee Thomason39ede242012-01-20 11:27:56 -0800145 // After parsing, if *end != 0, it can be set to zero.
146 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800147 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800148 char* end;
149};
150
U-Lama\Lee560bd472011-12-28 19:42:49 -0800151
U-Stream\Leeae25a442012-02-17 17:48:16 -0800152/*
153 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
154 Has a small initial memory pool, so that low or no usage will not
155 cause a call to new/delete
156*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800157template <class T, int INIT>
158class DynArray
159{
160public:
161 DynArray< T, INIT >()
162 {
163 mem = pool;
164 allocated = INIT;
165 size = 0;
166 }
167 ~DynArray()
168 {
169 if ( mem != pool ) {
170 delete mem;
171 }
172 }
173 void Push( T t )
174 {
175 EnsureCapacity( size+1 );
176 mem[size++] = t;
177 }
178
179 T* PushArr( int count )
180 {
181 EnsureCapacity( size+count );
182 T* ret = &mem[size];
183 size += count;
184 return ret;
185 }
186 T Pop() {
187 return mem[--size];
188 }
189 void PopArr( int count )
190 {
191 TIXMLASSERT( size >= count );
192 size -= count;
193 }
194
U-Stream\Leeae25a442012-02-17 17:48:16 -0800195 bool Empty() const { return size == 0; }
196 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
197 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
198 int Size() const { return size; }
199 int Capacity() const { return allocated; }
200 const T* Mem() const { return mem; }
201 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800202
203
204private:
205 void EnsureCapacity( int cap ) {
206 if ( cap > allocated ) {
207 int newAllocated = cap * 2;
208 T* newMem = new T[newAllocated];
209 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
210 if ( mem != pool ) delete [] mem;
211 mem = newMem;
212 allocated = newAllocated;
213 }
214 }
215
216 T* mem;
217 T pool[INIT];
218 int allocated; // objects allocated
219 int size; // number objects in use
220};
221
Lee Thomason50adb4c2012-02-13 15:07:09 -0800222
U-Stream\Leeae25a442012-02-17 17:48:16 -0800223/*
224 Parent virtual class a a pool for fast allocation
225 and deallocation of objects.
226*/
Lee Thomasond1983222012-02-06 08:41:24 -0800227class MemPool
228{
229public:
230 MemPool() {}
231 virtual ~MemPool() {}
232
233 virtual int ItemSize() const = 0;
234 virtual void* Alloc() = 0;
235 virtual void Free( void* ) = 0;
236};
237
Lee Thomason50adb4c2012-02-13 15:07:09 -0800238
U-Stream\Leeae25a442012-02-17 17:48:16 -0800239/*
240 Template child class to create pools of the correct type.
241*/
Lee Thomasond1983222012-02-06 08:41:24 -0800242template< int SIZE >
243class MemPoolT : public MemPool
244{
245public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800246 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800247 ~MemPoolT() {
248 // Delete the blocks.
249 for( int i=0; i<blockPtrs.Size(); ++i ) {
250 delete blockPtrs[i];
251 }
252 }
253
254 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800255 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800256
257 virtual void* Alloc() {
258 if ( !root ) {
259 // Need a new block.
260 Block* block = new Block();
261 blockPtrs.Push( block );
262
263 for( int i=0; i<COUNT-1; ++i ) {
264 block->chunk[i].next = &block->chunk[i+1];
265 }
266 block->chunk[COUNT-1].next = 0;
267 root = block->chunk;
268 }
269 void* result = root;
270 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800271
272 ++currentAllocs;
273 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
274 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800275 return result;
276 }
277 virtual void Free( void* mem ) {
278 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800279 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800280 Chunk* chunk = (Chunk*)mem;
281 memset( chunk, 0xfe, sizeof(Chunk) );
282 chunk->next = root;
283 root = chunk;
284 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800285 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800286 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
287 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800288 }
Lee Thomasond1983222012-02-06 08:41:24 -0800289
290private:
291 enum { COUNT = 1024/SIZE };
292 union Chunk {
293 Chunk* next;
294 char mem[SIZE];
295 };
296 struct Block {
297 Chunk chunk[COUNT];
298 };
299 DynArray< Block*, 10 > blockPtrs;
300 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800301
302 int currentAllocs;
303 int nAllocs;
304 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800305};
306
Lee Thomason2c85a712012-01-31 08:24:24 -0800307
Lee Thomason56bdd022012-02-09 18:16:58 -0800308
309/**
310 Implements the interface to the "Visitor pattern" (see the Accept() method.)
311 If you call the Accept() method, it requires being passed a XMLVisitor
312 class to handle callbacks. For nodes that contain other nodes (Document, Element)
313 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
314 are simply called with Visit().
315
316 If you return 'true' from a Visit method, recursive parsing will continue. If you return
317 false, <b>no children of this node or its sibilings</b> will be Visited.
318
319 All flavors of Visit methods have a default implementation that returns 'true' (continue
320 visiting). You need to only override methods that are interesting to you.
321
322 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
323
324 You should never change the document from a callback.
325
326 @sa XMLNode::Accept()
327*/
328class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800329{
330public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800331 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800332
Lee Thomason56bdd022012-02-09 18:16:58 -0800333 /// Visit a document.
334 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
335 /// Visit a document.
336 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
337
338 /// Visit an element.
339 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
340 /// Visit an element.
341 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
342
343 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800344 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800345 /// Visit a text node
346 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
347 /// Visit a comment node
348 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
349 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800350 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800351};
352
353
U-Stream\Leeae25a442012-02-17 17:48:16 -0800354/*
355 Utility functionality.
356*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800357class XMLUtil
358{
Lee Thomasond1983222012-02-06 08:41:24 -0800359public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800360 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
361 // correct, but simple, and usually works.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800362 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
363 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800364
365 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
366 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800367 if ( p == q ) {
368 return true;
369 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800370 while( *p && *q && *p == *q && n<nChar ) {
371 ++p; ++q; ++n;
372 }
373 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
374 return true;
375 }
376 return false;
377 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800378 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800379 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
380 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800381
382 static const char* ReadBOM( const char* p, bool* hasBOM );
383 // p is the starting location,
384 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800385 static const char* GetCharacterRef( const char* p, char* value, int* length );
386 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800387};
388
Lee Thomason5cae8972012-01-24 18:03:07 -0800389
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800390/** XMLNode is a base class for every object that is in the
391 XML Document Object Model (DOM), except XMLAttributes.
392 Nodes have siblings, a parent, and children which can
393 be navigated. A node is always in a XMLDocument.
394 The type of a TiXmlNode can be queried, and it can
395 be cast to its more defined type.
396
397 An XMLDocument allocates memory for all its Nodes.
398 When the XMLDocument gets deleted, all its Nodes
399 will also be deleted.
400
401 @verbatim
402 A Document can contain: Element (container or leaf)
403 Comment (leaf)
404 Unknown (leaf)
405 Declaration( leaf )
406
407 An Element can contain: Element (container or leaf)
408 Text (leaf)
409 Attributes (not on tree)
410 Comment (leaf)
411 Unknown (leaf)
412
413 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800414*/
Lee Thomasond1983222012-02-06 08:41:24 -0800415class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800416{
417 friend class XMLDocument;
418 friend class XMLElement;
419public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800420
421 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800422 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800423 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800424 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800425
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800426 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
427 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
428 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
429 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
430 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
431 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800432
Lee Thomason50f97b22012-02-11 16:33:40 -0800433 virtual const XMLElement* ToElement() const { return 0; }
434 virtual const XMLText* ToText() const { return 0; }
435 virtual const XMLComment* ToComment() const { return 0; }
436 virtual const XMLDocument* ToDocument() const { return 0; }
437 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
438 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800439
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800440 /** The meaning of 'value' changes for the specific type.
441 @verbatim
442 Document: empy
443 Element: name of the element
444 Comment: the comment text
445 Unknown: the tag contents
446 Text: the text string
447 @endverbatim
448 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800449 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800450 /** Set the Value of an XML node.
451 @sa Value()
452 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800453 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800454
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800455 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800456 const XMLNode* Parent() const { return parent; }
457 XMLNode* Parent() { return parent; }
458
Lee Thomason50f97b22012-02-11 16:33:40 -0800459 /// Returns true if this node has no children.
460 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800461
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800462 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800463 const XMLNode* FirstChild() const { return firstChild; }
464 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800465 /** Get the first child element, or optionally the first child
466 element with the specified name.
467 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800468 const XMLElement* FirstChildElement( const char* value=0 ) const;
469 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800470
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800471 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800472 const XMLNode* LastChild() const { return lastChild; }
473 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800474
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800475 /** Get the last child element or optionally the last child
476 element with the specified name.
477 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800478 const XMLElement* LastChildElement( const char* value=0 ) const;
479 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
480
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800481 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800482 const XMLNode* PreviousSibling() const { return prev; }
483 XMLNode* PreviousSibling() { return prev; }
484
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800485 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800486 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
487 XMLElement* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800488
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800489 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800490 const XMLNode* NextSibling() const { return next; }
491 XMLNode* NextSibling() { return next; }
492
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800493 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800494 const XMLElement* NextSiblingElement( const char* value=0 ) const;
495 XMLElement* NextSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800496
Lee Thomason1ff38e02012-02-14 18:18:16 -0800497 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800498 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800499 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800500 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800501
502 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800503 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800504 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800505 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800506 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800507 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800508 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800509 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800510 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
511
U-Stream\Leeae25a442012-02-17 17:48:16 -0800512 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800513 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800514 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800515 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800516
517 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800518 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800519 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800520 void DeleteChild( XMLNode* node );
521
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800522 /**
523 Make a copy of this node, but not its children.
524 You may pass in a Document pointer that will be
525 the owner of the new Node. If the 'document' is
526 null, then the node returned will be allocated
527 from the current Document. (this->GetDocument())
528
529 Note: if called on a XMLDocument, this will return null.
530 */
531 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
532
533 /**
534 Test if 2 nodes are the same, but don't test children.
535 The 2 nodes do not need to be in the same Document.
536
537 Note: if called on a XMLDocument, this will return false.
538 */
539 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
540
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800541 /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
542 XML tree will be conditionally visited and the host will be called back
543 via the TiXmlVisitor interface.
544
545 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
546 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
547 interface versus any other.)
548
549 The interface has been based on ideas from:
550
551 - http://www.saxproject.org/
552 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
553
554 Which are both good references for "visiting".
555
556 An example of using Accept():
557 @verbatim
558 TiXmlPrinter printer;
559 tinyxmlDoc.Accept( &printer );
560 const char* xmlcstr = printer.CStr();
561 @endverbatim
562 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800563 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800564
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800565 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800566 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800567
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800568protected:
569 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800570 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800571 XMLNode( const XMLNode& ); // not supported
572 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800573
Lee Thomason3f57d272012-01-11 15:30:03 -0800574 XMLDocument* document;
575 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800576 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800577
578 XMLNode* firstChild;
579 XMLNode* lastChild;
580
581 XMLNode* prev;
582 XMLNode* next;
583
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800584private:
Lee Thomasond1983222012-02-06 08:41:24 -0800585 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800586 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800587};
588
589
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800590/** XML text.
591
592 Note that a text node can have child element nodes, for example:
593 @verbatim
594 <root>This is <b>bold</b></root>
595 @endverbatim
596
597 A text node can have 2 ways to output the next. "normal" output
598 and CDATA. It will default to the mode it was parsed from the XML file and
599 you generally want to leave it alone, but you can change the output mode with
600 SetCDATA() and query it with CDATA().
601*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800602class XMLText : public XMLNode
603{
Lee Thomason2c85a712012-01-31 08:24:24 -0800604 friend class XMLBase;
605 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800606public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800607 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800608
Lee Thomason751da522012-02-10 08:50:51 -0800609 virtual XMLText* ToText() { return this; }
610 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800611
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800612 /// Declare whether this should be CDATA or standard text.
613 void SetCData( bool isCData ) { this->isCData = isCData; }
614 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800615 bool CData() const { return isCData; }
616
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800617 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800618 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
619 virtual bool ShallowEqual( const XMLNode* compare ) const;
620
Lee Thomason5492a1c2012-01-23 15:32:10 -0800621
622protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800623 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
624 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800625 XMLText( const XMLText& ); // not supported
626 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800627
628private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800629 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800630};
631
632
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800633/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800634class XMLComment : public XMLNode
635{
Lee Thomason2c85a712012-01-31 08:24:24 -0800636 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800637public:
Lee Thomason751da522012-02-10 08:50:51 -0800638 virtual XMLComment* ToComment() { return this; }
639 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800640
Lee Thomason56bdd022012-02-09 18:16:58 -0800641 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800642
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800643 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800644 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
645 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800646
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800647protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800648 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800649 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800650 XMLComment( const XMLComment& ); // not supported
651 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800652
Lee Thomason3f57d272012-01-11 15:30:03 -0800653private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800654};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800655
656
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800657/** In correct XML the declaration is the first entry in the file.
658 @verbatim
659 <?xml version="1.0" standalone="yes"?>
660 @endverbatim
661
662 TinyXML2 will happily read or write files without a declaration,
663 however.
664
665 The text of the declaration isn't interpreted. It is parsed
666 and written as a string.
667*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800668class XMLDeclaration : public XMLNode
669{
670 friend class XMLDocument;
671public:
672 virtual XMLDeclaration* ToDeclaration() { return this; }
673 virtual const XMLDeclaration* ToDeclaration() const { return this; }
674
675 virtual bool Accept( XMLVisitor* visitor ) const;
676
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800677 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800678 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
679 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800680
681protected:
682 XMLDeclaration( XMLDocument* doc );
683 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800684 XMLDeclaration( const XMLDeclaration& ); // not supported
685 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800686};
687
688
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800689/** Any tag that tinyXml doesn't recognize is saved as an
690 unknown. It is a tag of text, but should not be modified.
691 It will be written back to the XML, unchanged, when the file
692 is saved.
693
694 DTD tags get thrown into TiXmlUnknowns.
695*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800696class XMLUnknown : public XMLNode
697{
698 friend class XMLDocument;
699public:
700 virtual XMLUnknown* ToUnknown() { return this; }
701 virtual const XMLUnknown* ToUnknown() const { return this; }
702
703 virtual bool Accept( XMLVisitor* visitor ) const;
704
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800705 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800706 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
707 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800708
709protected:
710 XMLUnknown( XMLDocument* doc );
711 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800712 XMLUnknown( const XMLUnknown& ); // not supported
713 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800714};
715
716
Lee Thomason1ff38e02012-02-14 18:18:16 -0800717enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800718 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800719 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800720
Lee Thomason1ff38e02012-02-14 18:18:16 -0800721 NO_ATTRIBUTE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800722 WRONG_ATTRIBUTE_TYPE,
723
724 ERROR_FILE_NOT_FOUND,
725 ERROR_ELEMENT_MISMATCH,
726 ERROR_PARSING_ELEMENT,
727 ERROR_PARSING_ATTRIBUTE,
728 ERROR_IDENTIFYING_TAG,
729 ERROR_PARSING_TEXT,
730 ERROR_PARSING_CDATA,
731 ERROR_PARSING_COMMENT,
732 ERROR_PARSING_DECLARATION,
Lee Thomasond6277762012-02-22 16:00:12 -0800733 ERROR_PARSING_UNKNOWN,
734 ERROR_EMPTY_DOCUMENT,
Lee Thomason (grinliz)784607f2012-02-24 16:23:40 -0800735 ERROR_MISMATCHED_ELEMENT,
736 ERROR_PARSING
Lee Thomason1ff38e02012-02-14 18:18:16 -0800737};
738
739
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800740/** An attribute is a name-value pair. Elements have an arbitrary
741 number of attributes, each with a unique name.
742
743 @note The attributes are not XMLNodes. You may only query the
744 Next() attribute in a list.
745*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800746class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800747{
748 friend class XMLElement;
749public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800750 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
751 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
752 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800753
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800754 /** IntAttribute interprets the attribute as an integer, and returns the value.
755 If the value isn't an integer, 0 will be returned. There is no error checking;
756 use QueryIntAttribute() if you need error checking.
757 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800758 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800759 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800760 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800761 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800762 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800763 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800764 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800765 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800766 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800767
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800768 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
769 in the provided paremeter. The function will return XML_NO_ERROR on success,
770 and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
771 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800772 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800773 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800774 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800775 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800776 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800777 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800778 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800779 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800780 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800781
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800782 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800783 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800784 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800785 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800786 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800787 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800788 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800789 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800790 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800791 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800792 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800793 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800794
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800795private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800796 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800797
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800798 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800799 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800800 XMLAttribute( const XMLAttribute& ); // not supported
801 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800802 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800803
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800804 char* ParseDeep( char* p );
805
Lee Thomason751da522012-02-10 08:50:51 -0800806 mutable StrPair name;
807 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800808 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800809 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800810};
811
812
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800813/** The element is a container class. It has a value, the element name,
814 and can contain other elements, text, comments, and unknowns.
815 Elements also contain an arbitrary number of attributes.
816*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800817class XMLElement : public XMLNode
818{
Lee Thomason2c85a712012-01-31 08:24:24 -0800819 friend class XMLBase;
820 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800821public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800822 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800823 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800824 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800825 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800826
Lee Thomason751da522012-02-10 08:50:51 -0800827 virtual XMLElement* ToElement() { return this; }
828 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800829 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800830
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800831 /** Given an attribute name, Attribute() returns the value
832 for the attribute of that name, or null if none exists.
833 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800834 const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); }
Lee Thomason751da522012-02-10 08:50:51 -0800835
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800836 /** Given an attribute name, IntAttribute() returns the value
837 of the attribute interpreted as an integer. 0 will be
838 returned if there is an error. For a method with error
839 checking, see QueryIntAttribute()
840 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800841 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800842 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800843 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800844 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800845 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800846 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800847 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800848 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800849 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
850
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800851 /** Given an attribute name, QueryIntAttribute() returns
852 XML_NO_ERROR, WRONG_ATTRIBUTE_TYPE if the conversion
853 can't be performed, or NO_ATTRIBUTE if the attribute
854 doesn't exist. If successful, the result of the conversion
855 will be written to 'value'. If not successful, nothing will
856 be written to 'value'. This allows you to provide default
857 value:
858
859 @verbatim
860 int value = 10;
861 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
862 @endverbatim
863 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800864 int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800865 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800866 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800867 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800868 int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800869 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800870 int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleValue( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800871 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800872 int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatValue( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800873
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800874 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800875 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800876 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800877 void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800878 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800879 void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800880 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800881 void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800882 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800883 void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800884
U-Stream\Leeae25a442012-02-17 17:48:16 -0800885 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800886 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800887 */
888 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800889
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800890 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800891 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800892 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800893 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800894
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800895 /** Convenience function for easy access to the text inside an element. Although easy
896 and concise, GetText() is limited compared to getting the TiXmlText child
897 and accessing it directly.
898
899 If the first child of 'this' is a TiXmlText, the GetText()
900 returns the character string of the Text node, else null is returned.
901
902 This is a convenient method for getting the text of simple contained text:
903 @verbatim
904 <foo>This is text</foo>
905 const char* str = fooElement->GetText();
906 @endverbatim
907
908 'str' will be a pointer to "This is text".
909
910 Note that this function can be misleading. If the element foo was created from
911 this XML:
912 @verbatim
913 <foo><b>This is text</b></foo>
914 @endverbatim
915
916 then the value of str would be null. The first child node isn't a text node, it is
917 another element. From this XML:
918 @verbatim
919 <foo>This is <b>text</b></foo>
920 @endverbatim
921 GetText() will return "This is ".
922 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800923 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800924
Lee Thomason2c85a712012-01-31 08:24:24 -0800925 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800926 enum {
927 OPEN, // <foo>
928 CLOSED, // <foo/>
929 CLOSING // </foo>
930 };
931 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800932 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800933 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
934 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800935
Lee Thomason50adb4c2012-02-13 15:07:09 -0800936private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800937 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800938 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800939 XMLElement( const XMLElement& ); // not supported
940 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800941
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800942 XMLAttribute* FindAttribute( const char* name );
943 XMLAttribute* FindOrCreateAttribute( const char* name );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800944 void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800945 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -0800946
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800947 int closingType;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800948 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800949};
950
951
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800952/** A document binds together all the functionality.
953 It can be saved, loaded, and printed to the screen.
954 All Nodes are connected and allocated to a Document.
955 If the Document is deleted, all its Nodes are also deleted.
956*/
Lee Thomason67d61312012-01-24 16:01:51 -0800957class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800958{
Lee Thomasond1983222012-02-06 08:41:24 -0800959 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800960public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800961 /// constructor
Lee Thomason18d68bd2012-01-26 18:17:26 -0800962 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800963 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800964
Lee Thomason751da522012-02-10 08:50:51 -0800965 virtual XMLDocument* ToDocument() { return this; }
966 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800967
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800968 /**
969 Parse an XML file from a character string.
970 Returns XML_NO_ERROR (0) on success, or
971 an errorID.
972 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800973 int Parse( const char* xml );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800974 /**
975 Load an XML file from disk.
976 Returns XML_NO_ERROR (0) on success, or
977 an errorID.
978 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800979 int LoadFile( const char* filename );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800980 /**
981 Load an XML file from disk. You are responsible
982 for providing and closing the FILE*.
983
984 Returns XML_NO_ERROR (0) on success, or
985 an errorID.
986 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800987 int LoadFile( FILE* );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800988 /**
989 Save the XML file to disk.
990 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800991 void SaveFile( const char* filename );
992
993 bool HasBOM() const { return writeBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800994
995 /** Return the root element of DOM. Equivalent to FirstChildElement().
996 To get the first node, use FirstChild().
997 */
Lee Thomasond6277762012-02-22 16:00:12 -0800998 XMLElement* RootElement() { return FirstChildElement(); }
999 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001000
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001001 /** Print the Document. If the Printer is not provided, it will
1002 print to stdout. If you provide Printer, this can print to a file:
1003 @verbatim
1004 XMLPrinter printer( fp );
1005 doc.Print( &printer );
1006 @endverbatim
1007
1008 Or you can use a printer to print to memory:
1009 @verbatim
1010 XMLPrinter printer;
1011 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001012 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001013 @endverbatim
1014 */
1015 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001016 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001017
Lee Thomason1ff38e02012-02-14 18:18:16 -08001018 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001019 Create a new Element associated with
1020 this Document. The memory for the Element
1021 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001022 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001023 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001024 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001025 Create a new Comment associated with
1026 this Document. The memory for the Comment
1027 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001028 */
1029 XMLComment* NewComment( const char* comment );
1030 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001031 Create a new Text associated with
1032 this Document. The memory for the Text
1033 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001034 */
1035 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001036 /**
1037 Create a new Declaration associated with
1038 this Document. The memory for the object
1039 is managed by the Document.
1040 */
1041 XMLDeclaration* NewDeclaration( const char* text );
1042 /**
1043 Create a new Unknown associated with
1044 this Document. The memory for the object
1045 is managed by the Document.
1046 */
1047 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001048
U-Stream\Leeae25a442012-02-17 17:48:16 -08001049 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001050 Delete a node associated with this documented.
1051 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001052 */
1053 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1054
Lee Thomason67d61312012-01-24 16:01:51 -08001055 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001056
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001057 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001058 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001059 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001060 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001061 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001062 const char* GetErrorStr1() const { return errorStr1; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001063 /// Return possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001064 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001065 /// If there is an error, print it to stdout
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001066 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001067
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001068 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001069 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001070
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001071 virtual XMLNode* ShallowClone( XMLDocument* document ) const { return 0; }
1072 virtual bool ShallowEqual( const XMLNode* compare ) const { return false; }
1073
Lee Thomason3f57d272012-01-11 15:30:03 -08001074private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001075 XMLDocument( const XMLDocument& ); // not supported
1076 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001077 void InitDocument();
1078
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001079 bool writeBOM;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001080 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001081 const char* errorStr1;
1082 const char* errorStr2;
1083 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001084
1085 MemPoolT< sizeof(XMLElement) > elementPool;
1086 MemPoolT< sizeof(XMLAttribute) > attributePool;
1087 MemPoolT< sizeof(XMLText) > textPool;
1088 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001089};
1090
Lee Thomason7c913cd2012-01-26 18:32:34 -08001091
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001092
1093/**
1094 Printing functionality. The XMLPrinter gives you more
1095 options than the XMLDocument::Print() method.
1096
1097 It can:
1098 -# Print to memory.
1099 -# Print to a file you provide
1100 -# Print XML without a XMLDocument.
1101
1102 Print to Memory
1103
1104 @verbatim
1105 XMLPrinter printer;
1106 doc->Print( &printer );
1107 SomeFunctior( printer.CStr() );
1108 @endverbatim
1109
1110 Print to a File
1111
1112 You provide the file pointer.
1113 @verbatim
1114 XMLPrinter printer( fp );
1115 doc.Print( &printer );
1116 @endverbatim
1117
1118 Print without a XMLDocument
1119
1120 When loading, an XML parser is very useful. However, sometimes
1121 when saving, it just gets in the way. The code is often set up
1122 for streaming, and constructing the DOM is just overhead.
1123
1124 The Printer supports the streaming case. The following code
1125 prints out a trivially simple XML file without ever creating
1126 an XML document.
1127
1128 @verbatim
1129 XMLPrinter printer( fp );
1130 printer.OpenElement( "foo" );
1131 printer.PushAttribute( "foo", "bar" );
1132 printer.CloseElement();
1133 @endverbatim
1134*/
1135class XMLPrinter : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -08001136{
1137public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001138 /** Construct the printer. If the FILE* is specified,
1139 this will print to the FILE. Else it will print
1140 to memory, and the result is available in CStr()
1141 */
1142 XMLPrinter( FILE* file=0 );
1143 ~XMLPrinter() {}
Lee Thomason5cae8972012-01-24 18:03:07 -08001144
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001145 /** If streaming, write the BOM and declaration. */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001146 void PushHeader( bool writeBOM, bool writeDeclaration );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001147 /** If streaming, start writing an element.
1148 The element must be closed with CloseElement()
1149 */
Lee Thomason56bdd022012-02-09 18:16:58 -08001150 void OpenElement( const char* name );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001151 /// If streaming, add an attribute to an open element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001152 void PushAttribute( const char* name, const char* value );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001153 void PushAttribute( const char* name, int value );
1154 void PushAttribute( const char* name, unsigned value );
1155 void PushAttribute( const char* name, bool value );
1156 void PushAttribute( const char* name, double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001157 /// If streaming, close the Element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001158 void CloseElement();
1159
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001160 /// Add a text node.
Lee Thomason50f97b22012-02-11 16:33:40 -08001161 void PushText( const char* text, bool cdata=false );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001162 /// Add a comment
Lee Thomason5cae8972012-01-24 18:03:07 -08001163 void PushComment( const char* comment );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001164
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001165 void PushDeclaration( const char* value );
1166 void PushUnknown( const char* value );
Lee Thomason5cae8972012-01-24 18:03:07 -08001167
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001168 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
Lee Thomason751da522012-02-10 08:50:51 -08001169 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1170
1171 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1172 virtual bool VisitExit( const XMLElement& element );
1173
1174 virtual bool Visit( const XMLText& text );
1175 virtual bool Visit( const XMLComment& comment );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001176 virtual bool Visit( const XMLDeclaration& declaration );
1177 virtual bool Visit( const XMLUnknown& unknown );
Lee Thomason751da522012-02-10 08:50:51 -08001178
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001179 /**
1180 If in print to memory mode, return a pointer to
1181 the XML file in memory.
1182 */
U-Stream\Leeae25a442012-02-17 17:48:16 -08001183 const char* CStr() const { return buffer.Mem(); }
Lee Thomason751da522012-02-10 08:50:51 -08001184
Lee Thomason5cae8972012-01-24 18:03:07 -08001185private:
1186 void SealElement();
1187 void PrintSpace( int depth );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001188 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001189 void Print( const char* format, ... );
Lee Thomason5cae8972012-01-24 18:03:07 -08001190
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001191 bool elementJustOpened;
1192 bool firstElement;
Lee Thomason5cae8972012-01-24 18:03:07 -08001193 FILE* fp;
1194 int depth;
Lee Thomason56bdd022012-02-09 18:16:58 -08001195 int textDepth;
1196
Lee Thomason857b8682012-01-25 17:50:25 -08001197 enum {
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001198 ENTITY_RANGE = 64,
1199 BUF_SIZE = 200
Lee Thomason857b8682012-01-25 17:50:25 -08001200 };
1201 bool entityFlag[ENTITY_RANGE];
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001202 bool restrictedEntityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -08001203
Lee Thomason2c85a712012-01-31 08:24:24 -08001204 DynArray< const char*, 10 > stack;
U-Stream\Leeae25a442012-02-17 17:48:16 -08001205 DynArray< char, 20 > buffer, accumulator;
Lee Thomason5cae8972012-01-24 18:03:07 -08001206};
1207
1208
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001209}; // tinyxml2
1210
U-Lama\Lee560bd472011-12-28 19:42:49 -08001211
1212
U-Stream\Leeae25a442012-02-17 17:48:16 -08001213#endif // TINYXML2_INCLUDED