blob: 066e38d0e5cac35da4e0b5a7ea1ab374128d6d78 [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.
Lee Thomason50adb4c2012-02-13 15:07:09 -080016 - tests from xml1
17 - perf test: xml1
18 - perf test: xenowar
Lee Thomason2c85a712012-01-31 08:24:24 -080019*/
20
U-Lama\Lee4cee6112011-12-31 14:58:18 -080021#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -080022#include <ctype.h>
23#include <stdio.h>
Lee Thomason2c85a712012-01-31 08:24:24 -080024#include <memory.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -080025
26#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
27 #ifndef DEBUG
28 #define DEBUG
29 #endif
30#endif
31
32
33#if defined(DEBUG)
34 #if defined(_MSC_VER)
35 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
36 #elif defined (ANDROID_NDK)
37 #include <android/log.h>
38 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
39 #else
40 #include <assert.h>
41 #define TIXMLASSERT assert
42 #endif
43#else
44 #define TIXMLASSERT( x ) {}
45#endif
46
U-Lama\Leee13c3e62011-12-28 14:36:55 -080047
48namespace tinyxml2
49{
Lee Thomasonce0763e2012-01-11 15:43:54 -080050class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080051class XMLElement;
52class XMLAttribute;
53class XMLComment;
54class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080055class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080056class XMLDeclaration;
57class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080058
Lee Thomason5cae8972012-01-24 18:03:07 -080059class XMLStreamer;
60
Lee Thomason39ede242012-01-20 11:27:56 -080061class StrPair
62{
Lee Thomasond34f52c2012-01-20 12:55:24 -080063public:
Lee Thomason39ede242012-01-20 11:27:56 -080064 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080065 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -080066 NEEDS_NEWLINE_NORMALIZATION = 0x02,
67
68 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
69 ATTRIBUTE_NAME = 0,
70 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
71 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -080072 };
73
74 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -080075 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -080076 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
77 }
78 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -080079 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -080080
Lee Thomason2c85a712012-01-31 08:24:24 -080081 void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
Lee Thomason56bdd022012-02-09 18:16:58 -080082 char* ParseText( char* in, const char* endTag, int strFlags );
83 char* ParseName( char* in );
84
Lee Thomason2c85a712012-01-31 08:24:24 -080085
Lee Thomason39ede242012-01-20 11:27:56 -080086private:
Lee Thomasone4422302012-01-20 17:59:50 -080087 enum {
88 NEEDS_FLUSH = 0x100
89 };
90
Lee Thomason39ede242012-01-20 11:27:56 -080091 // After parsing, if *end != 0, it can be set to zero.
92 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -080093 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -080094 char* end;
95};
96
U-Lama\Lee560bd472011-12-28 19:42:49 -080097
Lee Thomason2c85a712012-01-31 08:24:24 -080098template <class T, int INIT>
99class DynArray
100{
101public:
102 DynArray< T, INIT >()
103 {
104 mem = pool;
105 allocated = INIT;
106 size = 0;
107 }
108 ~DynArray()
109 {
110 if ( mem != pool ) {
111 delete mem;
112 }
113 }
114 void Push( T t )
115 {
116 EnsureCapacity( size+1 );
117 mem[size++] = t;
118 }
119
120 T* PushArr( int count )
121 {
122 EnsureCapacity( size+count );
123 T* ret = &mem[size];
124 size += count;
125 return ret;
126 }
127 T Pop() {
128 return mem[--size];
129 }
130 void PopArr( int count )
131 {
132 TIXMLASSERT( size >= count );
133 size -= count;
134 }
135
136 bool Empty() const { return size == 0; }
137 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
138 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
139 int Size() const { return size; }
140 const T* Mem() const { return mem; }
141 T* Mem() { return mem; }
142
143
144private:
145 void EnsureCapacity( int cap ) {
146 if ( cap > allocated ) {
147 int newAllocated = cap * 2;
148 T* newMem = new T[newAllocated];
149 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
150 if ( mem != pool ) delete [] mem;
151 mem = newMem;
152 allocated = newAllocated;
153 }
154 }
155
156 T* mem;
157 T pool[INIT];
158 int allocated; // objects allocated
159 int size; // number objects in use
160};
161
Lee Thomason50adb4c2012-02-13 15:07:09 -0800162
Lee Thomasond1983222012-02-06 08:41:24 -0800163class MemPool
164{
165public:
166 MemPool() {}
167 virtual ~MemPool() {}
168
169 virtual int ItemSize() const = 0;
170 virtual void* Alloc() = 0;
171 virtual void Free( void* ) = 0;
172};
173
Lee Thomason50adb4c2012-02-13 15:07:09 -0800174
Lee Thomasond1983222012-02-06 08:41:24 -0800175template< int SIZE >
176class MemPoolT : public MemPool
177{
178public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800179 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800180 ~MemPoolT() {
181 // Delete the blocks.
182 for( int i=0; i<blockPtrs.Size(); ++i ) {
183 delete blockPtrs[i];
184 }
185 }
186
187 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800188 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800189
190 virtual void* Alloc() {
191 if ( !root ) {
192 // Need a new block.
193 Block* block = new Block();
194 blockPtrs.Push( block );
195
196 for( int i=0; i<COUNT-1; ++i ) {
197 block->chunk[i].next = &block->chunk[i+1];
198 }
199 block->chunk[COUNT-1].next = 0;
200 root = block->chunk;
201 }
202 void* result = root;
203 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800204
205 ++currentAllocs;
206 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
207 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800208 return result;
209 }
210 virtual void Free( void* mem ) {
211 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800212 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800213 Chunk* chunk = (Chunk*)mem;
214 memset( chunk, 0xfe, sizeof(Chunk) );
215 chunk->next = root;
216 root = chunk;
217 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800218 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800219 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
220 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800221 }
Lee Thomasond1983222012-02-06 08:41:24 -0800222
223private:
224 enum { COUNT = 1024/SIZE };
225 union Chunk {
226 Chunk* next;
227 char mem[SIZE];
228 };
229 struct Block {
230 Chunk chunk[COUNT];
231 };
232 DynArray< Block*, 10 > blockPtrs;
233 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800234
235 int currentAllocs;
236 int nAllocs;
237 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800238};
239
Lee Thomason2c85a712012-01-31 08:24:24 -0800240
Lee Thomason56bdd022012-02-09 18:16:58 -0800241
242/**
243 Implements the interface to the "Visitor pattern" (see the Accept() method.)
244 If you call the Accept() method, it requires being passed a XMLVisitor
245 class to handle callbacks. For nodes that contain other nodes (Document, Element)
246 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
247 are simply called with Visit().
248
249 If you return 'true' from a Visit method, recursive parsing will continue. If you return
250 false, <b>no children of this node or its sibilings</b> will be Visited.
251
252 All flavors of Visit methods have a default implementation that returns 'true' (continue
253 visiting). You need to only override methods that are interesting to you.
254
255 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
256
257 You should never change the document from a callback.
258
259 @sa XMLNode::Accept()
260*/
261class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800262{
263public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800264 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800265
Lee Thomason56bdd022012-02-09 18:16:58 -0800266 /// Visit a document.
267 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
268 /// Visit a document.
269 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
270
271 /// Visit an element.
272 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
273 /// Visit an element.
274 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
275
276 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800277 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800278 /// Visit a text node
279 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
280 /// Visit a comment node
281 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
282 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800283 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800284};
285
286
287class XMLUtil
288{
Lee Thomasond1983222012-02-06 08:41:24 -0800289public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800290 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
291 // correct, but simple, and usually works.
292 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
293 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800294
295 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
296 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800297 if ( p == q ) {
298 return true;
299 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800300 while( *p && *q && *p == *q && n<nChar ) {
301 ++p; ++q; ++n;
302 }
303 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
304 return true;
305 }
306 return false;
307 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800308 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800309 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
310 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800311};
312
Lee Thomason5cae8972012-01-24 18:03:07 -0800313
Lee Thomasond1983222012-02-06 08:41:24 -0800314class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800315{
316 friend class XMLDocument;
317 friend class XMLElement;
318public:
Lee Thomason751da522012-02-10 08:50:51 -0800319 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800320 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800321
Lee Thomason56bdd022012-02-09 18:16:58 -0800322 virtual XMLElement* ToElement() { return 0; }
323 virtual XMLText* ToText() { return 0; }
324 virtual XMLComment* ToComment() { return 0; }
325 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason50f97b22012-02-11 16:33:40 -0800326 virtual XMLDeclaration* ToDeclaration() { return 0; }
327 virtual XMLUnknown* ToUnknown() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800328
Lee Thomason50f97b22012-02-11 16:33:40 -0800329 virtual const XMLElement* ToElement() const { return 0; }
330 virtual const XMLText* ToText() const { return 0; }
331 virtual const XMLComment* ToComment() const { return 0; }
332 virtual const XMLDocument* ToDocument() const { return 0; }
333 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
334 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800335
Lee Thomason2c85a712012-01-31 08:24:24 -0800336 const char* Value() const { return value.GetStr(); }
337 void SetValue( const char* val ) { value.SetInternedStr( val ); }
338
Lee Thomason751da522012-02-10 08:50:51 -0800339 const XMLNode* Parent() const { return parent; }
340 XMLNode* Parent() { return parent; }
341
Lee Thomason50f97b22012-02-11 16:33:40 -0800342 /// Returns true if this node has no children.
343 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800344
Lee Thomason56bdd022012-02-09 18:16:58 -0800345 const XMLNode* FirstChild() const { return firstChild; }
346 XMLNode* FirstChild() { return firstChild; }
347 const XMLElement* FirstChildElement( const char* value=0 ) const;
348 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800349
Lee Thomason56bdd022012-02-09 18:16:58 -0800350 const XMLNode* LastChild() const { return lastChild; }
351 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800352
Lee Thomason56bdd022012-02-09 18:16:58 -0800353 const XMLElement* LastChildElement( const char* value=0 ) const;
354 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
355
356 const XMLNode* PreviousSibling() const { return prev; }
357 XMLNode* PreviousSibling() { return prev; }
358
359 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
360 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
361
362 const XMLNode* NextSibling() const { return next; }
363 XMLNode* NextSibling() { return next; }
364
365 const XMLNode* NextSiblingElement( const char* value=0 ) const;
366 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
367
368 XMLNode* InsertEndChild( XMLNode* addThis );
369 XMLNode* InsertFirstChild( XMLNode* addThis );
370 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
371
372 void ClearChildren();
373 void DeleteChild( XMLNode* node );
374
375 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason751da522012-02-10 08:50:51 -0800376 //virtual void Print( XMLStreamer* streamer );
Lee Thomason56bdd022012-02-09 18:16:58 -0800377
Lee Thomason67d61312012-01-24 16:01:51 -0800378 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800379 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800380
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800381protected:
382 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800383 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800384 XMLNode( const XMLNode& ); // not supported
385 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800386
Lee Thomason3f57d272012-01-11 15:30:03 -0800387 XMLDocument* document;
388 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800389 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800390
391 XMLNode* firstChild;
392 XMLNode* lastChild;
393
394 XMLNode* prev;
395 XMLNode* next;
396
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800397private:
Lee Thomasond1983222012-02-06 08:41:24 -0800398 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800399 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800400};
401
402
Lee Thomason5492a1c2012-01-23 15:32:10 -0800403class XMLText : public XMLNode
404{
Lee Thomason2c85a712012-01-31 08:24:24 -0800405 friend class XMLBase;
406 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800407public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800408 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800409
Lee Thomason751da522012-02-10 08:50:51 -0800410 virtual XMLText* ToText() { return this; }
411 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800412
Lee Thomason50f97b22012-02-11 16:33:40 -0800413 void SetCData( bool value ) { isCData = true; }
414 bool CData() const { return isCData; }
415
Lee Thomason5492a1c2012-01-23 15:32:10 -0800416 char* ParseDeep( char* );
417
418protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800419 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
420 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800421 XMLText( const XMLText& ); // not supported
422 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800423
424private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800425 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800426};
427
428
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800429class XMLComment : public XMLNode
430{
Lee Thomason2c85a712012-01-31 08:24:24 -0800431 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800432public:
Lee Thomason751da522012-02-10 08:50:51 -0800433 virtual XMLComment* ToComment() { return this; }
434 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800435
Lee Thomason56bdd022012-02-09 18:16:58 -0800436 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800437
Lee Thomasonce0763e2012-01-11 15:43:54 -0800438 char* ParseDeep( char* );
439
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800440protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800441 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800442 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800443 XMLComment( const XMLComment& ); // not supported
444 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800445
Lee Thomason3f57d272012-01-11 15:30:03 -0800446private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800447};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800448
449
Lee Thomason50f97b22012-02-11 16:33:40 -0800450class XMLDeclaration : public XMLNode
451{
452 friend class XMLDocument;
453public:
454 virtual XMLDeclaration* ToDeclaration() { return this; }
455 virtual const XMLDeclaration* ToDeclaration() const { return this; }
456
457 virtual bool Accept( XMLVisitor* visitor ) const;
458
459 char* ParseDeep( char* );
460
461protected:
462 XMLDeclaration( XMLDocument* doc );
463 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800464 XMLDeclaration( const XMLDeclaration& ); // not supported
465 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800466};
467
468
469class XMLUnknown : public XMLNode
470{
471 friend class XMLDocument;
472public:
473 virtual XMLUnknown* ToUnknown() { return this; }
474 virtual const XMLUnknown* ToUnknown() const { return this; }
475
476 virtual bool Accept( XMLVisitor* visitor ) const;
477
478 char* ParseDeep( char* );
479
480protected:
481 XMLUnknown( XMLDocument* doc );
482 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800483 XMLUnknown( const XMLUnknown& ); // not supported
484 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800485};
486
487
Lee Thomason56bdd022012-02-09 18:16:58 -0800488class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800489{
490 friend class XMLElement;
491public:
Lee Thomason751da522012-02-10 08:50:51 -0800492 const char* Name() const { return name.GetStr(); }
493 const char* Value() const { return value.GetStr(); }
494 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800495
Lee Thomason50adb4c2012-02-13 15:07:09 -0800496 int QueryIntAttribute( const char* name, int* value ) const;
497 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const;
498 int QueryBoolAttribute( const char* name, bool* value ) const;
499 int QueryDoubleAttribute( const char* name, double* _value ) const;
500 int QueryFloatAttribute( const char* name, float* _value ) const;
501
502 void SetAttribute( const char* name, const char* value );
503 void SetAttribute( const char* name, int value );
504 void SetAttribute( const char* name, unsigned value );
505 void SetAttribute( const char* name, bool value );
506 void SetAttribute( const char* name, double value );
507
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800508private:
Lee Thomasond1983222012-02-06 08:41:24 -0800509 XMLAttribute( XMLElement* element ) : next( 0 ) {}
510 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800511 XMLAttribute( const XMLAttribute& ); // not supported
512 void operator=( const XMLAttribute& ); // not supported
513
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800514 char* ParseDeep( char* p );
515
Lee Thomason751da522012-02-10 08:50:51 -0800516 mutable StrPair name;
517 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800518 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800519 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800520};
521
522
523class XMLElement : public XMLNode
524{
Lee Thomason2c85a712012-01-31 08:24:24 -0800525 friend class XMLBase;
526 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800527public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800528 const char* Name() const { return Value(); }
529 void SetName( const char* str ) { SetValue( str ); }
530
Lee Thomason751da522012-02-10 08:50:51 -0800531 virtual XMLElement* ToElement() { return this; }
532 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800533 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800534
Lee Thomason751da522012-02-10 08:50:51 -0800535 const char* Attribute( const char* name ) const;
536
537 int QueryIntAttribute( const char* name, int* value ) const;
538 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const;
539 int QueryBoolAttribute( const char* name, bool* value ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800540 int QueryDoubleAttribute( const char* name, double* _value ) const;
541 int QueryFloatAttribute( const char* name, float* _value ) const;
542
543 void SetAttribute( const char* name, const char* value );
544 void SetAttribute( const char* name, int value );
545 void SetAttribute( const char* name, unsigned value );
546 void SetAttribute( const char* name, bool value );
547 void SetAttribute( const char* name, double value );
548
549 void RemoveAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800550
551 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
552
Lee Thomason50f97b22012-02-11 16:33:40 -0800553 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800554
Lee Thomason2c85a712012-01-31 08:24:24 -0800555 // internal:
556 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800557 char* ParseDeep( char* p );
558
Lee Thomason50adb4c2012-02-13 15:07:09 -0800559private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800560 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800561 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800562 XMLElement( const XMLElement& ); // not supported
563 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800564
Lee Thomason67d61312012-01-24 16:01:51 -0800565 char* ParseAttributes( char* p, bool *closedElement );
566
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800567 bool closing;
568 XMLAttribute* rootAttribute;
Lee Thomason751da522012-02-10 08:50:51 -0800569 XMLAttribute* lastAttribute; // fixme: remove
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800570};
571
572
Lee Thomason67d61312012-01-24 16:01:51 -0800573class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800574{
Lee Thomasond1983222012-02-06 08:41:24 -0800575 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800576public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800577 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800578 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800579
Lee Thomason751da522012-02-10 08:50:51 -0800580 virtual XMLDocument* ToDocument() { return this; }
581 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800582
Lee Thomason7c913cd2012-01-26 18:32:34 -0800583 int Parse( const char* );
584 int Load( const char* );
585 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800586
Lee Thomason5cae8972012-01-24 18:03:07 -0800587 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800588 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800589
Lee Thomason2c85a712012-01-31 08:24:24 -0800590 XMLElement* NewElement( const char* name );
591
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800593 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800594 ERROR_ELEMENT_MISMATCH,
595 ERROR_PARSING_ELEMENT,
Lee Thomason50f97b22012-02-11 16:33:40 -0800596 ERROR_PARSING_ATTRIBUTE,
597 ERROR_IDENTIFYING_TAG
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800598 };
Lee Thomason67d61312012-01-24 16:01:51 -0800599 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800600
Lee Thomason7c913cd2012-01-26 18:32:34 -0800601 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800602 int GetErrorID() const { return errorID; }
603 const char* GetErrorStr1() const { return errorStr1; }
604 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800605
Lee Thomasond1983222012-02-06 08:41:24 -0800606 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800607
Lee Thomason3f57d272012-01-11 15:30:03 -0800608private:
Lee Thomason50adb4c2012-02-13 15:07:09 -0800609 XMLDocument( const XMLDocument& ); // not supported
610 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -0800611 void InitDocument();
612
Lee Thomason7c913cd2012-01-26 18:32:34 -0800613 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800614 const char* errorStr1;
615 const char* errorStr2;
616 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800617
618 MemPoolT< sizeof(XMLElement) > elementPool;
619 MemPoolT< sizeof(XMLAttribute) > attributePool;
620 MemPoolT< sizeof(XMLText) > textPool;
621 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800622};
623
Lee Thomason7c913cd2012-01-26 18:32:34 -0800624
Lee Thomason751da522012-02-10 08:50:51 -0800625class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800626{
627public:
628 XMLStreamer( FILE* file );
629 ~XMLStreamer() {}
630
Lee Thomason56bdd022012-02-09 18:16:58 -0800631 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800632 void PushAttribute( const char* name, const char* value );
633 void CloseElement();
634
Lee Thomason50f97b22012-02-11 16:33:40 -0800635 void PushText( const char* text, bool cdata=false );
Lee Thomason5cae8972012-01-24 18:03:07 -0800636 void PushComment( const char* comment );
637
Lee Thomason751da522012-02-10 08:50:51 -0800638 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
639 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
640
641 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
642 virtual bool VisitExit( const XMLElement& element );
643
644 virtual bool Visit( const XMLText& text );
645 virtual bool Visit( const XMLComment& comment );
646
647
Lee Thomason5cae8972012-01-24 18:03:07 -0800648private:
649 void SealElement();
650 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800651 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800652
653 FILE* fp;
654 int depth;
655 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800656 int textDepth;
657
Lee Thomason857b8682012-01-25 17:50:25 -0800658 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800659 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800660 };
661 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800662
Lee Thomason2c85a712012-01-31 08:24:24 -0800663 DynArray< const char*, 10 > stack;
Lee Thomason5cae8972012-01-24 18:03:07 -0800664};
665
666
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800667}; // tinyxml2
668
U-Lama\Lee560bd472011-12-28 19:42:49 -0800669
670
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800671#endif // TINYXML2_INCLUDED