blob: 2e46ba13d24bbd8b852d15ae4199e0c47a0d5db8 [file] [log] [blame]
Lee Thomason50f97b22012-02-11 16:33:40 -08001#ifndef TINYXML_INCLUDED
U-Lama\Leee13c3e62011-12-28 14:36:55 -08002#define TINYXML2_INCLUDED
3
Lee Thomason2c85a712012-01-31 08:24:24 -08004/*
5 TODO
Lee Thomason50adb4c2012-02-13 15:07:09 -08006 X const and non-const versions of API
Lee Thomason455c9d42012-02-06 09:14:14 -08007 X memory pool the class construction
Lee Thomason50adb4c2012-02-13 15:07:09 -08008 X attribute accessors
9 X node navigation
Lee Thomason2c85a712012-01-31 08:24:24 -080010 - handles
Lee Thomason50adb4c2012-02-13 15:07:09 -080011 X visit pattern - change streamer?
12 X make constructors protected
13 X hide copy constructor
14 X hide = operator
Lee Thomason56bdd022012-02-09 18:16:58 -080015 X UTF8 support: isAlpha, etc.
U-Stream\Leeae25a442012-02-17 17:48:16 -080016 X string buffer for sets. (Grr.)
Lee Thomason1ff38e02012-02-14 18:18:16 -080017 - MS BOM
18 - print to memory buffer
Lee Thomason50adb4c2012-02-13 15:07:09 -080019 - tests from xml1
Lee Thomason1ff38e02012-02-14 18:18:16 -080020 - xml1 tests especially UTF-8
Lee Thomason50adb4c2012-02-13 15:07:09 -080021 - perf test: xml1
22 - perf test: xenowar
U-Stream\Leeae25a442012-02-17 17:48:16 -080023 - test: load(char*)
24 - test: load(FILE*)
25
Lee Thomason2c85a712012-01-31 08:24:24 -080026*/
27
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
33#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
34 #ifndef DEBUG
35 #define DEBUG
36 #endif
37#endif
38
39
40#if defined(DEBUG)
41 #if defined(_MSC_VER)
42 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
43 #elif defined (ANDROID_NDK)
44 #include <android/log.h>
45 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
46 #else
47 #include <assert.h>
48 #define TIXMLASSERT assert
49 #endif
50#else
51 #define TIXMLASSERT( x ) {}
52#endif
53
U-Lama\Leee13c3e62011-12-28 14:36:55 -080054
Lee Thomason1a1d4a72012-02-15 09:09:25 -080055// Deprecated library function hell. Compilers want to use the
56// new safe versions. This probably doesn't fully address the problem,
57// but it gets closer. There are too many compilers for me to fully
58// test. If you get compilation troubles, undefine TIXML_SAFE
59
60#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
61 // Microsoft visual studio, version 2005 and higher.
62 #define TIXML_SNPRINTF _snprintf_s
63 #define TIXML_SSCANF sscanf_s
64#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
65 // Microsoft visual studio, version 6 and higher.
66 //#pragma message( "Using _sn* functions." )
67 #define TIXML_SNPRINTF _snprintf
68 #define TIXML_SSCANF sscanf
69#elif defined(__GNUC__) && (__GNUC__ >= 3 )
U-Stream\Leeae25a442012-02-17 17:48:16 -080070 // GCC version 3 and higher
Lee Thomason1a1d4a72012-02-15 09:09:25 -080071 //#warning( "Using sn* functions." )
72 #define TIXML_SNPRINTF snprintf
73 #define TIXML_SSCANF sscanf
74#else
75 #define TIXML_SNPRINTF snprintf
76 #define TIXML_SSCANF sscanf
77#endif
Lee Thomason1ff38e02012-02-14 18:18:16 -080078
79
U-Lama\Leee13c3e62011-12-28 14:36:55 -080080namespace tinyxml2
81{
Lee Thomasonce0763e2012-01-11 15:43:54 -080082class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080083class XMLElement;
84class XMLAttribute;
85class XMLComment;
86class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080087class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080088class XMLDeclaration;
89class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080090
Lee Thomason5cae8972012-01-24 18:03:07 -080091class XMLStreamer;
92
U-Stream\Leeae25a442012-02-17 17:48:16 -080093/*
94 A class that wraps strings. Normally stores the start and end
95 pointers into the XML file itself, and will apply normalization
96 and entity transalion if actually read. Can also store (and memory
97 manage) a traditional char[]
98*/
Lee Thomason39ede242012-01-20 11:27:56 -080099class StrPair
100{
Lee Thomasond34f52c2012-01-20 12:55:24 -0800101public:
Lee Thomason39ede242012-01-20 11:27:56 -0800102 enum {
Lee Thomasone4422302012-01-20 17:59:50 -0800103 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -0800104 NEEDS_NEWLINE_NORMALIZATION = 0x02,
105
106 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
107 ATTRIBUTE_NAME = 0,
108 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
109 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -0800110 };
111
112 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800113 ~StrPair();
114
Lee Thomasone4422302012-01-20 17:59:50 -0800115 void Set( char* start, char* end, int flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800116 Reset();
Lee Thomason39ede242012-01-20 11:27:56 -0800117 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
118 }
119 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800120 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800121
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800122 void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; }
123 void SetStr( const char* str, int flags=0 );
124
Lee Thomason56bdd022012-02-09 18:16:58 -0800125 char* ParseText( char* in, const char* endTag, int strFlags );
126 char* ParseName( char* in );
127
Lee Thomason2c85a712012-01-31 08:24:24 -0800128
Lee Thomason39ede242012-01-20 11:27:56 -0800129private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800130 void Reset();
131
Lee Thomasone4422302012-01-20 17:59:50 -0800132 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800133 NEEDS_FLUSH = 0x100,
134 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800135 };
136
Lee Thomason39ede242012-01-20 11:27:56 -0800137 // After parsing, if *end != 0, it can be set to zero.
138 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800139 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800140 char* end;
141};
142
U-Lama\Lee560bd472011-12-28 19:42:49 -0800143
U-Stream\Leeae25a442012-02-17 17:48:16 -0800144/*
145 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
146 Has a small initial memory pool, so that low or no usage will not
147 cause a call to new/delete
148*/
Lee Thomason2c85a712012-01-31 08:24:24 -0800149template <class T, int INIT>
150class DynArray
151{
152public:
153 DynArray< T, INIT >()
154 {
155 mem = pool;
156 allocated = INIT;
157 size = 0;
158 }
159 ~DynArray()
160 {
161 if ( mem != pool ) {
162 delete mem;
163 }
164 }
165 void Push( T t )
166 {
167 EnsureCapacity( size+1 );
168 mem[size++] = t;
169 }
170
171 T* PushArr( int count )
172 {
173 EnsureCapacity( size+count );
174 T* ret = &mem[size];
175 size += count;
176 return ret;
177 }
178 T Pop() {
179 return mem[--size];
180 }
181 void PopArr( int count )
182 {
183 TIXMLASSERT( size >= count );
184 size -= count;
185 }
186
U-Stream\Leeae25a442012-02-17 17:48:16 -0800187 bool Empty() const { return size == 0; }
188 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
189 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
190 int Size() const { return size; }
191 int Capacity() const { return allocated; }
192 const T* Mem() const { return mem; }
193 T* Mem() { return mem; }
Lee Thomason2c85a712012-01-31 08:24:24 -0800194
195
196private:
197 void EnsureCapacity( int cap ) {
198 if ( cap > allocated ) {
199 int newAllocated = cap * 2;
200 T* newMem = new T[newAllocated];
201 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
202 if ( mem != pool ) delete [] mem;
203 mem = newMem;
204 allocated = newAllocated;
205 }
206 }
207
208 T* mem;
209 T pool[INIT];
210 int allocated; // objects allocated
211 int size; // number objects in use
212};
213
Lee Thomason50adb4c2012-02-13 15:07:09 -0800214
U-Stream\Leeae25a442012-02-17 17:48:16 -0800215/*
216 Parent virtual class a a pool for fast allocation
217 and deallocation of objects.
218*/
Lee Thomasond1983222012-02-06 08:41:24 -0800219class MemPool
220{
221public:
222 MemPool() {}
223 virtual ~MemPool() {}
224
225 virtual int ItemSize() const = 0;
226 virtual void* Alloc() = 0;
227 virtual void Free( void* ) = 0;
228};
229
Lee Thomason50adb4c2012-02-13 15:07:09 -0800230
U-Stream\Leeae25a442012-02-17 17:48:16 -0800231/*
232 Template child class to create pools of the correct type.
233*/
Lee Thomasond1983222012-02-06 08:41:24 -0800234template< int SIZE >
235class MemPoolT : public MemPool
236{
237public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800238 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800239 ~MemPoolT() {
240 // Delete the blocks.
241 for( int i=0; i<blockPtrs.Size(); ++i ) {
242 delete blockPtrs[i];
243 }
244 }
245
246 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800247 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800248
249 virtual void* Alloc() {
250 if ( !root ) {
251 // Need a new block.
252 Block* block = new Block();
253 blockPtrs.Push( block );
254
255 for( int i=0; i<COUNT-1; ++i ) {
256 block->chunk[i].next = &block->chunk[i+1];
257 }
258 block->chunk[COUNT-1].next = 0;
259 root = block->chunk;
260 }
261 void* result = root;
262 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800263
264 ++currentAllocs;
265 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
266 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800267 return result;
268 }
269 virtual void Free( void* mem ) {
270 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800271 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800272 Chunk* chunk = (Chunk*)mem;
273 memset( chunk, 0xfe, sizeof(Chunk) );
274 chunk->next = root;
275 root = chunk;
276 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800277 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800278 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
279 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800280 }
Lee Thomasond1983222012-02-06 08:41:24 -0800281
282private:
283 enum { COUNT = 1024/SIZE };
284 union Chunk {
285 Chunk* next;
286 char mem[SIZE];
287 };
288 struct Block {
289 Chunk chunk[COUNT];
290 };
291 DynArray< Block*, 10 > blockPtrs;
292 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800293
294 int currentAllocs;
295 int nAllocs;
296 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800297};
298
Lee Thomason2c85a712012-01-31 08:24:24 -0800299
Lee Thomason56bdd022012-02-09 18:16:58 -0800300
301/**
302 Implements the interface to the "Visitor pattern" (see the Accept() method.)
303 If you call the Accept() method, it requires being passed a XMLVisitor
304 class to handle callbacks. For nodes that contain other nodes (Document, Element)
305 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
306 are simply called with Visit().
307
308 If you return 'true' from a Visit method, recursive parsing will continue. If you return
309 false, <b>no children of this node or its sibilings</b> will be Visited.
310
311 All flavors of Visit methods have a default implementation that returns 'true' (continue
312 visiting). You need to only override methods that are interesting to you.
313
314 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
315
316 You should never change the document from a callback.
317
318 @sa XMLNode::Accept()
319*/
320class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800321{
322public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800323 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800324
Lee Thomason56bdd022012-02-09 18:16:58 -0800325 /// Visit a document.
326 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
327 /// Visit a document.
328 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
329
330 /// Visit an element.
331 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
332 /// Visit an element.
333 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
334
335 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800336 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800337 /// Visit a text node
338 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
339 /// Visit a comment node
340 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
341 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800342 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800343};
344
345
U-Stream\Leeae25a442012-02-17 17:48:16 -0800346/*
347 Utility functionality.
348*/
Lee Thomason56bdd022012-02-09 18:16:58 -0800349class XMLUtil
350{
Lee Thomasond1983222012-02-06 08:41:24 -0800351public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800352 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
353 // correct, but simple, and usually works.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800354 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
355 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800356
357 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
358 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800359 if ( p == q ) {
360 return true;
361 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800362 while( *p && *q && *p == *q && n<nChar ) {
363 ++p; ++q; ++n;
364 }
365 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
366 return true;
367 }
368 return false;
369 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800370 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800371 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
372 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800373};
374
Lee Thomason5cae8972012-01-24 18:03:07 -0800375
Lee Thomasond1983222012-02-06 08:41:24 -0800376class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800377{
378 friend class XMLDocument;
379 friend class XMLElement;
380public:
Lee Thomason751da522012-02-10 08:50:51 -0800381 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800383
Lee Thomason56bdd022012-02-09 18:16:58 -0800384 virtual XMLElement* ToElement() { return 0; }
385 virtual XMLText* ToText() { return 0; }
386 virtual XMLComment* ToComment() { return 0; }
387 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason50f97b22012-02-11 16:33:40 -0800388 virtual XMLDeclaration* ToDeclaration() { return 0; }
389 virtual XMLUnknown* ToUnknown() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800390
Lee Thomason50f97b22012-02-11 16:33:40 -0800391 virtual const XMLElement* ToElement() const { return 0; }
392 virtual const XMLText* ToText() const { return 0; }
393 virtual const XMLComment* ToComment() const { return 0; }
394 virtual const XMLDocument* ToDocument() const { return 0; }
395 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
396 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800397
Lee Thomason2c85a712012-01-31 08:24:24 -0800398 const char* Value() const { return value.GetStr(); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800399 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800400
Lee Thomason751da522012-02-10 08:50:51 -0800401 const XMLNode* Parent() const { return parent; }
402 XMLNode* Parent() { return parent; }
403
Lee Thomason50f97b22012-02-11 16:33:40 -0800404 /// Returns true if this node has no children.
405 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800406
Lee Thomason56bdd022012-02-09 18:16:58 -0800407 const XMLNode* FirstChild() const { return firstChild; }
408 XMLNode* FirstChild() { return firstChild; }
409 const XMLElement* FirstChildElement( const char* value=0 ) const;
410 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800411
Lee Thomason56bdd022012-02-09 18:16:58 -0800412 const XMLNode* LastChild() const { return lastChild; }
413 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800414
Lee Thomason56bdd022012-02-09 18:16:58 -0800415 const XMLElement* LastChildElement( const char* value=0 ) const;
416 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
417
418 const XMLNode* PreviousSibling() const { return prev; }
419 XMLNode* PreviousSibling() { return prev; }
420
421 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
422 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
423
424 const XMLNode* NextSibling() const { return next; }
425 XMLNode* NextSibling() { return next; }
426
427 const XMLNode* NextSiblingElement( const char* value=0 ) const;
428 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
429
Lee Thomason1ff38e02012-02-14 18:18:16 -0800430 /**
431
432 Tests: Programmatic DOM
433 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800434 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800435 /**
436
437 Tests: Programmatic DOM
438 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800439 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800440 /**
441
442 Tests: Programmatic DOM
443 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800444 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
445
U-Stream\Leeae25a442012-02-17 17:48:16 -0800446 /**
447 Tests: All (used by destructor)
448 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800449 void ClearChildren();
U-Stream\Leeae25a442012-02-17 17:48:16 -0800450
451 /**
452 Tests: Progammatic DOM
453 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800454 void DeleteChild( XMLNode* node );
455
456 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason56bdd022012-02-09 18:16:58 -0800457
Lee Thomason67d61312012-01-24 16:01:51 -0800458 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800459 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800460
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800461protected:
462 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800463 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800464 XMLNode( const XMLNode& ); // not supported
465 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800466
Lee Thomason3f57d272012-01-11 15:30:03 -0800467 XMLDocument* document;
468 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800469 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800470
471 XMLNode* firstChild;
472 XMLNode* lastChild;
473
474 XMLNode* prev;
475 XMLNode* next;
476
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800477private:
Lee Thomasond1983222012-02-06 08:41:24 -0800478 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800479 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800480};
481
482
Lee Thomason5492a1c2012-01-23 15:32:10 -0800483class XMLText : public XMLNode
484{
Lee Thomason2c85a712012-01-31 08:24:24 -0800485 friend class XMLBase;
486 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800487public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800488 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800489
Lee Thomason751da522012-02-10 08:50:51 -0800490 virtual XMLText* ToText() { return this; }
491 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800492
Lee Thomason50f97b22012-02-11 16:33:40 -0800493 void SetCData( bool value ) { isCData = true; }
494 bool CData() const { return isCData; }
495
Lee Thomason5492a1c2012-01-23 15:32:10 -0800496 char* ParseDeep( char* );
497
498protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800499 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
500 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800501 XMLText( const XMLText& ); // not supported
502 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800503
504private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800505 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800506};
507
508
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800509class XMLComment : public XMLNode
510{
Lee Thomason2c85a712012-01-31 08:24:24 -0800511 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800512public:
Lee Thomason751da522012-02-10 08:50:51 -0800513 virtual XMLComment* ToComment() { return this; }
514 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800515
Lee Thomason56bdd022012-02-09 18:16:58 -0800516 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800517
Lee Thomasonce0763e2012-01-11 15:43:54 -0800518 char* ParseDeep( char* );
519
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800520protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800521 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800522 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800523 XMLComment( const XMLComment& ); // not supported
524 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800525
Lee Thomason3f57d272012-01-11 15:30:03 -0800526private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800527};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800528
529
Lee Thomason50f97b22012-02-11 16:33:40 -0800530class XMLDeclaration : public XMLNode
531{
532 friend class XMLDocument;
533public:
534 virtual XMLDeclaration* ToDeclaration() { return this; }
535 virtual const XMLDeclaration* ToDeclaration() const { return this; }
536
537 virtual bool Accept( XMLVisitor* visitor ) const;
538
539 char* ParseDeep( char* );
540
541protected:
542 XMLDeclaration( XMLDocument* doc );
543 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800544 XMLDeclaration( const XMLDeclaration& ); // not supported
545 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800546};
547
548
549class XMLUnknown : public XMLNode
550{
551 friend class XMLDocument;
552public:
553 virtual XMLUnknown* ToUnknown() { return this; }
554 virtual const XMLUnknown* ToUnknown() const { return this; }
555
556 virtual bool Accept( XMLVisitor* visitor ) const;
557
558 char* ParseDeep( char* );
559
560protected:
561 XMLUnknown( XMLDocument* doc );
562 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800563 XMLUnknown( const XMLUnknown& ); // not supported
564 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800565};
566
567
Lee Thomason1ff38e02012-02-14 18:18:16 -0800568enum {
569 ATTRIBUTE_SUCCESS,
570 NO_ATTRIBUTE,
571 WRONG_ATTRIBUTE_TYPE
572};
573
574
Lee Thomason56bdd022012-02-09 18:16:58 -0800575class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800576{
577 friend class XMLElement;
578public:
Lee Thomason751da522012-02-10 08:50:51 -0800579 const char* Name() const { return name.GetStr(); }
580 const char* Value() const { return value.GetStr(); }
581 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800582
U-Stream\Leeae25a442012-02-17 17:48:16 -0800583 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( &i ); return i; }
584 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( &i ); return i; }
585 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( &b ); return b; }
586 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( &d ); return d; }
587 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( &f ); return f; }
588
Lee Thomason1ff38e02012-02-14 18:18:16 -0800589 int QueryIntAttribute( int* value ) const;
590 int QueryUnsignedAttribute( unsigned int* value ) const;
591 int QueryBoolAttribute( bool* value ) const;
592 int QueryDoubleAttribute( double* value ) const;
593 int QueryFloatAttribute( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800594
Lee Thomason1ff38e02012-02-14 18:18:16 -0800595 void SetAttribute( const char* value );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800596 void SetAttribute( int value );
597 void SetAttribute( unsigned value );
598 void SetAttribute( bool value );
599 void SetAttribute( double value );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800600 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800601
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800602private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800603 enum { BUF_SIZE = 200 };
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800604
Lee Thomasond1983222012-02-06 08:41:24 -0800605 XMLAttribute( XMLElement* element ) : next( 0 ) {}
606 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800607 XMLAttribute( const XMLAttribute& ); // not supported
608 void operator=( const XMLAttribute& ); // not supported
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800609 void SetName( const char* name );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800610
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800611 char* ParseDeep( char* p );
612
Lee Thomason751da522012-02-10 08:50:51 -0800613 mutable StrPair name;
614 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800615 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800616 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800617};
618
619
620class XMLElement : public XMLNode
621{
Lee Thomason2c85a712012-01-31 08:24:24 -0800622 friend class XMLBase;
623 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800624public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800625 const char* Name() const { return Value(); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800626 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800627
Lee Thomason751da522012-02-10 08:50:51 -0800628 virtual XMLElement* ToElement() { return this; }
629 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800630 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800631
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800632 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 -0800633
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800634 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
635 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
636 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
637 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
638 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
639
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800640 int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); }
641 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); }
642 int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); }
643 int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); }
644 int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800645
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800646 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
647 void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
648 void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
649 void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
650 void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800651
U-Stream\Leeae25a442012-02-17 17:48:16 -0800652 /**
653 Tests: Programmatic DOM
654 */
655 void DeleteAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800656
657 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800658 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800659
Lee Thomason50f97b22012-02-11 16:33:40 -0800660 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800661
Lee Thomason2c85a712012-01-31 08:24:24 -0800662 // internal:
663 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800664 char* ParseDeep( char* p );
665
Lee Thomason50adb4c2012-02-13 15:07:09 -0800666private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800667 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800668 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800669 XMLElement( const XMLElement& ); // not supported
670 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800671
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800672 XMLAttribute* FindAttribute( const char* name );
673 XMLAttribute* FindOrCreateAttribute( const char* name );
U-Stream\Lee09a11c52012-02-17 08:31:16 -0800674 void LinkAttribute( XMLAttribute* attrib );
Lee Thomason67d61312012-01-24 16:01:51 -0800675 char* ParseAttributes( char* p, bool *closedElement );
676
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800677 bool closing;
678 XMLAttribute* rootAttribute;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800679};
680
681
Lee Thomason67d61312012-01-24 16:01:51 -0800682class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800683{
Lee Thomasond1983222012-02-06 08:41:24 -0800684 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800685public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800686 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800687 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800688
Lee Thomason751da522012-02-10 08:50:51 -0800689 virtual XMLDocument* ToDocument() { return this; }
690 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800691
Lee Thomason7c913cd2012-01-26 18:32:34 -0800692 int Parse( const char* );
693 int Load( const char* );
694 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800695
Lee Thomason5cae8972012-01-24 18:03:07 -0800696 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800697 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800698
Lee Thomason1ff38e02012-02-14 18:18:16 -0800699 /**
U-Stream\Leeae25a442012-02-17 17:48:16 -0800700 Tests: Programmatic DOM
Lee Thomason1ff38e02012-02-14 18:18:16 -0800701 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800702 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800703 /**
U-Stream\Leeae25a442012-02-17 17:48:16 -0800704 Tests: Programmatic DOM
Lee Thomason1ff38e02012-02-14 18:18:16 -0800705 */
706 XMLComment* NewComment( const char* comment );
707 /**
U-Stream\Leeae25a442012-02-17 17:48:16 -0800708 Tests: Programmatic DOM
Lee Thomason1ff38e02012-02-14 18:18:16 -0800709 */
710 XMLText* NewText( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -0800711
U-Stream\Leeae25a442012-02-17 17:48:16 -0800712 /**
713 Tests: Programmatic DOM
714 */
715 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
716
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800717 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800718 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800719 ERROR_ELEMENT_MISMATCH,
720 ERROR_PARSING_ELEMENT,
Lee Thomason50f97b22012-02-11 16:33:40 -0800721 ERROR_PARSING_ATTRIBUTE,
722 ERROR_IDENTIFYING_TAG
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800723 };
Lee Thomason67d61312012-01-24 16:01:51 -0800724 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800725
Lee Thomason7c913cd2012-01-26 18:32:34 -0800726 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800727 int GetErrorID() const { return errorID; }
728 const char* GetErrorStr1() const { return errorStr1; }
729 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800730
Lee Thomasond1983222012-02-06 08:41:24 -0800731 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800732
Lee Thomason3f57d272012-01-11 15:30:03 -0800733private:
Lee Thomason50adb4c2012-02-13 15:07:09 -0800734 XMLDocument( const XMLDocument& ); // not supported
735 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -0800736 void InitDocument();
737
Lee Thomason7c913cd2012-01-26 18:32:34 -0800738 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800739 const char* errorStr1;
740 const char* errorStr2;
741 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800742
743 MemPoolT< sizeof(XMLElement) > elementPool;
744 MemPoolT< sizeof(XMLAttribute) > attributePool;
745 MemPoolT< sizeof(XMLText) > textPool;
746 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800747};
748
Lee Thomason7c913cd2012-01-26 18:32:34 -0800749
Lee Thomason751da522012-02-10 08:50:51 -0800750class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800751{
752public:
U-Stream\Leeae25a442012-02-17 17:48:16 -0800753 XMLStreamer( FILE* file=0 );
Lee Thomason5cae8972012-01-24 18:03:07 -0800754 ~XMLStreamer() {}
755
Lee Thomason56bdd022012-02-09 18:16:58 -0800756 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800757 void PushAttribute( const char* name, const char* value );
758 void CloseElement();
759
Lee Thomason50f97b22012-02-11 16:33:40 -0800760 void PushText( const char* text, bool cdata=false );
Lee Thomason5cae8972012-01-24 18:03:07 -0800761 void PushComment( const char* comment );
762
Lee Thomason751da522012-02-10 08:50:51 -0800763 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
764 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
765
766 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
767 virtual bool VisitExit( const XMLElement& element );
768
769 virtual bool Visit( const XMLText& text );
770 virtual bool Visit( const XMLComment& comment );
771
U-Stream\Leeae25a442012-02-17 17:48:16 -0800772 const char* CStr() const { return buffer.Mem(); }
Lee Thomason751da522012-02-10 08:50:51 -0800773
Lee Thomason5cae8972012-01-24 18:03:07 -0800774private:
775 void SealElement();
776 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800777 void PrintString( const char* ); // prints out, after detecting entities.
U-Stream\Leeae25a442012-02-17 17:48:16 -0800778 void Print( const char* format, ... );
Lee Thomason5cae8972012-01-24 18:03:07 -0800779
780 FILE* fp;
781 int depth;
782 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800783 int textDepth;
784
Lee Thomason857b8682012-01-25 17:50:25 -0800785 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800786 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800787 };
788 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800789
Lee Thomason2c85a712012-01-31 08:24:24 -0800790 DynArray< const char*, 10 > stack;
U-Stream\Leeae25a442012-02-17 17:48:16 -0800791 DynArray< char, 20 > buffer, accumulator;
Lee Thomason5cae8972012-01-24 18:03:07 -0800792};
793
794
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800795}; // tinyxml2
796
U-Lama\Lee560bd472011-12-28 19:42:49 -0800797
798
U-Stream\Leeae25a442012-02-17 17:48:16 -0800799#endif // TINYXML2_INCLUDED