blob: d02e5cd94a71e0697d15a27f1a6e70bbe162978f [file] [log] [blame]
U-Lama\Leee13c3e62011-12-28 14:36:55 -08001#ifndef TINYXML2_INCLUDED
2#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;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080053
Lee Thomason5cae8972012-01-24 18:03:07 -080054class XMLStreamer;
55
Lee Thomason39ede242012-01-20 11:27:56 -080056class StrPair
57{
Lee Thomasond34f52c2012-01-20 12:55:24 -080058public:
Lee Thomason39ede242012-01-20 11:27:56 -080059 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080060 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -080061 NEEDS_NEWLINE_NORMALIZATION = 0x02,
62
63 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
64 ATTRIBUTE_NAME = 0,
65 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
66 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -080067 };
68
69 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -080070 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -080071 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
72 }
73 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -080074 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -080075
Lee Thomason2c85a712012-01-31 08:24:24 -080076 void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
Lee Thomason56bdd022012-02-09 18:16:58 -080077 char* ParseText( char* in, const char* endTag, int strFlags );
78 char* ParseName( char* in );
79
Lee Thomason2c85a712012-01-31 08:24:24 -080080
Lee Thomason39ede242012-01-20 11:27:56 -080081private:
Lee Thomasone4422302012-01-20 17:59:50 -080082 enum {
83 NEEDS_FLUSH = 0x100
84 };
85
Lee Thomason39ede242012-01-20 11:27:56 -080086 // After parsing, if *end != 0, it can be set to zero.
87 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -080088 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -080089 char* end;
90};
91
U-Lama\Lee560bd472011-12-28 19:42:49 -080092
Lee Thomason2c85a712012-01-31 08:24:24 -080093template <class T, int INIT>
94class DynArray
95{
96public:
97 DynArray< T, INIT >()
98 {
99 mem = pool;
100 allocated = INIT;
101 size = 0;
102 }
103 ~DynArray()
104 {
105 if ( mem != pool ) {
106 delete mem;
107 }
108 }
109 void Push( T t )
110 {
111 EnsureCapacity( size+1 );
112 mem[size++] = t;
113 }
114
115 T* PushArr( int count )
116 {
117 EnsureCapacity( size+count );
118 T* ret = &mem[size];
119 size += count;
120 return ret;
121 }
122 T Pop() {
123 return mem[--size];
124 }
125 void PopArr( int count )
126 {
127 TIXMLASSERT( size >= count );
128 size -= count;
129 }
130
131 bool Empty() const { return size == 0; }
132 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
133 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
134 int Size() const { return size; }
135 const T* Mem() const { return mem; }
136 T* Mem() { return mem; }
137
138
139private:
140 void EnsureCapacity( int cap ) {
141 if ( cap > allocated ) {
142 int newAllocated = cap * 2;
143 T* newMem = new T[newAllocated];
144 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
145 if ( mem != pool ) delete [] mem;
146 mem = newMem;
147 allocated = newAllocated;
148 }
149 }
150
151 T* mem;
152 T pool[INIT];
153 int allocated; // objects allocated
154 int size; // number objects in use
155};
156
Lee Thomasond1983222012-02-06 08:41:24 -0800157class MemPool
158{
159public:
160 MemPool() {}
161 virtual ~MemPool() {}
162
163 virtual int ItemSize() const = 0;
164 virtual void* Alloc() = 0;
165 virtual void Free( void* ) = 0;
166};
167
168template< int SIZE >
169class MemPoolT : public MemPool
170{
171public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800172 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800173 ~MemPoolT() {
174 // Delete the blocks.
175 for( int i=0; i<blockPtrs.Size(); ++i ) {
176 delete blockPtrs[i];
177 }
178 }
179
180 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800181 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800182
183 virtual void* Alloc() {
184 if ( !root ) {
185 // Need a new block.
186 Block* block = new Block();
187 blockPtrs.Push( block );
188
189 for( int i=0; i<COUNT-1; ++i ) {
190 block->chunk[i].next = &block->chunk[i+1];
191 }
192 block->chunk[COUNT-1].next = 0;
193 root = block->chunk;
194 }
195 void* result = root;
196 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800197
198 ++currentAllocs;
199 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
200 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800201 return result;
202 }
203 virtual void Free( void* mem ) {
204 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800205 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800206 Chunk* chunk = (Chunk*)mem;
207 memset( chunk, 0xfe, sizeof(Chunk) );
208 chunk->next = root;
209 root = chunk;
210 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800211 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800212 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
213 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800214 }
Lee Thomasond1983222012-02-06 08:41:24 -0800215
216private:
217 enum { COUNT = 1024/SIZE };
218 union Chunk {
219 Chunk* next;
220 char mem[SIZE];
221 };
222 struct Block {
223 Chunk chunk[COUNT];
224 };
225 DynArray< Block*, 10 > blockPtrs;
226 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800227
228 int currentAllocs;
229 int nAllocs;
230 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800231};
232
Lee Thomason2c85a712012-01-31 08:24:24 -0800233
Lee Thomason56bdd022012-02-09 18:16:58 -0800234
235/**
236 Implements the interface to the "Visitor pattern" (see the Accept() method.)
237 If you call the Accept() method, it requires being passed a XMLVisitor
238 class to handle callbacks. For nodes that contain other nodes (Document, Element)
239 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
240 are simply called with Visit().
241
242 If you return 'true' from a Visit method, recursive parsing will continue. If you return
243 false, <b>no children of this node or its sibilings</b> will be Visited.
244
245 All flavors of Visit methods have a default implementation that returns 'true' (continue
246 visiting). You need to only override methods that are interesting to you.
247
248 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
249
250 You should never change the document from a callback.
251
252 @sa XMLNode::Accept()
253*/
254class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800255{
256public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800257 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800258
Lee Thomason56bdd022012-02-09 18:16:58 -0800259 /// Visit a document.
260 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
261 /// Visit a document.
262 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
263
264 /// Visit an element.
265 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
266 /// Visit an element.
267 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
268
269 /// Visit a declaration
270 //virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; }
271 /// Visit a text node
272 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
273 /// Visit a comment node
274 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
275 /// Visit an unknown node
276 //virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
277};
278
279
280class XMLUtil
281{
Lee Thomasond1983222012-02-06 08:41:24 -0800282public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800283 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
284 // correct, but simple, and usually works.
285 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
286 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800287
288 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
289 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800290 if ( p == q ) {
291 return true;
292 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800293 while( *p && *q && *p == *q && n<nChar ) {
294 ++p; ++q; ++n;
295 }
296 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
297 return true;
298 }
299 return false;
300 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800301 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800302 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
303 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800304};
305
Lee Thomason5cae8972012-01-24 18:03:07 -0800306
Lee Thomasond1983222012-02-06 08:41:24 -0800307class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800308{
309 friend class XMLDocument;
310 friend class XMLElement;
311public:
Lee Thomason751da522012-02-10 08:50:51 -0800312 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800313 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800314
Lee Thomason56bdd022012-02-09 18:16:58 -0800315 virtual XMLElement* ToElement() { return 0; }
316 virtual XMLText* ToText() { return 0; }
317 virtual XMLComment* ToComment() { return 0; }
318 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800319
Lee Thomason751da522012-02-10 08:50:51 -0800320 virtual const XMLElement* ToElement() const { return 0; }
321 virtual const XMLText* ToText() const { return 0; }
322 virtual const XMLComment* ToComment() const { return 0; }
323 virtual const XMLDocument* ToDocument() const { return 0; }
324
Lee Thomason2c85a712012-01-31 08:24:24 -0800325 const char* Value() const { return value.GetStr(); }
326 void SetValue( const char* val ) { value.SetInternedStr( val ); }
327
Lee Thomason751da522012-02-10 08:50:51 -0800328 const XMLNode* Parent() const { return parent; }
329 XMLNode* Parent() { return parent; }
330
331 /// Returns true if this node has no children.
332 bool NoChildren() const { return !firstChild; }
333
Lee Thomason56bdd022012-02-09 18:16:58 -0800334 const XMLNode* FirstChild() const { return firstChild; }
335 XMLNode* FirstChild() { return firstChild; }
336 const XMLElement* FirstChildElement( const char* value=0 ) const;
337 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800338
Lee Thomason56bdd022012-02-09 18:16:58 -0800339 const XMLNode* LastChild() const { return lastChild; }
340 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800341
Lee Thomason56bdd022012-02-09 18:16:58 -0800342 const XMLElement* LastChildElement( const char* value=0 ) const;
343 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
344
345 const XMLNode* PreviousSibling() const { return prev; }
346 XMLNode* PreviousSibling() { return prev; }
347
348 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
349 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
350
351 const XMLNode* NextSibling() const { return next; }
352 XMLNode* NextSibling() { return next; }
353
354 const XMLNode* NextSiblingElement( const char* value=0 ) const;
355 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
356
357 XMLNode* InsertEndChild( XMLNode* addThis );
358 XMLNode* InsertFirstChild( XMLNode* addThis );
359 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
360
361 void ClearChildren();
362 void DeleteChild( XMLNode* node );
363
364 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason751da522012-02-10 08:50:51 -0800365 //virtual void Print( XMLStreamer* streamer );
Lee Thomason56bdd022012-02-09 18:16:58 -0800366
Lee Thomason67d61312012-01-24 16:01:51 -0800367 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800368 void SetTextParent() { isTextParent = true; }
369 bool IsTextParent() const { return isTextParent; }
370 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800371
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800372protected:
373 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800374 virtual ~XMLNode();
375
Lee Thomason3f57d272012-01-11 15:30:03 -0800376 XMLDocument* document;
377 XMLNode* parent;
Lee Thomason67d61312012-01-24 16:01:51 -0800378 bool isTextParent;
Lee Thomason2c85a712012-01-31 08:24:24 -0800379 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800380
381 XMLNode* firstChild;
382 XMLNode* lastChild;
383
384 XMLNode* prev;
385 XMLNode* next;
386
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800387private:
Lee Thomasond1983222012-02-06 08:41:24 -0800388 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800389 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800390};
391
392
Lee Thomason5492a1c2012-01-23 15:32:10 -0800393class XMLText : public XMLNode
394{
Lee Thomason2c85a712012-01-31 08:24:24 -0800395 friend class XMLBase;
396 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800397public:
Lee Thomason751da522012-02-10 08:50:51 -0800398 //virtual void Print( XMLStreamer* streamer );
Lee Thomason2c85a712012-01-31 08:24:24 -0800399
Lee Thomason56bdd022012-02-09 18:16:58 -0800400 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800401 virtual XMLText* ToText() { return this; }
402 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800403
404 char* ParseDeep( char* );
405
406protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800407 XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800408 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800409
410private:
Lee Thomason5492a1c2012-01-23 15:32:10 -0800411};
412
413
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800414class XMLComment : public XMLNode
415{
Lee Thomason2c85a712012-01-31 08:24:24 -0800416 friend class XMLBase;
417 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800418public:
Lee Thomason751da522012-02-10 08:50:51 -0800419 virtual XMLComment* ToComment() { return this; }
420 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800421
Lee Thomason56bdd022012-02-09 18:16:58 -0800422 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800423
Lee Thomasonce0763e2012-01-11 15:43:54 -0800424 char* ParseDeep( char* );
425
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800426protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800427 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800428 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800429
Lee Thomason3f57d272012-01-11 15:30:03 -0800430private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800431};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800432
433
Lee Thomason56bdd022012-02-09 18:16:58 -0800434class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800435{
436 friend class XMLElement;
437public:
Lee Thomason751da522012-02-10 08:50:51 -0800438 //virtual void Print( XMLStreamer* streamer );
439
440 const char* Name() const { return name.GetStr(); }
441 const char* Value() const { return value.GetStr(); }
442 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800443
444private:
Lee Thomasond1983222012-02-06 08:41:24 -0800445 XMLAttribute( XMLElement* element ) : next( 0 ) {}
446 virtual ~XMLAttribute() {}
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800447 char* ParseDeep( char* p );
448
Lee Thomason751da522012-02-10 08:50:51 -0800449 mutable StrPair name;
450 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800451 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800452 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800453};
454
455
456class XMLElement : public XMLNode
457{
Lee Thomason2c85a712012-01-31 08:24:24 -0800458 friend class XMLBase;
459 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800460public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800461 const char* Name() const { return Value(); }
462 void SetName( const char* str ) { SetValue( str ); }
463
Lee Thomason751da522012-02-10 08:50:51 -0800464 virtual XMLElement* ToElement() { return this; }
465 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800466 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800467
Lee Thomason751da522012-02-10 08:50:51 -0800468 const char* Attribute( const char* name ) const;
469
470 int QueryIntAttribute( const char* name, int* value ) const;
471 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const;
472 int QueryBoolAttribute( const char* name, bool* value ) const;
473 int QueryDoubleAttribute( const char* name, double* _value ) const;
474 int QueryFloatAttribute( const char* name, float* _value ) const;
475
476 void SetAttribute( const char* name, const char* value );
477 void SetAttribute( const char* name, int value );
478 void SetAttribute( const char* name, unsigned value );
479 void SetAttribute( const char* name, bool value );
480 void SetAttribute( const char* name, double value );
481
482 void RemoveAttribute( const char* name );
483
484 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
485
486 const char* GetText() const;
487
Lee Thomason2c85a712012-01-31 08:24:24 -0800488 // internal:
489 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800490 char* ParseDeep( char* p );
491
492protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800493 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800494 virtual ~XMLElement();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800495
496private:
Lee Thomason67d61312012-01-24 16:01:51 -0800497 char* ParseAttributes( char* p, bool *closedElement );
498
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800499 bool closing;
500 XMLAttribute* rootAttribute;
Lee Thomason751da522012-02-10 08:50:51 -0800501 XMLAttribute* lastAttribute; // fixme: remove
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800502};
503
504
Lee Thomason67d61312012-01-24 16:01:51 -0800505class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800506{
Lee Thomasond1983222012-02-06 08:41:24 -0800507 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800508public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800509 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800510 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800511
Lee Thomason751da522012-02-10 08:50:51 -0800512 virtual XMLDocument* ToDocument() { return this; }
513 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800514
Lee Thomason7c913cd2012-01-26 18:32:34 -0800515 int Parse( const char* );
516 int Load( const char* );
517 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800518
Lee Thomason5cae8972012-01-24 18:03:07 -0800519 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800520 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800521
Lee Thomason2c85a712012-01-31 08:24:24 -0800522 XMLElement* NewElement( const char* name );
523
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800524 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800525 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800526 ERROR_ELEMENT_MISMATCH,
527 ERROR_PARSING_ELEMENT,
528 ERROR_PARSING_ATTRIBUTE
529 };
Lee Thomason67d61312012-01-24 16:01:51 -0800530 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800531
Lee Thomason7c913cd2012-01-26 18:32:34 -0800532 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800533 int GetErrorID() const { return errorID; }
534 const char* GetErrorStr1() const { return errorStr1; }
535 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800536
Lee Thomasond1983222012-02-06 08:41:24 -0800537 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800538
Lee Thomason3f57d272012-01-11 15:30:03 -0800539private:
Lee Thomasond1983222012-02-06 08:41:24 -0800540
Lee Thomason3f57d272012-01-11 15:30:03 -0800541 XMLDocument( const XMLDocument& ); // intentionally not implemented
Lee Thomason18d68bd2012-01-26 18:17:26 -0800542 void InitDocument();
543
Lee Thomason7c913cd2012-01-26 18:32:34 -0800544 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800545 const char* errorStr1;
546 const char* errorStr2;
547 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800548
549 MemPoolT< sizeof(XMLElement) > elementPool;
550 MemPoolT< sizeof(XMLAttribute) > attributePool;
551 MemPoolT< sizeof(XMLText) > textPool;
552 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800553};
554
Lee Thomason7c913cd2012-01-26 18:32:34 -0800555
Lee Thomason751da522012-02-10 08:50:51 -0800556class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800557{
558public:
559 XMLStreamer( FILE* file );
560 ~XMLStreamer() {}
561
Lee Thomason56bdd022012-02-09 18:16:58 -0800562 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800563 void PushAttribute( const char* name, const char* value );
564 void CloseElement();
565
566 void PushText( const char* text );
567 void PushComment( const char* comment );
568
Lee Thomason751da522012-02-10 08:50:51 -0800569 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
570 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
571
572 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
573 virtual bool VisitExit( const XMLElement& element );
574
575 virtual bool Visit( const XMLText& text );
576 virtual bool Visit( const XMLComment& comment );
577
578
Lee Thomason5cae8972012-01-24 18:03:07 -0800579private:
580 void SealElement();
581 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800582 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800583
584 FILE* fp;
585 int depth;
586 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800587 int textDepth;
588
Lee Thomason857b8682012-01-25 17:50:25 -0800589 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800590 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800591 };
592 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800593
Lee Thomason2c85a712012-01-31 08:24:24 -0800594 DynArray< const char*, 10 > stack;
Lee Thomason5cae8972012-01-24 18:03:07 -0800595};
596
597
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800598}; // tinyxml2
599
U-Lama\Lee560bd472011-12-28 19:42:49 -0800600
601
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800602#endif // TINYXML2_INCLUDED