blob: 0cf859b8b0c9bfe37933c628c10cbd627b7245b9 [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 Thomason1ff38e02012-02-14 18:18:16 -080016 - string buffer for sets. (Grr.)
17 - MS BOM
18 - print to memory buffer
Lee Thomason50adb4c2012-02-13 15:07:09 -080019 - tests from xml1
Lee Thomason1ff38e02012-02-14 18:18:16 -080020 - xml1 tests especially UTF-8
Lee Thomason50adb4c2012-02-13 15:07:09 -080021 - perf test: xml1
22 - perf test: xenowar
Lee Thomason2c85a712012-01-31 08:24:24 -080023*/
24
U-Lama\Lee4cee6112011-12-31 14:58:18 -080025#include <limits.h>
Lee Thomasonce0763e2012-01-11 15:43:54 -080026#include <ctype.h>
27#include <stdio.h>
Lee Thomason2c85a712012-01-31 08:24:24 -080028#include <memory.h>
U-Lama\Lee4cee6112011-12-31 14:58:18 -080029
30#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
31 #ifndef DEBUG
32 #define DEBUG
33 #endif
34#endif
35
36
37#if defined(DEBUG)
38 #if defined(_MSC_VER)
39 #define TIXMLASSERT( x ) if ( !(x)) { _asm { int 3 } } //if ( !(x)) WinDebugBreak()
40 #elif defined (ANDROID_NDK)
41 #include <android/log.h>
42 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
43 #else
44 #include <assert.h>
45 #define TIXMLASSERT assert
46 #endif
47#else
48 #define TIXMLASSERT( x ) {}
49#endif
50
U-Lama\Leee13c3e62011-12-28 14:36:55 -080051
Lee Thomason1ff38e02012-02-14 18:18:16 -080052// Deprecated library function hell. Compilers want to use the
53// new safe versions. This probably doesn't fully address the problem,
54// but it gets closer. There are too many compilers for me to fully
55// test. If you get compilation troubles, undefine TIXML_SAFE
56
57#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
58 // Microsoft visual studio, version 2005 and higher.
59 #define TIXML_SNPRINTF _snprintf_s
60 #define TIXML_SSCANF sscanf_s
61#elif defined(_MSC_VER) && (_MSC_VER >= 1200 )
62 // Microsoft visual studio, version 6 and higher.
63 //#pragma message( "Using _sn* functions." )
64 #define TIXML_SNPRINTF _snprintf
65 #define TIXML_SSCANF sscanf
66#elif defined(__GNUC__) && (__GNUC__ >= 3 )
67 // GCC version 3 and higher.s
68 //#warning( "Using sn* functions." )
69 #define TIXML_SNPRINTF snprintf
70 #define TIXML_SSCANF sscanf
71#else
72 #define TIXML_SNPRINTF snprintf
73 #define TIXML_SSCANF sscanf
74#endif
75
76
U-Lama\Leee13c3e62011-12-28 14:36:55 -080077namespace tinyxml2
78{
Lee Thomasonce0763e2012-01-11 15:43:54 -080079class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -080080class XMLElement;
81class XMLAttribute;
82class XMLComment;
83class XMLNode;
Lee Thomason5492a1c2012-01-23 15:32:10 -080084class XMLText;
Lee Thomason50f97b22012-02-11 16:33:40 -080085class XMLDeclaration;
86class XMLUnknown;
U-Lama\Leee13c3e62011-12-28 14:36:55 -080087
Lee Thomason5cae8972012-01-24 18:03:07 -080088class XMLStreamer;
89
Lee Thomason39ede242012-01-20 11:27:56 -080090class StrPair
91{
Lee Thomasond34f52c2012-01-20 12:55:24 -080092public:
Lee Thomason39ede242012-01-20 11:27:56 -080093 enum {
Lee Thomasone4422302012-01-20 17:59:50 -080094 NEEDS_ENTITY_PROCESSING = 0x01,
Lee Thomason18d68bd2012-01-26 18:17:26 -080095 NEEDS_NEWLINE_NORMALIZATION = 0x02,
96
97 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
98 ATTRIBUTE_NAME = 0,
99 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
100 COMMENT = NEEDS_NEWLINE_NORMALIZATION,
Lee Thomason39ede242012-01-20 11:27:56 -0800101 };
102
103 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
Lee Thomasone4422302012-01-20 17:59:50 -0800104 void Set( char* start, char* end, int flags ) {
Lee Thomason39ede242012-01-20 11:27:56 -0800105 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
106 }
107 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800108 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800109
Lee Thomason2c85a712012-01-31 08:24:24 -0800110 void SetInternedStr( const char* str ) { this->start = (char*) str; this->end = 0; this->flags = 0; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800111 char* ParseText( char* in, const char* endTag, int strFlags );
112 char* ParseName( char* in );
113
Lee Thomason2c85a712012-01-31 08:24:24 -0800114
Lee Thomason39ede242012-01-20 11:27:56 -0800115private:
Lee Thomasone4422302012-01-20 17:59:50 -0800116 enum {
117 NEEDS_FLUSH = 0x100
118 };
119
Lee Thomason39ede242012-01-20 11:27:56 -0800120 // After parsing, if *end != 0, it can be set to zero.
121 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800122 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800123 char* end;
124};
125
U-Lama\Lee560bd472011-12-28 19:42:49 -0800126
Lee Thomason2c85a712012-01-31 08:24:24 -0800127template <class T, int INIT>
128class DynArray
129{
130public:
131 DynArray< T, INIT >()
132 {
133 mem = pool;
134 allocated = INIT;
135 size = 0;
136 }
137 ~DynArray()
138 {
139 if ( mem != pool ) {
140 delete mem;
141 }
142 }
143 void Push( T t )
144 {
145 EnsureCapacity( size+1 );
146 mem[size++] = t;
147 }
148
149 T* PushArr( int count )
150 {
151 EnsureCapacity( size+count );
152 T* ret = &mem[size];
153 size += count;
154 return ret;
155 }
156 T Pop() {
157 return mem[--size];
158 }
159 void PopArr( int count )
160 {
161 TIXMLASSERT( size >= count );
162 size -= count;
163 }
164
165 bool Empty() const { return size == 0; }
166 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
167 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
168 int Size() const { return size; }
169 const T* Mem() const { return mem; }
170 T* Mem() { return mem; }
171
172
173private:
174 void EnsureCapacity( int cap ) {
175 if ( cap > allocated ) {
176 int newAllocated = cap * 2;
177 T* newMem = new T[newAllocated];
178 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
179 if ( mem != pool ) delete [] mem;
180 mem = newMem;
181 allocated = newAllocated;
182 }
183 }
184
185 T* mem;
186 T pool[INIT];
187 int allocated; // objects allocated
188 int size; // number objects in use
189};
190
Lee Thomason50adb4c2012-02-13 15:07:09 -0800191
Lee Thomasond1983222012-02-06 08:41:24 -0800192class MemPool
193{
194public:
195 MemPool() {}
196 virtual ~MemPool() {}
197
198 virtual int ItemSize() const = 0;
199 virtual void* Alloc() = 0;
200 virtual void Free( void* ) = 0;
201};
202
Lee Thomason50adb4c2012-02-13 15:07:09 -0800203
Lee Thomasond1983222012-02-06 08:41:24 -0800204template< int SIZE >
205class MemPoolT : public MemPool
206{
207public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800208 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800209 ~MemPoolT() {
210 // Delete the blocks.
211 for( int i=0; i<blockPtrs.Size(); ++i ) {
212 delete blockPtrs[i];
213 }
214 }
215
216 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800217 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800218
219 virtual void* Alloc() {
220 if ( !root ) {
221 // Need a new block.
222 Block* block = new Block();
223 blockPtrs.Push( block );
224
225 for( int i=0; i<COUNT-1; ++i ) {
226 block->chunk[i].next = &block->chunk[i+1];
227 }
228 block->chunk[COUNT-1].next = 0;
229 root = block->chunk;
230 }
231 void* result = root;
232 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800233
234 ++currentAllocs;
235 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
236 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800237 return result;
238 }
239 virtual void Free( void* mem ) {
240 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800241 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800242 Chunk* chunk = (Chunk*)mem;
243 memset( chunk, 0xfe, sizeof(Chunk) );
244 chunk->next = root;
245 root = chunk;
246 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800247 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800248 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
249 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800250 }
Lee Thomasond1983222012-02-06 08:41:24 -0800251
252private:
253 enum { COUNT = 1024/SIZE };
254 union Chunk {
255 Chunk* next;
256 char mem[SIZE];
257 };
258 struct Block {
259 Chunk chunk[COUNT];
260 };
261 DynArray< Block*, 10 > blockPtrs;
262 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800263
264 int currentAllocs;
265 int nAllocs;
266 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800267};
268
Lee Thomason2c85a712012-01-31 08:24:24 -0800269
Lee Thomason56bdd022012-02-09 18:16:58 -0800270
271/**
272 Implements the interface to the "Visitor pattern" (see the Accept() method.)
273 If you call the Accept() method, it requires being passed a XMLVisitor
274 class to handle callbacks. For nodes that contain other nodes (Document, Element)
275 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
276 are simply called with Visit().
277
278 If you return 'true' from a Visit method, recursive parsing will continue. If you return
279 false, <b>no children of this node or its sibilings</b> will be Visited.
280
281 All flavors of Visit methods have a default implementation that returns 'true' (continue
282 visiting). You need to only override methods that are interesting to you.
283
284 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
285
286 You should never change the document from a callback.
287
288 @sa XMLNode::Accept()
289*/
290class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800291{
292public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800293 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800294
Lee Thomason56bdd022012-02-09 18:16:58 -0800295 /// Visit a document.
296 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
297 /// Visit a document.
298 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
299
300 /// Visit an element.
301 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
302 /// Visit an element.
303 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
304
305 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800306 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800307 /// Visit a text node
308 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
309 /// Visit a comment node
310 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
311 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800312 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800313};
314
315
316class XMLUtil
317{
Lee Thomasond1983222012-02-06 08:41:24 -0800318public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800319 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
320 // correct, but simple, and usually works.
321 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
322 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800323
324 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
325 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800326 if ( p == q ) {
327 return true;
328 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800329 while( *p && *q && *p == *q && n<nChar ) {
330 ++p; ++q; ++n;
331 }
332 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
333 return true;
334 }
335 return false;
336 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800337 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800338 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
339 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800340};
341
Lee Thomason5cae8972012-01-24 18:03:07 -0800342
Lee Thomasond1983222012-02-06 08:41:24 -0800343class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800344{
345 friend class XMLDocument;
346 friend class XMLElement;
347public:
Lee Thomason751da522012-02-10 08:50:51 -0800348 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800349 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800350
Lee Thomason56bdd022012-02-09 18:16:58 -0800351 virtual XMLElement* ToElement() { return 0; }
352 virtual XMLText* ToText() { return 0; }
353 virtual XMLComment* ToComment() { return 0; }
354 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason50f97b22012-02-11 16:33:40 -0800355 virtual XMLDeclaration* ToDeclaration() { return 0; }
356 virtual XMLUnknown* ToUnknown() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800357
Lee Thomason50f97b22012-02-11 16:33:40 -0800358 virtual const XMLElement* ToElement() const { return 0; }
359 virtual const XMLText* ToText() const { return 0; }
360 virtual const XMLComment* ToComment() const { return 0; }
361 virtual const XMLDocument* ToDocument() const { return 0; }
362 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
363 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800364
Lee Thomason2c85a712012-01-31 08:24:24 -0800365 const char* Value() const { return value.GetStr(); }
366 void SetValue( const char* val ) { value.SetInternedStr( val ); }
367
Lee Thomason751da522012-02-10 08:50:51 -0800368 const XMLNode* Parent() const { return parent; }
369 XMLNode* Parent() { return parent; }
370
Lee Thomason50f97b22012-02-11 16:33:40 -0800371 /// Returns true if this node has no children.
372 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800373
Lee Thomason56bdd022012-02-09 18:16:58 -0800374 const XMLNode* FirstChild() const { return firstChild; }
375 XMLNode* FirstChild() { return firstChild; }
376 const XMLElement* FirstChildElement( const char* value=0 ) const;
377 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800378
Lee Thomason56bdd022012-02-09 18:16:58 -0800379 const XMLNode* LastChild() const { return lastChild; }
380 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800381
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 const XMLElement* LastChildElement( const char* value=0 ) const;
383 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
384
385 const XMLNode* PreviousSibling() const { return prev; }
386 XMLNode* PreviousSibling() { return prev; }
387
388 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
389 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
390
391 const XMLNode* NextSibling() const { return next; }
392 XMLNode* NextSibling() { return next; }
393
394 const XMLNode* NextSiblingElement( const char* value=0 ) const;
395 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
396
Lee Thomason1ff38e02012-02-14 18:18:16 -0800397 /**
398
399 Tests: Programmatic DOM
400 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800401 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800402 /**
403
404 Tests: Programmatic DOM
405 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800406 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800407 /**
408
409 Tests: Programmatic DOM
410 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800411 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
412
413 void ClearChildren();
414 void DeleteChild( XMLNode* node );
415
416 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason751da522012-02-10 08:50:51 -0800417 //virtual void Print( XMLStreamer* streamer );
Lee Thomason56bdd022012-02-09 18:16:58 -0800418
Lee Thomason67d61312012-01-24 16:01:51 -0800419 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800420 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800421
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800422protected:
423 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800424 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800425 XMLNode( const XMLNode& ); // not supported
426 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800427
Lee Thomason3f57d272012-01-11 15:30:03 -0800428 XMLDocument* document;
429 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800430 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800431
432 XMLNode* firstChild;
433 XMLNode* lastChild;
434
435 XMLNode* prev;
436 XMLNode* next;
437
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800438private:
Lee Thomasond1983222012-02-06 08:41:24 -0800439 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800440 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800441};
442
443
Lee Thomason5492a1c2012-01-23 15:32:10 -0800444class XMLText : public XMLNode
445{
Lee Thomason2c85a712012-01-31 08:24:24 -0800446 friend class XMLBase;
447 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800448public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800449 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800450
Lee Thomason751da522012-02-10 08:50:51 -0800451 virtual XMLText* ToText() { return this; }
452 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800453
Lee Thomason50f97b22012-02-11 16:33:40 -0800454 void SetCData( bool value ) { isCData = true; }
455 bool CData() const { return isCData; }
456
Lee Thomason5492a1c2012-01-23 15:32:10 -0800457 char* ParseDeep( char* );
458
459protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800460 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
461 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800462 XMLText( const XMLText& ); // not supported
463 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800464
465private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800466 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800467};
468
469
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800470class XMLComment : public XMLNode
471{
Lee Thomason2c85a712012-01-31 08:24:24 -0800472 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800473public:
Lee Thomason751da522012-02-10 08:50:51 -0800474 virtual XMLComment* ToComment() { return this; }
475 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800476
Lee Thomason56bdd022012-02-09 18:16:58 -0800477 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800478
Lee Thomasonce0763e2012-01-11 15:43:54 -0800479 char* ParseDeep( char* );
480
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800481protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800482 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800483 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800484 XMLComment( const XMLComment& ); // not supported
485 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800486
Lee Thomason3f57d272012-01-11 15:30:03 -0800487private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800488};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800489
490
Lee Thomason50f97b22012-02-11 16:33:40 -0800491class XMLDeclaration : public XMLNode
492{
493 friend class XMLDocument;
494public:
495 virtual XMLDeclaration* ToDeclaration() { return this; }
496 virtual const XMLDeclaration* ToDeclaration() const { return this; }
497
498 virtual bool Accept( XMLVisitor* visitor ) const;
499
500 char* ParseDeep( char* );
501
502protected:
503 XMLDeclaration( XMLDocument* doc );
504 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800505 XMLDeclaration( const XMLDeclaration& ); // not supported
506 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800507};
508
509
510class XMLUnknown : public XMLNode
511{
512 friend class XMLDocument;
513public:
514 virtual XMLUnknown* ToUnknown() { return this; }
515 virtual const XMLUnknown* ToUnknown() const { return this; }
516
517 virtual bool Accept( XMLVisitor* visitor ) const;
518
519 char* ParseDeep( char* );
520
521protected:
522 XMLUnknown( XMLDocument* doc );
523 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800524 XMLUnknown( const XMLUnknown& ); // not supported
525 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800526};
527
528
Lee Thomason1ff38e02012-02-14 18:18:16 -0800529enum {
530 ATTRIBUTE_SUCCESS,
531 NO_ATTRIBUTE,
532 WRONG_ATTRIBUTE_TYPE
533};
534
535
Lee Thomason56bdd022012-02-09 18:16:58 -0800536class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800537{
538 friend class XMLElement;
539public:
Lee Thomason751da522012-02-10 08:50:51 -0800540 const char* Name() const { return name.GetStr(); }
541 const char* Value() const { return value.GetStr(); }
542 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800543
Lee Thomason1ff38e02012-02-14 18:18:16 -0800544 int QueryIntAttribute( int* value ) const;
545 int QueryUnsignedAttribute( unsigned int* value ) const;
546 int QueryBoolAttribute( bool* value ) const;
547 int QueryDoubleAttribute( double* value ) const;
548 int QueryFloatAttribute( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800549
Lee Thomason1ff38e02012-02-14 18:18:16 -0800550 void SetAttribute( const char* value );
551
552 // NOTE: other sets aren't supported...need to deal with memory model?
553 /*
554 void SetAttribute( int value );
555 void SetAttribute( unsigned value );
556 void SetAttribute( bool value );
557 void SetAttribute( double value );
558 */
Lee Thomason50adb4c2012-02-13 15:07:09 -0800559
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800560private:
Lee Thomasond1983222012-02-06 08:41:24 -0800561 XMLAttribute( XMLElement* element ) : next( 0 ) {}
562 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800563 XMLAttribute( const XMLAttribute& ); // not supported
564 void operator=( const XMLAttribute& ); // not supported
565
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800566 char* ParseDeep( char* p );
567
Lee Thomason751da522012-02-10 08:50:51 -0800568 mutable StrPair name;
569 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800570 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800571 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800572};
573
574
575class XMLElement : public XMLNode
576{
Lee Thomason2c85a712012-01-31 08:24:24 -0800577 friend class XMLBase;
578 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800579public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800580 const char* Name() const { return Value(); }
581 void SetName( const char* str ) { SetValue( str ); }
582
Lee Thomason751da522012-02-10 08:50:51 -0800583 virtual XMLElement* ToElement() { return this; }
584 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800585 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800586
Lee Thomason751da522012-02-10 08:50:51 -0800587 const char* Attribute( const char* name ) const;
588
589 int QueryIntAttribute( const char* name, int* value ) const;
590 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const;
591 int QueryBoolAttribute( const char* name, bool* value ) const;
Lee Thomason50f97b22012-02-11 16:33:40 -0800592 int QueryDoubleAttribute( const char* name, double* _value ) const;
593 int QueryFloatAttribute( const char* name, float* _value ) const;
594
595 void SetAttribute( const char* name, const char* value );
596 void SetAttribute( const char* name, int value );
597 void SetAttribute( const char* name, unsigned value );
598 void SetAttribute( const char* name, bool value );
599 void SetAttribute( const char* name, double value );
600
601 void RemoveAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800602
603 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
604
Lee Thomason50f97b22012-02-11 16:33:40 -0800605 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800606
Lee Thomason2c85a712012-01-31 08:24:24 -0800607 // internal:
608 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800609 char* ParseDeep( char* p );
610
Lee Thomason50adb4c2012-02-13 15:07:09 -0800611private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800612 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800613 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800614 XMLElement( const XMLElement& ); // not supported
615 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800616
Lee Thomason67d61312012-01-24 16:01:51 -0800617 char* ParseAttributes( char* p, bool *closedElement );
618
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800619 bool closing;
620 XMLAttribute* rootAttribute;
Lee Thomason751da522012-02-10 08:50:51 -0800621 XMLAttribute* lastAttribute; // fixme: remove
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800622};
623
624
Lee Thomason67d61312012-01-24 16:01:51 -0800625class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800626{
Lee Thomasond1983222012-02-06 08:41:24 -0800627 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800628public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800629 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800630 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800631
Lee Thomason751da522012-02-10 08:50:51 -0800632 virtual XMLDocument* ToDocument() { return this; }
633 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800634
Lee Thomason7c913cd2012-01-26 18:32:34 -0800635 int Parse( const char* );
636 int Load( const char* );
637 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800638
Lee Thomason5cae8972012-01-24 18:03:07 -0800639 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800640 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800641
Lee Thomason1ff38e02012-02-14 18:18:16 -0800642 /**
643 Testing: Programmatic DOM
644 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800645 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800646 /**
647 Testing: Programmatic DOM
648 */
649 XMLComment* NewComment( const char* comment );
650 /**
651 Testing: Programmatic DOM
652 */
653 XMLText* NewText( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -0800654
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800655 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800656 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800657 ERROR_ELEMENT_MISMATCH,
658 ERROR_PARSING_ELEMENT,
Lee Thomason50f97b22012-02-11 16:33:40 -0800659 ERROR_PARSING_ATTRIBUTE,
660 ERROR_IDENTIFYING_TAG
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800661 };
Lee Thomason67d61312012-01-24 16:01:51 -0800662 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800663
Lee Thomason7c913cd2012-01-26 18:32:34 -0800664 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800665 int GetErrorID() const { return errorID; }
666 const char* GetErrorStr1() const { return errorStr1; }
667 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800668
Lee Thomasond1983222012-02-06 08:41:24 -0800669 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800670
Lee Thomason3f57d272012-01-11 15:30:03 -0800671private:
Lee Thomason50adb4c2012-02-13 15:07:09 -0800672 XMLDocument( const XMLDocument& ); // not supported
673 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -0800674 void InitDocument();
675
Lee Thomason7c913cd2012-01-26 18:32:34 -0800676 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800677 const char* errorStr1;
678 const char* errorStr2;
679 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800680
681 MemPoolT< sizeof(XMLElement) > elementPool;
682 MemPoolT< sizeof(XMLAttribute) > attributePool;
683 MemPoolT< sizeof(XMLText) > textPool;
684 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800685};
686
Lee Thomason7c913cd2012-01-26 18:32:34 -0800687
Lee Thomason751da522012-02-10 08:50:51 -0800688class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800689{
690public:
691 XMLStreamer( FILE* file );
692 ~XMLStreamer() {}
693
Lee Thomason56bdd022012-02-09 18:16:58 -0800694 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800695 void PushAttribute( const char* name, const char* value );
696 void CloseElement();
697
Lee Thomason50f97b22012-02-11 16:33:40 -0800698 void PushText( const char* text, bool cdata=false );
Lee Thomason5cae8972012-01-24 18:03:07 -0800699 void PushComment( const char* comment );
700
Lee Thomason751da522012-02-10 08:50:51 -0800701 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
702 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
703
704 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
705 virtual bool VisitExit( const XMLElement& element );
706
707 virtual bool Visit( const XMLText& text );
708 virtual bool Visit( const XMLComment& comment );
709
710
Lee Thomason5cae8972012-01-24 18:03:07 -0800711private:
712 void SealElement();
713 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800714 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800715
716 FILE* fp;
717 int depth;
718 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800719 int textDepth;
720
Lee Thomason857b8682012-01-25 17:50:25 -0800721 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800722 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800723 };
724 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800725
Lee Thomason2c85a712012-01-31 08:24:24 -0800726 DynArray< const char*, 10 > stack;
Lee Thomason5cae8972012-01-24 18:03:07 -0800727};
728
729
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800730}; // tinyxml2
731
U-Lama\Lee560bd472011-12-28 19:42:49 -0800732
733
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800734#endif // TINYXML2_INCLUDED