blob: 27f38c9526be1b3278bba0c8f623c53ef4b9c31a [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
6 - const and non-const versions of API
Lee Thomason455c9d42012-02-06 09:14:14 -08007 X memory pool the class construction
Lee Thomason2c85a712012-01-31 08:24:24 -08008 - attribute accessors
9 - node navigation
10 - handles
11 - visit pattern - change streamer?
12 - make constructors protected
13 - hide copy constructor
14 - hide = operator
Lee Thomason56bdd022012-02-09 18:16:58 -080015 X UTF8 support: isAlpha, etc.
Lee Thomason2c85a712012-01-31 08:24:24 -080016*/
17
U-Lama\Lee4cee6112011-12-31 14:58:18 -080018#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -080019#include <ctype.h>
20#include <stdio.h>
Lee Thomason2c85a712012-01-31 08:24:24 -080021#include <memory.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -080022
23#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
24 #ifndef DEBUG
25 #define DEBUG
26 #endif
27#endif
28
29
30#if defined(DEBUG)
31 #if defined(_MSC_VER)
32 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
33 #elif defined (ANDROID_NDK)
34 #include <android/log.h>
35 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
36 #else
37 #include <assert.h>
38 #define TIXMLASSERT assert
39 #endif
40#else
41 #define TIXMLASSERT( x ) {}
42#endif
43
U-Lama\Leee13c3e62011-12-28 14:36:55 -080044
45namespace tinyxml2
46{
Lee Thomasonce0763e2012-01-11 15:43:54 -080047class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080048class XMLElement;
49class XMLAttribute;
50class XMLComment;
51class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080052class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080053class XMLDeclaration;
54class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080055
Lee Thomason5cae8972012-01-24 18:03:07 -080056class XMLStreamer;
57
Lee Thomason39ede242012-01-20 11:27:56 -080058class StrPair
59{
Lee Thomasond34f52c2012-01-20 12:55:24 -080060public:
Lee Thomason39ede242012-01-20 11:27:56 -080061 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080062 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -080063 NEEDS_NEWLINE_NORMALIZATION = 0x02,
64
65 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
66 ATTRIBUTE_NAME = 0,
67 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
68 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -080069 };
70
71 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -080072 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -080073 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
74 }
75 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -080076 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -080077
Lee Thomason2c85a712012-01-31 08:24:24 -080078 void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
Lee Thomason56bdd022012-02-09 18:16:58 -080079 char* ParseText( char* in, const char* endTag, int strFlags );
80 char* ParseName( char* in );
81
Lee Thomason2c85a712012-01-31 08:24:24 -080082
Lee Thomason39ede242012-01-20 11:27:56 -080083private:
Lee Thomasone4422302012-01-20 17:59:50 -080084 enum {
85 NEEDS_FLUSH = 0x100
86 };
87
Lee Thomason39ede242012-01-20 11:27:56 -080088 // After parsing, if *end != 0, it can be set to zero.
89 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -080090 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -080091 char* end;
92};
93
U-Lama\Lee560bd472011-12-28 19:42:49 -080094
Lee Thomason2c85a712012-01-31 08:24:24 -080095template <class T, int INIT>
96class DynArray
97{
98public:
99 DynArray< T, INIT >()
100 {
101 mem = pool;
102 allocated = INIT;
103 size = 0;
104 }
105 ~DynArray()
106 {
107 if ( mem != pool ) {
108 delete mem;
109 }
110 }
111 void Push( T t )
112 {
113 EnsureCapacity( size+1 );
114 mem[size++] = t;
115 }
116
117 T* PushArr( int count )
118 {
119 EnsureCapacity( size+count );
120 T* ret = &mem[size];
121 size += count;
122 return ret;
123 }
124 T Pop() {
125 return mem[--size];
126 }
127 void PopArr( int count )
128 {
129 TIXMLASSERT( size >= count );
130 size -= count;
131 }
132
133 bool Empty() const { return size == 0; }
134 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
135 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
136 int Size() const { return size; }
137 const T* Mem() const { return mem; }
138 T* Mem() { return mem; }
139
140
141private:
142 void EnsureCapacity( int cap ) {
143 if ( cap > allocated ) {
144 int newAllocated = cap * 2;
145 T* newMem = new T[newAllocated];
146 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
147 if ( mem != pool ) delete [] mem;
148 mem = newMem;
149 allocated = newAllocated;
150 }
151 }
152
153 T* mem;
154 T pool[INIT];
155 int allocated; // objects allocated
156 int size; // number objects in use
157};
158
Lee Thomasond1983222012-02-06 08:41:24 -0800159class MemPool
160{
161public:
162 MemPool() {}
163 virtual ~MemPool() {}
164
165 virtual int ItemSize() const = 0;
166 virtual void* Alloc() = 0;
167 virtual void Free( void* ) = 0;
168};
169
170template< int SIZE >
171class MemPoolT : public MemPool
172{
173public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800174 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800175 ~MemPoolT() {
176 // Delete the blocks.
177 for( int i=0; i<blockPtrs.Size(); ++i ) {
178 delete blockPtrs[i];
179 }
180 }
181
182 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800183 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800184
185 virtual void* Alloc() {
186 if ( !root ) {
187 // Need a new block.
188 Block* block = new Block();
189 blockPtrs.Push( block );
190
191 for( int i=0; i<COUNT-1; ++i ) {
192 block->chunk[i].next = &block->chunk[i+1];
193 }
194 block->chunk[COUNT-1].next = 0;
195 root = block->chunk;
196 }
197 void* result = root;
198 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800199
200 ++currentAllocs;
201 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
202 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800203 return result;
204 }
205 virtual void Free( void* mem ) {
206 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800207 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800208 Chunk* chunk = (Chunk*)mem;
209 memset( chunk, 0xfe, sizeof(Chunk) );
210 chunk->next = root;
211 root = chunk;
212 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800213 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800214 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
215 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800216 }
Lee Thomasond1983222012-02-06 08:41:24 -0800217
218private:
219 enum { COUNT = 1024/SIZE };
220 union Chunk {
221 Chunk* next;
222 char mem[SIZE];
223 };
224 struct Block {
225 Chunk chunk[COUNT];
226 };
227 DynArray< Block*, 10 > blockPtrs;
228 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800229
230 int currentAllocs;
231 int nAllocs;
232 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800233};
234
Lee Thomason2c85a712012-01-31 08:24:24 -0800235
Lee Thomason56bdd022012-02-09 18:16:58 -0800236
237/**
238 Implements the interface to the "Visitor pattern" (see the Accept() method.)
239 If you call the Accept() method, it requires being passed a XMLVisitor
240 class to handle callbacks. For nodes that contain other nodes (Document, Element)
241 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
242 are simply called with Visit().
243
244 If you return 'true' from a Visit method, recursive parsing will continue. If you return
245 false, <b>no children of this node or its sibilings</b> will be Visited.
246
247 All flavors of Visit methods have a default implementation that returns 'true' (continue
248 visiting). You need to only override methods that are interesting to you.
249
250 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
251
252 You should never change the document from a callback.
253
254 @sa XMLNode::Accept()
255*/
256class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800257{
258public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800259 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800260
Lee Thomason56bdd022012-02-09 18:16:58 -0800261 /// Visit a document.
262 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
263 /// Visit a document.
264 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
265
266 /// Visit an element.
267 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
268 /// Visit an element.
269 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
270
271 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800272 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800273 /// Visit a text node
274 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
275 /// Visit a comment node
276 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
277 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800278 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800279};
280
281
282class XMLUtil
283{
Lee Thomasond1983222012-02-06 08:41:24 -0800284public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800285 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
286 // correct, but simple, and usually works.
287 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
288 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800289
290 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
291 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800292 if ( p == q ) {
293 return true;
294 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800295 while( *p && *q && *p == *q && n<nChar ) {
296 ++p; ++q; ++n;
297 }
298 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
299 return true;
300 }
301 return false;
302 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800303 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800304 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
305 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800306};
307
Lee Thomason5cae8972012-01-24 18:03:07 -0800308
Lee Thomasond1983222012-02-06 08:41:24 -0800309class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800310{
311 friend class XMLDocument;
312 friend class XMLElement;
313public:
Lee Thomason751da522012-02-10 08:50:51 -0800314 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800315 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800316
Lee Thomason56bdd022012-02-09 18:16:58 -0800317 virtual XMLElement* ToElement() { return 0; }
318 virtual XMLText* ToText() { return 0; }
319 virtual XMLComment* ToComment() { return 0; }
320 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason50f97b22012-02-11 16:33:40 -0800321 virtual XMLDeclaration* ToDeclaration() { return 0; }
322 virtual XMLUnknown* ToUnknown() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800323
Lee Thomason50f97b22012-02-11 16:33:40 -0800324 virtual const XMLElement* ToElement() const { return 0; }
325 virtual const XMLText* ToText() const { return 0; }
326 virtual const XMLComment* ToComment() const { return 0; }
327 virtual const XMLDocument* ToDocument() const { return 0; }
328 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
329 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800330
Lee Thomason2c85a712012-01-31 08:24:24 -0800331 const char* Value() const { return value.GetStr(); }
332 void SetValue( const char* val ) { value.SetInternedStr( val ); }
333
Lee Thomason751da522012-02-10 08:50:51 -0800334 const XMLNode* Parent() const { return parent; }
335 XMLNode* Parent() { return parent; }
336
Lee Thomason50f97b22012-02-11 16:33:40 -0800337 /// Returns true if this node has no children.
338 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800339
Lee Thomason56bdd022012-02-09 18:16:58 -0800340 const XMLNode* FirstChild() const { return firstChild; }
341 XMLNode* FirstChild() { return firstChild; }
342 const XMLElement* FirstChildElement( const char* value=0 ) const;
343 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800344
Lee Thomason56bdd022012-02-09 18:16:58 -0800345 const XMLNode* LastChild() const { return lastChild; }
346 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800347
Lee Thomason56bdd022012-02-09 18:16:58 -0800348 const XMLElement* LastChildElement( const char* value=0 ) const;
349 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
350
351 const XMLNode* PreviousSibling() const { return prev; }
352 XMLNode* PreviousSibling() { return prev; }
353
354 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
355 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
356
357 const XMLNode* NextSibling() const { return next; }
358 XMLNode* NextSibling() { return next; }
359
360 const XMLNode* NextSiblingElement( const char* value=0 ) const;
361 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
362
363 XMLNode* InsertEndChild( XMLNode* addThis );
364 XMLNode* InsertFirstChild( XMLNode* addThis );
365 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
366
367 void ClearChildren();
368 void DeleteChild( XMLNode* node );
369
370 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason751da522012-02-10 08:50:51 -0800371 //virtual void Print( XMLStreamer* streamer );
Lee Thomason56bdd022012-02-09 18:16:58 -0800372
Lee Thomason67d61312012-01-24 16:01:51 -0800373 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800374 void SetTextParent() { isTextParent = true; }
375 bool IsTextParent() const { return isTextParent; }
376 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800377
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800378protected:
379 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800380 virtual ~XMLNode();
381
Lee Thomason3f57d272012-01-11 15:30:03 -0800382 XMLDocument* document;
383 XMLNode* parent;
Lee Thomason67d61312012-01-24 16:01:51 -0800384 bool isTextParent;
Lee Thomason2c85a712012-01-31 08:24:24 -0800385 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800386
387 XMLNode* firstChild;
388 XMLNode* lastChild;
389
390 XMLNode* prev;
391 XMLNode* next;
392
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800393private:
Lee Thomasond1983222012-02-06 08:41:24 -0800394 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800395 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800396};
397
398
Lee Thomason5492a1c2012-01-23 15:32:10 -0800399class XMLText : public XMLNode
400{
Lee Thomason2c85a712012-01-31 08:24:24 -0800401 friend class XMLBase;
402 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800403public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800404 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800405 virtual XMLText* ToText() { return this; }
406 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800407
Lee Thomason50f97b22012-02-11 16:33:40 -0800408 void SetCData( bool value ) { isCData = true; }
409 bool CData() const { return isCData; }
410
Lee Thomason5492a1c2012-01-23 15:32:10 -0800411 char* ParseDeep( char* );
412
413protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800414 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
415 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800416
417private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800418 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800419};
420
421
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800422class XMLComment : public XMLNode
423{
Lee Thomason2c85a712012-01-31 08:24:24 -0800424 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800425public:
Lee Thomason751da522012-02-10 08:50:51 -0800426 virtual XMLComment* ToComment() { return this; }
427 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800428
Lee Thomason56bdd022012-02-09 18:16:58 -0800429 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800430
Lee Thomasonce0763e2012-01-11 15:43:54 -0800431 char* ParseDeep( char* );
432
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800433protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800434 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800435 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800436
Lee Thomason3f57d272012-01-11 15:30:03 -0800437private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800438};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800439
440
Lee Thomason50f97b22012-02-11 16:33:40 -0800441class XMLDeclaration : public XMLNode
442{
443 friend class XMLDocument;
444public:
445 virtual XMLDeclaration* ToDeclaration() { return this; }
446 virtual const XMLDeclaration* ToDeclaration() const { return this; }
447
448 virtual bool Accept( XMLVisitor* visitor ) const;
449
450 char* ParseDeep( char* );
451
452protected:
453 XMLDeclaration( XMLDocument* doc );
454 virtual ~XMLDeclaration();
455};
456
457
458class XMLUnknown : public XMLNode
459{
460 friend class XMLDocument;
461public:
462 virtual XMLUnknown* ToUnknown() { return this; }
463 virtual const XMLUnknown* ToUnknown() const { return this; }
464
465 virtual bool Accept( XMLVisitor* visitor ) const;
466
467 char* ParseDeep( char* );
468
469protected:
470 XMLUnknown( XMLDocument* doc );
471 virtual ~XMLUnknown();
472};
473
474
Lee Thomason56bdd022012-02-09 18:16:58 -0800475class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800476{
477 friend class XMLElement;
478public:
Lee Thomason751da522012-02-10 08:50:51 -0800479 //virtual void Print( XMLStreamer* streamer );
480
481 const char* Name() const { return name.GetStr(); }
482 const char* Value() const { return value.GetStr(); }
483 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800484
485private:
Lee Thomasond1983222012-02-06 08:41:24 -0800486 XMLAttribute( XMLElement* element ) : next( 0 ) {}
487 virtual ~XMLAttribute() {}
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800488 char* ParseDeep( char* p );
489
Lee Thomason751da522012-02-10 08:50:51 -0800490 mutable StrPair name;
491 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800492 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800493 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800494};
495
496
497class XMLElement : public XMLNode
498{
Lee Thomason2c85a712012-01-31 08:24:24 -0800499 friend class XMLBase;
500 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800501public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800502 const char* Name() const { return Value(); }
503 void SetName( const char* str ) { SetValue( str ); }
504
Lee Thomason751da522012-02-10 08:50:51 -0800505 virtual XMLElement* ToElement() { return this; }
506 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800507 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800508
Lee Thomason751da522012-02-10 08:50:51 -0800509 const char* Attribute( const char* name ) const;
510
511 int QueryIntAttribute( const char* name, int* value ) const;
512 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const;
513 int QueryBoolAttribute( const char* name, bool* value ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800514 int QueryDoubleAttribute( const char* name, double* _value ) const;
515 int QueryFloatAttribute( const char* name, float* _value ) const;
516
517 void SetAttribute( const char* name, const char* value );
518 void SetAttribute( const char* name, int value );
519 void SetAttribute( const char* name, unsigned value );
520 void SetAttribute( const char* name, bool value );
521 void SetAttribute( const char* name, double value );
522
523 void RemoveAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800524
525 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
526
Lee Thomason50f97b22012-02-11 16:33:40 -0800527 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800528
Lee Thomason2c85a712012-01-31 08:24:24 -0800529 // internal:
530 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800531 char* ParseDeep( char* p );
532
533protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800534 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800535 virtual ~XMLElement();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800536
537private:
Lee Thomason67d61312012-01-24 16:01:51 -0800538 char* ParseAttributes( char* p, bool *closedElement );
539
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800540 bool closing;
541 XMLAttribute* rootAttribute;
Lee Thomason751da522012-02-10 08:50:51 -0800542 XMLAttribute* lastAttribute; // fixme: remove
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800543};
544
545
Lee Thomason67d61312012-01-24 16:01:51 -0800546class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800547{
Lee Thomasond1983222012-02-06 08:41:24 -0800548 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800549public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800550 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800551 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800552
Lee Thomason751da522012-02-10 08:50:51 -0800553 virtual XMLDocument* ToDocument() { return this; }
554 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800555
Lee Thomason7c913cd2012-01-26 18:32:34 -0800556 int Parse( const char* );
557 int Load( const char* );
558 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800559
Lee Thomason5cae8972012-01-24 18:03:07 -0800560 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800561 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800562
Lee Thomason2c85a712012-01-31 08:24:24 -0800563 XMLElement* NewElement( const char* name );
564
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800565 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800566 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800567 ERROR_ELEMENT_MISMATCH,
568 ERROR_PARSING_ELEMENT,
Lee Thomason50f97b22012-02-11 16:33:40 -0800569 ERROR_PARSING_ATTRIBUTE,
570 ERROR_IDENTIFYING_TAG
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800571 };
Lee Thomason67d61312012-01-24 16:01:51 -0800572 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800573
Lee Thomason7c913cd2012-01-26 18:32:34 -0800574 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800575 int GetErrorID() const { return errorID; }
576 const char* GetErrorStr1() const { return errorStr1; }
577 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800578
Lee Thomasond1983222012-02-06 08:41:24 -0800579 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800580
Lee Thomason3f57d272012-01-11 15:30:03 -0800581private:
Lee Thomasond1983222012-02-06 08:41:24 -0800582
Lee Thomason3f57d272012-01-11 15:30:03 -0800583 XMLDocument( const XMLDocument& ); // intentionally not implemented
Lee Thomason18d68bd2012-01-26 18:17:26 -0800584 void InitDocument();
585
Lee Thomason7c913cd2012-01-26 18:32:34 -0800586 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800587 const char* errorStr1;
588 const char* errorStr2;
589 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800590
591 MemPoolT< sizeof(XMLElement) > elementPool;
592 MemPoolT< sizeof(XMLAttribute) > attributePool;
593 MemPoolT< sizeof(XMLText) > textPool;
594 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800595};
596
Lee Thomason7c913cd2012-01-26 18:32:34 -0800597
Lee Thomason751da522012-02-10 08:50:51 -0800598class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800599{
600public:
601 XMLStreamer( FILE* file );
602 ~XMLStreamer() {}
603
Lee Thomason56bdd022012-02-09 18:16:58 -0800604 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800605 void PushAttribute( const char* name, const char* value );
606 void CloseElement();
607
Lee Thomason50f97b22012-02-11 16:33:40 -0800608 void PushText( const char* text, bool cdata=false );
Lee Thomason5cae8972012-01-24 18:03:07 -0800609 void PushComment( const char* comment );
610
Lee Thomason751da522012-02-10 08:50:51 -0800611 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
612 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
613
614 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
615 virtual bool VisitExit( const XMLElement& element );
616
617 virtual bool Visit( const XMLText& text );
618 virtual bool Visit( const XMLComment& comment );
619
620
Lee Thomason5cae8972012-01-24 18:03:07 -0800621private:
622 void SealElement();
623 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800624 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800625
626 FILE* fp;
627 int depth;
628 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800629 int textDepth;
630
Lee Thomason857b8682012-01-25 17:50:25 -0800631 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800632 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800633 };
634 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800635
Lee Thomason2c85a712012-01-31 08:24:24 -0800636 DynArray< const char*, 10 > stack;
Lee Thomason5cae8972012-01-24 18:03:07 -0800637};
638
639
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800640}; // tinyxml2
641
U-Lama\Lee560bd472011-12-28 19:42:49 -0800642
643
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800644#endif // TINYXML2_INCLUDED