blob: 67e6d2d0c1e4c04c9cdcc21d07eb427c93b9b521 [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 Thomason1a1d4a72012-02-15 09:09:25 -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
Lee Thomason1ff38e02012-02-14 18:18:16 -080075
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 Thomason1a1d4a72012-02-15 09:09:25 -0800104 ~StrPair();
105
Lee Thomasone4422302012-01-20 17:59:50 -0800106 void Set( char* start, char* end, int flags ) {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800107 Reset();
Lee Thomason39ede242012-01-20 11:27:56 -0800108 this->start = start; this->end = end; this->flags = flags | NEEDS_FLUSH;
109 }
110 const char* GetStr();
Lee Thomasone4422302012-01-20 17:59:50 -0800111 bool Empty() const { return start == end; }
Lee Thomason39ede242012-01-20 11:27:56 -0800112
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800113 void SetInternedStr( const char* str ) { Reset(); this->start = (char*) str; }
114 void SetStr( const char* str, int flags=0 );
115
Lee Thomason56bdd022012-02-09 18:16:58 -0800116 char* ParseText( char* in, const char* endTag, int strFlags );
117 char* ParseName( char* in );
118
Lee Thomason2c85a712012-01-31 08:24:24 -0800119
Lee Thomason39ede242012-01-20 11:27:56 -0800120private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800121 void Reset();
122
Lee Thomasone4422302012-01-20 17:59:50 -0800123 enum {
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800124 NEEDS_FLUSH = 0x100,
125 NEEDS_DELETE = 0x200
Lee Thomasone4422302012-01-20 17:59:50 -0800126 };
127
Lee Thomason39ede242012-01-20 11:27:56 -0800128 // After parsing, if *end != 0, it can be set to zero.
129 int flags;
Lee Thomasone4422302012-01-20 17:59:50 -0800130 char* start;
Lee Thomason39ede242012-01-20 11:27:56 -0800131 char* end;
132};
133
U-Lama\Lee560bd472011-12-28 19:42:49 -0800134
Lee Thomason2c85a712012-01-31 08:24:24 -0800135template <class T, int INIT>
136class DynArray
137{
138public:
139 DynArray< T, INIT >()
140 {
141 mem = pool;
142 allocated = INIT;
143 size = 0;
144 }
145 ~DynArray()
146 {
147 if ( mem != pool ) {
148 delete mem;
149 }
150 }
151 void Push( T t )
152 {
153 EnsureCapacity( size+1 );
154 mem[size++] = t;
155 }
156
157 T* PushArr( int count )
158 {
159 EnsureCapacity( size+count );
160 T* ret = &mem[size];
161 size += count;
162 return ret;
163 }
164 T Pop() {
165 return mem[--size];
166 }
167 void PopArr( int count )
168 {
169 TIXMLASSERT( size >= count );
170 size -= count;
171 }
172
173 bool Empty() const { return size == 0; }
174 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
175 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
176 int Size() const { return size; }
177 const T* Mem() const { return mem; }
178 T* Mem() { return mem; }
179
180
181private:
182 void EnsureCapacity( int cap ) {
183 if ( cap > allocated ) {
184 int newAllocated = cap * 2;
185 T* newMem = new T[newAllocated];
186 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
187 if ( mem != pool ) delete [] mem;
188 mem = newMem;
189 allocated = newAllocated;
190 }
191 }
192
193 T* mem;
194 T pool[INIT];
195 int allocated; // objects allocated
196 int size; // number objects in use
197};
198
Lee Thomason50adb4c2012-02-13 15:07:09 -0800199
Lee Thomasond1983222012-02-06 08:41:24 -0800200class MemPool
201{
202public:
203 MemPool() {}
204 virtual ~MemPool() {}
205
206 virtual int ItemSize() const = 0;
207 virtual void* Alloc() = 0;
208 virtual void Free( void* ) = 0;
209};
210
Lee Thomason50adb4c2012-02-13 15:07:09 -0800211
Lee Thomasond1983222012-02-06 08:41:24 -0800212template< int SIZE >
213class MemPoolT : public MemPool
214{
215public:
Lee Thomason455c9d42012-02-06 09:14:14 -0800216 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
Lee Thomasond1983222012-02-06 08:41:24 -0800217 ~MemPoolT() {
218 // Delete the blocks.
219 for( int i=0; i<blockPtrs.Size(); ++i ) {
220 delete blockPtrs[i];
221 }
222 }
223
224 virtual int ItemSize() const { return SIZE; }
Lee Thomason455c9d42012-02-06 09:14:14 -0800225 int CurrentAllocs() const { return currentAllocs; }
Lee Thomasond1983222012-02-06 08:41:24 -0800226
227 virtual void* Alloc() {
228 if ( !root ) {
229 // Need a new block.
230 Block* block = new Block();
231 blockPtrs.Push( block );
232
233 for( int i=0; i<COUNT-1; ++i ) {
234 block->chunk[i].next = &block->chunk[i+1];
235 }
236 block->chunk[COUNT-1].next = 0;
237 root = block->chunk;
238 }
239 void* result = root;
240 root = root->next;
Lee Thomason455c9d42012-02-06 09:14:14 -0800241
242 ++currentAllocs;
243 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
244 nAllocs++;
Lee Thomasond1983222012-02-06 08:41:24 -0800245 return result;
246 }
247 virtual void Free( void* mem ) {
248 if ( !mem ) return;
Lee Thomason455c9d42012-02-06 09:14:14 -0800249 --currentAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800250 Chunk* chunk = (Chunk*)mem;
251 memset( chunk, 0xfe, sizeof(Chunk) );
252 chunk->next = root;
253 root = chunk;
254 }
Lee Thomason455c9d42012-02-06 09:14:14 -0800255 void Trace( const char* name ) {
Lee Thomason43f59302012-02-06 18:18:11 -0800256 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
257 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
Lee Thomason455c9d42012-02-06 09:14:14 -0800258 }
Lee Thomasond1983222012-02-06 08:41:24 -0800259
260private:
261 enum { COUNT = 1024/SIZE };
262 union Chunk {
263 Chunk* next;
264 char mem[SIZE];
265 };
266 struct Block {
267 Chunk chunk[COUNT];
268 };
269 DynArray< Block*, 10 > blockPtrs;
270 Chunk* root;
Lee Thomason455c9d42012-02-06 09:14:14 -0800271
272 int currentAllocs;
273 int nAllocs;
274 int maxAllocs;
Lee Thomasond1983222012-02-06 08:41:24 -0800275};
276
Lee Thomason2c85a712012-01-31 08:24:24 -0800277
Lee Thomason56bdd022012-02-09 18:16:58 -0800278
279/**
280 Implements the interface to the "Visitor pattern" (see the Accept() method.)
281 If you call the Accept() method, it requires being passed a XMLVisitor
282 class to handle callbacks. For nodes that contain other nodes (Document, Element)
283 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves
284 are simply called with Visit().
285
286 If you return 'true' from a Visit method, recursive parsing will continue. If you return
287 false, <b>no children of this node or its sibilings</b> will be Visited.
288
289 All flavors of Visit methods have a default implementation that returns 'true' (continue
290 visiting). You need to only override methods that are interesting to you.
291
292 Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting.
293
294 You should never change the document from a callback.
295
296 @sa XMLNode::Accept()
297*/
298class XMLVisitor
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800299{
300public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800301 virtual ~XMLVisitor() {}
Lee Thomasond1983222012-02-06 08:41:24 -0800302
Lee Thomason56bdd022012-02-09 18:16:58 -0800303 /// Visit a document.
304 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
305 /// Visit a document.
306 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
307
308 /// Visit an element.
309 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
310 /// Visit an element.
311 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
312
313 /// Visit a declaration
Lee Thomason50f97b22012-02-11 16:33:40 -0800314 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800315 /// Visit a text node
316 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
317 /// Visit a comment node
318 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
319 /// Visit an unknown node
Lee Thomason50f97b22012-02-11 16:33:40 -0800320 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800321};
322
323
324class XMLUtil
325{
Lee Thomasond1983222012-02-06 08:41:24 -0800326public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800327 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
328 // correct, but simple, and usually works.
329 static const char* SkipWhiteSpace( const char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
330 static char* SkipWhiteSpace( char* p ) { while( IsUTF8Continuation(*p) || isspace( *p ) ) { ++p; } return p; }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800331
332 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
333 int n = 0;
Lee Thomasond34f52c2012-01-20 12:55:24 -0800334 if ( p == q ) {
335 return true;
336 }
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800337 while( *p && *q && *p == *q && n<nChar ) {
338 ++p; ++q; ++n;
339 }
340 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
341 return true;
342 }
343 return false;
344 }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800345 inline static int IsUTF8Continuation( unsigned char p ) { return p & 0x80; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800346 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
347 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800348};
349
Lee Thomason5cae8972012-01-24 18:03:07 -0800350
Lee Thomasond1983222012-02-06 08:41:24 -0800351class XMLNode
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800352{
353 friend class XMLDocument;
354 friend class XMLElement;
355public:
Lee Thomason751da522012-02-10 08:50:51 -0800356 const XMLDocument* GetDocument() const { return document; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800357 XMLDocument* GetDocument() { return document; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800358
Lee Thomason56bdd022012-02-09 18:16:58 -0800359 virtual XMLElement* ToElement() { return 0; }
360 virtual XMLText* ToText() { return 0; }
361 virtual XMLComment* ToComment() { return 0; }
362 virtual XMLDocument* ToDocument() { return 0; }
Lee Thomason50f97b22012-02-11 16:33:40 -0800363 virtual XMLDeclaration* ToDeclaration() { return 0; }
364 virtual XMLUnknown* ToUnknown() { return 0; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800365
Lee Thomason50f97b22012-02-11 16:33:40 -0800366 virtual const XMLElement* ToElement() const { return 0; }
367 virtual const XMLText* ToText() const { return 0; }
368 virtual const XMLComment* ToComment() const { return 0; }
369 virtual const XMLDocument* ToDocument() const { return 0; }
370 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
371 virtual const XMLUnknown* ToUnknown() const { return 0; }
Lee Thomason751da522012-02-10 08:50:51 -0800372
Lee Thomason2c85a712012-01-31 08:24:24 -0800373 const char* Value() const { return value.GetStr(); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800374 void SetValue( const char* val, bool staticMem=false );
Lee Thomason2c85a712012-01-31 08:24:24 -0800375
Lee Thomason751da522012-02-10 08:50:51 -0800376 const XMLNode* Parent() const { return parent; }
377 XMLNode* Parent() { return parent; }
378
Lee Thomason50f97b22012-02-11 16:33:40 -0800379 /// Returns true if this node has no children.
380 bool NoChildren() const { return !firstChild; }
Lee Thomason751da522012-02-10 08:50:51 -0800381
Lee Thomason56bdd022012-02-09 18:16:58 -0800382 const XMLNode* FirstChild() const { return firstChild; }
383 XMLNode* FirstChild() { return firstChild; }
384 const XMLElement* FirstChildElement( const char* value=0 ) const;
385 XMLElement* FirstChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value )); }
Lee Thomason3f57d272012-01-11 15:30:03 -0800386
Lee Thomason56bdd022012-02-09 18:16:58 -0800387 const XMLNode* LastChild() const { return lastChild; }
388 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800389
Lee Thomason56bdd022012-02-09 18:16:58 -0800390 const XMLElement* LastChildElement( const char* value=0 ) const;
391 XMLElement* LastChildElement( const char* value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) ); }
392
393 const XMLNode* PreviousSibling() const { return prev; }
394 XMLNode* PreviousSibling() { return prev; }
395
396 const XMLNode* PreviousSiblingElement( const char* value=0 ) const ;
397 XMLNode* PreviousSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) ); }
398
399 const XMLNode* NextSibling() const { return next; }
400 XMLNode* NextSibling() { return next; }
401
402 const XMLNode* NextSiblingElement( const char* value=0 ) const;
403 XMLNode* NextSiblingElement( const char* value=0 ) { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) ); }
404
Lee Thomason1ff38e02012-02-14 18:18:16 -0800405 /**
406
407 Tests: Programmatic DOM
408 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800409 XMLNode* InsertEndChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800410 /**
411
412 Tests: Programmatic DOM
413 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800414 XMLNode* InsertFirstChild( XMLNode* addThis );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800415 /**
416
417 Tests: Programmatic DOM
418 */
Lee Thomason56bdd022012-02-09 18:16:58 -0800419 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
420
421 void ClearChildren();
422 void DeleteChild( XMLNode* node );
423
424 virtual bool Accept( XMLVisitor* visitor ) const = 0;
Lee Thomason751da522012-02-10 08:50:51 -0800425 //virtual void Print( XMLStreamer* streamer );
Lee Thomason56bdd022012-02-09 18:16:58 -0800426
Lee Thomason67d61312012-01-24 16:01:51 -0800427 virtual char* ParseDeep( char* );
Lee Thomason67d61312012-01-24 16:01:51 -0800428 virtual bool IsClosingElement() const { return false; }
Lee Thomason3f57d272012-01-11 15:30:03 -0800429
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800430protected:
431 XMLNode( XMLDocument* );
Lee Thomasond1983222012-02-06 08:41:24 -0800432 virtual ~XMLNode();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800433 XMLNode( const XMLNode& ); // not supported
434 void operator=( const XMLNode& ); // not supported
Lee Thomasond1983222012-02-06 08:41:24 -0800435
Lee Thomason3f57d272012-01-11 15:30:03 -0800436 XMLDocument* document;
437 XMLNode* parent;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800438 mutable StrPair value;
Lee Thomason3f57d272012-01-11 15:30:03 -0800439
440 XMLNode* firstChild;
441 XMLNode* lastChild;
442
443 XMLNode* prev;
444 XMLNode* next;
445
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800446private:
Lee Thomasond1983222012-02-06 08:41:24 -0800447 MemPool* memPool;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800448 void Unlink( XMLNode* child );
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800449};
450
451
Lee Thomason5492a1c2012-01-23 15:32:10 -0800452class XMLText : public XMLNode
453{
Lee Thomason2c85a712012-01-31 08:24:24 -0800454 friend class XMLBase;
455 friend class XMLDocument;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800456public:
Lee Thomason56bdd022012-02-09 18:16:58 -0800457 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800458
Lee Thomason751da522012-02-10 08:50:51 -0800459 virtual XMLText* ToText() { return this; }
460 virtual const XMLText* ToText() const { return this; }
Lee Thomason5492a1c2012-01-23 15:32:10 -0800461
Lee Thomason50f97b22012-02-11 16:33:40 -0800462 void SetCData( bool value ) { isCData = true; }
463 bool CData() const { return isCData; }
464
Lee Thomason5492a1c2012-01-23 15:32:10 -0800465 char* ParseDeep( char* );
466
467protected:
Lee Thomason50f97b22012-02-11 16:33:40 -0800468 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
469 virtual ~XMLText() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800470 XMLText( const XMLText& ); // not supported
471 void operator=( const XMLText& ); // not supported
Lee Thomason5492a1c2012-01-23 15:32:10 -0800472
473private:
Lee Thomason50f97b22012-02-11 16:33:40 -0800474 bool isCData;
Lee Thomason5492a1c2012-01-23 15:32:10 -0800475};
476
477
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800478class XMLComment : public XMLNode
479{
Lee Thomason2c85a712012-01-31 08:24:24 -0800480 friend class XMLDocument;
Lee Thomason3f57d272012-01-11 15:30:03 -0800481public:
Lee Thomason751da522012-02-10 08:50:51 -0800482 virtual XMLComment* ToComment() { return this; }
483 virtual const XMLComment* ToComment() const { return this; }
Lee Thomasonce0763e2012-01-11 15:43:54 -0800484
Lee Thomason56bdd022012-02-09 18:16:58 -0800485 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800486
Lee Thomasonce0763e2012-01-11 15:43:54 -0800487 char* ParseDeep( char* );
488
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800489protected:
Lee Thomason2c85a712012-01-31 08:24:24 -0800490 XMLComment( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800491 virtual ~XMLComment();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800492 XMLComment( const XMLComment& ); // not supported
493 void operator=( const XMLComment& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800494
Lee Thomason3f57d272012-01-11 15:30:03 -0800495private:
U-Lama\Lee4cee6112011-12-31 14:58:18 -0800496};
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800497
498
Lee Thomason50f97b22012-02-11 16:33:40 -0800499class XMLDeclaration : public XMLNode
500{
501 friend class XMLDocument;
502public:
503 virtual XMLDeclaration* ToDeclaration() { return this; }
504 virtual const XMLDeclaration* ToDeclaration() const { return this; }
505
506 virtual bool Accept( XMLVisitor* visitor ) const;
507
508 char* ParseDeep( char* );
509
510protected:
511 XMLDeclaration( XMLDocument* doc );
512 virtual ~XMLDeclaration();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800513 XMLDeclaration( const XMLDeclaration& ); // not supported
514 void operator=( const XMLDeclaration& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800515};
516
517
518class XMLUnknown : public XMLNode
519{
520 friend class XMLDocument;
521public:
522 virtual XMLUnknown* ToUnknown() { return this; }
523 virtual const XMLUnknown* ToUnknown() const { return this; }
524
525 virtual bool Accept( XMLVisitor* visitor ) const;
526
527 char* ParseDeep( char* );
528
529protected:
530 XMLUnknown( XMLDocument* doc );
531 virtual ~XMLUnknown();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800532 XMLUnknown( const XMLUnknown& ); // not supported
533 void operator=( const XMLUnknown& ); // not supported
Lee Thomason50f97b22012-02-11 16:33:40 -0800534};
535
536
Lee Thomason1ff38e02012-02-14 18:18:16 -0800537enum {
538 ATTRIBUTE_SUCCESS,
539 NO_ATTRIBUTE,
540 WRONG_ATTRIBUTE_TYPE
541};
542
543
Lee Thomason56bdd022012-02-09 18:16:58 -0800544class XMLAttribute
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800545{
546 friend class XMLElement;
547public:
Lee Thomason751da522012-02-10 08:50:51 -0800548 const char* Name() const { return name.GetStr(); }
549 const char* Value() const { return value.GetStr(); }
550 const XMLAttribute* Next() const { return next; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800551
Lee Thomason1ff38e02012-02-14 18:18:16 -0800552 int QueryIntAttribute( int* value ) const;
553 int QueryUnsignedAttribute( unsigned int* value ) const;
554 int QueryBoolAttribute( bool* value ) const;
555 int QueryDoubleAttribute( double* value ) const;
556 int QueryFloatAttribute( float* value ) const;
Lee Thomason50adb4c2012-02-13 15:07:09 -0800557
Lee Thomason1ff38e02012-02-14 18:18:16 -0800558 void SetAttribute( const char* value );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800559 void SetAttribute( int value );
560 void SetAttribute( unsigned value );
561 void SetAttribute( bool value );
562 void SetAttribute( double value );
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800563 void SetAttribute( float value );
Lee Thomason50adb4c2012-02-13 15:07:09 -0800564
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800565private:
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800566 enum { BUF_SIZE = 200 };
Lee Thomasond1983222012-02-06 08:41:24 -0800567 XMLAttribute( XMLElement* element ) : next( 0 ) {}
568 virtual ~XMLAttribute() {}
Lee Thomason50adb4c2012-02-13 15:07:09 -0800569 XMLAttribute( const XMLAttribute& ); // not supported
570 void operator=( const XMLAttribute& ); // not supported
571
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800572 char* ParseDeep( char* p );
573
Lee Thomason751da522012-02-10 08:50:51 -0800574 mutable StrPair name;
575 mutable StrPair value;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800576 XMLAttribute* next;
Lee Thomason43f59302012-02-06 18:18:11 -0800577 MemPool* memPool;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800578};
579
580
581class XMLElement : public XMLNode
582{
Lee Thomason2c85a712012-01-31 08:24:24 -0800583 friend class XMLBase;
584 friend class XMLDocument;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800585public:
Lee Thomason2c85a712012-01-31 08:24:24 -0800586 const char* Name() const { return Value(); }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800587 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
Lee Thomason2c85a712012-01-31 08:24:24 -0800588
Lee Thomason751da522012-02-10 08:50:51 -0800589 virtual XMLElement* ToElement() { return this; }
590 virtual const XMLElement* ToElement() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800591 virtual bool Accept( XMLVisitor* visitor ) const;
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800592
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800593 const char* Attribute( const char* name ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return 0; return a->Value(); }
Lee Thomason751da522012-02-10 08:50:51 -0800594
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800595 int QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryIntAttribute( value ); }
596 int QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryUnsignedAttribute( value ); }
597 int QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryBoolAttribute( value ); }
598 int QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryDoubleAttribute( value ); }
599 int QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return NO_ATTRIBUTE; return a->QueryFloatAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800600
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800601 void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
602 void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
603 void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
604 void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
605 void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); }
Lee Thomason50f97b22012-02-11 16:33:40 -0800606
607 void RemoveAttribute( const char* name );
Lee Thomason751da522012-02-10 08:50:51 -0800608
609 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800610 const XMLAttribute* FindAttribute( const char* name ) const;
Lee Thomason751da522012-02-10 08:50:51 -0800611
Lee Thomason50f97b22012-02-11 16:33:40 -0800612 const char* GetText() const;
Lee Thomason751da522012-02-10 08:50:51 -0800613
Lee Thomason2c85a712012-01-31 08:24:24 -0800614 // internal:
615 virtual bool IsClosingElement() const { return closing; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800616 char* ParseDeep( char* p );
617
Lee Thomason50adb4c2012-02-13 15:07:09 -0800618private:
Lee Thomason2c85a712012-01-31 08:24:24 -0800619 XMLElement( XMLDocument* doc );
Lee Thomasond1983222012-02-06 08:41:24 -0800620 virtual ~XMLElement();
Lee Thomason50adb4c2012-02-13 15:07:09 -0800621 XMLElement( const XMLElement& ); // not supported
622 void operator=( const XMLElement& ); // not supported
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800623
Lee Thomason1a1d4a72012-02-15 09:09:25 -0800624 XMLAttribute* FindAttribute( const char* name );
625 XMLAttribute* FindOrCreateAttribute( const char* name );
Lee Thomason67d61312012-01-24 16:01:51 -0800626 char* ParseAttributes( char* p, bool *closedElement );
627
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800628 bool closing;
629 XMLAttribute* rootAttribute;
Lee Thomason751da522012-02-10 08:50:51 -0800630 XMLAttribute* lastAttribute; // fixme: remove
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800631};
632
633
Lee Thomason67d61312012-01-24 16:01:51 -0800634class XMLDocument : public XMLNode
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800635{
Lee Thomasond1983222012-02-06 08:41:24 -0800636 friend class XMLElement;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800637public:
Lee Thomason18d68bd2012-01-26 18:17:26 -0800638 XMLDocument();
Lee Thomason3f57d272012-01-11 15:30:03 -0800639 ~XMLDocument();
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800640
Lee Thomason751da522012-02-10 08:50:51 -0800641 virtual XMLDocument* ToDocument() { return this; }
642 virtual const XMLDocument* ToDocument() const { return this; }
Lee Thomason56bdd022012-02-09 18:16:58 -0800643
Lee Thomason7c913cd2012-01-26 18:32:34 -0800644 int Parse( const char* );
645 int Load( const char* );
646 int Load( FILE* );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800647
Lee Thomason5cae8972012-01-24 18:03:07 -0800648 void Print( XMLStreamer* streamer=0 );
Lee Thomason56bdd022012-02-09 18:16:58 -0800649 virtual bool Accept( XMLVisitor* visitor ) const;
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800650
Lee Thomason1ff38e02012-02-14 18:18:16 -0800651 /**
652 Testing: Programmatic DOM
653 */
Lee Thomason2c85a712012-01-31 08:24:24 -0800654 XMLElement* NewElement( const char* name );
Lee Thomason1ff38e02012-02-14 18:18:16 -0800655 /**
656 Testing: Programmatic DOM
657 */
658 XMLComment* NewComment( const char* comment );
659 /**
660 Testing: Programmatic DOM
661 */
662 XMLText* NewText( const char* text );
Lee Thomason2c85a712012-01-31 08:24:24 -0800663
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800664 enum {
Lee Thomason18d68bd2012-01-26 18:17:26 -0800665 NO_ERROR = 0,
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800666 ERROR_ELEMENT_MISMATCH,
667 ERROR_PARSING_ELEMENT,
Lee Thomason50f97b22012-02-11 16:33:40 -0800668 ERROR_PARSING_ATTRIBUTE,
669 ERROR_IDENTIFYING_TAG
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800670 };
Lee Thomason67d61312012-01-24 16:01:51 -0800671 void SetError( int error, const char* str1, const char* str2 );
Lee Thomason18d68bd2012-01-26 18:17:26 -0800672
Lee Thomason7c913cd2012-01-26 18:32:34 -0800673 bool Error() const { return errorID != NO_ERROR; }
Lee Thomason18d68bd2012-01-26 18:17:26 -0800674 int GetErrorID() const { return errorID; }
675 const char* GetErrorStr1() const { return errorStr1; }
676 const char* GetErrorStr2() const { return errorStr2; }
Lee Thomason8a5dfee2012-01-18 17:43:40 -0800677
Lee Thomasond1983222012-02-06 08:41:24 -0800678 char* Identify( char* p, XMLNode** node );
Lee Thomason2c85a712012-01-31 08:24:24 -0800679
Lee Thomason3f57d272012-01-11 15:30:03 -0800680private:
Lee Thomason50adb4c2012-02-13 15:07:09 -0800681 XMLDocument( const XMLDocument& ); // not supported
682 void operator=( const XMLDocument& ); // not supported
Lee Thomason18d68bd2012-01-26 18:17:26 -0800683 void InitDocument();
684
Lee Thomason7c913cd2012-01-26 18:32:34 -0800685 int errorID;
Lee Thomason18d68bd2012-01-26 18:17:26 -0800686 const char* errorStr1;
687 const char* errorStr2;
688 char* charBuffer;
Lee Thomasond1983222012-02-06 08:41:24 -0800689
690 MemPoolT< sizeof(XMLElement) > elementPool;
691 MemPoolT< sizeof(XMLAttribute) > attributePool;
692 MemPoolT< sizeof(XMLText) > textPool;
693 MemPoolT< sizeof(XMLComment) > commentPool;
Lee Thomason5cae8972012-01-24 18:03:07 -0800694};
695
Lee Thomason7c913cd2012-01-26 18:32:34 -0800696
Lee Thomason751da522012-02-10 08:50:51 -0800697class XMLStreamer : public XMLVisitor
Lee Thomason5cae8972012-01-24 18:03:07 -0800698{
699public:
700 XMLStreamer( FILE* file );
701 ~XMLStreamer() {}
702
Lee Thomason56bdd022012-02-09 18:16:58 -0800703 void OpenElement( const char* name );
Lee Thomason5cae8972012-01-24 18:03:07 -0800704 void PushAttribute( const char* name, const char* value );
705 void CloseElement();
706
Lee Thomason50f97b22012-02-11 16:33:40 -0800707 void PushText( const char* text, bool cdata=false );
Lee Thomason5cae8972012-01-24 18:03:07 -0800708 void PushComment( const char* comment );
709
Lee Thomason751da522012-02-10 08:50:51 -0800710 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
711 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
712
713 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
714 virtual bool VisitExit( const XMLElement& element );
715
716 virtual bool Visit( const XMLText& text );
717 virtual bool Visit( const XMLComment& comment );
718
719
Lee Thomason5cae8972012-01-24 18:03:07 -0800720private:
721 void SealElement();
722 void PrintSpace( int depth );
Lee Thomason857b8682012-01-25 17:50:25 -0800723 void PrintString( const char* ); // prints out, after detecting entities.
Lee Thomason5cae8972012-01-24 18:03:07 -0800724
725 FILE* fp;
726 int depth;
727 bool elementJustOpened;
Lee Thomason56bdd022012-02-09 18:16:58 -0800728 int textDepth;
729
Lee Thomason857b8682012-01-25 17:50:25 -0800730 enum {
Lee Thomason951d8832012-01-26 08:47:06 -0800731 ENTITY_RANGE = 64
Lee Thomason857b8682012-01-25 17:50:25 -0800732 };
733 bool entityFlag[ENTITY_RANGE];
Lee Thomason5cae8972012-01-24 18:03:07 -0800734
Lee Thomason2c85a712012-01-31 08:24:24 -0800735 DynArray< const char*, 10 > stack;
Lee Thomason5cae8972012-01-24 18:03:07 -0800736};
737
738
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800739}; // tinyxml2
740
U-Lama\Lee560bd472011-12-28 19:42:49 -0800741
742
U-Lama\Leee13c3e62011-12-28 14:36:55 -0800743#endif // TINYXML2_INCLUDED