blob: cfe297f1058c9fd1b0ebdde5d78df0bf7d03b015 [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
234/*
235class StringStack
236{
237public:
238 StringStack();
239 virtual ~StringStack();
240
241 void Push( const char* str );
242 const char* Pop();
243
244 int NumPositive() const { return nPositive; }
245
246private:
247 DynArray< char, 50 > mem;
248 int nPositive; // number of strings with len > 0
249};
250*/
251
252/*
253class StringPool
254{
255public:
256 enum { INIT_SIZE=20 };
257
258 StringPool() : size( 0 ) {
259 const char** mem = pool.PushArr( INIT_SIZE );
260 memset( (void*)mem, 0, sizeof(char)*INIT_SIZE );
261 }
262 ~StringPool() {}
263
264 const char* Intern( const char* str );
265
266private:
267 // FNV hash
268 int Hash( const char* s ) {
269 #define FNV_32_PRIME ((int)0x01000193)
270 int hval = 0;
271 while (*s) {
272 hval *= FNV_32_PRIME;
273 hval ^= (int)*s++;
274 }
275 return hval;
276 }
277
278 int size;
279 DynArray< const char*, INIT_SIZE > pool; // the hash table
280 StringStack store; // memory for the interned strings
281};
282*/
283
Lee Thomason56bdd022012-02-09 18:16:58 -0800284
285/**
286 Implements the interface to the "Visitor pattern" (see the Accept() method.)
287 If you call the Accept() method, it requires being passed a XMLVisitor
288 class to handle callbacks. For nodes that contain other nodes (Document, Element)
289 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
290 are simply called with Visit().
291
292 If you return 'true' from a Visit method, recursive parsing will continue. If you return
293 false, <b>no children of this node or its sibilings</b> will be Visited.
294
295 All flavors of Visit methods have a default implementation that returns 'true' (continue
296 visiting). You need to only override methods that are interesting to you.
297
298 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
299
300 You should never change the document from a callback.
301
302 @sa XMLNode::Accept()
303*/
304class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800305{
306public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800307 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800308
Lee Thomason56bdd022012-02-09 18:16:58 -0800309 /// Visit a document.
310 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
311 /// Visit a document.
312 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
313
314 /// Visit an element.
315 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
316 /// Visit an element.
317 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
318
319 /// Visit a declaration
320 //virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; }
321 /// Visit a text node
322 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
323 /// Visit a comment node
324 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
325 /// Visit an unknown node
326 //virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; }
327};
328
329
330class XMLUtil
331{
Lee Thomasond1983222012-02-06 08:41:24 -0800332public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800333 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
334 // correct, but simple, and usually works.
335 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
336 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800337
338 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
339 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800340 if ( p == q ) {
341 return true;
342 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800343 while( *p && *q && *p == *q && n<nChar ) {
344 ++p; ++q; ++n;
345 }
346 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
347 return true;
348 }
349 return false;
350 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800351 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800352 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
353 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800354};
355
Lee Thomason5cae8972012-01-24 18:03:07 -0800356
Lee Thomasond1983222012-02-06 08:41:24 -0800357class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800358{
359 friend class XMLDocument;
360 friend class XMLElement;
361public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800362 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800363
Lee Thomason56bdd022012-02-09 18:16:58 -0800364 virtual XMLElement* ToElement() { return 0; }
365 virtual XMLText* ToText() { return 0; }
366 virtual XMLComment* ToComment() { return 0; }
367 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800368
Lee Thomason2c85a712012-01-31 08:24:24 -0800369 const char* Value() const { return value.GetStr(); }
370 void SetValue( const char* val ) { value.SetInternedStr( val ); }
371
Lee Thomason56bdd022012-02-09 18:16:58 -0800372 const XMLNode* FirstChild() const { return firstChild; }
373 XMLNode* FirstChild() { return firstChild; }
374 const XMLElement* FirstChildElement( const char* value=0 ) const;
375 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800376
Lee Thomason56bdd022012-02-09 18:16:58 -0800377 const XMLNode* LastChild() const { return lastChild; }
378 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800379
Lee Thomason56bdd022012-02-09 18:16:58 -0800380 const XMLElement* LastChildElement( const char* value=0 ) const;
381 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
382
383 const XMLNode* PreviousSibling() const { return prev; }
384 XMLNode* PreviousSibling() { return prev; }
385
386 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
387 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
388
389 const XMLNode* NextSibling() const { return next; }
390 XMLNode* NextSibling() { return next; }
391
392 const XMLNode* NextSiblingElement( const char* value=0 ) const;
393 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
394
395 XMLNode* InsertEndChild( XMLNode* addThis );
396 XMLNode* InsertFirstChild( XMLNode* addThis );
397 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
398
399 void ClearChildren();
400 void DeleteChild( XMLNode* node );
401
402 virtual bool Accept( XMLVisitor* visitor ) const = 0;
403 virtual void Print( XMLStreamer* streamer );
404
Lee Thomason67d61312012-01-24 16:01:51 -0800405 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800406 void SetTextParent() { isTextParent = true; }
407 bool IsTextParent() const { return isTextParent; }
408 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800409
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800410protected:
411 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800412 virtual ~XMLNode();
413
Lee Thomason3f57d272012-01-11 15:30:03 -0800414 XMLDocument* document;
415 XMLNode* parent;
Lee Thomason67d61312012-01-24 16:01:51 -0800416 bool isTextParent;
Lee Thomason2c85a712012-01-31 08:24:24 -0800417 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800418
419 XMLNode* firstChild;
420 XMLNode* lastChild;
421
422 XMLNode* prev;
423 XMLNode* next;
424
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800425private:
Lee Thomasond1983222012-02-06 08:41:24 -0800426 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800427 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800428};
429
430
Lee Thomason5492a1c2012-01-23 15:32:10 -0800431class XMLText : public XMLNode
432{
Lee Thomason2c85a712012-01-31 08:24:24 -0800433 friend class XMLBase;
434 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800435public:
Lee Thomason5cae8972012-01-24 18:03:07 -0800436 virtual void Print( XMLStreamer* streamer );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800437 const char* Value() { return value.GetStr(); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800438 void SetValue( const char* );
439
Lee Thomason56bdd022012-02-09 18:16:58 -0800440 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800441 virtual XMLText* ToText() { return this; }
442
443 char* ParseDeep( char* );
444
445protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800446 XMLText( XMLDocument* doc ) : XMLNode( doc ) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800447 virtual ~XMLText() {}
Lee Thomason5492a1c2012-01-23 15:32:10 -0800448
449private:
Lee Thomason5492a1c2012-01-23 15:32:10 -0800450};
451
452
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800453class XMLComment : public XMLNode
454{
Lee Thomason2c85a712012-01-31 08:24:24 -0800455 friend class XMLBase;
456 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800457public:
Lee Thomason5cae8972012-01-24 18:03:07 -0800458 virtual void Print( XMLStreamer* );
Lee Thomason5492a1c2012-01-23 15:32:10 -0800459 virtual XMLComment* ToComment() { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800460
Lee Thomasond34f52c2012-01-20 12:55:24 -0800461 const char* Value() { return value.GetStr(); }
Lee Thomason56bdd022012-02-09 18:16:58 -0800462 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800463
Lee Thomasonce0763e2012-01-11 15:43:54 -0800464 char* ParseDeep( char* );
465
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800466protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800467 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800468 virtual ~XMLComment();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800469
Lee Thomason3f57d272012-01-11 15:30:03 -0800470private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800471};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800472
473
Lee Thomason56bdd022012-02-09 18:16:58 -0800474class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800475{
476 friend class XMLElement;
477public:
Lee Thomason5cae8972012-01-24 18:03:07 -0800478 virtual void Print( XMLStreamer* streamer );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800479
480private:
Lee Thomasond1983222012-02-06 08:41:24 -0800481 XMLAttribute( XMLElement* element ) : next( 0 ) {}
482 virtual ~XMLAttribute() {}
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800483 char* ParseDeep( char* p );
484
Lee Thomason22aead12012-01-23 13:29:35 -0800485 StrPair name;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800486 StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800487 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800488 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800489};
490
491
492class XMLElement : public XMLNode
493{
Lee Thomason2c85a712012-01-31 08:24:24 -0800494 friend class XMLBase;
495 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800496public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800497 const char* Name() const { return Value(); }
498 void SetName( const char* str ) { SetValue( str ); }
499
Lee Thomason5cae8972012-01-24 18:03:07 -0800500 virtual void Print( XMLStreamer* );
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800501
502 virtual XMLElement* ToElement() { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800503 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800504
Lee Thomason2c85a712012-01-31 08:24:24 -0800505 // internal:
506 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800507 char* ParseDeep( char* p );
508
509protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800510 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800511 virtual ~XMLElement();
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800512
513private:
Lee Thomason67d61312012-01-24 16:01:51 -0800514 char* ParseAttributes( char* p, bool *closedElement );
515
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800516 bool closing;
517 XMLAttribute* rootAttribute;
518 XMLAttribute* lastAttribute;
519};
520
521
Lee Thomason67d61312012-01-24 16:01:51 -0800522class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800523{
Lee Thomasond1983222012-02-06 08:41:24 -0800524 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800525public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800526 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800527 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800528
Lee Thomason56bdd022012-02-09 18:16:58 -0800529 virtual XMLDocument* ToDocument() { return this; }
530
Lee Thomason7c913cd2012-01-26 18:32:34 -0800531 int Parse( const char* );
532 int Load( const char* );
533 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800534
Lee Thomason5cae8972012-01-24 18:03:07 -0800535 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800536 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800537
Lee Thomason2c85a712012-01-31 08:24:24 -0800538 XMLElement* NewElement( const char* name );
539
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800540 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800541 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800542 ERROR_ELEMENT_MISMATCH,
543 ERROR_PARSING_ELEMENT,
544 ERROR_PARSING_ATTRIBUTE
545 };
Lee Thomason67d61312012-01-24 16:01:51 -0800546 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800547
Lee Thomason7c913cd2012-01-26 18:32:34 -0800548 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800549 int GetErrorID() const { return errorID; }
550 const char* GetErrorStr1() const { return errorStr1; }
551 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800552
Lee Thomasond1983222012-02-06 08:41:24 -0800553 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800554
Lee Thomason3f57d272012-01-11 15:30:03 -0800555private:
Lee Thomasond1983222012-02-06 08:41:24 -0800556
Lee Thomason3f57d272012-01-11 15:30:03 -0800557 XMLDocument( const XMLDocument& ); // intentionally not implemented
Lee Thomason18d68bd2012-01-26 18:17:26 -0800558 void InitDocument();
559
Lee Thomason7c913cd2012-01-26 18:32:34 -0800560 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800561 const char* errorStr1;
562 const char* errorStr2;
563 char* charBuffer;
Lee Thomason2c85a712012-01-31 08:24:24 -0800564 //StringStack stringPool;
Lee Thomasond1983222012-02-06 08:41:24 -0800565
566 MemPoolT< sizeof(XMLElement) > elementPool;
567 MemPoolT< sizeof(XMLAttribute) > attributePool;
568 MemPoolT< sizeof(XMLText) > textPool;
569 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800570};
571
Lee Thomason7c913cd2012-01-26 18:32:34 -0800572
Lee Thomason56bdd022012-02-09 18:16:58 -0800573class XMLStreamer
Lee Thomason5cae8972012-01-24 18:03:07 -0800574{
575public:
576 XMLStreamer( FILE* file );
577 ~XMLStreamer() {}
578
Lee Thomason56bdd022012-02-09 18:16:58 -0800579 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800580 void PushAttribute( const char* name, const char* value );
581 void CloseElement();
582
583 void PushText( const char* text );
584 void PushComment( const char* comment );
585
586private:
587 void SealElement();
588 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800589 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason56bdd022012-02-09 18:16:58 -0800590/* bool TextOnStack() const {
Lee Thomason2c85a712012-01-31 08:24:24 -0800591 for( int i=0; i<text.Size(); ++i ) {
592 if ( text[i] == 'T' )
593 return true;
594 }
595 return false;
Lee Thomason56bdd022012-02-09 18:16:58 -0800596 }*/
Lee Thomason5cae8972012-01-24 18:03:07 -0800597
598 FILE* fp;
599 int depth;
600 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800601 int textDepth;
602
Lee Thomason857b8682012-01-25 17:50:25 -0800603 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800604 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800605 };
606 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800607
Lee Thomason2c85a712012-01-31 08:24:24 -0800608 DynArray< const char*, 10 > stack;
Lee Thomason56bdd022012-02-09 18:16:58 -0800609 //DynArray< char, 10 > text;
Lee Thomason5cae8972012-01-24 18:03:07 -0800610};
611
612
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800613}; // tinyxml2
614
U-Lama\Lee560bd472011-12-28 19:42:49 -0800615
616
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800617#endif // TINYXML2_INCLUDED