stratgame

annotate 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
rev   line source
nuclear@0 1 /*
nuclear@0 2 Original code by Lee Thomason (www.grinninglizard.com)
nuclear@0 3
nuclear@0 4 This software is provided 'as-is', without any express or implied
nuclear@0 5 warranty. In no event will the authors be held liable for any
nuclear@0 6 damages arising from the use of this software.
nuclear@0 7
nuclear@0 8 Permission is granted to anyone to use this software for any
nuclear@0 9 purpose, including commercial applications, and to alter it and
nuclear@0 10 redistribute it freely, subject to the following restrictions:
nuclear@0 11
nuclear@0 12 1. The origin of this software must not be misrepresented; you must
nuclear@0 13 not claim that you wrote the original software. If you use this
nuclear@0 14 software in a product, an acknowledgment in the product documentation
nuclear@0 15 would be appreciated but is not required.
nuclear@0 16
nuclear@0 17 2. Altered source versions must be plainly marked as such, and
nuclear@0 18 must not be misrepresented as being the original software.
nuclear@0 19
nuclear@0 20 3. This notice may not be removed or altered from any source
nuclear@0 21 distribution.
nuclear@0 22 */
nuclear@0 23
nuclear@0 24 #ifndef TINYXML2_INCLUDED
nuclear@0 25 #define TINYXML2_INCLUDED
nuclear@0 26
nuclear@0 27 #include <cctype>
nuclear@0 28 #include <climits>
nuclear@0 29 #include <cstdio>
nuclear@0 30 #include <cstring>
nuclear@0 31 #include <cstdarg>
nuclear@0 32
nuclear@0 33 /*
nuclear@0 34 TODO: intern strings instead of allocation.
nuclear@0 35 */
nuclear@0 36 /*
nuclear@0 37 gcc: g++ -Wall tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
nuclear@0 38 */
nuclear@0 39
nuclear@0 40 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
nuclear@0 41 #ifndef DEBUG
nuclear@0 42 #define DEBUG
nuclear@0 43 #endif
nuclear@0 44 #endif
nuclear@0 45
nuclear@0 46
nuclear@0 47 #if defined(DEBUG)
nuclear@0 48 #if defined(_MSC_VER)
nuclear@0 49 #define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
nuclear@0 50 #elif defined (ANDROID_NDK)
nuclear@0 51 #include <android/log.h>
nuclear@0 52 #define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
nuclear@0 53 #else
nuclear@0 54 #include <assert.h>
nuclear@0 55 #define TIXMLASSERT assert
nuclear@0 56 #endif
nuclear@0 57 #else
nuclear@0 58 #define TIXMLASSERT( x ) {}
nuclear@0 59 #endif
nuclear@0 60
nuclear@0 61
nuclear@0 62 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
nuclear@0 63 // Microsoft visual studio, version 2005 and higher.
nuclear@0 64 /*int _snprintf_s(
nuclear@0 65 char *buffer,
nuclear@0 66 size_t sizeOfBuffer,
nuclear@0 67 size_t count,
nuclear@0 68 const char *format [,
nuclear@0 69 argument] ...
nuclear@0 70 );*/
nuclear@0 71 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) {
nuclear@0 72 va_list va;
nuclear@0 73 va_start( va, format );
nuclear@0 74 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
nuclear@0 75 va_end( va );
nuclear@0 76 return result;
nuclear@0 77 }
nuclear@0 78 #define TIXML_SSCANF sscanf_s
nuclear@0 79 #else
nuclear@0 80 // GCC version 3 and higher
nuclear@0 81 //#warning( "Using sn* functions." )
nuclear@0 82 #define TIXML_SNPRINTF snprintf
nuclear@0 83 #define TIXML_SSCANF sscanf
nuclear@0 84 #endif
nuclear@0 85
nuclear@0 86 static const int TIXML2_MAJOR_VERSION = 1;
nuclear@0 87 static const int TIXML2_MINOR_VERSION = 0;
nuclear@0 88 static const int TIXML2_PATCH_VERSION = 1;
nuclear@0 89
nuclear@0 90 namespace tinyxml2
nuclear@0 91 {
nuclear@0 92 class XMLDocument;
nuclear@0 93 class XMLElement;
nuclear@0 94 class XMLAttribute;
nuclear@0 95 class XMLComment;
nuclear@0 96 class XMLNode;
nuclear@0 97 class XMLText;
nuclear@0 98 class XMLDeclaration;
nuclear@0 99 class XMLUnknown;
nuclear@0 100
nuclear@0 101 class XMLPrinter;
nuclear@0 102
nuclear@0 103 /*
nuclear@0 104 A class that wraps strings. Normally stores the start and end
nuclear@0 105 pointers into the XML file itself, and will apply normalization
nuclear@0 106 and entity translation if actually read. Can also store (and memory
nuclear@0 107 manage) a traditional char[]
nuclear@0 108 */
nuclear@0 109 class StrPair
nuclear@0 110 {
nuclear@0 111 public:
nuclear@0 112 enum {
nuclear@0 113 NEEDS_ENTITY_PROCESSING = 0x01,
nuclear@0 114 NEEDS_NEWLINE_NORMALIZATION = 0x02,
nuclear@0 115
nuclear@0 116 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 117 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 118 ATTRIBUTE_NAME = 0,
nuclear@0 119 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 120 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 121 COMMENT = NEEDS_NEWLINE_NORMALIZATION
nuclear@0 122 };
nuclear@0 123
nuclear@0 124 StrPair() : flags( 0 ), start( 0 ), end( 0 ) {}
nuclear@0 125 ~StrPair();
nuclear@0 126
nuclear@0 127 void Set( char* _start, char* _end, int _flags ) {
nuclear@0 128 Reset();
nuclear@0 129 this->start = _start; this->end = _end; this->flags = _flags | NEEDS_FLUSH;
nuclear@0 130 }
nuclear@0 131 const char* GetStr();
nuclear@0 132 bool Empty() const { return start == end; }
nuclear@0 133
nuclear@0 134 void SetInternedStr( const char* str ) { Reset(); this->start = const_cast<char*>(str); }
nuclear@0 135 void SetStr( const char* str, int flags=0 );
nuclear@0 136
nuclear@0 137 char* ParseText( char* in, const char* endTag, int strFlags );
nuclear@0 138 char* ParseName( char* in );
nuclear@0 139
nuclear@0 140
nuclear@0 141 private:
nuclear@0 142 void Reset();
nuclear@0 143
nuclear@0 144 enum {
nuclear@0 145 NEEDS_FLUSH = 0x100,
nuclear@0 146 NEEDS_DELETE = 0x200
nuclear@0 147 };
nuclear@0 148
nuclear@0 149 // After parsing, if *end != 0, it can be set to zero.
nuclear@0 150 int flags;
nuclear@0 151 char* start;
nuclear@0 152 char* end;
nuclear@0 153 };
nuclear@0 154
nuclear@0 155
nuclear@0 156 /*
nuclear@0 157 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
nuclear@0 158 Has a small initial memory pool, so that low or no usage will not
nuclear@0 159 cause a call to new/delete
nuclear@0 160 */
nuclear@0 161 template <class T, int INIT>
nuclear@0 162 class DynArray
nuclear@0 163 {
nuclear@0 164 public:
nuclear@0 165 DynArray< T, INIT >()
nuclear@0 166 {
nuclear@0 167 mem = pool;
nuclear@0 168 allocated = INIT;
nuclear@0 169 size = 0;
nuclear@0 170 }
nuclear@0 171 ~DynArray()
nuclear@0 172 {
nuclear@0 173 if ( mem != pool ) {
nuclear@0 174 delete [] mem;
nuclear@0 175 }
nuclear@0 176 }
nuclear@0 177 void Push( T t )
nuclear@0 178 {
nuclear@0 179 EnsureCapacity( size+1 );
nuclear@0 180 mem[size++] = t;
nuclear@0 181 }
nuclear@0 182
nuclear@0 183 T* PushArr( int count )
nuclear@0 184 {
nuclear@0 185 EnsureCapacity( size+count );
nuclear@0 186 T* ret = &mem[size];
nuclear@0 187 size += count;
nuclear@0 188 return ret;
nuclear@0 189 }
nuclear@0 190 T Pop() {
nuclear@0 191 return mem[--size];
nuclear@0 192 }
nuclear@0 193 void PopArr( int count )
nuclear@0 194 {
nuclear@0 195 TIXMLASSERT( size >= count );
nuclear@0 196 size -= count;
nuclear@0 197 }
nuclear@0 198
nuclear@0 199 bool Empty() const { return size == 0; }
nuclear@0 200 T& operator[](int i) { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
nuclear@0 201 const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < size ); return mem[i]; }
nuclear@0 202 int Size() const { return size; }
nuclear@0 203 int Capacity() const { return allocated; }
nuclear@0 204 const T* Mem() const { return mem; }
nuclear@0 205 T* Mem() { return mem; }
nuclear@0 206
nuclear@0 207
nuclear@0 208 private:
nuclear@0 209 void EnsureCapacity( int cap ) {
nuclear@0 210 if ( cap > allocated ) {
nuclear@0 211 int newAllocated = cap * 2;
nuclear@0 212 T* newMem = new T[newAllocated];
nuclear@0 213 memcpy( newMem, mem, sizeof(T)*size ); // warning: not using constructors, only works for PODs
nuclear@0 214 if ( mem != pool ) delete [] mem;
nuclear@0 215 mem = newMem;
nuclear@0 216 allocated = newAllocated;
nuclear@0 217 }
nuclear@0 218 }
nuclear@0 219
nuclear@0 220 T* mem;
nuclear@0 221 T pool[INIT];
nuclear@0 222 int allocated; // objects allocated
nuclear@0 223 int size; // number objects in use
nuclear@0 224 };
nuclear@0 225
nuclear@0 226
nuclear@0 227 /*
nuclear@0 228 Parent virtual class of a pool for fast allocation
nuclear@0 229 and deallocation of objects.
nuclear@0 230 */
nuclear@0 231 class MemPool
nuclear@0 232 {
nuclear@0 233 public:
nuclear@0 234 MemPool() {}
nuclear@0 235 virtual ~MemPool() {}
nuclear@0 236
nuclear@0 237 virtual int ItemSize() const = 0;
nuclear@0 238 virtual void* Alloc() = 0;
nuclear@0 239 virtual void Free( void* ) = 0;
nuclear@0 240 };
nuclear@0 241
nuclear@0 242
nuclear@0 243 /*
nuclear@0 244 Template child class to create pools of the correct type.
nuclear@0 245 */
nuclear@0 246 template< int SIZE >
nuclear@0 247 class MemPoolT : public MemPool
nuclear@0 248 {
nuclear@0 249 public:
nuclear@0 250 MemPoolT() : root(0), currentAllocs(0), nAllocs(0), maxAllocs(0) {}
nuclear@0 251 ~MemPoolT() {
nuclear@0 252 // Delete the blocks.
nuclear@0 253 for( int i=0; i<blockPtrs.Size(); ++i ) {
nuclear@0 254 delete blockPtrs[i];
nuclear@0 255 }
nuclear@0 256 }
nuclear@0 257
nuclear@0 258 virtual int ItemSize() const { return SIZE; }
nuclear@0 259 int CurrentAllocs() const { return currentAllocs; }
nuclear@0 260
nuclear@0 261 virtual void* Alloc() {
nuclear@0 262 if ( !root ) {
nuclear@0 263 // Need a new block.
nuclear@0 264 Block* block = new Block();
nuclear@0 265 blockPtrs.Push( block );
nuclear@0 266
nuclear@0 267 for( int i=0; i<COUNT-1; ++i ) {
nuclear@0 268 block->chunk[i].next = &block->chunk[i+1];
nuclear@0 269 }
nuclear@0 270 block->chunk[COUNT-1].next = 0;
nuclear@0 271 root = block->chunk;
nuclear@0 272 }
nuclear@0 273 void* result = root;
nuclear@0 274 root = root->next;
nuclear@0 275
nuclear@0 276 ++currentAllocs;
nuclear@0 277 if ( currentAllocs > maxAllocs ) maxAllocs = currentAllocs;
nuclear@0 278 nAllocs++;
nuclear@0 279 return result;
nuclear@0 280 }
nuclear@0 281 virtual void Free( void* mem ) {
nuclear@0 282 if ( !mem ) return;
nuclear@0 283 --currentAllocs;
nuclear@0 284 Chunk* chunk = (Chunk*)mem;
nuclear@0 285 memset( chunk, 0xfe, sizeof(Chunk) );
nuclear@0 286 chunk->next = root;
nuclear@0 287 root = chunk;
nuclear@0 288 }
nuclear@0 289 void Trace( const char* name ) {
nuclear@0 290 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
nuclear@0 291 name, maxAllocs, maxAllocs*SIZE/1024, currentAllocs, SIZE, nAllocs, blockPtrs.Size() );
nuclear@0 292 }
nuclear@0 293
nuclear@0 294 private:
nuclear@0 295 enum { COUNT = 1024/SIZE };
nuclear@0 296 union Chunk {
nuclear@0 297 Chunk* next;
nuclear@0 298 char mem[SIZE];
nuclear@0 299 };
nuclear@0 300 struct Block {
nuclear@0 301 Chunk chunk[COUNT];
nuclear@0 302 };
nuclear@0 303 DynArray< Block*, 10 > blockPtrs;
nuclear@0 304 Chunk* root;
nuclear@0 305
nuclear@0 306 int currentAllocs;
nuclear@0 307 int nAllocs;
nuclear@0 308 int maxAllocs;
nuclear@0 309 };
nuclear@0 310
nuclear@0 311
nuclear@0 312
nuclear@0 313 /**
nuclear@0 314 Implements the interface to the "Visitor pattern" (see the Accept() method.)
nuclear@0 315 If you call the Accept() method, it requires being passed a XMLVisitor
nuclear@0 316 class to handle callbacks. For nodes that contain other nodes (Document, Element)
nuclear@0 317 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
nuclear@0 318 are simply called with Visit().
nuclear@0 319
nuclear@0 320 If you return 'true' from a Visit method, recursive parsing will continue. If you return
nuclear@0 321 false, <b>no children of this node or its sibilings</b> will be visited.
nuclear@0 322
nuclear@0 323 All flavors of Visit methods have a default implementation that returns 'true' (continue
nuclear@0 324 visiting). You need to only override methods that are interesting to you.
nuclear@0 325
nuclear@0 326 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
nuclear@0 327
nuclear@0 328 You should never change the document from a callback.
nuclear@0 329
nuclear@0 330 @sa XMLNode::Accept()
nuclear@0 331 */
nuclear@0 332 class XMLVisitor
nuclear@0 333 {
nuclear@0 334 public:
nuclear@0 335 virtual ~XMLVisitor() {}
nuclear@0 336
nuclear@0 337 /// Visit a document.
nuclear@0 338 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; }
nuclear@0 339 /// Visit a document.
nuclear@0 340 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
nuclear@0 341
nuclear@0 342 /// Visit an element.
nuclear@0 343 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; }
nuclear@0 344 /// Visit an element.
nuclear@0 345 virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; }
nuclear@0 346
nuclear@0 347 /// Visit a declaration.
nuclear@0 348 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; }
nuclear@0 349 /// Visit a text node.
nuclear@0 350 virtual bool Visit( const XMLText& /*text*/ ) { return true; }
nuclear@0 351 /// Visit a comment node.
nuclear@0 352 virtual bool Visit( const XMLComment& /*comment*/ ) { return true; }
nuclear@0 353 /// Visit an unknown node.
nuclear@0 354 virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; }
nuclear@0 355 };
nuclear@0 356
nuclear@0 357
nuclear@0 358 /*
nuclear@0 359 Utility functionality.
nuclear@0 360 */
nuclear@0 361 class XMLUtil
nuclear@0 362 {
nuclear@0 363 public:
nuclear@0 364 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
nuclear@0 365 // correct, but simple, and usually works.
nuclear@0 366 static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
nuclear@0 367 static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *p ) ) { ++p; } return p; }
nuclear@0 368
nuclear@0 369 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
nuclear@0 370 int n = 0;
nuclear@0 371 if ( p == q ) {
nuclear@0 372 return true;
nuclear@0 373 }
nuclear@0 374 while( *p && *q && *p == *q && n<nChar ) {
nuclear@0 375 ++p; ++q; ++n;
nuclear@0 376 }
nuclear@0 377 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
nuclear@0 378 return true;
nuclear@0 379 }
nuclear@0 380 return false;
nuclear@0 381 }
nuclear@0 382 inline static int IsUTF8Continuation( const char p ) { return p & 0x80; }
nuclear@0 383 inline static int IsAlphaNum( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalnum( anyByte ) : 1; }
nuclear@0 384 inline static int IsAlpha( unsigned char anyByte ) { return ( anyByte < 128 ) ? isalpha( anyByte ) : 1; }
nuclear@0 385
nuclear@0 386 static const char* ReadBOM( const char* p, bool* hasBOM );
nuclear@0 387 // p is the starting location,
nuclear@0 388 // the UTF-8 value of the entity will be placed in value, and length filled in.
nuclear@0 389 static const char* GetCharacterRef( const char* p, char* value, int* length );
nuclear@0 390 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
nuclear@0 391 };
nuclear@0 392
nuclear@0 393
nuclear@0 394 /** XMLNode is a base class for every object that is in the
nuclear@0 395 XML Document Object Model (DOM), except XMLAttributes.
nuclear@0 396 Nodes have siblings, a parent, and children which can
nuclear@0 397 be navigated. A node is always in a XMLDocument.
nuclear@0 398 The type of a XMLNode can be queried, and it can
nuclear@0 399 be cast to its more defined type.
nuclear@0 400
nuclear@0 401 A XMLDocument allocates memory for all its Nodes.
nuclear@0 402 When the XMLDocument gets deleted, all its Nodes
nuclear@0 403 will also be deleted.
nuclear@0 404
nuclear@0 405 @verbatim
nuclear@0 406 A Document can contain: Element (container or leaf)
nuclear@0 407 Comment (leaf)
nuclear@0 408 Unknown (leaf)
nuclear@0 409 Declaration( leaf )
nuclear@0 410
nuclear@0 411 An Element can contain: Element (container or leaf)
nuclear@0 412 Text (leaf)
nuclear@0 413 Attributes (not on tree)
nuclear@0 414 Comment (leaf)
nuclear@0 415 Unknown (leaf)
nuclear@0 416
nuclear@0 417 @endverbatim
nuclear@0 418 */
nuclear@0 419 class XMLNode
nuclear@0 420 {
nuclear@0 421 friend class XMLDocument;
nuclear@0 422 friend class XMLElement;
nuclear@0 423 public:
nuclear@0 424
nuclear@0 425 /// Get the XMLDocument that owns this XMLNode.
nuclear@0 426 const XMLDocument* GetDocument() const { return document; }
nuclear@0 427 /// Get the XMLDocument that owns this XMLNode.
nuclear@0 428 XMLDocument* GetDocument() { return document; }
nuclear@0 429
nuclear@0 430 virtual XMLElement* ToElement() { return 0; } ///< Safely cast to an Element, or null.
nuclear@0 431 virtual XMLText* ToText() { return 0; } ///< Safely cast to Text, or null.
nuclear@0 432 virtual XMLComment* ToComment() { return 0; } ///< Safely cast to a Comment, or null.
nuclear@0 433 virtual XMLDocument* ToDocument() { return 0; } ///< Safely cast to a Document, or null.
nuclear@0 434 virtual XMLDeclaration* ToDeclaration() { return 0; } ///< Safely cast to a Declaration, or null.
nuclear@0 435 virtual XMLUnknown* ToUnknown() { return 0; } ///< Safely cast to an Unknown, or null.
nuclear@0 436
nuclear@0 437 virtual const XMLElement* ToElement() const { return 0; }
nuclear@0 438 virtual const XMLText* ToText() const { return 0; }
nuclear@0 439 virtual const XMLComment* ToComment() const { return 0; }
nuclear@0 440 virtual const XMLDocument* ToDocument() const { return 0; }
nuclear@0 441 virtual const XMLDeclaration* ToDeclaration() const { return 0; }
nuclear@0 442 virtual const XMLUnknown* ToUnknown() const { return 0; }
nuclear@0 443
nuclear@0 444 /** The meaning of 'value' changes for the specific type.
nuclear@0 445 @verbatim
nuclear@0 446 Document: empty
nuclear@0 447 Element: name of the element
nuclear@0 448 Comment: the comment text
nuclear@0 449 Unknown: the tag contents
nuclear@0 450 Text: the text string
nuclear@0 451 @endverbatim
nuclear@0 452 */
nuclear@0 453 const char* Value() const { return value.GetStr(); }
nuclear@0 454 /** Set the Value of an XML node.
nuclear@0 455 @sa Value()
nuclear@0 456 */
nuclear@0 457 void SetValue( const char* val, bool staticMem=false );
nuclear@0 458
nuclear@0 459 /// Get the parent of this node on the DOM.
nuclear@0 460 const XMLNode* Parent() const { return parent; }
nuclear@0 461 XMLNode* Parent() { return parent; }
nuclear@0 462
nuclear@0 463 /// Returns true if this node has no children.
nuclear@0 464 bool NoChildren() const { return !firstChild; }
nuclear@0 465
nuclear@0 466 /// Get the first child node, or null if none exists.
nuclear@0 467 const XMLNode* FirstChild() const { return firstChild; }
nuclear@0 468 XMLNode* FirstChild() { return firstChild; }
nuclear@0 469 /** Get the first child element, or optionally the first child
nuclear@0 470 element with the specified name.
nuclear@0 471 */
nuclear@0 472 const XMLElement* FirstChildElement( const char* value=0 ) const;
nuclear@0 473 XMLElement* FirstChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( _value )); }
nuclear@0 474
nuclear@0 475 /// Get the last child node, or null if none exists.
nuclear@0 476 const XMLNode* LastChild() const { return lastChild; }
nuclear@0 477 XMLNode* LastChild() { return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() ); }
nuclear@0 478
nuclear@0 479 /** Get the last child element or optionally the last child
nuclear@0 480 element with the specified name.
nuclear@0 481 */
nuclear@0 482 const XMLElement* LastChildElement( const char* value=0 ) const;
nuclear@0 483 XMLElement* LastChildElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(_value) ); }
nuclear@0 484
nuclear@0 485 /// Get the previous (left) sibling node of this node.
nuclear@0 486 const XMLNode* PreviousSibling() const { return prev; }
nuclear@0 487 XMLNode* PreviousSibling() { return prev; }
nuclear@0 488
nuclear@0 489 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
nuclear@0 490 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
nuclear@0 491 XMLElement* PreviousSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( _value ) ); }
nuclear@0 492
nuclear@0 493 /// Get the next (right) sibling node of this node.
nuclear@0 494 const XMLNode* NextSibling() const { return next; }
nuclear@0 495 XMLNode* NextSibling() { return next; }
nuclear@0 496
nuclear@0 497 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
nuclear@0 498 const XMLElement* NextSiblingElement( const char* value=0 ) const;
nuclear@0 499 XMLElement* NextSiblingElement( const char* _value=0 ) { return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( _value ) ); }
nuclear@0 500
nuclear@0 501 /**
nuclear@0 502 Add a child node as the last (right) child.
nuclear@0 503 */
nuclear@0 504 XMLNode* InsertEndChild( XMLNode* addThis );
nuclear@0 505
nuclear@0 506 XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); }
nuclear@0 507 /**
nuclear@0 508 Add a child node as the first (left) child.
nuclear@0 509 */
nuclear@0 510 XMLNode* InsertFirstChild( XMLNode* addThis );
nuclear@0 511 /**
nuclear@0 512 Add a node after the specified child node.
nuclear@0 513 */
nuclear@0 514 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
nuclear@0 515
nuclear@0 516 /**
nuclear@0 517 Delete all the children of this node.
nuclear@0 518 */
nuclear@0 519 void DeleteChildren();
nuclear@0 520
nuclear@0 521 /**
nuclear@0 522 Delete a child of this node.
nuclear@0 523 */
nuclear@0 524 void DeleteChild( XMLNode* node );
nuclear@0 525
nuclear@0 526 /**
nuclear@0 527 Make a copy of this node, but not its children.
nuclear@0 528 You may pass in a Document pointer that will be
nuclear@0 529 the owner of the new Node. If the 'document' is
nuclear@0 530 null, then the node returned will be allocated
nuclear@0 531 from the current Document. (this->GetDocument())
nuclear@0 532
nuclear@0 533 Note: if called on a XMLDocument, this will return null.
nuclear@0 534 */
nuclear@0 535 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
nuclear@0 536
nuclear@0 537 /**
nuclear@0 538 Test if 2 nodes are the same, but don't test children.
nuclear@0 539 The 2 nodes do not need to be in the same Document.
nuclear@0 540
nuclear@0 541 Note: if called on a XMLDocument, this will return false.
nuclear@0 542 */
nuclear@0 543 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
nuclear@0 544
nuclear@0 545 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
nuclear@0 546 XML tree will be conditionally visited and the host will be called back
nuclear@0 547 via the TiXmlVisitor interface.
nuclear@0 548
nuclear@0 549 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
nuclear@0 550 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
nuclear@0 551 interface versus any other.)
nuclear@0 552
nuclear@0 553 The interface has been based on ideas from:
nuclear@0 554
nuclear@0 555 - http://www.saxproject.org/
nuclear@0 556 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
nuclear@0 557
nuclear@0 558 Which are both good references for "visiting".
nuclear@0 559
nuclear@0 560 An example of using Accept():
nuclear@0 561 @verbatim
nuclear@0 562 TiXmlPrinter printer;
nuclear@0 563 tinyxmlDoc.Accept( &printer );
nuclear@0 564 const char* xmlcstr = printer.CStr();
nuclear@0 565 @endverbatim
nuclear@0 566 */
nuclear@0 567 virtual bool Accept( XMLVisitor* visitor ) const = 0;
nuclear@0 568
nuclear@0 569 // internal
nuclear@0 570 virtual char* ParseDeep( char*, StrPair* );
nuclear@0 571
nuclear@0 572 protected:
nuclear@0 573 XMLNode( XMLDocument* );
nuclear@0 574 virtual ~XMLNode();
nuclear@0 575 XMLNode( const XMLNode& ); // not supported
nuclear@0 576 void operator=( const XMLNode& ); // not supported
nuclear@0 577
nuclear@0 578 XMLDocument* document;
nuclear@0 579 XMLNode* parent;
nuclear@0 580 mutable StrPair value;
nuclear@0 581
nuclear@0 582 XMLNode* firstChild;
nuclear@0 583 XMLNode* lastChild;
nuclear@0 584
nuclear@0 585 XMLNode* prev;
nuclear@0 586 XMLNode* next;
nuclear@0 587
nuclear@0 588 private:
nuclear@0 589 MemPool* memPool;
nuclear@0 590 void Unlink( XMLNode* child );
nuclear@0 591 };
nuclear@0 592
nuclear@0 593
nuclear@0 594 /** XML text.
nuclear@0 595
nuclear@0 596 Note that a text node can have child element nodes, for example:
nuclear@0 597 @verbatim
nuclear@0 598 <root>This is <b>bold</b></root>
nuclear@0 599 @endverbatim
nuclear@0 600
nuclear@0 601 A text node can have 2 ways to output the next. "normal" output
nuclear@0 602 and CDATA. It will default to the mode it was parsed from the XML file and
nuclear@0 603 you generally want to leave it alone, but you can change the output mode with
nuclear@0 604 SetCDATA() and query it with CDATA().
nuclear@0 605 */
nuclear@0 606 class XMLText : public XMLNode
nuclear@0 607 {
nuclear@0 608 friend class XMLBase;
nuclear@0 609 friend class XMLDocument;
nuclear@0 610 public:
nuclear@0 611 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 612
nuclear@0 613 virtual XMLText* ToText() { return this; }
nuclear@0 614 virtual const XMLText* ToText() const { return this; }
nuclear@0 615
nuclear@0 616 /// Declare whether this should be CDATA or standard text.
nuclear@0 617 void SetCData( bool _isCData ) { this->isCData = _isCData; }
nuclear@0 618 /// Returns true if this is a CDATA text element.
nuclear@0 619 bool CData() const { return isCData; }
nuclear@0 620
nuclear@0 621 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 622 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 623 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 624
nuclear@0 625
nuclear@0 626 protected:
nuclear@0 627 XMLText( XMLDocument* doc ) : XMLNode( doc ), isCData( false ) {}
nuclear@0 628 virtual ~XMLText() {}
nuclear@0 629 XMLText( const XMLText& ); // not supported
nuclear@0 630 void operator=( const XMLText& ); // not supported
nuclear@0 631
nuclear@0 632 private:
nuclear@0 633 bool isCData;
nuclear@0 634 };
nuclear@0 635
nuclear@0 636
nuclear@0 637 /** An XML Comment. */
nuclear@0 638 class XMLComment : public XMLNode
nuclear@0 639 {
nuclear@0 640 friend class XMLDocument;
nuclear@0 641 public:
nuclear@0 642 virtual XMLComment* ToComment() { return this; }
nuclear@0 643 virtual const XMLComment* ToComment() const { return this; }
nuclear@0 644
nuclear@0 645 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 646
nuclear@0 647 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 648 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 649 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 650
nuclear@0 651 protected:
nuclear@0 652 XMLComment( XMLDocument* doc );
nuclear@0 653 virtual ~XMLComment();
nuclear@0 654 XMLComment( const XMLComment& ); // not supported
nuclear@0 655 void operator=( const XMLComment& ); // not supported
nuclear@0 656
nuclear@0 657 private:
nuclear@0 658 };
nuclear@0 659
nuclear@0 660
nuclear@0 661 /** In correct XML the declaration is the first entry in the file.
nuclear@0 662 @verbatim
nuclear@0 663 <?xml version="1.0" standalone="yes"?>
nuclear@0 664 @endverbatim
nuclear@0 665
nuclear@0 666 TinyXML2 will happily read or write files without a declaration,
nuclear@0 667 however.
nuclear@0 668
nuclear@0 669 The text of the declaration isn't interpreted. It is parsed
nuclear@0 670 and written as a string.
nuclear@0 671 */
nuclear@0 672 class XMLDeclaration : public XMLNode
nuclear@0 673 {
nuclear@0 674 friend class XMLDocument;
nuclear@0 675 public:
nuclear@0 676 virtual XMLDeclaration* ToDeclaration() { return this; }
nuclear@0 677 virtual const XMLDeclaration* ToDeclaration() const { return this; }
nuclear@0 678
nuclear@0 679 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 680
nuclear@0 681 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 682 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 683 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 684
nuclear@0 685 protected:
nuclear@0 686 XMLDeclaration( XMLDocument* doc );
nuclear@0 687 virtual ~XMLDeclaration();
nuclear@0 688 XMLDeclaration( const XMLDeclaration& ); // not supported
nuclear@0 689 void operator=( const XMLDeclaration& ); // not supported
nuclear@0 690 };
nuclear@0 691
nuclear@0 692
nuclear@0 693 /** Any tag that tinyXml doesn't recognize is saved as an
nuclear@0 694 unknown. It is a tag of text, but should not be modified.
nuclear@0 695 It will be written back to the XML, unchanged, when the file
nuclear@0 696 is saved.
nuclear@0 697
nuclear@0 698 DTD tags get thrown into TiXmlUnknowns.
nuclear@0 699 */
nuclear@0 700 class XMLUnknown : public XMLNode
nuclear@0 701 {
nuclear@0 702 friend class XMLDocument;
nuclear@0 703 public:
nuclear@0 704 virtual XMLUnknown* ToUnknown() { return this; }
nuclear@0 705 virtual const XMLUnknown* ToUnknown() const { return this; }
nuclear@0 706
nuclear@0 707 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 708
nuclear@0 709 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 710 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 711 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 712
nuclear@0 713 protected:
nuclear@0 714 XMLUnknown( XMLDocument* doc );
nuclear@0 715 virtual ~XMLUnknown();
nuclear@0 716 XMLUnknown( const XMLUnknown& ); // not supported
nuclear@0 717 void operator=( const XMLUnknown& ); // not supported
nuclear@0 718 };
nuclear@0 719
nuclear@0 720
nuclear@0 721 enum {
nuclear@0 722 XML_NO_ERROR = 0,
nuclear@0 723 XML_SUCCESS = 0,
nuclear@0 724
nuclear@0 725 XML_NO_ATTRIBUTE,
nuclear@0 726 XML_WRONG_ATTRIBUTE_TYPE,
nuclear@0 727
nuclear@0 728 XML_ERROR_FILE_NOT_FOUND,
nuclear@0 729 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
nuclear@0 730 XML_ERROR_ELEMENT_MISMATCH,
nuclear@0 731 XML_ERROR_PARSING_ELEMENT,
nuclear@0 732 XML_ERROR_PARSING_ATTRIBUTE,
nuclear@0 733 XML_ERROR_IDENTIFYING_TAG,
nuclear@0 734 XML_ERROR_PARSING_TEXT,
nuclear@0 735 XML_ERROR_PARSING_CDATA,
nuclear@0 736 XML_ERROR_PARSING_COMMENT,
nuclear@0 737 XML_ERROR_PARSING_DECLARATION,
nuclear@0 738 XML_ERROR_PARSING_UNKNOWN,
nuclear@0 739 XML_ERROR_EMPTY_DOCUMENT,
nuclear@0 740 XML_ERROR_MISMATCHED_ELEMENT,
nuclear@0 741 XML_ERROR_PARSING
nuclear@0 742 };
nuclear@0 743
nuclear@0 744
nuclear@0 745 /** An attribute is a name-value pair. Elements have an arbitrary
nuclear@0 746 number of attributes, each with a unique name.
nuclear@0 747
nuclear@0 748 @note The attributes are not XMLNodes. You may only query the
nuclear@0 749 Next() attribute in a list.
nuclear@0 750 */
nuclear@0 751 class XMLAttribute
nuclear@0 752 {
nuclear@0 753 friend class XMLElement;
nuclear@0 754 public:
nuclear@0 755 const char* Name() const { return name.GetStr(); } ///< The name of the attribute.
nuclear@0 756 const char* Value() const { return value.GetStr(); } ///< The value of the attribute.
nuclear@0 757 const XMLAttribute* Next() const { return next; } ///< The next attribute in the list.
nuclear@0 758
nuclear@0 759 /** IntAttribute interprets the attribute as an integer, and returns the value.
nuclear@0 760 If the value isn't an integer, 0 will be returned. There is no error checking;
nuclear@0 761 use QueryIntAttribute() if you need error checking.
nuclear@0 762 */
nuclear@0 763 int IntValue() const { int i=0; QueryIntValue( &i ); return i; }
nuclear@0 764 /// Query as an unsigned integer. See IntAttribute()
nuclear@0 765 unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; }
nuclear@0 766 /// Query as a boolean. See IntAttribute()
nuclear@0 767 bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; }
nuclear@0 768 /// Query as a double. See IntAttribute()
nuclear@0 769 double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; }
nuclear@0 770 /// Query as a float. See IntAttribute()
nuclear@0 771 float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; }
nuclear@0 772
nuclear@0 773 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
nuclear@0 774 in the provided paremeter. The function will return XML_NO_ERROR on success,
nuclear@0 775 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
nuclear@0 776 */
nuclear@0 777 int QueryIntValue( int* value ) const;
nuclear@0 778 /// See QueryIntAttribute
nuclear@0 779 int QueryUnsignedValue( unsigned int* value ) const;
nuclear@0 780 /// See QueryIntAttribute
nuclear@0 781 int QueryBoolValue( bool* value ) const;
nuclear@0 782 /// See QueryIntAttribute
nuclear@0 783 int QueryDoubleValue( double* value ) const;
nuclear@0 784 /// See QueryIntAttribute
nuclear@0 785 int QueryFloatValue( float* value ) const;
nuclear@0 786
nuclear@0 787 /// Set the attribute to a string value.
nuclear@0 788 void SetAttribute( const char* value );
nuclear@0 789 /// Set the attribute to value.
nuclear@0 790 void SetAttribute( int value );
nuclear@0 791 /// Set the attribute to value.
nuclear@0 792 void SetAttribute( unsigned value );
nuclear@0 793 /// Set the attribute to value.
nuclear@0 794 void SetAttribute( bool value );
nuclear@0 795 /// Set the attribute to value.
nuclear@0 796 void SetAttribute( double value );
nuclear@0 797 /// Set the attribute to value.
nuclear@0 798 void SetAttribute( float value );
nuclear@0 799
nuclear@0 800 private:
nuclear@0 801 enum { BUF_SIZE = 200 };
nuclear@0 802
nuclear@0 803 XMLAttribute() : next( 0 ) {}
nuclear@0 804 virtual ~XMLAttribute() {}
nuclear@0 805 XMLAttribute( const XMLAttribute& ); // not supported
nuclear@0 806 void operator=( const XMLAttribute& ); // not supported
nuclear@0 807 void SetName( const char* name );
nuclear@0 808
nuclear@0 809 char* ParseDeep( char* p, bool processEntities );
nuclear@0 810
nuclear@0 811 mutable StrPair name;
nuclear@0 812 mutable StrPair value;
nuclear@0 813 XMLAttribute* next;
nuclear@0 814 MemPool* memPool;
nuclear@0 815 };
nuclear@0 816
nuclear@0 817
nuclear@0 818 /** The element is a container class. It has a value, the element name,
nuclear@0 819 and can contain other elements, text, comments, and unknowns.
nuclear@0 820 Elements also contain an arbitrary number of attributes.
nuclear@0 821 */
nuclear@0 822 class XMLElement : public XMLNode
nuclear@0 823 {
nuclear@0 824 friend class XMLBase;
nuclear@0 825 friend class XMLDocument;
nuclear@0 826 public:
nuclear@0 827 /// Get the name of an element (which is the Value() of the node.)
nuclear@0 828 const char* Name() const { return Value(); }
nuclear@0 829 /// Set the name of the element.
nuclear@0 830 void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); }
nuclear@0 831
nuclear@0 832 virtual XMLElement* ToElement() { return this; }
nuclear@0 833 virtual const XMLElement* ToElement() const { return this; }
nuclear@0 834 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 835
nuclear@0 836 /** Given an attribute name, Attribute() returns the value
nuclear@0 837 for the attribute of that name, or null if none
nuclear@0 838 exists. For example:
nuclear@0 839
nuclear@0 840 @verbatim
nuclear@0 841 const char* value = ele->Attribute( "foo" );
nuclear@0 842 @endverbatim
nuclear@0 843
nuclear@0 844 The 'value' parameter is normally null. However, if specified,
nuclear@0 845 the attribute will only be returned if the 'name' and 'value'
nuclear@0 846 match. This allow you to write code:
nuclear@0 847
nuclear@0 848 @verbatim
nuclear@0 849 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
nuclear@0 850 @endverbatim
nuclear@0 851
nuclear@0 852 rather than:
nuclear@0 853 @verbatim
nuclear@0 854 if ( ele->Attribute( "foo" ) ) {
nuclear@0 855 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
nuclear@0 856 }
nuclear@0 857 @endverbatim
nuclear@0 858 */
nuclear@0 859 const char* Attribute( const char* name, const char* value=0 ) const;
nuclear@0 860
nuclear@0 861 /** Given an attribute name, IntAttribute() returns the value
nuclear@0 862 of the attribute interpreted as an integer. 0 will be
nuclear@0 863 returned if there is an error. For a method with error
nuclear@0 864 checking, see QueryIntAttribute()
nuclear@0 865 */
nuclear@0 866 int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; }
nuclear@0 867 /// See IntAttribute()
nuclear@0 868 unsigned UnsignedAttribute( const char* name ) const{ unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; }
nuclear@0 869 /// See IntAttribute()
nuclear@0 870 bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; }
nuclear@0 871 /// See IntAttribute()
nuclear@0 872 double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; }
nuclear@0 873 /// See IntAttribute()
nuclear@0 874 float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; }
nuclear@0 875
nuclear@0 876 /** Given an attribute name, QueryIntAttribute() returns
nuclear@0 877 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
nuclear@0 878 can't be performed, or XML_NO_ATTRIBUTE if the attribute
nuclear@0 879 doesn't exist. If successful, the result of the conversion
nuclear@0 880 will be written to 'value'. If not successful, nothing will
nuclear@0 881 be written to 'value'. This allows you to provide default
nuclear@0 882 value:
nuclear@0 883
nuclear@0 884 @verbatim
nuclear@0 885 int value = 10;
nuclear@0 886 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
nuclear@0 887 @endverbatim
nuclear@0 888 */
nuclear@0 889 int QueryIntAttribute( const char* name, int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryIntValue( _value ); }
nuclear@0 890 /// See QueryIntAttribute()
nuclear@0 891 int QueryUnsignedAttribute( const char* name, unsigned int* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryUnsignedValue( _value ); }
nuclear@0 892 /// See QueryIntAttribute()
nuclear@0 893 int QueryBoolAttribute( const char* name, bool* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryBoolValue( _value ); }
nuclear@0 894 /// See QueryIntAttribute()
nuclear@0 895 int QueryDoubleAttribute( const char* name, double* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryDoubleValue( _value ); }
nuclear@0 896 /// See QueryIntAttribute()
nuclear@0 897 int QueryFloatAttribute( const char* name, float* _value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) return XML_NO_ATTRIBUTE; return a->QueryFloatValue( _value ); }
nuclear@0 898
nuclear@0 899 /// Sets the named attribute to value.
nuclear@0 900 void SetAttribute( const char* name, const char* _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
nuclear@0 901 /// Sets the named attribute to value.
nuclear@0 902 void SetAttribute( const char* name, int _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
nuclear@0 903 /// Sets the named attribute to value.
nuclear@0 904 void SetAttribute( const char* name, unsigned _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
nuclear@0 905 /// Sets the named attribute to value.
nuclear@0 906 void SetAttribute( const char* name, bool _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
nuclear@0 907 /// Sets the named attribute to value.
nuclear@0 908 void SetAttribute( const char* name, double _value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( _value ); }
nuclear@0 909
nuclear@0 910 /**
nuclear@0 911 Delete an attribute.
nuclear@0 912 */
nuclear@0 913 void DeleteAttribute( const char* name );
nuclear@0 914
nuclear@0 915 /// Return the first attribute in the list.
nuclear@0 916 const XMLAttribute* FirstAttribute() const { return rootAttribute; }
nuclear@0 917 /// Query a specific attribute in the list.
nuclear@0 918 const XMLAttribute* FindAttribute( const char* name ) const;
nuclear@0 919
nuclear@0 920 /** Convenience function for easy access to the text inside an element. Although easy
nuclear@0 921 and concise, GetText() is limited compared to getting the TiXmlText child
nuclear@0 922 and accessing it directly.
nuclear@0 923
nuclear@0 924 If the first child of 'this' is a TiXmlText, the GetText()
nuclear@0 925 returns the character string of the Text node, else null is returned.
nuclear@0 926
nuclear@0 927 This is a convenient method for getting the text of simple contained text:
nuclear@0 928 @verbatim
nuclear@0 929 <foo>This is text</foo>
nuclear@0 930 const char* str = fooElement->GetText();
nuclear@0 931 @endverbatim
nuclear@0 932
nuclear@0 933 'str' will be a pointer to "This is text".
nuclear@0 934
nuclear@0 935 Note that this function can be misleading. If the element foo was created from
nuclear@0 936 this XML:
nuclear@0 937 @verbatim
nuclear@0 938 <foo><b>This is text</b></foo>
nuclear@0 939 @endverbatim
nuclear@0 940
nuclear@0 941 then the value of str would be null. The first child node isn't a text node, it is
nuclear@0 942 another element. From this XML:
nuclear@0 943 @verbatim
nuclear@0 944 <foo>This is <b>text</b></foo>
nuclear@0 945 @endverbatim
nuclear@0 946 GetText() will return "This is ".
nuclear@0 947 */
nuclear@0 948 const char* GetText() const;
nuclear@0 949
nuclear@0 950 // internal:
nuclear@0 951 enum {
nuclear@0 952 OPEN, // <foo>
nuclear@0 953 CLOSED, // <foo/>
nuclear@0 954 CLOSING // </foo>
nuclear@0 955 };
nuclear@0 956 int ClosingType() const { return closingType; }
nuclear@0 957 char* ParseDeep( char* p, StrPair* endTag );
nuclear@0 958 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 959 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 960
nuclear@0 961 private:
nuclear@0 962 XMLElement( XMLDocument* doc );
nuclear@0 963 virtual ~XMLElement();
nuclear@0 964 XMLElement( const XMLElement& ); // not supported
nuclear@0 965 void operator=( const XMLElement& ); // not supported
nuclear@0 966
nuclear@0 967 XMLAttribute* FindAttribute( const char* name );
nuclear@0 968 XMLAttribute* FindOrCreateAttribute( const char* name );
nuclear@0 969 //void LinkAttribute( XMLAttribute* attrib );
nuclear@0 970 char* ParseAttributes( char* p );
nuclear@0 971
nuclear@0 972 int closingType;
nuclear@0 973 // The attribute list is ordered; there is no 'lastAttribute'
nuclear@0 974 // because the list needs to be scanned for dupes before adding
nuclear@0 975 // a new attribute.
nuclear@0 976 XMLAttribute* rootAttribute;
nuclear@0 977 };
nuclear@0 978
nuclear@0 979
nuclear@0 980 /** A Document binds together all the functionality.
nuclear@0 981 It can be saved, loaded, and printed to the screen.
nuclear@0 982 All Nodes are connected and allocated to a Document.
nuclear@0 983 If the Document is deleted, all its Nodes are also deleted.
nuclear@0 984 */
nuclear@0 985 class XMLDocument : public XMLNode
nuclear@0 986 {
nuclear@0 987 friend class XMLElement;
nuclear@0 988 public:
nuclear@0 989 /// constructor
nuclear@0 990 XMLDocument( bool processEntities = true );
nuclear@0 991 ~XMLDocument();
nuclear@0 992
nuclear@0 993 virtual XMLDocument* ToDocument() { return this; }
nuclear@0 994 virtual const XMLDocument* ToDocument() const { return this; }
nuclear@0 995
nuclear@0 996 /**
nuclear@0 997 Parse an XML file from a character string.
nuclear@0 998 Returns XML_NO_ERROR (0) on success, or
nuclear@0 999 an errorID.
nuclear@0 1000 */
nuclear@0 1001 int Parse( const char* xml );
nuclear@0 1002
nuclear@0 1003 /**
nuclear@0 1004 Load an XML file from disk.
nuclear@0 1005 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1006 an errorID.
nuclear@0 1007 */
nuclear@0 1008 int LoadFile( const char* filename );
nuclear@0 1009
nuclear@0 1010 /**
nuclear@0 1011 Load an XML file from disk. You are responsible
nuclear@0 1012 for providing and closing the FILE*.
nuclear@0 1013
nuclear@0 1014 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1015 an errorID.
nuclear@0 1016 */
nuclear@0 1017 int LoadFile( FILE* );
nuclear@0 1018
nuclear@0 1019 /**
nuclear@0 1020 Save the XML file to disk.
nuclear@0 1021 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1022 an errorID.
nuclear@0 1023 */
nuclear@0 1024 int SaveFile( const char* filename );
nuclear@0 1025
nuclear@0 1026 /**
nuclear@0 1027 Save the XML file to disk. You are responsible
nuclear@0 1028 for providing and closing the FILE*.
nuclear@0 1029
nuclear@0 1030 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1031 an errorID.
nuclear@0 1032 */
nuclear@0 1033 int SaveFile( FILE* );
nuclear@0 1034
nuclear@0 1035 bool ProcessEntities() const { return processEntities; }
nuclear@0 1036
nuclear@0 1037 /**
nuclear@0 1038 Returns true if this document has a leading Byte Order Mark of UTF8.
nuclear@0 1039 */
nuclear@0 1040 bool HasBOM() const { return writeBOM; }
nuclear@0 1041 /** Sets whether to write the BOM when writing the file.
nuclear@0 1042 */
nuclear@0 1043 void SetBOM( bool useBOM ) { writeBOM = useBOM; }
nuclear@0 1044
nuclear@0 1045 /** Return the root element of DOM. Equivalent to FirstChildElement().
nuclear@0 1046 To get the first node, use FirstChild().
nuclear@0 1047 */
nuclear@0 1048 XMLElement* RootElement() { return FirstChildElement(); }
nuclear@0 1049 const XMLElement* RootElement() const { return FirstChildElement(); }
nuclear@0 1050
nuclear@0 1051 /** Print the Document. If the Printer is not provided, it will
nuclear@0 1052 print to stdout. If you provide Printer, this can print to a file:
nuclear@0 1053 @verbatim
nuclear@0 1054 XMLPrinter printer( fp );
nuclear@0 1055 doc.Print( &printer );
nuclear@0 1056 @endverbatim
nuclear@0 1057
nuclear@0 1058 Or you can use a printer to print to memory:
nuclear@0 1059 @verbatim
nuclear@0 1060 XMLPrinter printer;
nuclear@0 1061 doc->Print( &printer );
nuclear@0 1062 // printer.CStr() has a const char* to the XML
nuclear@0 1063 @endverbatim
nuclear@0 1064 */
nuclear@0 1065 void Print( XMLPrinter* streamer=0 );
nuclear@0 1066 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 1067
nuclear@0 1068 /**
nuclear@0 1069 Create a new Element associated with
nuclear@0 1070 this Document. The memory for the Element
nuclear@0 1071 is managed by the Document.
nuclear@0 1072 */
nuclear@0 1073 XMLElement* NewElement( const char* name );
nuclear@0 1074 /**
nuclear@0 1075 Create a new Comment associated with
nuclear@0 1076 this Document. The memory for the Comment
nuclear@0 1077 is managed by the Document.
nuclear@0 1078 */
nuclear@0 1079 XMLComment* NewComment( const char* comment );
nuclear@0 1080 /**
nuclear@0 1081 Create a new Text associated with
nuclear@0 1082 this Document. The memory for the Text
nuclear@0 1083 is managed by the Document.
nuclear@0 1084 */
nuclear@0 1085 XMLText* NewText( const char* text );
nuclear@0 1086 /**
nuclear@0 1087 Create a new Declaration associated with
nuclear@0 1088 this Document. The memory for the object
nuclear@0 1089 is managed by the Document.
nuclear@0 1090
nuclear@0 1091 If the 'text' param is null, the standard
nuclear@0 1092 declaration is used.:
nuclear@0 1093 @verbatim
nuclear@0 1094 <?xml version="1.0" encoding="UTF-8"?>
nuclear@0 1095 @endverbatim
nuclear@0 1096 */
nuclear@0 1097 XMLDeclaration* NewDeclaration( const char* text=0 );
nuclear@0 1098 /**
nuclear@0 1099 Create a new Unknown associated with
nuclear@0 1100 this Document. The memory for the object
nuclear@0 1101 is managed by the Document.
nuclear@0 1102 */
nuclear@0 1103 XMLUnknown* NewUnknown( const char* text );
nuclear@0 1104
nuclear@0 1105 /**
nuclear@0 1106 Delete a node associated with this document.
nuclear@0 1107 It will be unlinked from the DOM.
nuclear@0 1108 */
nuclear@0 1109 void DeleteNode( XMLNode* node ) { node->parent->DeleteChild( node ); }
nuclear@0 1110
nuclear@0 1111 void SetError( int error, const char* str1, const char* str2 );
nuclear@0 1112
nuclear@0 1113 /// Return true if there was an error parsing the document.
nuclear@0 1114 bool Error() const { return errorID != XML_NO_ERROR; }
nuclear@0 1115 /// Return the errorID.
nuclear@0 1116 int ErrorID() const { return errorID; }
nuclear@0 1117 /// Return a possibly helpful diagnostic location or string.
nuclear@0 1118 const char* GetErrorStr1() const { return errorStr1; }
nuclear@0 1119 /// Return a possibly helpful secondary diagnostic location or string.
nuclear@0 1120 const char* GetErrorStr2() const { return errorStr2; }
nuclear@0 1121 /// If there is an error, print it to stdout.
nuclear@0 1122 void PrintError() const;
nuclear@0 1123
nuclear@0 1124 // internal
nuclear@0 1125 char* Identify( char* p, XMLNode** node );
nuclear@0 1126
nuclear@0 1127 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; }
nuclear@0 1128 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; }
nuclear@0 1129
nuclear@0 1130 private:
nuclear@0 1131 XMLDocument( const XMLDocument& ); // not supported
nuclear@0 1132 void operator=( const XMLDocument& ); // not supported
nuclear@0 1133 void InitDocument();
nuclear@0 1134
nuclear@0 1135 bool writeBOM;
nuclear@0 1136 bool processEntities;
nuclear@0 1137 int errorID;
nuclear@0 1138 const char* errorStr1;
nuclear@0 1139 const char* errorStr2;
nuclear@0 1140 char* charBuffer;
nuclear@0 1141
nuclear@0 1142 MemPoolT< sizeof(XMLElement) > elementPool;
nuclear@0 1143 MemPoolT< sizeof(XMLAttribute) > attributePool;
nuclear@0 1144 MemPoolT< sizeof(XMLText) > textPool;
nuclear@0 1145 MemPoolT< sizeof(XMLComment) > commentPool;
nuclear@0 1146 };
nuclear@0 1147
nuclear@0 1148
nuclear@0 1149 /**
nuclear@0 1150 A XMLHandle is a class that wraps a node pointer with null checks; this is
nuclear@0 1151 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
nuclear@0 1152 DOM structure. It is a separate utility class.
nuclear@0 1153
nuclear@0 1154 Take an example:
nuclear@0 1155 @verbatim
nuclear@0 1156 <Document>
nuclear@0 1157 <Element attributeA = "valueA">
nuclear@0 1158 <Child attributeB = "value1" />
nuclear@0 1159 <Child attributeB = "value2" />
nuclear@0 1160 </Element>
nuclear@0 1161 </Document>
nuclear@0 1162 @endverbatim
nuclear@0 1163
nuclear@0 1164 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
nuclear@0 1165 easy to write a *lot* of code that looks like:
nuclear@0 1166
nuclear@0 1167 @verbatim
nuclear@0 1168 XMLElement* root = document.FirstChildElement( "Document" );
nuclear@0 1169 if ( root )
nuclear@0 1170 {
nuclear@0 1171 XMLElement* element = root->FirstChildElement( "Element" );
nuclear@0 1172 if ( element )
nuclear@0 1173 {
nuclear@0 1174 XMLElement* child = element->FirstChildElement( "Child" );
nuclear@0 1175 if ( child )
nuclear@0 1176 {
nuclear@0 1177 XMLElement* child2 = child->NextSiblingElement( "Child" );
nuclear@0 1178 if ( child2 )
nuclear@0 1179 {
nuclear@0 1180 // Finally do something useful.
nuclear@0 1181 @endverbatim
nuclear@0 1182
nuclear@0 1183 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
nuclear@0 1184 of such code. A XMLHandle checks for null pointers so it is perfectly safe
nuclear@0 1185 and correct to use:
nuclear@0 1186
nuclear@0 1187 @verbatim
nuclear@0 1188 XMLHandle docHandle( &document );
nuclear@0 1189 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
nuclear@0 1190 if ( child2 )
nuclear@0 1191 {
nuclear@0 1192 // do something useful
nuclear@0 1193 @endverbatim
nuclear@0 1194
nuclear@0 1195 Which is MUCH more concise and useful.
nuclear@0 1196
nuclear@0 1197 It is also safe to copy handles - internally they are nothing more than node pointers.
nuclear@0 1198 @verbatim
nuclear@0 1199 XMLHandle handleCopy = handle;
nuclear@0 1200 @endverbatim
nuclear@0 1201
nuclear@0 1202 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
nuclear@0 1203 */
nuclear@0 1204 class XMLHandle
nuclear@0 1205 {
nuclear@0 1206 public:
nuclear@0 1207 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
nuclear@0 1208 XMLHandle( XMLNode* _node ) { node = _node; }
nuclear@0 1209 /// Create a handle from a node.
nuclear@0 1210 XMLHandle( XMLNode& _node ) { node = &_node; }
nuclear@0 1211 /// Copy constructor
nuclear@0 1212 XMLHandle( const XMLHandle& ref ) { node = ref.node; }
nuclear@0 1213 /// Assignment
nuclear@0 1214 XMLHandle operator=( const XMLHandle& ref ) { node = ref.node; return *this; }
nuclear@0 1215
nuclear@0 1216 /// Get the first child of this handle.
nuclear@0 1217 XMLHandle FirstChild() { return XMLHandle( node ? node->FirstChild() : 0 ); }
nuclear@0 1218 /// Get the first child element of this handle.
nuclear@0 1219 XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( node ? node->FirstChildElement( value ) : 0 ); }
nuclear@0 1220 /// Get the last child of this handle.
nuclear@0 1221 XMLHandle LastChild() { return XMLHandle( node ? node->LastChild() : 0 ); }
nuclear@0 1222 /// Get the last child element of this handle.
nuclear@0 1223 XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( node ? node->LastChildElement( _value ) : 0 ); }
nuclear@0 1224 /// Get the previous sibling of this handle.
nuclear@0 1225 XMLHandle PreviousSibling() { return XMLHandle( node ? node->PreviousSibling() : 0 ); }
nuclear@0 1226 /// Get the previous sibling element of this handle.
nuclear@0 1227 XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
nuclear@0 1228 /// Get the next sibling of this handle.
nuclear@0 1229 XMLHandle NextSibling() { return XMLHandle( node ? node->NextSibling() : 0 ); }
nuclear@0 1230 /// Get the next sibling element of this handle.
nuclear@0 1231 XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
nuclear@0 1232
nuclear@0 1233 /// Safe cast to XMLNode. This can return null.
nuclear@0 1234 XMLNode* ToNode() { return node; }
nuclear@0 1235 /// Safe cast to XMLElement. This can return null.
nuclear@0 1236 XMLElement* ToElement() { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
nuclear@0 1237 /// Safe cast to XMLText. This can return null.
nuclear@0 1238 XMLText* ToText() { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
nuclear@0 1239 /// Safe cast to XMLUnknown. This can return null.
nuclear@0 1240 XMLUnknown* ToUnknown() { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
nuclear@0 1241 /// Safe cast to XMLDeclaration. This can return null.
nuclear@0 1242 XMLDeclaration* ToDeclaration() { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
nuclear@0 1243
nuclear@0 1244 private:
nuclear@0 1245 XMLNode* node;
nuclear@0 1246 };
nuclear@0 1247
nuclear@0 1248
nuclear@0 1249 /**
nuclear@0 1250 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
nuclear@0 1251 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
nuclear@0 1252 */
nuclear@0 1253 class XMLConstHandle
nuclear@0 1254 {
nuclear@0 1255 public:
nuclear@0 1256 XMLConstHandle( const XMLNode* _node ) { node = _node; }
nuclear@0 1257 XMLConstHandle( const XMLNode& _node ) { node = &_node; }
nuclear@0 1258 XMLConstHandle( const XMLConstHandle& ref ) { node = ref.node; }
nuclear@0 1259
nuclear@0 1260 XMLConstHandle operator=( const XMLConstHandle& ref ) { node = ref.node; return *this; }
nuclear@0 1261
nuclear@0 1262 const XMLConstHandle FirstChild() const { return XMLConstHandle( node ? node->FirstChild() : 0 ); }
nuclear@0 1263 const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( node ? node->FirstChildElement( value ) : 0 ); }
nuclear@0 1264 const XMLConstHandle LastChild() const { return XMLConstHandle( node ? node->LastChild() : 0 ); }
nuclear@0 1265 const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->LastChildElement( _value ) : 0 ); }
nuclear@0 1266 const XMLConstHandle PreviousSibling() const { return XMLConstHandle( node ? node->PreviousSibling() : 0 ); }
nuclear@0 1267 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->PreviousSiblingElement( _value ) : 0 ); }
nuclear@0 1268 const XMLConstHandle NextSibling() const { return XMLConstHandle( node ? node->NextSibling() : 0 ); }
nuclear@0 1269 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( node ? node->NextSiblingElement( _value ) : 0 ); }
nuclear@0 1270
nuclear@0 1271
nuclear@0 1272 const XMLNode* ToNode() const { return node; }
nuclear@0 1273 const XMLElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
nuclear@0 1274 const XMLText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
nuclear@0 1275 const XMLUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
nuclear@0 1276 const XMLDeclaration* ToDeclaration() const { return ( ( node && node->ToDeclaration() ) ? node->ToDeclaration() : 0 ); }
nuclear@0 1277
nuclear@0 1278 private:
nuclear@0 1279 const XMLNode* node;
nuclear@0 1280 };
nuclear@0 1281
nuclear@0 1282
nuclear@0 1283 /**
nuclear@0 1284 Printing functionality. The XMLPrinter gives you more
nuclear@0 1285 options than the XMLDocument::Print() method.
nuclear@0 1286
nuclear@0 1287 It can:
nuclear@0 1288 -# Print to memory.
nuclear@0 1289 -# Print to a file you provide.
nuclear@0 1290 -# Print XML without a XMLDocument.
nuclear@0 1291
nuclear@0 1292 Print to Memory
nuclear@0 1293
nuclear@0 1294 @verbatim
nuclear@0 1295 XMLPrinter printer;
nuclear@0 1296 doc->Print( &printer );
nuclear@0 1297 SomeFunction( printer.CStr() );
nuclear@0 1298 @endverbatim
nuclear@0 1299
nuclear@0 1300 Print to a File
nuclear@0 1301
nuclear@0 1302 You provide the file pointer.
nuclear@0 1303 @verbatim
nuclear@0 1304 XMLPrinter printer( fp );
nuclear@0 1305 doc.Print( &printer );
nuclear@0 1306 @endverbatim
nuclear@0 1307
nuclear@0 1308 Print without a XMLDocument
nuclear@0 1309
nuclear@0 1310 When loading, an XML parser is very useful. However, sometimes
nuclear@0 1311 when saving, it just gets in the way. The code is often set up
nuclear@0 1312 for streaming, and constructing the DOM is just overhead.
nuclear@0 1313
nuclear@0 1314 The Printer supports the streaming case. The following code
nuclear@0 1315 prints out a trivially simple XML file without ever creating
nuclear@0 1316 an XML document.
nuclear@0 1317
nuclear@0 1318 @verbatim
nuclear@0 1319 XMLPrinter printer( fp );
nuclear@0 1320 printer.OpenElement( "foo" );
nuclear@0 1321 printer.PushAttribute( "foo", "bar" );
nuclear@0 1322 printer.CloseElement();
nuclear@0 1323 @endverbatim
nuclear@0 1324 */
nuclear@0 1325 class XMLPrinter : public XMLVisitor
nuclear@0 1326 {
nuclear@0 1327 public:
nuclear@0 1328 /** Construct the printer. If the FILE* is specified,
nuclear@0 1329 this will print to the FILE. Else it will print
nuclear@0 1330 to memory, and the result is available in CStr()
nuclear@0 1331 */
nuclear@0 1332 XMLPrinter( FILE* file=0 );
nuclear@0 1333 ~XMLPrinter() {}
nuclear@0 1334
nuclear@0 1335 /** If streaming, write the BOM and declaration. */
nuclear@0 1336 void PushHeader( bool writeBOM, bool writeDeclaration );
nuclear@0 1337 /** If streaming, start writing an element.
nuclear@0 1338 The element must be closed with CloseElement()
nuclear@0 1339 */
nuclear@0 1340 void OpenElement( const char* name );
nuclear@0 1341 /// If streaming, add an attribute to an open element.
nuclear@0 1342 void PushAttribute( const char* name, const char* value );
nuclear@0 1343 void PushAttribute( const char* name, int value );
nuclear@0 1344 void PushAttribute( const char* name, unsigned value );
nuclear@0 1345 void PushAttribute( const char* name, bool value );
nuclear@0 1346 void PushAttribute( const char* name, double value );
nuclear@0 1347 /// If streaming, close the Element.
nuclear@0 1348 void CloseElement();
nuclear@0 1349
nuclear@0 1350 /// Add a text node.
nuclear@0 1351 void PushText( const char* text, bool cdata=false );
nuclear@0 1352 /// Add a comment.
nuclear@0 1353 void PushComment( const char* comment );
nuclear@0 1354
nuclear@0 1355 void PushDeclaration( const char* value );
nuclear@0 1356 void PushUnknown( const char* value );
nuclear@0 1357
nuclear@0 1358 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
nuclear@0 1359 virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; }
nuclear@0 1360
nuclear@0 1361 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
nuclear@0 1362 virtual bool VisitExit( const XMLElement& element );
nuclear@0 1363
nuclear@0 1364 virtual bool Visit( const XMLText& text );
nuclear@0 1365 virtual bool Visit( const XMLComment& comment );
nuclear@0 1366 virtual bool Visit( const XMLDeclaration& declaration );
nuclear@0 1367 virtual bool Visit( const XMLUnknown& unknown );
nuclear@0 1368
nuclear@0 1369 /**
nuclear@0 1370 If in print to memory mode, return a pointer to
nuclear@0 1371 the XML file in memory.
nuclear@0 1372 */
nuclear@0 1373 const char* CStr() const { return buffer.Mem(); }
nuclear@0 1374
nuclear@0 1375 private:
nuclear@0 1376 void SealElement();
nuclear@0 1377 void PrintSpace( int depth );
nuclear@0 1378 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
nuclear@0 1379 void Print( const char* format, ... );
nuclear@0 1380
nuclear@0 1381 bool elementJustOpened;
nuclear@0 1382 bool firstElement;
nuclear@0 1383 FILE* fp;
nuclear@0 1384 int depth;
nuclear@0 1385 int textDepth;
nuclear@0 1386 bool processEntities;
nuclear@0 1387
nuclear@0 1388 enum {
nuclear@0 1389 ENTITY_RANGE = 64,
nuclear@0 1390 BUF_SIZE = 200
nuclear@0 1391 };
nuclear@0 1392 bool entityFlag[ENTITY_RANGE];
nuclear@0 1393 bool restrictedEntityFlag[ENTITY_RANGE];
nuclear@0 1394
nuclear@0 1395 DynArray< const char*, 10 > stack;
nuclear@0 1396 DynArray< char, 20 > buffer, accumulator;
nuclear@0 1397 };
nuclear@0 1398
nuclear@0 1399
nuclear@0 1400 } // tinyxml2
nuclear@0 1401
nuclear@0 1402
nuclear@0 1403 #endif // TINYXML2_INCLUDED