blob: 81f1dddef447fad012a1713ff4fae9f62b45a915 [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 Thomason1ff38e02012-02-14 18:18:16 -0800501 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800502 Add a child node as the first (left) child.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800503 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800504 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800505 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800506 Add a node after the specified child node.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800507 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800508 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
509
U-Stream\Leeae25a442012-02-17 17:48:16 -0800510 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800511 Delete all the children of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800512 */
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800513 void DeleteChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800514
515 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800516 Delete a child of this node.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800517 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800518 void DeleteChild( XMLNode* node );
519
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800520 /**
521 Make a copy of this node, but not its children.
522 You may pass in a Document pointer that will be
523 the owner of the new Node. If the 'document' is
524 null, then the node returned will be allocated
525 from the current Document. (this->GetDocument())
526
527 Note: if called on a XMLDocument, this will return null.
528 */
529 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
530
531 /**
532 Test if 2 nodes are the same, but don't test children.
533 The 2 nodes do not need to be in the same Document.
534
535 Note: if called on a XMLDocument, this will return false.
536 */
537 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
538
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800539 /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the
540 XML tree will be conditionally visited and the host will be called back
541 via the TiXmlVisitor interface.
542
543 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
544 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
545 interface versus any other.)
546
547 The interface has been based on ideas from:
548
549 - http://www.saxproject.org/
550 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
551
552 Which are both good references for "visiting".
553
554 An example of using Accept():
555 @verbatim
556 TiXmlPrinter printer;
557 tinyxmlDoc.Accept( &printer );
558 const char* xmlcstr = printer.CStr();
559 @endverbatim
560 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800561 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800562
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800563 // internal
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800564 virtual char* ParseDeep( char*, StrPair* );
Lee Thomason3f57d272012-01-11 15:30:03 -0800565
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800566protected:
567 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800568 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800569 XMLNode( const XMLNode& ); // not supported
570 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800571
Lee Thomason3f57d272012-01-11 15:30:03 -0800572 XMLDocument* document;
573 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800574 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800575
576 XMLNode* firstChild;
577 XMLNode* lastChild;
578
579 XMLNode* prev;
580 XMLNode* next;
581
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800582private:
Lee Thomasond1983222012-02-06 08:41:24 -0800583 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800584 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800585};
586
587
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800588/** XML text.
589
590 Note that a text node can have child element nodes, for example:
591 @verbatim
592 <root>This is <b>bold</b></root>
593 @endverbatim
594
595 A text node can have 2 ways to output the next. "normal" output
596 and CDATA. It will default to the mode it was parsed from the XML file and
597 you generally want to leave it alone, but you can change the output mode with
598 SetCDATA() and query it with CDATA().
599*/
Lee Thomason5492a1c2012-01-23 15:32:10 -0800600class XMLText : public XMLNode
601{
Lee Thomason2c85a712012-01-31 08:24:24 -0800602 friend class XMLBase;
603 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800604public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800605 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800606
Lee Thomason751da522012-02-10 08:50:51 -0800607 virtual XMLText* ToText() { return this; }
608 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800609
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800610 /// Declare whether this should be CDATA or standard text.
611 void SetCData( bool isCData ) { this->isCData = isCData; }
612 /// Returns true if this is a CDATA text element.
Lee Thomason50f97b22012-02-11 16:33:40 -0800613 bool CData() const { return isCData; }
614
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800615 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800616 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
617 virtual bool ShallowEqual( const XMLNode* compare ) const;
618
Lee Thomason5492a1c2012-01-23 15:32:10 -0800619
620protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800621 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
622 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800623 XMLText( const XMLText& ); // not supported
624 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800625
626private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800627 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800628};
629
630
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800631/** An XML Comment. */
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800632class XMLComment : public XMLNode
633{
Lee Thomason2c85a712012-01-31 08:24:24 -0800634 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800635public:
Lee Thomason751da522012-02-10 08:50:51 -0800636 virtual XMLComment* ToComment() { return this; }
637 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800638
Lee Thomason56bdd022012-02-09 18:16:58 -0800639 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800640
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800641 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800642 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
643 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomasonce0763e2012-01-11 15:43:54 -0800644
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800645protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800646 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800647 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800648 XMLComment( const XMLComment& ); // not supported
649 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800650
Lee Thomason3f57d272012-01-11 15:30:03 -0800651private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800652};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800653
654
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800655/** In correct XML the declaration is the first entry in the file.
656 @verbatim
657 <?xml version="1.0" standalone="yes"?>
658 @endverbatim
659
660 TinyXML2 will happily read or write files without a declaration,
661 however.
662
663 The text of the declaration isn't interpreted. It is parsed
664 and written as a string.
665*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800666class XMLDeclaration : public XMLNode
667{
668 friend class XMLDocument;
669public:
670 virtual XMLDeclaration* ToDeclaration() { return this; }
671 virtual const XMLDeclaration* ToDeclaration() const { return this; }
672
673 virtual bool Accept( XMLVisitor* visitor ) const;
674
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800675 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800676 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
677 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800678
679protected:
680 XMLDeclaration( XMLDocument* doc );
681 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800682 XMLDeclaration( const XMLDeclaration& ); // not supported
683 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800684};
685
686
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800687/** Any tag that tinyXml doesn't recognize is saved as an
688 unknown. It is a tag of text, but should not be modified.
689 It will be written back to the XML, unchanged, when the file
690 is saved.
691
692 DTD tags get thrown into TiXmlUnknowns.
693*/
Lee Thomason50f97b22012-02-11 16:33:40 -0800694class XMLUnknown : public XMLNode
695{
696 friend class XMLDocument;
697public:
698 virtual XMLUnknown* ToUnknown() { return this; }
699 virtual const XMLUnknown* ToUnknown() const { return this; }
700
701 virtual bool Accept( XMLVisitor* visitor ) const;
702
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800703 char* ParseDeep( char*, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800704 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
705 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800706
707protected:
708 XMLUnknown( XMLDocument* doc );
709 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800710 XMLUnknown( const XMLUnknown& ); // not supported
711 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800712};
713
714
Lee Thomason1ff38e02012-02-14 18:18:16 -0800715enum {
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800716 XML_NO_ERROR = 0,
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800717 XML_SUCCESS = 0,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800718
Lee Thomason1ff38e02012-02-14 18:18:16 -0800719 NO_ATTRIBUTE,
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800720 WRONG_ATTRIBUTE_TYPE,
721
722 ERROR_FILE_NOT_FOUND,
723 ERROR_ELEMENT_MISMATCH,
724 ERROR_PARSING_ELEMENT,
725 ERROR_PARSING_ATTRIBUTE,
726 ERROR_IDENTIFYING_TAG,
727 ERROR_PARSING_TEXT,
728 ERROR_PARSING_CDATA,
729 ERROR_PARSING_COMMENT,
730 ERROR_PARSING_DECLARATION,
Lee Thomasond6277762012-02-22 16:00:12 -0800731 ERROR_PARSING_UNKNOWN,
732 ERROR_EMPTY_DOCUMENT,
Lee Thomason (grinliz)784607f2012-02-24 16:23:40 -0800733 ERROR_MISMATCHED_ELEMENT,
734 ERROR_PARSING
Lee Thomason1ff38e02012-02-14 18:18:16 -0800735};
736
737
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800738/** An attribute is a name-value pair. Elements have an arbitrary
739 number of attributes, each with a unique name.
740
741 @note The attributes are not XMLNodes. You may only query the
742 Next() attribute in a list.
743*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800744class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800745{
746 friend class XMLElement;
747public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800748 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
749 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
750 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800751
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800752 /** IntAttribute interprets the attribute as an integer, and returns the value.
753 If the value isn't an integer, 0 will be returned. There is no error checking;
754 use QueryIntAttribute() if you need error checking.
755 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800756 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800757 /// Query as an unsigned integer. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800758 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800759 /// Query as a boolean. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800760 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800761 /// Query as a double. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800762 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800763 /// Query as a float. See IntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800764 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
U-Stream\Leeae25a442012-02-17 17:48:16 -0800765
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800766 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
767 in the provided paremeter. The function will return XML_NO_ERROR on success,
768 and WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
769 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800770 int QueryIntValue( int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800771 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800772 int QueryUnsignedValue( unsigned int* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800773 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800774 int QueryBoolValue( bool* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800775 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800776 int QueryDoubleValue( double* value ) const;
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800777 /// See QueryIntAttribute
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800778 int QueryFloatValue( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800779
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800780 /// Set the attribute to a string value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800781 void SetAttribute( const char* value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800782 /// Set the attribute to value.
Lee Thomason1ff38e02012-02-14 18:18:16 -0800783 void SetAttribute( int 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( unsigned 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( bool 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( double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800790 /// Set the attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800791 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800792
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800793private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800794 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800795
Lee Thomason (grinliz)9b093cc2012-02-25 21:30:18 -0800796 XMLAttribute() : next( 0 ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800797 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800798 XMLAttribute( const XMLAttribute& ); // not supported
799 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800800 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800801
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800802 char* ParseDeep( char* p );
803
Lee Thomason751da522012-02-10 08:50:51 -0800804 mutable StrPair name;
805 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800806 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800807 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800808};
809
810
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800811/** The element is a container class. It has a value, the element name,
812 and can contain other elements, text, comments, and unknowns.
813 Elements also contain an arbitrary number of attributes.
814*/
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800815class XMLElement : public XMLNode
816{
Lee Thomason2c85a712012-01-31 08:24:24 -0800817 friend class XMLBase;
818 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800819public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800820 /// Get the name of an element (which is the Value() of the node.)
Lee Thomason2c85a712012-01-31 08:24:24 -0800821 const char* Name() const { return Value(); }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800822 /// Set the name of the element.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800823 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800824
Lee Thomason751da522012-02-10 08:50:51 -0800825 virtual XMLElement* ToElement() { return this; }
826 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800827 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800828
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800829 /** Given an attribute name, Attribute() returns the value
830 for the attribute of that name, or null if none exists.
831 */
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800832 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 -0800833
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800834 /** Given an attribute name, IntAttribute() returns the value
835 of the attribute interpreted as an integer. 0 will be
836 returned if there is an error. For a method with error
837 checking, see QueryIntAttribute()
838 */
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800839 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800840 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800841 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( 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 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800844 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800845 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800846 /// See IntAttribute()
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800847 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
848
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800849 /** Given an attribute name, QueryIntAttribute() returns
850 XML_NO_ERROR, WRONG_ATTRIBUTE_TYPE if the conversion
851 can't be performed, or NO_ATTRIBUTE if the attribute
852 doesn't exist. If successful, the result of the conversion
853 will be written to 'value'. If not successful, nothing will
854 be written to 'value'. This allows you to provide default
855 value:
856
857 @verbatim
858 int value = 10;
859 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
860 @endverbatim
861 */
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800862 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 -0800863 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800864 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 -0800865 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800866 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 -0800867 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800868 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 -0800869 /// See QueryIntAttribute()
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800870 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 -0800871
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800872 /// Sets the named attribute to value.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800873 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
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, int 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, unsigned 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, bool 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, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800882
U-Stream\Leeae25a442012-02-17 17:48:16 -0800883 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800884 Delete an attribute.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800885 */
886 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800887
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800888 /// Return the first attribute in the list.
Lee Thomason751da522012-02-10 08:50:51 -0800889 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800890 /// Query a specific attribute in the list.
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800891 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800892
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800893 /** Convenience function for easy access to the text inside an element. Although easy
894 and concise, GetText() is limited compared to getting the TiXmlText child
895 and accessing it directly.
896
897 If the first child of 'this' is a TiXmlText, the GetText()
898 returns the character string of the Text node, else null is returned.
899
900 This is a convenient method for getting the text of simple contained text:
901 @verbatim
902 <foo>This is text</foo>
903 const char* str = fooElement->GetText();
904 @endverbatim
905
906 'str' will be a pointer to "This is text".
907
908 Note that this function can be misleading. If the element foo was created from
909 this XML:
910 @verbatim
911 <foo><b>This is text</b></foo>
912 @endverbatim
913
914 then the value of str would be null. The first child node isn't a text node, it is
915 another element. From this XML:
916 @verbatim
917 <foo>This is <b>text</b></foo>
918 @endverbatim
919 GetText() will return "This is ".
920 */
Lee Thomason50f97b22012-02-11 16:33:40 -0800921 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800922
Lee Thomason2c85a712012-01-31 08:24:24 -0800923 // internal:
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800924 enum {
925 OPEN, // <foo>
926 CLOSED, // <foo/>
927 CLOSING // </foo>
928 };
929 int ClosingType() const { return closingType; }
Lee Thomason (grinliz)7468f112012-02-24 08:56:50 -0800930 char* ParseDeep( char* p, StrPair* endTag );
Lee Thomason7d00b9a2012-02-27 17:54:22 -0800931 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
932 virtual bool ShallowEqual( const XMLNode* compare ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800933
Lee Thomason50adb4c2012-02-13 15:07:09 -0800934private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800935 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800936 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800937 XMLElement( const XMLElement& ); // not supported
938 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800939
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800940 XMLAttribute* FindAttribute( const char* name );
941 XMLAttribute* FindOrCreateAttribute( const char* name );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800942 void LinkAttribute( XMLAttribute* attrib );
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800943 char* ParseAttributes( char* p );
Lee Thomason67d61312012-01-24 16:01:51 -0800944
Lee Thomason (grinliz)46a14cf2012-02-23 22:27:28 -0800945 int closingType;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800946 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800947};
948
949
Lee Thomason (grinliz)9c38d132012-02-24 21:50:50 -0800950/** A document binds together all the functionality.
951 It can be saved, loaded, and printed to the screen.
952 All Nodes are connected and allocated to a Document.
953 If the Document is deleted, all its Nodes are also deleted.
954*/
Lee Thomason67d61312012-01-24 16:01:51 -0800955class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800956{
Lee Thomasond1983222012-02-06 08:41:24 -0800957 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800958public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800959 /// constructor
Lee Thomason18d68bd2012-01-26 18:17:26 -0800960 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800961 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800962
Lee Thomason751da522012-02-10 08:50:51 -0800963 virtual XMLDocument* ToDocument() { return this; }
964 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800965
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800966 /**
967 Parse an XML file from a character string.
968 Returns XML_NO_ERROR (0) on success, or
969 an errorID.
970 */
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -0800971 int Parse( const char* xml );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800972 /**
973 Load an XML file from disk.
974 Returns XML_NO_ERROR (0) on success, or
975 an errorID.
976 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800977 int LoadFile( const char* filename );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800978 /**
979 Load an XML file from disk. You are responsible
980 for providing and closing the FILE*.
981
982 Returns XML_NO_ERROR (0) on success, or
983 an errorID.
984 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800985 int LoadFile( FILE* );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800986 /**
987 Save the XML file to disk.
988 */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -0800989 void SaveFile( const char* filename );
990
991 bool HasBOM() const { return writeBOM; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800992
993 /** Return the root element of DOM. Equivalent to FirstChildElement().
994 To get the first node, use FirstChild().
995 */
Lee Thomasond6277762012-02-22 16:00:12 -0800996 XMLElement* RootElement() { return FirstChildElement(); }
997 const XMLElement* RootElement() const { return FirstChildElement(); }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800998
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -0800999 /** Print the Document. If the Printer is not provided, it will
1000 print to stdout. If you provide Printer, this can print to a file:
1001 @verbatim
1002 XMLPrinter printer( fp );
1003 doc.Print( &printer );
1004 @endverbatim
1005
1006 Or you can use a printer to print to memory:
1007 @verbatim
1008 XMLPrinter printer;
1009 doc->Print( &printer );
Lee Thomason (grinliz)28129862012-02-25 21:11:20 -08001010 // printer.CStr() has a const char* to the XML
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001011 @endverbatim
1012 */
1013 void Print( XMLPrinter* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -08001014 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001015
Lee Thomason1ff38e02012-02-14 18:18:16 -08001016 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001017 Create a new Element associated with
1018 this Document. The memory for the Element
1019 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001020 */
Lee Thomason2c85a712012-01-31 08:24:24 -08001021 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -08001022 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001023 Create a new Comment associated with
1024 this Document. The memory for the Comment
1025 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001026 */
1027 XMLComment* NewComment( const char* comment );
1028 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001029 Create a new Text associated with
1030 this Document. The memory for the Text
1031 is managed by the Document.
Lee Thomason1ff38e02012-02-14 18:18:16 -08001032 */
1033 XMLText* NewText( const char* text );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001034 /**
1035 Create a new Declaration associated with
1036 this Document. The memory for the object
1037 is managed by the Document.
1038 */
1039 XMLDeclaration* NewDeclaration( const char* text );
1040 /**
1041 Create a new Unknown associated with
1042 this Document. The memory for the object
1043 is managed by the Document.
1044 */
1045 XMLUnknown* NewUnknown( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -08001046
U-Stream\Leeae25a442012-02-17 17:48:16 -08001047 /**
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001048 Delete a node associated with this documented.
1049 It will be unlinked from the DOM.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001050 */
1051 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
1052
Lee Thomason67d61312012-01-24 16:01:51 -08001053 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -08001054
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001055 /// Return true if there was an error parsing the document.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001056 bool Error() const { return errorID != XML_NO_ERROR; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001057 /// Return the errorID.
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001058 int ErrorID() const { return errorID; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001059 /// Return a possibly helpful diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001060 const char* GetErrorStr1() const { return errorStr1; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001061 /// Return possibly helpful secondary diagnostic location or string.
Lee Thomason18d68bd2012-01-26 18:17:26 -08001062 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001063 /// If there is an error, print it to stdout
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001064 void PrintError() const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -08001065
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001066 // internal
Lee Thomasond1983222012-02-06 08:41:24 -08001067 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -08001068
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001069 virtual XMLNode* ShallowClone( XMLDocument* document ) const { return 0; }
1070 virtual bool ShallowEqual( const XMLNode* compare ) const { return false; }
1071
Lee Thomason3f57d272012-01-11 15:30:03 -08001072private:
Lee Thomason50adb4c2012-02-13 15:07:09 -08001073 XMLDocument( const XMLDocument& ); // not supported
1074 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -08001075 void InitDocument();
1076
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001077 bool writeBOM;
Lee Thomason7c913cd2012-01-26 18:32:34 -08001078 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -08001079 const char* errorStr1;
1080 const char* errorStr2;
1081 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -08001082
1083 MemPoolT< sizeof(XMLElement) > elementPool;
1084 MemPoolT< sizeof(XMLAttribute) > attributePool;
1085 MemPoolT< sizeof(XMLText) > textPool;
1086 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -08001087};
1088
Lee Thomason7c913cd2012-01-26 18:32:34 -08001089
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001090
1091/**
1092 Printing functionality. The XMLPrinter gives you more
1093 options than the XMLDocument::Print() method.
1094
1095 It can:
1096 -# Print to memory.
1097 -# Print to a file you provide
1098 -# Print XML without a XMLDocument.
1099
1100 Print to Memory
1101
1102 @verbatim
1103 XMLPrinter printer;
1104 doc->Print( &printer );
1105 SomeFunctior( printer.CStr() );
1106 @endverbatim
1107
1108 Print to a File
1109
1110 You provide the file pointer.
1111 @verbatim
1112 XMLPrinter printer( fp );
1113 doc.Print( &printer );
1114 @endverbatim
1115
1116 Print without a XMLDocument
1117
1118 When loading, an XML parser is very useful. However, sometimes
1119 when saving, it just gets in the way. The code is often set up
1120 for streaming, and constructing the DOM is just overhead.
1121
1122 The Printer supports the streaming case. The following code
1123 prints out a trivially simple XML file without ever creating
1124 an XML document.
1125
1126 @verbatim
1127 XMLPrinter printer( fp );
1128 printer.OpenElement( "foo" );
1129 printer.PushAttribute( "foo", "bar" );
1130 printer.CloseElement();
1131 @endverbatim
1132*/
1133class XMLPrinter : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -08001134{
1135public:
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001136 /** Construct the printer. If the FILE* is specified,
1137 this will print to the FILE. Else it will print
1138 to memory, and the result is available in CStr()
1139 */
1140 XMLPrinter( FILE* file=0 );
1141 ~XMLPrinter() {}
Lee Thomason5cae8972012-01-24 18:03:07 -08001142
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001143 /** If streaming, write the BOM and declaration. */
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001144 void PushHeader( bool writeBOM, bool writeDeclaration );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001145 /** If streaming, start writing an element.
1146 The element must be closed with CloseElement()
1147 */
Lee Thomason56bdd022012-02-09 18:16:58 -08001148 void OpenElement( const char* name );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001149 /// If streaming, add an attribute to an open element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001150 void PushAttribute( const char* name, const char* value );
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001151 void PushAttribute( const char* name, int value );
1152 void PushAttribute( const char* name, unsigned value );
1153 void PushAttribute( const char* name, bool value );
1154 void PushAttribute( const char* name, double value );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001155 /// If streaming, close the Element.
Lee Thomason5cae8972012-01-24 18:03:07 -08001156 void CloseElement();
1157
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001158 /// Add a text node.
Lee Thomason50f97b22012-02-11 16:33:40 -08001159 void PushText( const char* text, bool cdata=false );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001160 /// Add a comment
Lee Thomason5cae8972012-01-24 18:03:07 -08001161 void PushComment( const char* comment );
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001162
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001163 void PushDeclaration( const char* value );
1164 void PushUnknown( const char* value );
Lee Thomason5cae8972012-01-24 18:03:07 -08001165
Lee Thomason (grinliz)68db57e2012-02-21 09:08:12 -08001166 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
Lee Thomason751da522012-02-10 08:50:51 -08001167 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
1168
1169 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
1170 virtual bool VisitExit( const XMLElement& element );
1171
1172 virtual bool Visit( const XMLText& text );
1173 virtual bool Visit( const XMLComment& comment );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001174 virtual bool Visit( const XMLDeclaration& declaration );
1175 virtual bool Visit( const XMLUnknown& unknown );
Lee Thomason751da522012-02-10 08:50:51 -08001176
Lee Thomason (grinliz)2a1cd272012-02-24 17:37:53 -08001177 /**
1178 If in print to memory mode, return a pointer to
1179 the XML file in memory.
1180 */
U-Stream\Leeae25a442012-02-17 17:48:16 -08001181 const char* CStr() const { return buffer.Mem(); }
Lee Thomason751da522012-02-10 08:50:51 -08001182
Lee Thomason5cae8972012-01-24 18:03:07 -08001183private:
1184 void SealElement();
1185 void PrintSpace( int depth );
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001186 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
U-Stream\Leeae25a442012-02-17 17:48:16 -08001187 void Print( const char* format, ... );
Lee Thomason5cae8972012-01-24 18:03:07 -08001188
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001189 bool elementJustOpened;
1190 bool firstElement;
Lee Thomason5cae8972012-01-24 18:03:07 -08001191 FILE* fp;
1192 int depth;
Lee Thomason56bdd022012-02-09 18:16:58 -08001193 int textDepth;
1194
Lee Thomason857b8682012-01-25 17:50:25 -08001195 enum {
Lee Thomason7d00b9a2012-02-27 17:54:22 -08001196 ENTITY_RANGE = 64,
1197 BUF_SIZE = 200
Lee Thomason857b8682012-01-25 17:50:25 -08001198 };
1199 bool entityFlag[ENTITY_RANGE];
Lee Thomason (grinliz)bd0a8ac2012-02-20 20:14:33 -08001200 bool restrictedEntityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -08001201
Lee Thomason2c85a712012-01-31 08:24:24 -08001202 DynArray< const char*, 10 > stack;
U-Stream\Leeae25a442012-02-17 17:48:16 -08001203 DynArray< char, 20 > buffer, accumulator;
Lee Thomason5cae8972012-01-24 18:03:07 -08001204};
1205
1206
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001207}; // tinyxml2
1208
U-Lama\Lee560bd472011-12-28 19:42:49 -08001209
1210
U-Stream\Leeae25a442012-02-17 17:48:16 -08001211#endif // TINYXML2_INCLUDED