blob: d1ae0d7da71d143f7b9421946328ef7582eddf33 [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
Lee Thomason27057312012-03-02 09:04:53 -080087static const int TIXML2_MAJOR_VERSION = 0;
88static const int TIXML2_MINOR_VERSION = 9;
89static const int TIXML2_PATCH_VERSION = 0;
Lee Thomason1ff38e02012-02-14 18:18:16 -080090
U-Lama\Leee13c3e62011-12-28 14:36:55 -080091namespace tinyxml2
92{
Lee Thomasonce0763e2012-01-11 15:43:54 -080093class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080094class XMLElement;
95class XMLAttribute;
96class XMLComment;
97class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080098class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080099class XMLDeclaration;
100class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800101
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800102class XMLPrinter;
Lee Thomason5cae8972012-01-24 18:03:07 -0800103
U-Stream\Leeae25a442012-02-17 17:48:16 -0800104/*
105 A class that wraps strings. Normally stores the start and end
106 pointers into the XML file itself, and will apply normalization
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800107 and entity translation if actually read. Can also store (and memory
U-Stream\Leeae25a442012-02-17 17:48:16 -0800108 manage) a traditional char[]
109*/
Lee Thomason39ede242012-01-20 11:27:56 -0800110class StrPair
111{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800112public:
Lee Thomason39ede242012-01-20 11:27:56 -0800113 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800114 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800115 NEEDS_NEWLINE_NORMALIZATION = 0x02,
116
117 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
118 ATTRIBUTE_NAME = 0,
119 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
120 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -0800121 };
122
123 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800124 ~StrPair();
125
Lee Thomasone4422302012-01-20 17:59:50 -0800126 void Set( char* start, char* end, int flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800127 Reset();
Lee Thomason39ede242012-01-20 11:27:56 -0800128 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
129 }
130 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800131 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800132
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800133 void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; }
134 void SetStr( const char* str, int flags=0 );
135
Lee Thomason56bdd022012-02-09 18:16:58 -0800136 char* ParseText( char* in, const char* endTag, int strFlags );
137 char* ParseName( char* in );
138
Lee Thomason2c85a712012-01-31 08:24:24 -0800139
Lee Thomason39ede242012-01-20 11:27:56 -0800140private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800141 void Reset();
142
Lee Thomasone4422302012-01-20 17:59:50 -0800143 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800144 NEEDS_FLUSH = 0x100,
145 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800146 };
147
Lee Thomason39ede242012-01-20 11:27:56 -0800148 // After parsing, if *end != 0, it can be set to zero.
149 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800150 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800151 char* end;
152};
153
U-Lama\Lee560bd472011-12-28 19:42:49 -0800154
U-Stream\Leeae25a442012-02-17 17:48:16 -0800155/*
156 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
157 Has a small initial memory pool, so that low or no usage will not
158 cause a call to new/delete
159*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800160template <class T, int INIT>
161class DynArray
162{
163public:
164 DynArray< T, INIT >()
165 {
166 mem = pool;
167 allocated = INIT;
168 size = 0;
169 }
170 ~DynArray()
171 {
172 if ( mem != pool ) {
173 delete mem;
174 }
175 }
176 void Push( T t )
177 {
178 EnsureCapacity( size+1 );
179 mem[size++] = t;
180 }
181
182 T* PushArr( int count )
183 {
184 EnsureCapacity( size+count );
185 T* ret = &mem[size];
186 size += count;
187 return ret;
188 }
189 T Pop() {
190 return mem[--size];
191 }
192 void PopArr( int count )
193 {
194 TIXMLASSERT( size >= count );
195 size -= count;
196 }
197
U-Stream\Leeae25a442012-02-17 17:48:16 -0800198 bool Empty() const { return size == 0; }
199 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
200 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
201 int Size() const { return size; }
202 int Capacity() const { return allocated; }
203 const T* Mem() const { return mem; }
204 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800205
206
207private:
208 void EnsureCapacity( int cap ) {
209 if ( cap > allocated ) {
210 int newAllocated = cap * 2;
211 T* newMem = new T[newAllocated];
212 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
213 if ( mem != pool ) delete [] mem;
214 mem = newMem;
215 allocated = newAllocated;
216 }
217 }
218
219 T* mem;
220 T pool[INIT];
221 int allocated; // objects allocated
222 int size; // number objects in use
223};
224
Lee Thomason50adb4c2012-02-13 15:07:09 -0800225
U-Stream\Leeae25a442012-02-17 17:48:16 -0800226/*
227 Parent virtual class a a pool for fast allocation
228 and deallocation of objects.
229*/
Lee Thomasond1983222012-02-06 08:41:24 -0800230class MemPool
231{
232public:
233 MemPool() {}
234 virtual ~MemPool() {}
235
236 virtual int ItemSize() const = 0;
237 virtual void* Alloc() = 0;
238 virtual void Free( void* ) = 0;
239};
240
Lee Thomason50adb4c2012-02-13 15:07:09 -0800241
U-Stream\Leeae25a442012-02-17 17:48:16 -0800242/*
243 Template child class to create pools of the correct type.
244*/
Lee Thomasond1983222012-02-06 08:41:24 -0800245template< int SIZE >
246class MemPoolT : public MemPool
247{
248public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800249 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800250 ~MemPoolT() {
251 // Delete the blocks.
252 for( int i=0; i<blockPtrs.Size(); ++i ) {
253 delete blockPtrs[i];
254 }
255 }
256
257 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800258 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800259
260 virtual void* Alloc() {
261 if ( !root ) {
262 // Need a new block.
263 Block* block = new Block();
264 blockPtrs.Push( block );
265
266 for( int i=0; i<COUNT-1; ++i ) {
267 block->chunk[i].next = &block->chunk[i+1];
268 }
269 block->chunk[COUNT-1].next = 0;
270 root = block->chunk;
271 }
272 void* result = root;
273 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800274
275 ++currentAllocs;
276 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
277 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800278 return result;
279 }
280 virtual void Free( void* mem ) {
281 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800282 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800283 Chunk* chunk = (Chunk*)mem;
284 memset( chunk, 0xfe, sizeof(Chunk) );
285 chunk->next = root;
286 root = chunk;
287 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800288 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800289 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
290 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800291 }
Lee Thomasond1983222012-02-06 08:41:24 -0800292
293private:
294 enum { COUNT = 1024/SIZE };
295 union Chunk {
296 Chunk* next;
297 char mem[SIZE];
298 };
299 struct Block {
300 Chunk chunk[COUNT];
301 };
302 DynArray< Block*, 10 > blockPtrs;
303 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800304
305 int currentAllocs;
306 int nAllocs;
307 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800308};
309
Lee Thomason2c85a712012-01-31 08:24:24 -0800310
Lee Thomason56bdd022012-02-09 18:16:58 -0800311
312/**
313 Implements the interface to the "Visitor pattern" (see the Accept() method.)
314 If you call the Accept() method, it requires being passed a XMLVisitor
315 class to handle callbacks. For nodes that contain other nodes (Document, Element)
316 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
317 are simply called with Visit().
318
319 If you return 'true' from a Visit method, recursive parsing will continue. If you return
320 false, <b>no children of this node or its sibilings</b> will be Visited.
321
322 All flavors of Visit methods have a default implementation that returns 'true' (continue
323 visiting). You need to only override methods that are interesting to you.
324
325 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
326
327 You should never change the document from a callback.
328
329 @sa XMLNode::Accept()
330*/
331class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800332{
333public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800334 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800335
Lee Thomason56bdd022012-02-09 18:16:58 -0800336 /// Visit a document.
337 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
338 /// Visit a document.
339 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
340
341 /// Visit an element.
342 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
343 /// Visit an element.
344 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
345
346 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800347 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800348 /// Visit a text node
349 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
350 /// Visit a comment node
351 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
352 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800353 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800354};
355
356
U-Stream\Leeae25a442012-02-17 17:48:16 -0800357/*
358 Utility functionality.
359*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800360class XMLUtil
361{
Lee Thomasond1983222012-02-06 08:41:24 -0800362public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800363 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
364 // correct, but simple, and usually works.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800365 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
366 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800367
368 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
369 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800370 if ( p == q ) {
371 return true;
372 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800373 while( *p && *q && *p == *q && n<nChar ) {
374 ++p; ++q; ++n;
375 }
376 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
377 return true;
378 }
379 return false;
380 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800381 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
383 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800384
385 static const char* ReadBOM( const char* p, bool* hasBOM );
386 // p is the starting location,
387 // the UTF-8 value of the entity will be placed in value, and length filled in.
Lee Thomasond6277762012-02-22 16:00:12 -0800388 static const char* GetCharacterRef( const char* p, char* value, int* length );
389 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800390};
391
Lee Thomason5cae8972012-01-24 18:03:07 -0800392
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800393/** XMLNode is a base class for every object that is in the
394 XML Document Object Model (DOM), except XMLAttributes.
395 Nodes have siblings, a parent, and children which can
396 be navigated. A node is always in a XMLDocument.
397 The type of a TiXmlNode can be queried, and it can
398 be cast to its more defined type.
399
400 An XMLDocument allocates memory for all its Nodes.
401 When the XMLDocument gets deleted, all its Nodes
402 will also be deleted.
403
404 @verbatim
405 A Document can contain: Element (container or leaf)
406 Comment (leaf)
407 Unknown (leaf)
408 Declaration( leaf )
409
410 An Element can contain: Element (container or leaf)
411 Text (leaf)
412 Attributes (not on tree)
413 Comment (leaf)
414 Unknown (leaf)
415
416 @endverbatim
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800417*/
Lee Thomasond1983222012-02-06 08:41:24 -0800418class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800419{
420 friend class XMLDocument;
421 friend class XMLElement;
422public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800423
424 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason751da522012-02-10 08:50:51 -0800425 const XMLDocument* GetDocument() const { return document; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800426 /// Get the XMLDocument that owns this XMLNode.
Lee Thomason56bdd022012-02-09 18:16:58 -0800427 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800428
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800429 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
430 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
431 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
432 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
433 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
434 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800435
Lee Thomason50f97b22012-02-11 16:33:40 -0800436 virtual const XMLElement* ToElement() const { return 0; }
437 virtual const XMLText* ToText() const { return 0; }
438 virtual const XMLComment* ToComment() const { return 0; }
439 virtual const XMLDocument* ToDocument() const { return 0; }
440 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
441 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800442
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800443 /** The meaning of 'value' changes for the specific type.
444 @verbatim
445 Document: empy
446 Element: name of the element
447 Comment: the comment text
448 Unknown: the tag contents
449 Text: the text string
450 @endverbatim
451 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800452 const char* Value() const { return value.GetStr(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800453 /** Set the Value of an XML node.
454 @sa Value()
455 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800456 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800457
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800458 /// Get the parent of this node on the DOM.
Lee Thomason751da522012-02-10 08:50:51 -0800459 const XMLNode* Parent() const { return parent; }
460 XMLNode* Parent() { return parent; }
461
Lee Thomason50f97b22012-02-11 16:33:40 -0800462 /// Returns true if this node has no children.
463 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800464
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800465 /// Get the first child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800466 const XMLNode* FirstChild() const { return firstChild; }
467 XMLNode* FirstChild() { return firstChild; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800468 /** Get the first child element, or optionally the first child
469 element with the specified name.
470 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800471 const XMLElement* FirstChildElement( const char* value=0 ) const;
472 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800473
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800474 /// Get the last child node, or null if none exists.
Lee Thomason56bdd022012-02-09 18:16:58 -0800475 const XMLNode* LastChild() const { return lastChild; }
476 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800477
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800478 /** Get the last child element or optionally the last child
479 element with the specified name.
480 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800481 const XMLElement* LastChildElement( const char* value=0 ) const;
482 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
483
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800484 /// Get the previous (left) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800485 const XMLNode* PreviousSibling() const { return prev; }
486 XMLNode* PreviousSibling() { return prev; }
487
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800488 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800489 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
490 XMLElement* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800491
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800492 /// Get the next (right) sibling node of this node.
Lee Thomason56bdd022012-02-09 18:16:58 -0800493 const XMLNode* NextSibling() const { return next; }
494 XMLNode* NextSibling() { return next; }
495
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800496 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800497 const XMLElement* NextSiblingElement( const char* value=0 ) const;
498 XMLElement* NextSiblingElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800499
Lee Thomason1ff38e02012-02-14 18:18:16 -0800500 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800501 Add a child node as the last (right) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800502 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800503 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason618dbf82012-02-28 12:34:27 -0800504
505 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
Lee Thomason1ff38e02012-02-14 18:18:16 -0800506 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800507 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800508 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800509 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800510 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800511 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800512 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800513 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
514
U-Stream\Leeae25a442012-02-17 17:48:16 -0800515 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800516 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800517 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800518 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800519
520 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800521 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800522 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800523 void DeleteChild( XMLNode* node );
524
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800525 /**
526 Make a copy of this node, but not its children.
527 You may pass in a Document pointer that will be
528 the owner of the new Node. If the 'document' is
529 null, then the node returned will be allocated
530 from the current Document. (this->GetDocument())
531
532 Note: if called on a XMLDocument, this will return null.
533 */
534 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
535
536 /**
537 Test if 2 nodes are the same, but don't test children.
538 The 2 nodes do not need to be in the same Document.
539
540 Note: if called on a XMLDocument, this will return false.
541 */
542 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
543
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800544 /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
545 XML tree will be conditionally visited and the host will be called back
546 via the TiXmlVisitor interface.
547
548 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
549 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
550 interface versus any other.)
551
552 The interface has been based on ideas from:
553
554 - http://www.saxproject.org/
555 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
556
557 Which are both good references for "visiting".
558
559 An example of using Accept():
560 @verbatim
561 TiXmlPrinter printer;
562 tinyxmlDoc.Accept( &printer );
563 const char* xmlcstr = printer.CStr();
564 @endverbatim
565 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800566 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800567
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800568 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800569 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800570
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800571protected:
572 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800573 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800574 XMLNode( const XMLNode& ); // not supported
575 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800576
Lee Thomason3f57d272012-01-11 15:30:03 -0800577 XMLDocument* document;
578 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800579 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800580
581 XMLNode* firstChild;
582 XMLNode* lastChild;
583
584 XMLNode* prev;
585 XMLNode* next;
586
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800587private:
Lee Thomasond1983222012-02-06 08:41:24 -0800588 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800589 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800590};
591
592
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800593/** XML text.
594
595 Note that a text node can have child element nodes, for example:
596 @verbatim
597 <root>This is <b>bold</b></root>
598 @endverbatim
599
600 A text node can have 2 ways to output the next. "normal" output
601 and CDATA. It will default to the mode it was parsed from the XML file and
602 you generally want to leave it alone, but you can change the output mode with
603 SetCDATA() and query it with CDATA().
604*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800605class XMLText : public XMLNode
606{
Lee Thomason2c85a712012-01-31 08:24:24 -0800607 friend class XMLBase;
608 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800609public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800610 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800611
Lee Thomason751da522012-02-10 08:50:51 -0800612 virtual XMLText* ToText() { return this; }
613 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800614
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800615 /// Declare whether this should be CDATA or standard text.
616 void SetCData( bool isCData ) { this->isCData = isCData; }
617 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800618 bool CData() const { return isCData; }
619
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800620 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800621 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
622 virtual bool ShallowEqual( const XMLNode* compare ) const;
623
Lee Thomason5492a1c2012-01-23 15:32:10 -0800624
625protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800626 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
627 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800628 XMLText( const XMLText& ); // not supported
629 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800630
631private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800632 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800633};
634
635
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800636/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800637class XMLComment : public XMLNode
638{
Lee Thomason2c85a712012-01-31 08:24:24 -0800639 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800640public:
Lee Thomason751da522012-02-10 08:50:51 -0800641 virtual XMLComment* ToComment() { return this; }
642 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800643
Lee Thomason56bdd022012-02-09 18:16:58 -0800644 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800645
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800646 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800647 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
648 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800649
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800650protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800651 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800652 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800653 XMLComment( const XMLComment& ); // not supported
654 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800655
Lee Thomason3f57d272012-01-11 15:30:03 -0800656private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800657};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800658
659
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800660/** In correct XML the declaration is the first entry in the file.
661 @verbatim
662 <?xml version="1.0" standalone="yes"?>
663 @endverbatim
664
665 TinyXML2 will happily read or write files without a declaration,
666 however.
667
668 The text of the declaration isn't interpreted. It is parsed
669 and written as a string.
670*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800671class XMLDeclaration : public XMLNode
672{
673 friend class XMLDocument;
674public:
675 virtual XMLDeclaration* ToDeclaration() { return this; }
676 virtual const XMLDeclaration* ToDeclaration() const { return this; }
677
678 virtual bool Accept( XMLVisitor* visitor ) const;
679
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800680 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800681 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
682 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800683
684protected:
685 XMLDeclaration( XMLDocument* doc );
686 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800687 XMLDeclaration( const XMLDeclaration& ); // not supported
688 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800689};
690
691
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800692/** Any tag that tinyXml doesn't recognize is saved as an
693 unknown. It is a tag of text, but should not be modified.
694 It will be written back to the XML, unchanged, when the file
695 is saved.
696
697 DTD tags get thrown into TiXmlUnknowns.
698*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800699class XMLUnknown : public XMLNode
700{
701 friend class XMLDocument;
702public:
703 virtual XMLUnknown* ToUnknown() { return this; }
704 virtual const XMLUnknown* ToUnknown() 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 XMLUnknown( XMLDocument* doc );
714 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800715 XMLUnknown( const XMLUnknown& ); // not supported
716 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800717};
718
719
Lee Thomason1ff38e02012-02-14 18:18:16 -0800720enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800721 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800722 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800723
Lee Thomason1ff38e02012-02-14 18:18:16 -0800724 NO_ATTRIBUTE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800725 WRONG_ATTRIBUTE_TYPE,
726
727 ERROR_FILE_NOT_FOUND,
728 ERROR_ELEMENT_MISMATCH,
729 ERROR_PARSING_ELEMENT,
730 ERROR_PARSING_ATTRIBUTE,
731 ERROR_IDENTIFYING_TAG,
732 ERROR_PARSING_TEXT,
733 ERROR_PARSING_CDATA,
734 ERROR_PARSING_COMMENT,
735 ERROR_PARSING_DECLARATION,
Lee Thomasond6277762012-02-22 16:00:12 -0800736 ERROR_PARSING_UNKNOWN,
737 ERROR_EMPTY_DOCUMENT,
Lee Thomason (grinliz)784607f2012-02-24 16:23:40 -0800738 ERROR_MISMATCHED_ELEMENT,
739 ERROR_PARSING
Lee Thomason1ff38e02012-02-14 18:18:16 -0800740};
741
742
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800743/** An attribute is a name-value pair. Elements have an arbitrary
744 number of attributes, each with a unique name.
745
746 @note The attributes are not XMLNodes. You may only query the
747 Next() attribute in a list.
748*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800749class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800750{
751 friend class XMLElement;
752public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800753 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
754 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
755 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800756
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800757 /** IntAttribute interprets the attribute as an integer, and returns the value.
758 If the value isn't an integer, 0 will be returned. There is no error checking;
759 use QueryIntAttribute() if you need error checking.
760 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800761 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800762 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800763 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800764 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800765 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800766 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800767 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800768 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800769 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800770
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800771 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
772 in the provided paremeter. The function will return XML_NO_ERROR on success,
773 and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
774 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800775 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800776 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800777 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800778 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800779 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800780 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800781 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800782 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800783 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800784
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800785 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800786 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800787 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800788 void SetAttribute( int value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800789 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800790 void SetAttribute( unsigned value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800791 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800792 void SetAttribute( bool value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800793 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800794 void SetAttribute( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800795 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800796 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800797
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800798private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800799 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800800
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800801 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800802 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800803 XMLAttribute( const XMLAttribute& ); // not supported
804 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800805 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800806
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800807 char* ParseDeep( char* p );
808
Lee Thomason751da522012-02-10 08:50:51 -0800809 mutable StrPair name;
810 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800811 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800812 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800813};
814
815
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800816/** The element is a container class. It has a value, the element name,
817 and can contain other elements, text, comments, and unknowns.
818 Elements also contain an arbitrary number of attributes.
819*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800820class XMLElement : public XMLNode
821{
Lee Thomason2c85a712012-01-31 08:24:24 -0800822 friend class XMLBase;
823 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800824public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800825 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800826 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800827 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800828 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800829
Lee Thomason751da522012-02-10 08:50:51 -0800830 virtual XMLElement* ToElement() { return this; }
831 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800832 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800833
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800834 /** Given an attribute name, Attribute() returns the value
835 for the attribute of that name, or null if none exists.
836 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800837 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 -0800838
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800839 /** Given an attribute name, IntAttribute() returns the value
840 of the attribute interpreted as an integer. 0 will be
841 returned if there is an error. For a method with error
842 checking, see QueryIntAttribute()
843 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800844 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800845 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800846 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800847 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800848 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800849 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800850 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800851 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800852 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
853
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800854 /** Given an attribute name, QueryIntAttribute() returns
855 XML_NO_ERROR, WRONG_ATTRIBUTE_TYPE if the conversion
856 can't be performed, or NO_ATTRIBUTE if the attribute
857 doesn't exist. If successful, the result of the conversion
858 will be written to 'value'. If not successful, nothing will
859 be written to 'value'. This allows you to provide default
860 value:
861
862 @verbatim
863 int value = 10;
864 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
865 @endverbatim
866 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800867 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 -0800868 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800869 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 -0800870 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800871 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 -0800872 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800873 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 -0800874 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800875 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 -0800876
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800877 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800878 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800879 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800880 void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800881 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800882 void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800883 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800884 void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800885 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800886 void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800887
U-Stream\Leeae25a442012-02-17 17:48:16 -0800888 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800889 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800890 */
891 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800892
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800893 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800894 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800895 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800896 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800897
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800898 /** Convenience function for easy access to the text inside an element. Although easy
899 and concise, GetText() is limited compared to getting the TiXmlText child
900 and accessing it directly.
901
902 If the first child of 'this' is a TiXmlText, the GetText()
903 returns the character string of the Text node, else null is returned.
904
905 This is a convenient method for getting the text of simple contained text:
906 @verbatim
907 <foo>This is text</foo>
908 const char* str = fooElement->GetText();
909 @endverbatim
910
911 'str' will be a pointer to "This is text".
912
913 Note that this function can be misleading. If the element foo was created from
914 this XML:
915 @verbatim
916 <foo><b>This is text</b></foo>
917 @endverbatim
918
919 then the value of str would be null. The first child node isn't a text node, it is
920 another element. From this XML:
921 @verbatim
922 <foo>This is <b>text</b></foo>
923 @endverbatim
924 GetText() will return "This is ".
925 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800926 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800927
Lee Thomason2c85a712012-01-31 08:24:24 -0800928 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800929 enum {
930 OPEN, // <foo>
931 CLOSED, // <foo/>
932 CLOSING // </foo>
933 };
934 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800935 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800936 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
937 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800938
Lee Thomason50adb4c2012-02-13 15:07:09 -0800939private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800940 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800941 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800942 XMLElement( const XMLElement& ); // not supported
943 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800944
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800945 XMLAttribute* FindAttribute( const char* name );
946 XMLAttribute* FindOrCreateAttribute( const char* name );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800947 void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800948 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -0800949
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800950 int closingType;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800951 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800952};
953
954
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800955/** A document binds together all the functionality.
956 It can be saved, loaded, and printed to the screen.
957 All Nodes are connected and allocated to a Document.
958 If the Document is deleted, all its Nodes are also deleted.
959*/
Lee Thomason67d61312012-01-24 16:01:51 -0800960class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800961{
Lee Thomasond1983222012-02-06 08:41:24 -0800962 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800963public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800964 /// constructor
Lee Thomason18d68bd2012-01-26 18:17:26 -0800965 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800966 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800967
Lee Thomason751da522012-02-10 08:50:51 -0800968 virtual XMLDocument* ToDocument() { return this; }
969 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800970
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800971 /**
972 Parse an XML file from a character string.
973 Returns XML_NO_ERROR (0) on success, or
974 an errorID.
975 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800976 int Parse( const char* xml );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800977 /**
978 Load an XML file from disk.
979 Returns XML_NO_ERROR (0) on success, or
980 an errorID.
981 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800982 int LoadFile( const char* filename );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800983 /**
984 Load an XML file from disk. You are responsible
985 for providing and closing the FILE*.
986
987 Returns XML_NO_ERROR (0) on success, or
988 an errorID.
989 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800990 int LoadFile( FILE* );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800991 /**
992 Save the XML file to disk.
993 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800994 void SaveFile( const char* filename );
995
996 bool HasBOM() const { return writeBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800997
998 /** Return the root element of DOM. Equivalent to FirstChildElement().
999 To get the first node, use FirstChild().
1000 */
Lee Thomasond6277762012-02-22 16:00:12 -08001001 XMLElement* RootElement() { return FirstChildElement(); }
1002 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -08001003
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001004 /** Print the Document. If the Printer is not provided, it will
1005 print to stdout. If you provide Printer, this can print to a file:
1006 @verbatim
1007 XMLPrinter printer( fp );
1008 doc.Print( &printer );
1009 @endverbatim
1010
1011 Or you can use a printer to print to memory:
1012 @verbatim
1013 XMLPrinter printer;
1014 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001015 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001016 @endverbatim
1017 */
1018 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001019 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001020
Lee Thomason1ff38e02012-02-14 18:18:16 -08001021 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001022 Create a new Element associated with
1023 this Document. The memory for the Element
1024 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001025 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001026 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001027 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001028 Create a new Comment associated with
1029 this Document. The memory for the Comment
1030 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001031 */
1032 XMLComment* NewComment( const char* comment );
1033 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001034 Create a new Text associated with
1035 this Document. The memory for the Text
1036 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001037 */
1038 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001039 /**
1040 Create a new Declaration associated with
1041 this Document. The memory for the object
1042 is managed by the Document.
1043 */
1044 XMLDeclaration* NewDeclaration( const char* text );
1045 /**
1046 Create a new Unknown associated with
1047 this Document. The memory for the object
1048 is managed by the Document.
1049 */
1050 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001051
U-Stream\Leeae25a442012-02-17 17:48:16 -08001052 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001053 Delete a node associated with this documented.
1054 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001055 */
1056 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1057
Lee Thomason67d61312012-01-24 16:01:51 -08001058 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001059
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001060 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001061 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001062 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001063 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001064 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001065 const char* GetErrorStr1() const { return errorStr1; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001066 /// Return possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001067 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001068 /// If there is an error, print it to stdout
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001069 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001070
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001071 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001072 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001073
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001074 virtual XMLNode* ShallowClone( XMLDocument* document ) const { return 0; }
1075 virtual bool ShallowEqual( const XMLNode* compare ) const { return false; }
1076
Lee Thomason3f57d272012-01-11 15:30:03 -08001077private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001078 XMLDocument( const XMLDocument& ); // not supported
1079 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001080 void InitDocument();
1081
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001082 bool writeBOM;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001083 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001084 const char* errorStr1;
1085 const char* errorStr2;
1086 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001087
1088 MemPoolT< sizeof(XMLElement) > elementPool;
1089 MemPoolT< sizeof(XMLAttribute) > attributePool;
1090 MemPoolT< sizeof(XMLText) > textPool;
1091 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001092};
1093
Lee Thomason7c913cd2012-01-26 18:32:34 -08001094
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001095
1096/**
1097 Printing functionality. The XMLPrinter gives you more
1098 options than the XMLDocument::Print() method.
1099
1100 It can:
1101 -# Print to memory.
1102 -# Print to a file you provide
1103 -# Print XML without a XMLDocument.
1104
1105 Print to Memory
1106
1107 @verbatim
1108 XMLPrinter printer;
1109 doc->Print( &printer );
1110 SomeFunctior( printer.CStr() );
1111 @endverbatim
1112
1113 Print to a File
1114
1115 You provide the file pointer.
1116 @verbatim
1117 XMLPrinter printer( fp );
1118 doc.Print( &printer );
1119 @endverbatim
1120
1121 Print without a XMLDocument
1122
1123 When loading, an XML parser is very useful. However, sometimes
1124 when saving, it just gets in the way. The code is often set up
1125 for streaming, and constructing the DOM is just overhead.
1126
1127 The Printer supports the streaming case. The following code
1128 prints out a trivially simple XML file without ever creating
1129 an XML document.
1130
1131 @verbatim
1132 XMLPrinter printer( fp );
1133 printer.OpenElement( "foo" );
1134 printer.PushAttribute( "foo", "bar" );
1135 printer.CloseElement();
1136 @endverbatim
1137*/
1138class XMLPrinter : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -08001139{
1140public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001141 /** Construct the printer. If the FILE* is specified,
1142 this will print to the FILE. Else it will print
1143 to memory, and the result is available in CStr()
1144 */
1145 XMLPrinter( FILE* file=0 );
1146 ~XMLPrinter() {}
Lee Thomason5cae8972012-01-24 18:03:07 -08001147
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001148 /** If streaming, write the BOM and declaration. */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001149 void PushHeader( bool writeBOM, bool writeDeclaration );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001150 /** If streaming, start writing an element.
1151 The element must be closed with CloseElement()
1152 */
Lee Thomason56bdd022012-02-09 18:16:58 -08001153 void OpenElement( const char* name );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001154 /// If streaming, add an attribute to an open element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001155 void PushAttribute( const char* name, const char* value );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001156 void PushAttribute( const char* name, int value );
1157 void PushAttribute( const char* name, unsigned value );
1158 void PushAttribute( const char* name, bool value );
1159 void PushAttribute( const char* name, double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001160 /// If streaming, close the Element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001161 void CloseElement();
1162
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001163 /// Add a text node.
Lee Thomason50f97b22012-02-11 16:33:40 -08001164 void PushText( const char* text, bool cdata=false );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001165 /// Add a comment
Lee Thomason5cae8972012-01-24 18:03:07 -08001166 void PushComment( const char* comment );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001167
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001168 void PushDeclaration( const char* value );
1169 void PushUnknown( const char* value );
Lee Thomason5cae8972012-01-24 18:03:07 -08001170
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001171 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
Lee Thomason751da522012-02-10 08:50:51 -08001172 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1173
1174 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1175 virtual bool VisitExit( const XMLElement& element );
1176
1177 virtual bool Visit( const XMLText& text );
1178 virtual bool Visit( const XMLComment& comment );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001179 virtual bool Visit( const XMLDeclaration& declaration );
1180 virtual bool Visit( const XMLUnknown& unknown );
Lee Thomason751da522012-02-10 08:50:51 -08001181
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001182 /**
1183 If in print to memory mode, return a pointer to
1184 the XML file in memory.
1185 */
U-Stream\Leeae25a442012-02-17 17:48:16 -08001186 const char* CStr() const { return buffer.Mem(); }
Lee Thomason751da522012-02-10 08:50:51 -08001187
Lee Thomason5cae8972012-01-24 18:03:07 -08001188private:
1189 void SealElement();
1190 void PrintSpace( int depth );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001191 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001192 void Print( const char* format, ... );
Lee Thomason5cae8972012-01-24 18:03:07 -08001193
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001194 bool elementJustOpened;
1195 bool firstElement;
Lee Thomason5cae8972012-01-24 18:03:07 -08001196 FILE* fp;
1197 int depth;
Lee Thomason56bdd022012-02-09 18:16:58 -08001198 int textDepth;
1199
Lee Thomason857b8682012-01-25 17:50:25 -08001200 enum {
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001201 ENTITY_RANGE = 64,
1202 BUF_SIZE = 200
Lee Thomason857b8682012-01-25 17:50:25 -08001203 };
1204 bool entityFlag[ENTITY_RANGE];
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001205 bool restrictedEntityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -08001206
Lee Thomason2c85a712012-01-31 08:24:24 -08001207 DynArray< const char*, 10 > stack;
U-Stream\Leeae25a442012-02-17 17:48:16 -08001208 DynArray< char, 20 > buffer, accumulator;
Lee Thomason5cae8972012-01-24 18:03:07 -08001209};
1210
1211
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001212}; // tinyxml2
1213
U-Lama\Lee560bd472011-12-28 19:42:49 -08001214
1215
U-Stream\Leeae25a442012-02-17 17:48:16 -08001216#endif // TINYXML2_INCLUDED