stratgame
diff level/src/tinyxml2.h @ 0:86b53f76899f
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 21 May 2012 19:07:40 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/level/src/tinyxml2.h Mon May 21 19:07:40 2012 +0300 1.3 @@ -0,0 +1,1403 @@ 1.4 +/* 1.5 +Original code by Lee Thomason (www.grinninglizard.com) 1.6 + 1.7 +This software is provided 'as-is', without any express or implied 1.8 +warranty. In no event will the authors be held liable for any 1.9 +damages arising from the use of this software. 1.10 + 1.11 +Permission is granted to anyone to use this software for any 1.12 +purpose, including commercial applications, and to alter it and 1.13 +redistribute it freely, subject to the following restrictions: 1.14 + 1.15 +1. The origin of this software must not be misrepresented; you must 1.16 +not claim that you wrote the original software. If you use this 1.17 +software in a product, an acknowledgment in the product documentation 1.18 +would be appreciated but is not required. 1.19 + 1.20 +2. Altered source versions must be plainly marked as such, and 1.21 +must not be misrepresented as being the original software. 1.22 + 1.23 +3. This notice may not be removed or altered from any source 1.24 +distribution. 1.25 +*/ 1.26 + 1.27 +#ifndef TINYXML2_INCLUDED 1.28 +#define TINYXML2_INCLUDED 1.29 + 1.30 +#include <cctype> 1.31 +#include <climits> 1.32 +#include <cstdio> 1.33 +#include <cstring> 1.34 +#include <cstdarg> 1.35 + 1.36 +/* 1.37 + TODO: intern strings instead of allocation. 1.38 +*/ 1.39 +/* 1.40 + gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe 1.41 +*/ 1.42 + 1.43 +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) 1.44 + #ifndef DEBUG 1.45 + #define DEBUG 1.46 + #endif 1.47 +#endif 1.48 + 1.49 + 1.50 +#if defined(DEBUG) 1.51 + #if defined(_MSC_VER) 1.52 + #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak() 1.53 + #elif defined (ANDROID_NDK) 1.54 + #include <android/log.h> 1.55 + #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } 1.56 + #else 1.57 + #include <assert.h> 1.58 + #define TIXMLASSERT assert 1.59 + #endif 1.60 +#else 1.61 + #define TIXMLASSERT( x ) {} 1.62 +#endif 1.63 + 1.64 + 1.65 +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) 1.66 + // Microsoft visual studio, version 2005 and higher. 1.67 + /*int _snprintf_s( 1.68 + char *buffer, 1.69 + size_t sizeOfBuffer, 1.70 + size_t count, 1.71 + const char *format [, 1.72 + argument] ... 1.73 + );*/ 1.74 + inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) { 1.75 + va_list va; 1.76 + va_start( va, format ); 1.77 + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); 1.78 + va_end( va ); 1.79 + return result; 1.80 + } 1.81 + #define TIXML_SSCANF sscanf_s 1.82 +#else 1.83 + // GCC version 3 and higher 1.84 + //#warning( "Using sn* functions." ) 1.85 + #define TIXML_SNPRINTF snprintf 1.86 + #define TIXML_SSCANF sscanf 1.87 +#endif 1.88 + 1.89 +static const int TIXML2_MAJOR_VERSION = 1; 1.90 +static const int TIXML2_MINOR_VERSION = 0; 1.91 +static const int TIXML2_PATCH_VERSION = 1; 1.92 + 1.93 +namespace tinyxml2 1.94 +{ 1.95 +class XMLDocument; 1.96 +class XMLElement; 1.97 +class XMLAttribute; 1.98 +class XMLComment; 1.99 +class XMLNode; 1.100 +class XMLText; 1.101 +class XMLDeclaration; 1.102 +class XMLUnknown; 1.103 + 1.104 +class XMLPrinter; 1.105 + 1.106 +/* 1.107 + A class that wraps strings. Normally stores the start and end 1.108 + pointers into the XML file itself, and will apply normalization 1.109 + and entity translation if actually read. Can also store (and memory 1.110 + manage) a traditional char[] 1.111 +*/ 1.112 +class StrPair 1.113 +{ 1.114 +public: 1.115 + enum { 1.116 + NEEDS_ENTITY_PROCESSING = 0x01, 1.117 + NEEDS_NEWLINE_NORMALIZATION = 0x02, 1.118 + 1.119 + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 1.120 + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 1.121 + ATTRIBUTE_NAME = 0, 1.122 + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, 1.123 + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, 1.124 + COMMENT = NEEDS_NEWLINE_NORMALIZATION 1.125 + }; 1.126 + 1.127 + StrPair() : flags( 0 ), start( 0 ), end( 0 ) {} 1.128 + ~StrPair(); 1.129 + 1.130 + void Set( char* _start, char* _end, int _flags ) { 1.131 + Reset(); 1.132 + this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH; 1.133 + } 1.134 + const char* GetStr(); 1.135 + bool Empty() const { return start == end; } 1.136 + 1.137 + void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); } 1.138 + void SetStr( const char* str, int flags=0 ); 1.139 + 1.140 + char* ParseText( char* in, const char* endTag, int strFlags ); 1.141 + char* ParseName( char* in ); 1.142 + 1.143 + 1.144 +private: 1.145 + void Reset(); 1.146 + 1.147 + enum { 1.148 + NEEDS_FLUSH = 0x100, 1.149 + NEEDS_DELETE = 0x200 1.150 + }; 1.151 + 1.152 + // After parsing, if *end != 0, it can be set to zero. 1.153 + int flags; 1.154 + char* start; 1.155 + char* end; 1.156 +}; 1.157 + 1.158 + 1.159 +/* 1.160 + A dynamic array of Plain Old Data. Doesn't support constructors, etc. 1.161 + Has a small initial memory pool, so that low or no usage will not 1.162 + cause a call to new/delete 1.163 +*/ 1.164 +template <class T, int INIT> 1.165 +class DynArray 1.166 +{ 1.167 +public: 1.168 + DynArray< T, INIT >() 1.169 + { 1.170 + mem = pool; 1.171 + allocated = INIT; 1.172 + size = 0; 1.173 + } 1.174 + ~DynArray() 1.175 + { 1.176 + if ( mem != pool ) { 1.177 + delete [] mem; 1.178 + } 1.179 + } 1.180 + void Push( T t ) 1.181 + { 1.182 + EnsureCapacity( size+1 ); 1.183 + mem[size++] = t; 1.184 + } 1.185 + 1.186 + T* PushArr( int count ) 1.187 + { 1.188 + EnsureCapacity( size+count ); 1.189 + T* ret = &mem[size]; 1.190 + size += count; 1.191 + return ret; 1.192 + } 1.193 + T Pop() { 1.194 + return mem[--size]; 1.195 + } 1.196 + void PopArr( int count ) 1.197 + { 1.198 + TIXMLASSERT( size >= count ); 1.199 + size -= count; 1.200 + } 1.201 + 1.202 + bool Empty() const { return size == 0; } 1.203 + T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; } 1.204 + const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; } 1.205 + int Size() const { return size; } 1.206 + int Capacity() const { return allocated; } 1.207 + const T* Mem() const { return mem; } 1.208 + T* Mem() { return mem; } 1.209 + 1.210 + 1.211 +private: 1.212 + void EnsureCapacity( int cap ) { 1.213 + if ( cap > allocated ) { 1.214 + int newAllocated = cap * 2; 1.215 + T* newMem = new T[newAllocated]; 1.216 + memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs 1.217 + if ( mem != pool ) delete [] mem; 1.218 + mem = newMem; 1.219 + allocated = newAllocated; 1.220 + } 1.221 + } 1.222 + 1.223 + T* mem; 1.224 + T pool[INIT]; 1.225 + int allocated; // objects allocated 1.226 + int size; // number objects in use 1.227 +}; 1.228 + 1.229 + 1.230 +/* 1.231 + Parent virtual class of a pool for fast allocation 1.232 + and deallocation of objects. 1.233 +*/ 1.234 +class MemPool 1.235 +{ 1.236 +public: 1.237 + MemPool() {} 1.238 + virtual ~MemPool() {} 1.239 + 1.240 + virtual int ItemSize() const = 0; 1.241 + virtual void* Alloc() = 0; 1.242 + virtual void Free( void* ) = 0; 1.243 +}; 1.244 + 1.245 + 1.246 +/* 1.247 + Template child class to create pools of the correct type. 1.248 +*/ 1.249 +template< int SIZE > 1.250 +class MemPoolT : public MemPool 1.251 +{ 1.252 +public: 1.253 + MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {} 1.254 + ~MemPoolT() { 1.255 + // Delete the blocks. 1.256 + for( int i=0; i<blockPtrs.Size(); ++i ) { 1.257 + delete blockPtrs[i]; 1.258 + } 1.259 + } 1.260 + 1.261 + virtual int ItemSize() const { return SIZE; } 1.262 + int CurrentAllocs() const { return currentAllocs; } 1.263 + 1.264 + virtual void* Alloc() { 1.265 + if ( !root ) { 1.266 + // Need a new block. 1.267 + Block* block = new Block(); 1.268 + blockPtrs.Push( block ); 1.269 + 1.270 + for( int i=0; i<COUNT-1; ++i ) { 1.271 + block->chunk[i].next = &block->chunk[i+1]; 1.272 + } 1.273 + block->chunk[COUNT-1].next = 0; 1.274 + root = block->chunk; 1.275 + } 1.276 + void* result = root; 1.277 + root = root->next; 1.278 + 1.279 + ++currentAllocs; 1.280 + if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs; 1.281 + nAllocs++; 1.282 + return result; 1.283 + } 1.284 + virtual void Free( void* mem ) { 1.285 + if ( !mem ) return; 1.286 + --currentAllocs; 1.287 + Chunk* chunk = (Chunk*)mem; 1.288 + memset( chunk, 0xfe, sizeof(Chunk) ); 1.289 + chunk->next = root; 1.290 + root = chunk; 1.291 + } 1.292 + void Trace( const char* name ) { 1.293 + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", 1.294 + name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() ); 1.295 + } 1.296 + 1.297 +private: 1.298 + enum { COUNT = 1024/SIZE }; 1.299 + union Chunk { 1.300 + Chunk* next; 1.301 + char mem[SIZE]; 1.302 + }; 1.303 + struct Block { 1.304 + Chunk chunk[COUNT]; 1.305 + }; 1.306 + DynArray< Block*, 10 > blockPtrs; 1.307 + Chunk* root; 1.308 + 1.309 + int currentAllocs; 1.310 + int nAllocs; 1.311 + int maxAllocs; 1.312 +}; 1.313 + 1.314 + 1.315 + 1.316 +/** 1.317 + Implements the interface to the "Visitor pattern" (see the Accept() method.) 1.318 + If you call the Accept() method, it requires being passed a XMLVisitor 1.319 + class to handle callbacks. For nodes that contain other nodes (Document, Element) 1.320 + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs 1.321 + are simply called with Visit(). 1.322 + 1.323 + If you return 'true' from a Visit method, recursive parsing will continue. If you return 1.324 + false, <b>no children of this node or its sibilings</b> will be visited. 1.325 + 1.326 + All flavors of Visit methods have a default implementation that returns 'true' (continue 1.327 + visiting). You need to only override methods that are interesting to you. 1.328 + 1.329 + Generally Accept() is called on the TiXmlDocument, although all nodes support visiting. 1.330 + 1.331 + You should never change the document from a callback. 1.332 + 1.333 + @sa XMLNode::Accept() 1.334 +*/ 1.335 +class XMLVisitor 1.336 +{ 1.337 +public: 1.338 + virtual ~XMLVisitor() {} 1.339 + 1.340 + /// Visit a document. 1.341 + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; } 1.342 + /// Visit a document. 1.343 + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; } 1.344 + 1.345 + /// Visit an element. 1.346 + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; } 1.347 + /// Visit an element. 1.348 + virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; } 1.349 + 1.350 + /// Visit a declaration. 1.351 + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; } 1.352 + /// Visit a text node. 1.353 + virtual bool Visit( const XMLText& /*text*/ ) { return true; } 1.354 + /// Visit a comment node. 1.355 + virtual bool Visit( const XMLComment& /*comment*/ ) { return true; } 1.356 + /// Visit an unknown node. 1.357 + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; } 1.358 +}; 1.359 + 1.360 + 1.361 +/* 1.362 + Utility functionality. 1.363 +*/ 1.364 +class XMLUtil 1.365 +{ 1.366 +public: 1.367 + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't 1.368 + // correct, but simple, and usually works. 1.369 + static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; } 1.370 + static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; } 1.371 + 1.372 + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { 1.373 + int n = 0; 1.374 + if ( p == q ) { 1.375 + return true; 1.376 + } 1.377 + while( *p && *q && *p == *q && n<nChar ) { 1.378 + ++p; ++q; ++n; 1.379 + } 1.380 + if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) { 1.381 + return true; 1.382 + } 1.383 + return false; 1.384 + } 1.385 + inline static int IsUTF8Continuation( const char p ) { return p & 0x80; } 1.386 + inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; } 1.387 + inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; } 1.388 + 1.389 + static const char* ReadBOM( const char* p, bool* hasBOM ); 1.390 + // p is the starting location, 1.391 + // the UTF-8 value of the entity will be placed in value, and length filled in. 1.392 + static const char* GetCharacterRef( const char* p, char* value, int* length ); 1.393 + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); 1.394 +}; 1.395 + 1.396 + 1.397 +/** XMLNode is a base class for every object that is in the 1.398 + XML Document Object Model (DOM), except XMLAttributes. 1.399 + Nodes have siblings, a parent, and children which can 1.400 + be navigated. A node is always in a XMLDocument. 1.401 + The type of a XMLNode can be queried, and it can 1.402 + be cast to its more defined type. 1.403 + 1.404 + A XMLDocument allocates memory for all its Nodes. 1.405 + When the XMLDocument gets deleted, all its Nodes 1.406 + will also be deleted. 1.407 + 1.408 + @verbatim 1.409 + A Document can contain: Element (container or leaf) 1.410 + Comment (leaf) 1.411 + Unknown (leaf) 1.412 + Declaration( leaf ) 1.413 + 1.414 + An Element can contain: Element (container or leaf) 1.415 + Text (leaf) 1.416 + Attributes (not on tree) 1.417 + Comment (leaf) 1.418 + Unknown (leaf) 1.419 + 1.420 + @endverbatim 1.421 +*/ 1.422 +class XMLNode 1.423 +{ 1.424 + friend class XMLDocument; 1.425 + friend class XMLElement; 1.426 +public: 1.427 + 1.428 + /// Get the XMLDocument that owns this XMLNode. 1.429 + const XMLDocument* GetDocument() const { return document; } 1.430 + /// Get the XMLDocument that owns this XMLNode. 1.431 + XMLDocument* GetDocument() { return document; } 1.432 + 1.433 + virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null. 1.434 + virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null. 1.435 + virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null. 1.436 + virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null. 1.437 + virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null. 1.438 + virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null. 1.439 + 1.440 + virtual const XMLElement* ToElement() const { return 0; } 1.441 + virtual const XMLText* ToText() const { return 0; } 1.442 + virtual const XMLComment* ToComment() const { return 0; } 1.443 + virtual const XMLDocument* ToDocument() const { return 0; } 1.444 + virtual const XMLDeclaration* ToDeclaration() const { return 0; } 1.445 + virtual const XMLUnknown* ToUnknown() const { return 0; } 1.446 + 1.447 + /** The meaning of 'value' changes for the specific type. 1.448 + @verbatim 1.449 + Document: empty 1.450 + Element: name of the element 1.451 + Comment: the comment text 1.452 + Unknown: the tag contents 1.453 + Text: the text string 1.454 + @endverbatim 1.455 + */ 1.456 + const char* Value() const { return value.GetStr(); } 1.457 + /** Set the Value of an XML node. 1.458 + @sa Value() 1.459 + */ 1.460 + void SetValue( const char* val, bool staticMem=false ); 1.461 + 1.462 + /// Get the parent of this node on the DOM. 1.463 + const XMLNode* Parent() const { return parent; } 1.464 + XMLNode* Parent() { return parent; } 1.465 + 1.466 + /// Returns true if this node has no children. 1.467 + bool NoChildren() const { return !firstChild; } 1.468 + 1.469 + /// Get the first child node, or null if none exists. 1.470 + const XMLNode* FirstChild() const { return firstChild; } 1.471 + XMLNode* FirstChild() { return firstChild; } 1.472 + /** Get the first child element, or optionally the first child 1.473 + element with the specified name. 1.474 + */ 1.475 + const XMLElement* FirstChildElement( const char* value=0 ) const; 1.476 + XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); } 1.477 + 1.478 + /// Get the last child node, or null if none exists. 1.479 + const XMLNode* LastChild() const { return lastChild; } 1.480 + XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); } 1.481 + 1.482 + /** Get the last child element or optionally the last child 1.483 + element with the specified name. 1.484 + */ 1.485 + const XMLElement* LastChildElement( const char* value=0 ) const; 1.486 + XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); } 1.487 + 1.488 + /// Get the previous (left) sibling node of this node. 1.489 + const XMLNode* PreviousSibling() const { return prev; } 1.490 + XMLNode* PreviousSibling() { return prev; } 1.491 + 1.492 + /// Get the previous (left) sibling element of this node, with an opitionally supplied name. 1.493 + const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; 1.494 + XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); } 1.495 + 1.496 + /// Get the next (right) sibling node of this node. 1.497 + const XMLNode* NextSibling() const { return next; } 1.498 + XMLNode* NextSibling() { return next; } 1.499 + 1.500 + /// Get the next (right) sibling element of this node, with an opitionally supplied name. 1.501 + const XMLElement* NextSiblingElement( const char* value=0 ) const; 1.502 + XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); } 1.503 + 1.504 + /** 1.505 + Add a child node as the last (right) child. 1.506 + */ 1.507 + XMLNode* InsertEndChild( XMLNode* addThis ); 1.508 + 1.509 + XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); } 1.510 + /** 1.511 + Add a child node as the first (left) child. 1.512 + */ 1.513 + XMLNode* InsertFirstChild( XMLNode* addThis ); 1.514 + /** 1.515 + Add a node after the specified child node. 1.516 + */ 1.517 + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); 1.518 + 1.519 + /** 1.520 + Delete all the children of this node. 1.521 + */ 1.522 + void DeleteChildren(); 1.523 + 1.524 + /** 1.525 + Delete a child of this node. 1.526 + */ 1.527 + void DeleteChild( XMLNode* node ); 1.528 + 1.529 + /** 1.530 + Make a copy of this node, but not its children. 1.531 + You may pass in a Document pointer that will be 1.532 + the owner of the new Node. If the 'document' is 1.533 + null, then the node returned will be allocated 1.534 + from the current Document. (this->GetDocument()) 1.535 + 1.536 + Note: if called on a XMLDocument, this will return null. 1.537 + */ 1.538 + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; 1.539 + 1.540 + /** 1.541 + Test if 2 nodes are the same, but don't test children. 1.542 + The 2 nodes do not need to be in the same Document. 1.543 + 1.544 + Note: if called on a XMLDocument, this will return false. 1.545 + */ 1.546 + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; 1.547 + 1.548 + /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the 1.549 + XML tree will be conditionally visited and the host will be called back 1.550 + via the TiXmlVisitor interface. 1.551 + 1.552 + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse 1.553 + the XML for the callbacks, so the performance of TinyXML is unchanged by using this 1.554 + interface versus any other.) 1.555 + 1.556 + The interface has been based on ideas from: 1.557 + 1.558 + - http://www.saxproject.org/ 1.559 + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern 1.560 + 1.561 + Which are both good references for "visiting". 1.562 + 1.563 + An example of using Accept(): 1.564 + @verbatim 1.565 + TiXmlPrinter printer; 1.566 + tinyxmlDoc.Accept( &printer ); 1.567 + const char* xmlcstr = printer.CStr(); 1.568 + @endverbatim 1.569 + */ 1.570 + virtual bool Accept( XMLVisitor* visitor ) const = 0; 1.571 + 1.572 + // internal 1.573 + virtual char* ParseDeep( char*, StrPair* ); 1.574 + 1.575 +protected: 1.576 + XMLNode( XMLDocument* ); 1.577 + virtual ~XMLNode(); 1.578 + XMLNode( const XMLNode& ); // not supported 1.579 + void operator=( const XMLNode& ); // not supported 1.580 + 1.581 + XMLDocument* document; 1.582 + XMLNode* parent; 1.583 + mutable StrPair value; 1.584 + 1.585 + XMLNode* firstChild; 1.586 + XMLNode* lastChild; 1.587 + 1.588 + XMLNode* prev; 1.589 + XMLNode* next; 1.590 + 1.591 +private: 1.592 + MemPool* memPool; 1.593 + void Unlink( XMLNode* child ); 1.594 +}; 1.595 + 1.596 + 1.597 +/** XML text. 1.598 + 1.599 + Note that a text node can have child element nodes, for example: 1.600 + @verbatim 1.601 + <root>This is <b>bold</b></root> 1.602 + @endverbatim 1.603 + 1.604 + A text node can have 2 ways to output the next. "normal" output 1.605 + and CDATA. It will default to the mode it was parsed from the XML file and 1.606 + you generally want to leave it alone, but you can change the output mode with 1.607 + SetCDATA() and query it with CDATA(). 1.608 +*/ 1.609 +class XMLText : public XMLNode 1.610 +{ 1.611 + friend class XMLBase; 1.612 + friend class XMLDocument; 1.613 +public: 1.614 + virtual bool Accept( XMLVisitor* visitor ) const; 1.615 + 1.616 + virtual XMLText* ToText() { return this; } 1.617 + virtual const XMLText* ToText() const { return this; } 1.618 + 1.619 + /// Declare whether this should be CDATA or standard text. 1.620 + void SetCData( bool _isCData ) { this->isCData = _isCData; } 1.621 + /// Returns true if this is a CDATA text element. 1.622 + bool CData() const { return isCData; } 1.623 + 1.624 + char* ParseDeep( char*, StrPair* endTag ); 1.625 + virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1.626 + virtual bool ShallowEqual( const XMLNode* compare ) const; 1.627 + 1.628 + 1.629 +protected: 1.630 + XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {} 1.631 + virtual ~XMLText() {} 1.632 + XMLText( const XMLText& ); // not supported 1.633 + void operator=( const XMLText& ); // not supported 1.634 + 1.635 +private: 1.636 + bool isCData; 1.637 +}; 1.638 + 1.639 + 1.640 +/** An XML Comment. */ 1.641 +class XMLComment : public XMLNode 1.642 +{ 1.643 + friend class XMLDocument; 1.644 +public: 1.645 + virtual XMLComment* ToComment() { return this; } 1.646 + virtual const XMLComment* ToComment() const { return this; } 1.647 + 1.648 + virtual bool Accept( XMLVisitor* visitor ) const; 1.649 + 1.650 + char* ParseDeep( char*, StrPair* endTag ); 1.651 + virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1.652 + virtual bool ShallowEqual( const XMLNode* compare ) const; 1.653 + 1.654 +protected: 1.655 + XMLComment( XMLDocument* doc ); 1.656 + virtual ~XMLComment(); 1.657 + XMLComment( const XMLComment& ); // not supported 1.658 + void operator=( const XMLComment& ); // not supported 1.659 + 1.660 +private: 1.661 +}; 1.662 + 1.663 + 1.664 +/** In correct XML the declaration is the first entry in the file. 1.665 + @verbatim 1.666 + <?xml version="1.0" standalone="yes"?> 1.667 + @endverbatim 1.668 + 1.669 + TinyXML2 will happily read or write files without a declaration, 1.670 + however. 1.671 + 1.672 + The text of the declaration isn't interpreted. It is parsed 1.673 + and written as a string. 1.674 +*/ 1.675 +class XMLDeclaration : public XMLNode 1.676 +{ 1.677 + friend class XMLDocument; 1.678 +public: 1.679 + virtual XMLDeclaration* ToDeclaration() { return this; } 1.680 + virtual const XMLDeclaration* ToDeclaration() const { return this; } 1.681 + 1.682 + virtual bool Accept( XMLVisitor* visitor ) const; 1.683 + 1.684 + char* ParseDeep( char*, StrPair* endTag ); 1.685 + virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1.686 + virtual bool ShallowEqual( const XMLNode* compare ) const; 1.687 + 1.688 +protected: 1.689 + XMLDeclaration( XMLDocument* doc ); 1.690 + virtual ~XMLDeclaration(); 1.691 + XMLDeclaration( const XMLDeclaration& ); // not supported 1.692 + void operator=( const XMLDeclaration& ); // not supported 1.693 +}; 1.694 + 1.695 + 1.696 +/** Any tag that tinyXml doesn't recognize is saved as an 1.697 + unknown. It is a tag of text, but should not be modified. 1.698 + It will be written back to the XML, unchanged, when the file 1.699 + is saved. 1.700 + 1.701 + DTD tags get thrown into TiXmlUnknowns. 1.702 +*/ 1.703 +class XMLUnknown : public XMLNode 1.704 +{ 1.705 + friend class XMLDocument; 1.706 +public: 1.707 + virtual XMLUnknown* ToUnknown() { return this; } 1.708 + virtual const XMLUnknown* ToUnknown() const { return this; } 1.709 + 1.710 + virtual bool Accept( XMLVisitor* visitor ) const; 1.711 + 1.712 + char* ParseDeep( char*, StrPair* endTag ); 1.713 + virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1.714 + virtual bool ShallowEqual( const XMLNode* compare ) const; 1.715 + 1.716 +protected: 1.717 + XMLUnknown( XMLDocument* doc ); 1.718 + virtual ~XMLUnknown(); 1.719 + XMLUnknown( const XMLUnknown& ); // not supported 1.720 + void operator=( const XMLUnknown& ); // not supported 1.721 +}; 1.722 + 1.723 + 1.724 +enum { 1.725 + XML_NO_ERROR = 0, 1.726 + XML_SUCCESS = 0, 1.727 + 1.728 + XML_NO_ATTRIBUTE, 1.729 + XML_WRONG_ATTRIBUTE_TYPE, 1.730 + 1.731 + XML_ERROR_FILE_NOT_FOUND, 1.732 + XML_ERROR_FILE_COULD_NOT_BE_OPENED, 1.733 + XML_ERROR_ELEMENT_MISMATCH, 1.734 + XML_ERROR_PARSING_ELEMENT, 1.735 + XML_ERROR_PARSING_ATTRIBUTE, 1.736 + XML_ERROR_IDENTIFYING_TAG, 1.737 + XML_ERROR_PARSING_TEXT, 1.738 + XML_ERROR_PARSING_CDATA, 1.739 + XML_ERROR_PARSING_COMMENT, 1.740 + XML_ERROR_PARSING_DECLARATION, 1.741 + XML_ERROR_PARSING_UNKNOWN, 1.742 + XML_ERROR_EMPTY_DOCUMENT, 1.743 + XML_ERROR_MISMATCHED_ELEMENT, 1.744 + XML_ERROR_PARSING 1.745 +}; 1.746 + 1.747 + 1.748 +/** An attribute is a name-value pair. Elements have an arbitrary 1.749 + number of attributes, each with a unique name. 1.750 + 1.751 + @note The attributes are not XMLNodes. You may only query the 1.752 + Next() attribute in a list. 1.753 +*/ 1.754 +class XMLAttribute 1.755 +{ 1.756 + friend class XMLElement; 1.757 +public: 1.758 + const char* Name() const { return name.GetStr(); } ///< The name of the attribute. 1.759 + const char* Value() const { return value.GetStr(); } ///< The value of the attribute. 1.760 + const XMLAttribute* Next() const { return next; } ///< The next attribute in the list. 1.761 + 1.762 + /** IntAttribute interprets the attribute as an integer, and returns the value. 1.763 + If the value isn't an integer, 0 will be returned. There is no error checking; 1.764 + use QueryIntAttribute() if you need error checking. 1.765 + */ 1.766 + int IntValue() const { int i=0; QueryIntValue( &i ); return i; } 1.767 + /// Query as an unsigned integer. See IntAttribute() 1.768 + unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; } 1.769 + /// Query as a boolean. See IntAttribute() 1.770 + bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; } 1.771 + /// Query as a double. See IntAttribute() 1.772 + double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; } 1.773 + /// Query as a float. See IntAttribute() 1.774 + float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; } 1.775 + 1.776 + /** QueryIntAttribute interprets the attribute as an integer, and returns the value 1.777 + in the provided paremeter. The function will return XML_NO_ERROR on success, 1.778 + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. 1.779 + */ 1.780 + int QueryIntValue( int* value ) const; 1.781 + /// See QueryIntAttribute 1.782 + int QueryUnsignedValue( unsigned int* value ) const; 1.783 + /// See QueryIntAttribute 1.784 + int QueryBoolValue( bool* value ) const; 1.785 + /// See QueryIntAttribute 1.786 + int QueryDoubleValue( double* value ) const; 1.787 + /// See QueryIntAttribute 1.788 + int QueryFloatValue( float* value ) const; 1.789 + 1.790 + /// Set the attribute to a string value. 1.791 + void SetAttribute( const char* value ); 1.792 + /// Set the attribute to value. 1.793 + void SetAttribute( int value ); 1.794 + /// Set the attribute to value. 1.795 + void SetAttribute( unsigned value ); 1.796 + /// Set the attribute to value. 1.797 + void SetAttribute( bool value ); 1.798 + /// Set the attribute to value. 1.799 + void SetAttribute( double value ); 1.800 + /// Set the attribute to value. 1.801 + void SetAttribute( float value ); 1.802 + 1.803 +private: 1.804 + enum { BUF_SIZE = 200 }; 1.805 + 1.806 + XMLAttribute() : next( 0 ) {} 1.807 + virtual ~XMLAttribute() {} 1.808 + XMLAttribute( const XMLAttribute& ); // not supported 1.809 + void operator=( const XMLAttribute& ); // not supported 1.810 + void SetName( const char* name ); 1.811 + 1.812 + char* ParseDeep( char* p, bool processEntities ); 1.813 + 1.814 + mutable StrPair name; 1.815 + mutable StrPair value; 1.816 + XMLAttribute* next; 1.817 + MemPool* memPool; 1.818 +}; 1.819 + 1.820 + 1.821 +/** The element is a container class. It has a value, the element name, 1.822 + and can contain other elements, text, comments, and unknowns. 1.823 + Elements also contain an arbitrary number of attributes. 1.824 +*/ 1.825 +class XMLElement : public XMLNode 1.826 +{ 1.827 + friend class XMLBase; 1.828 + friend class XMLDocument; 1.829 +public: 1.830 + /// Get the name of an element (which is the Value() of the node.) 1.831 + const char* Name() const { return Value(); } 1.832 + /// Set the name of the element. 1.833 + void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); } 1.834 + 1.835 + virtual XMLElement* ToElement() { return this; } 1.836 + virtual const XMLElement* ToElement() const { return this; } 1.837 + virtual bool Accept( XMLVisitor* visitor ) const; 1.838 + 1.839 + /** Given an attribute name, Attribute() returns the value 1.840 + for the attribute of that name, or null if none 1.841 + exists. For example: 1.842 + 1.843 + @verbatim 1.844 + const char* value = ele->Attribute( "foo" ); 1.845 + @endverbatim 1.846 + 1.847 + The 'value' parameter is normally null. However, if specified, 1.848 + the attribute will only be returned if the 'name' and 'value' 1.849 + match. This allow you to write code: 1.850 + 1.851 + @verbatim 1.852 + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); 1.853 + @endverbatim 1.854 + 1.855 + rather than: 1.856 + @verbatim 1.857 + if ( ele->Attribute( "foo" ) ) { 1.858 + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); 1.859 + } 1.860 + @endverbatim 1.861 + */ 1.862 + const char* Attribute( const char* name, const char* value=0 ) const; 1.863 + 1.864 + /** Given an attribute name, IntAttribute() returns the value 1.865 + of the attribute interpreted as an integer. 0 will be 1.866 + returned if there is an error. For a method with error 1.867 + checking, see QueryIntAttribute() 1.868 + */ 1.869 + int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; } 1.870 + /// See IntAttribute() 1.871 + unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; } 1.872 + /// See IntAttribute() 1.873 + bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; } 1.874 + /// See IntAttribute() 1.875 + double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; } 1.876 + /// See IntAttribute() 1.877 + float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; } 1.878 + 1.879 + /** Given an attribute name, QueryIntAttribute() returns 1.880 + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion 1.881 + can't be performed, or XML_NO_ATTRIBUTE if the attribute 1.882 + doesn't exist. If successful, the result of the conversion 1.883 + will be written to 'value'. If not successful, nothing will 1.884 + be written to 'value'. This allows you to provide default 1.885 + value: 1.886 + 1.887 + @verbatim 1.888 + int value = 10; 1.889 + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 1.890 + @endverbatim 1.891 + */ 1.892 + int QueryIntAttribute( const char* name, int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); } 1.893 + /// See QueryIntAttribute() 1.894 + int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); } 1.895 + /// See QueryIntAttribute() 1.896 + int QueryBoolAttribute( const char* name, bool* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); } 1.897 + /// See QueryIntAttribute() 1.898 + int QueryDoubleAttribute( const char* name, double* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); } 1.899 + /// See QueryIntAttribute() 1.900 + int QueryFloatAttribute( const char* name, float* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); } 1.901 + 1.902 + /// Sets the named attribute to value. 1.903 + void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); } 1.904 + /// Sets the named attribute to value. 1.905 + void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); } 1.906 + /// Sets the named attribute to value. 1.907 + void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); } 1.908 + /// Sets the named attribute to value. 1.909 + void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); } 1.910 + /// Sets the named attribute to value. 1.911 + void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); } 1.912 + 1.913 + /** 1.914 + Delete an attribute. 1.915 + */ 1.916 + void DeleteAttribute( const char* name ); 1.917 + 1.918 + /// Return the first attribute in the list. 1.919 + const XMLAttribute* FirstAttribute() const { return rootAttribute; } 1.920 + /// Query a specific attribute in the list. 1.921 + const XMLAttribute* FindAttribute( const char* name ) const; 1.922 + 1.923 + /** Convenience function for easy access to the text inside an element. Although easy 1.924 + and concise, GetText() is limited compared to getting the TiXmlText child 1.925 + and accessing it directly. 1.926 + 1.927 + If the first child of 'this' is a TiXmlText, the GetText() 1.928 + returns the character string of the Text node, else null is returned. 1.929 + 1.930 + This is a convenient method for getting the text of simple contained text: 1.931 + @verbatim 1.932 + <foo>This is text</foo> 1.933 + const char* str = fooElement->GetText(); 1.934 + @endverbatim 1.935 + 1.936 + 'str' will be a pointer to "This is text". 1.937 + 1.938 + Note that this function can be misleading. If the element foo was created from 1.939 + this XML: 1.940 + @verbatim 1.941 + <foo><b>This is text</b></foo> 1.942 + @endverbatim 1.943 + 1.944 + then the value of str would be null. The first child node isn't a text node, it is 1.945 + another element. From this XML: 1.946 + @verbatim 1.947 + <foo>This is <b>text</b></foo> 1.948 + @endverbatim 1.949 + GetText() will return "This is ". 1.950 + */ 1.951 + const char* GetText() const; 1.952 + 1.953 + // internal: 1.954 + enum { 1.955 + OPEN, // <foo> 1.956 + CLOSED, // <foo/> 1.957 + CLOSING // </foo> 1.958 + }; 1.959 + int ClosingType() const { return closingType; } 1.960 + char* ParseDeep( char* p, StrPair* endTag ); 1.961 + virtual XMLNode* ShallowClone( XMLDocument* document ) const; 1.962 + virtual bool ShallowEqual( const XMLNode* compare ) const; 1.963 + 1.964 +private: 1.965 + XMLElement( XMLDocument* doc ); 1.966 + virtual ~XMLElement(); 1.967 + XMLElement( const XMLElement& ); // not supported 1.968 + void operator=( const XMLElement& ); // not supported 1.969 + 1.970 + XMLAttribute* FindAttribute( const char* name ); 1.971 + XMLAttribute* FindOrCreateAttribute( const char* name ); 1.972 + //void LinkAttribute( XMLAttribute* attrib ); 1.973 + char* ParseAttributes( char* p ); 1.974 + 1.975 + int closingType; 1.976 + // The attribute list is ordered; there is no 'lastAttribute' 1.977 + // because the list needs to be scanned for dupes before adding 1.978 + // a new attribute. 1.979 + XMLAttribute* rootAttribute; 1.980 +}; 1.981 + 1.982 + 1.983 +/** A Document binds together all the functionality. 1.984 + It can be saved, loaded, and printed to the screen. 1.985 + All Nodes are connected and allocated to a Document. 1.986 + If the Document is deleted, all its Nodes are also deleted. 1.987 +*/ 1.988 +class XMLDocument : public XMLNode 1.989 +{ 1.990 + friend class XMLElement; 1.991 +public: 1.992 + /// constructor 1.993 + XMLDocument( bool processEntities = true ); 1.994 + ~XMLDocument(); 1.995 + 1.996 + virtual XMLDocument* ToDocument() { return this; } 1.997 + virtual const XMLDocument* ToDocument() const { return this; } 1.998 + 1.999 + /** 1.1000 + Parse an XML file from a character string. 1.1001 + Returns XML_NO_ERROR (0) on success, or 1.1002 + an errorID. 1.1003 + */ 1.1004 + int Parse( const char* xml ); 1.1005 + 1.1006 + /** 1.1007 + Load an XML file from disk. 1.1008 + Returns XML_NO_ERROR (0) on success, or 1.1009 + an errorID. 1.1010 + */ 1.1011 + int LoadFile( const char* filename ); 1.1012 + 1.1013 + /** 1.1014 + Load an XML file from disk. You are responsible 1.1015 + for providing and closing the FILE*. 1.1016 + 1.1017 + Returns XML_NO_ERROR (0) on success, or 1.1018 + an errorID. 1.1019 + */ 1.1020 + int LoadFile( FILE* ); 1.1021 + 1.1022 + /** 1.1023 + Save the XML file to disk. 1.1024 + Returns XML_NO_ERROR (0) on success, or 1.1025 + an errorID. 1.1026 + */ 1.1027 + int SaveFile( const char* filename ); 1.1028 + 1.1029 + /** 1.1030 + Save the XML file to disk. You are responsible 1.1031 + for providing and closing the FILE*. 1.1032 + 1.1033 + Returns XML_NO_ERROR (0) on success, or 1.1034 + an errorID. 1.1035 + */ 1.1036 + int SaveFile( FILE* ); 1.1037 + 1.1038 + bool ProcessEntities() const { return processEntities; } 1.1039 + 1.1040 + /** 1.1041 + Returns true if this document has a leading Byte Order Mark of UTF8. 1.1042 + */ 1.1043 + bool HasBOM() const { return writeBOM; } 1.1044 + /** Sets whether to write the BOM when writing the file. 1.1045 + */ 1.1046 + void SetBOM( bool useBOM ) { writeBOM = useBOM; } 1.1047 + 1.1048 + /** Return the root element of DOM. Equivalent to FirstChildElement(). 1.1049 + To get the first node, use FirstChild(). 1.1050 + */ 1.1051 + XMLElement* RootElement() { return FirstChildElement(); } 1.1052 + const XMLElement* RootElement() const { return FirstChildElement(); } 1.1053 + 1.1054 + /** Print the Document. If the Printer is not provided, it will 1.1055 + print to stdout. If you provide Printer, this can print to a file: 1.1056 + @verbatim 1.1057 + XMLPrinter printer( fp ); 1.1058 + doc.Print( &printer ); 1.1059 + @endverbatim 1.1060 + 1.1061 + Or you can use a printer to print to memory: 1.1062 + @verbatim 1.1063 + XMLPrinter printer; 1.1064 + doc->Print( &printer ); 1.1065 + // printer.CStr() has a const char* to the XML 1.1066 + @endverbatim 1.1067 + */ 1.1068 + void Print( XMLPrinter* streamer=0 ); 1.1069 + virtual bool Accept( XMLVisitor* visitor ) const; 1.1070 + 1.1071 + /** 1.1072 + Create a new Element associated with 1.1073 + this Document. The memory for the Element 1.1074 + is managed by the Document. 1.1075 + */ 1.1076 + XMLElement* NewElement( const char* name ); 1.1077 + /** 1.1078 + Create a new Comment associated with 1.1079 + this Document. The memory for the Comment 1.1080 + is managed by the Document. 1.1081 + */ 1.1082 + XMLComment* NewComment( const char* comment ); 1.1083 + /** 1.1084 + Create a new Text associated with 1.1085 + this Document. The memory for the Text 1.1086 + is managed by the Document. 1.1087 + */ 1.1088 + XMLText* NewText( const char* text ); 1.1089 + /** 1.1090 + Create a new Declaration associated with 1.1091 + this Document. The memory for the object 1.1092 + is managed by the Document. 1.1093 + 1.1094 + If the 'text' param is null, the standard 1.1095 + declaration is used.: 1.1096 + @verbatim 1.1097 + <?xml version="1.0" encoding="UTF-8"?> 1.1098 + @endverbatim 1.1099 + */ 1.1100 + XMLDeclaration* NewDeclaration( const char* text=0 ); 1.1101 + /** 1.1102 + Create a new Unknown associated with 1.1103 + this Document. The memory for the object 1.1104 + is managed by the Document. 1.1105 + */ 1.1106 + XMLUnknown* NewUnknown( const char* text ); 1.1107 + 1.1108 + /** 1.1109 + Delete a node associated with this document. 1.1110 + It will be unlinked from the DOM. 1.1111 + */ 1.1112 + void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); } 1.1113 + 1.1114 + void SetError( int error, const char* str1, const char* str2 ); 1.1115 + 1.1116 + /// Return true if there was an error parsing the document. 1.1117 + bool Error() const { return errorID != XML_NO_ERROR; } 1.1118 + /// Return the errorID. 1.1119 + int ErrorID() const { return errorID; } 1.1120 + /// Return a possibly helpful diagnostic location or string. 1.1121 + const char* GetErrorStr1() const { return errorStr1; } 1.1122 + /// Return a possibly helpful secondary diagnostic location or string. 1.1123 + const char* GetErrorStr2() const { return errorStr2; } 1.1124 + /// If there is an error, print it to stdout. 1.1125 + void PrintError() const; 1.1126 + 1.1127 + // internal 1.1128 + char* Identify( char* p, XMLNode** node ); 1.1129 + 1.1130 + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; } 1.1131 + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; } 1.1132 + 1.1133 +private: 1.1134 + XMLDocument( const XMLDocument& ); // not supported 1.1135 + void operator=( const XMLDocument& ); // not supported 1.1136 + void InitDocument(); 1.1137 + 1.1138 + bool writeBOM; 1.1139 + bool processEntities; 1.1140 + int errorID; 1.1141 + const char* errorStr1; 1.1142 + const char* errorStr2; 1.1143 + char* charBuffer; 1.1144 + 1.1145 + MemPoolT< sizeof(XMLElement) > elementPool; 1.1146 + MemPoolT< sizeof(XMLAttribute) > attributePool; 1.1147 + MemPoolT< sizeof(XMLText) > textPool; 1.1148 + MemPoolT< sizeof(XMLComment) > commentPool; 1.1149 +}; 1.1150 + 1.1151 + 1.1152 +/** 1.1153 + A XMLHandle is a class that wraps a node pointer with null checks; this is 1.1154 + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML 1.1155 + DOM structure. It is a separate utility class. 1.1156 + 1.1157 + Take an example: 1.1158 + @verbatim 1.1159 + <Document> 1.1160 + <Element attributeA = "valueA"> 1.1161 + <Child attributeB = "value1" /> 1.1162 + <Child attributeB = "value2" /> 1.1163 + </Element> 1.1164 + </Document> 1.1165 + @endverbatim 1.1166 + 1.1167 + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very 1.1168 + easy to write a *lot* of code that looks like: 1.1169 + 1.1170 + @verbatim 1.1171 + XMLElement* root = document.FirstChildElement( "Document" ); 1.1172 + if ( root ) 1.1173 + { 1.1174 + XMLElement* element = root->FirstChildElement( "Element" ); 1.1175 + if ( element ) 1.1176 + { 1.1177 + XMLElement* child = element->FirstChildElement( "Child" ); 1.1178 + if ( child ) 1.1179 + { 1.1180 + XMLElement* child2 = child->NextSiblingElement( "Child" ); 1.1181 + if ( child2 ) 1.1182 + { 1.1183 + // Finally do something useful. 1.1184 + @endverbatim 1.1185 + 1.1186 + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity 1.1187 + of such code. A XMLHandle checks for null pointers so it is perfectly safe 1.1188 + and correct to use: 1.1189 + 1.1190 + @verbatim 1.1191 + XMLHandle docHandle( &document ); 1.1192 + XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement(); 1.1193 + if ( child2 ) 1.1194 + { 1.1195 + // do something useful 1.1196 + @endverbatim 1.1197 + 1.1198 + Which is MUCH more concise and useful. 1.1199 + 1.1200 + It is also safe to copy handles - internally they are nothing more than node pointers. 1.1201 + @verbatim 1.1202 + XMLHandle handleCopy = handle; 1.1203 + @endverbatim 1.1204 + 1.1205 + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. 1.1206 +*/ 1.1207 +class XMLHandle 1.1208 +{ 1.1209 +public: 1.1210 + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. 1.1211 + XMLHandle( XMLNode* _node ) { node = _node; } 1.1212 + /// Create a handle from a node. 1.1213 + XMLHandle( XMLNode& _node ) { node = &_node; } 1.1214 + /// Copy constructor 1.1215 + XMLHandle( const XMLHandle& ref ) { node = ref.node; } 1.1216 + /// Assignment 1.1217 + XMLHandle operator=( const XMLHandle& ref ) { node = ref.node; return *this; } 1.1218 + 1.1219 + /// Get the first child of this handle. 1.1220 + XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); } 1.1221 + /// Get the first child element of this handle. 1.1222 + XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); } 1.1223 + /// Get the last child of this handle. 1.1224 + XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); } 1.1225 + /// Get the last child element of this handle. 1.1226 + XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); } 1.1227 + /// Get the previous sibling of this handle. 1.1228 + XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); } 1.1229 + /// Get the previous sibling element of this handle. 1.1230 + XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); } 1.1231 + /// Get the next sibling of this handle. 1.1232 + XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); } 1.1233 + /// Get the next sibling element of this handle. 1.1234 + XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); } 1.1235 + 1.1236 + /// Safe cast to XMLNode. This can return null. 1.1237 + XMLNode* ToNode() { return node; } 1.1238 + /// Safe cast to XMLElement. This can return null. 1.1239 + XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } 1.1240 + /// Safe cast to XMLText. This can return null. 1.1241 + XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } 1.1242 + /// Safe cast to XMLUnknown. This can return null. 1.1243 + XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } 1.1244 + /// Safe cast to XMLDeclaration. This can return null. 1.1245 + XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); } 1.1246 + 1.1247 +private: 1.1248 + XMLNode* node; 1.1249 +}; 1.1250 + 1.1251 + 1.1252 +/** 1.1253 + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the 1.1254 + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. 1.1255 +*/ 1.1256 +class XMLConstHandle 1.1257 +{ 1.1258 +public: 1.1259 + XMLConstHandle( const XMLNode* _node ) { node = _node; } 1.1260 + XMLConstHandle( const XMLNode& _node ) { node = &_node; } 1.1261 + XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; } 1.1262 + 1.1263 + XMLConstHandle operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; } 1.1264 + 1.1265 + const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); } 1.1266 + const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); } 1.1267 + const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); } 1.1268 + const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); } 1.1269 + const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); } 1.1270 + const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); } 1.1271 + const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); } 1.1272 + const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); } 1.1273 + 1.1274 + 1.1275 + const XMLNode* ToNode() const { return node; } 1.1276 + const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } 1.1277 + const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } 1.1278 + const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } 1.1279 + const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); } 1.1280 + 1.1281 +private: 1.1282 + const XMLNode* node; 1.1283 +}; 1.1284 + 1.1285 + 1.1286 +/** 1.1287 + Printing functionality. The XMLPrinter gives you more 1.1288 + options than the XMLDocument::Print() method. 1.1289 + 1.1290 + It can: 1.1291 + -# Print to memory. 1.1292 + -# Print to a file you provide. 1.1293 + -# Print XML without a XMLDocument. 1.1294 + 1.1295 + Print to Memory 1.1296 + 1.1297 + @verbatim 1.1298 + XMLPrinter printer; 1.1299 + doc->Print( &printer ); 1.1300 + SomeFunction( printer.CStr() ); 1.1301 + @endverbatim 1.1302 + 1.1303 + Print to a File 1.1304 + 1.1305 + You provide the file pointer. 1.1306 + @verbatim 1.1307 + XMLPrinter printer( fp ); 1.1308 + doc.Print( &printer ); 1.1309 + @endverbatim 1.1310 + 1.1311 + Print without a XMLDocument 1.1312 + 1.1313 + When loading, an XML parser is very useful. However, sometimes 1.1314 + when saving, it just gets in the way. The code is often set up 1.1315 + for streaming, and constructing the DOM is just overhead. 1.1316 + 1.1317 + The Printer supports the streaming case. The following code 1.1318 + prints out a trivially simple XML file without ever creating 1.1319 + an XML document. 1.1320 + 1.1321 + @verbatim 1.1322 + XMLPrinter printer( fp ); 1.1323 + printer.OpenElement( "foo" ); 1.1324 + printer.PushAttribute( "foo", "bar" ); 1.1325 + printer.CloseElement(); 1.1326 + @endverbatim 1.1327 +*/ 1.1328 +class XMLPrinter : public XMLVisitor 1.1329 +{ 1.1330 +public: 1.1331 + /** Construct the printer. If the FILE* is specified, 1.1332 + this will print to the FILE. Else it will print 1.1333 + to memory, and the result is available in CStr() 1.1334 + */ 1.1335 + XMLPrinter( FILE* file=0 ); 1.1336 + ~XMLPrinter() {} 1.1337 + 1.1338 + /** If streaming, write the BOM and declaration. */ 1.1339 + void PushHeader( bool writeBOM, bool writeDeclaration ); 1.1340 + /** If streaming, start writing an element. 1.1341 + The element must be closed with CloseElement() 1.1342 + */ 1.1343 + void OpenElement( const char* name ); 1.1344 + /// If streaming, add an attribute to an open element. 1.1345 + void PushAttribute( const char* name, const char* value ); 1.1346 + void PushAttribute( const char* name, int value ); 1.1347 + void PushAttribute( const char* name, unsigned value ); 1.1348 + void PushAttribute( const char* name, bool value ); 1.1349 + void PushAttribute( const char* name, double value ); 1.1350 + /// If streaming, close the Element. 1.1351 + void CloseElement(); 1.1352 + 1.1353 + /// Add a text node. 1.1354 + void PushText( const char* text, bool cdata=false ); 1.1355 + /// Add a comment. 1.1356 + void PushComment( const char* comment ); 1.1357 + 1.1358 + void PushDeclaration( const char* value ); 1.1359 + void PushUnknown( const char* value ); 1.1360 + 1.1361 + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); 1.1362 + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; } 1.1363 + 1.1364 + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); 1.1365 + virtual bool VisitExit( const XMLElement& element ); 1.1366 + 1.1367 + virtual bool Visit( const XMLText& text ); 1.1368 + virtual bool Visit( const XMLComment& comment ); 1.1369 + virtual bool Visit( const XMLDeclaration& declaration ); 1.1370 + virtual bool Visit( const XMLUnknown& unknown ); 1.1371 + 1.1372 + /** 1.1373 + If in print to memory mode, return a pointer to 1.1374 + the XML file in memory. 1.1375 + */ 1.1376 + const char* CStr() const { return buffer.Mem(); } 1.1377 + 1.1378 +private: 1.1379 + void SealElement(); 1.1380 + void PrintSpace( int depth ); 1.1381 + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. 1.1382 + void Print( const char* format, ... ); 1.1383 + 1.1384 + bool elementJustOpened; 1.1385 + bool firstElement; 1.1386 + FILE* fp; 1.1387 + int depth; 1.1388 + int textDepth; 1.1389 + bool processEntities; 1.1390 + 1.1391 + enum { 1.1392 + ENTITY_RANGE = 64, 1.1393 + BUF_SIZE = 200 1.1394 + }; 1.1395 + bool entityFlag[ENTITY_RANGE]; 1.1396 + bool restrictedEntityFlag[ENTITY_RANGE]; 1.1397 + 1.1398 + DynArray< const char*, 10 > stack; 1.1399 + DynArray< char, 20 > buffer, accumulator; 1.1400 +}; 1.1401 + 1.1402 + 1.1403 +} // tinyxml2 1.1404 + 1.1405 + 1.1406 +#endif // TINYXML2_INCLUDED