ovr_sdk

annotate 3rdParty/TinyXml/tinyxml2.h @ 0:1b39a1b46319

initial 0.4.4
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 14 Jan 2015 06:51:16 +0200
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 #if defined(ANDROID_NDK) || defined(__BORLANDC__)
nuclear@0 28 # include <ctype.h>
nuclear@0 29 # include <limits.h>
nuclear@0 30 # include <stdio.h>
nuclear@0 31 # include <stdlib.h>
nuclear@0 32 # include <string.h>
nuclear@0 33 # include <stdarg.h>
nuclear@0 34 #else
nuclear@0 35 # include <cctype>
nuclear@0 36 # include <climits>
nuclear@0 37 # include <cstdio>
nuclear@0 38 # include <cstdlib>
nuclear@0 39 # include <cstring>
nuclear@0 40 # include <cstdarg>
nuclear@0 41 #endif
nuclear@0 42
nuclear@0 43 /*
nuclear@0 44 TODO: intern strings instead of allocation.
nuclear@0 45 */
nuclear@0 46 /*
nuclear@0 47 gcc:
nuclear@0 48 g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe
nuclear@0 49
nuclear@0 50 Formatting, Artistic Style:
nuclear@0 51 AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
nuclear@0 52 */
nuclear@0 53
nuclear@0 54 #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__)
nuclear@0 55 # ifndef DEBUG
nuclear@0 56 # define DEBUG
nuclear@0 57 # endif
nuclear@0 58 #endif
nuclear@0 59
nuclear@0 60
nuclear@0 61 #if defined(DEBUG)
nuclear@0 62 # if defined(_MSC_VER)
nuclear@0 63 # define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak()
nuclear@0 64 # elif defined (ANDROID_NDK)
nuclear@0 65 # include <android/log.h>
nuclear@0 66 # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
nuclear@0 67 # else
nuclear@0 68 # include <assert.h>
nuclear@0 69 # define TIXMLASSERT assert
nuclear@0 70 # endif
nuclear@0 71 # else
nuclear@0 72 # define TIXMLASSERT( x ) {}
nuclear@0 73 #endif
nuclear@0 74
nuclear@0 75
nuclear@0 76 #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
nuclear@0 77 // Microsoft visual studio, version 2005 and higher.
nuclear@0 78 /*int _snprintf_s(
nuclear@0 79 char *buffer,
nuclear@0 80 size_t sizeOfBuffer,
nuclear@0 81 size_t count,
nuclear@0 82 const char *format [,
nuclear@0 83 argument] ...
nuclear@0 84 );*/
nuclear@0 85 inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
nuclear@0 86 {
nuclear@0 87 va_list va;
nuclear@0 88 va_start( va, format );
nuclear@0 89 int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
nuclear@0 90 va_end( va );
nuclear@0 91 return result;
nuclear@0 92 }
nuclear@0 93 #define TIXML_SSCANF sscanf_s
nuclear@0 94 #else
nuclear@0 95 // GCC version 3 and higher
nuclear@0 96 //#warning( "Using sn* functions." )
nuclear@0 97 #define TIXML_SNPRINTF snprintf
nuclear@0 98 #define TIXML_SSCANF sscanf
nuclear@0 99 #endif
nuclear@0 100
nuclear@0 101 static const int TIXML2_MAJOR_VERSION = 1;
nuclear@0 102 static const int TIXML2_MINOR_VERSION = 0;
nuclear@0 103 static const int TIXML2_PATCH_VERSION = 9;
nuclear@0 104
nuclear@0 105 namespace tinyxml2
nuclear@0 106 {
nuclear@0 107 class XMLDocument;
nuclear@0 108 class XMLElement;
nuclear@0 109 class XMLAttribute;
nuclear@0 110 class XMLComment;
nuclear@0 111 class XMLNode;
nuclear@0 112 class XMLText;
nuclear@0 113 class XMLDeclaration;
nuclear@0 114 class XMLUnknown;
nuclear@0 115
nuclear@0 116 class XMLPrinter;
nuclear@0 117
nuclear@0 118 /*
nuclear@0 119 A class that wraps strings. Normally stores the start and end
nuclear@0 120 pointers into the XML file itself, and will apply normalization
nuclear@0 121 and entity translation if actually read. Can also store (and memory
nuclear@0 122 manage) a traditional char[]
nuclear@0 123 */
nuclear@0 124 class StrPair
nuclear@0 125 {
nuclear@0 126 public:
nuclear@0 127 enum {
nuclear@0 128 NEEDS_ENTITY_PROCESSING = 0x01,
nuclear@0 129 NEEDS_NEWLINE_NORMALIZATION = 0x02,
nuclear@0 130 COLLAPSE_WHITESPACE = 0x04,
nuclear@0 131
nuclear@0 132 TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 133 TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 134 ATTRIBUTE_NAME = 0,
nuclear@0 135 ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 136 ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION,
nuclear@0 137 COMMENT = NEEDS_NEWLINE_NORMALIZATION
nuclear@0 138 };
nuclear@0 139
nuclear@0 140 StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
nuclear@0 141 ~StrPair();
nuclear@0 142
nuclear@0 143 void Set( char* start, char* end, int flags ) {
nuclear@0 144 Reset();
nuclear@0 145 _start = start;
nuclear@0 146 _end = end;
nuclear@0 147 _flags = flags | NEEDS_FLUSH;
nuclear@0 148 }
nuclear@0 149
nuclear@0 150 const char* GetStr();
nuclear@0 151
nuclear@0 152 bool Empty() const {
nuclear@0 153 return _start == _end;
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 void SetInternedStr( const char* str ) {
nuclear@0 157 Reset();
nuclear@0 158 _start = const_cast<char*>(str);
nuclear@0 159 }
nuclear@0 160
nuclear@0 161 void SetStr( const char* str, int flags=0 );
nuclear@0 162
nuclear@0 163 char* ParseText( char* in, const char* endTag, int strFlags );
nuclear@0 164 char* ParseName( char* in );
nuclear@0 165
nuclear@0 166 private:
nuclear@0 167 void Reset();
nuclear@0 168 void CollapseWhitespace();
nuclear@0 169
nuclear@0 170 enum {
nuclear@0 171 NEEDS_FLUSH = 0x100,
nuclear@0 172 NEEDS_DELETE = 0x200
nuclear@0 173 };
nuclear@0 174
nuclear@0 175 // After parsing, if *end != 0, it can be set to zero.
nuclear@0 176 int _flags;
nuclear@0 177 char* _start;
nuclear@0 178 char* _end;
nuclear@0 179 };
nuclear@0 180
nuclear@0 181
nuclear@0 182 /*
nuclear@0 183 A dynamic array of Plain Old Data. Doesn't support constructors, etc.
nuclear@0 184 Has a small initial memory pool, so that low or no usage will not
nuclear@0 185 cause a call to new/delete
nuclear@0 186 */
nuclear@0 187 template <class T, int INIT>
nuclear@0 188 class DynArray
nuclear@0 189 {
nuclear@0 190 public:
nuclear@0 191 DynArray< T, INIT >() {
nuclear@0 192 _mem = _pool;
nuclear@0 193 _allocated = INIT;
nuclear@0 194 _size = 0;
nuclear@0 195 }
nuclear@0 196
nuclear@0 197 ~DynArray() {
nuclear@0 198 if ( _mem != _pool ) {
nuclear@0 199 delete [] _mem;
nuclear@0 200 }
nuclear@0 201 }
nuclear@0 202
nuclear@0 203 void Push( T t ) {
nuclear@0 204 EnsureCapacity( _size+1 );
nuclear@0 205 _mem[_size++] = t;
nuclear@0 206 }
nuclear@0 207
nuclear@0 208 T* PushArr( int count ) {
nuclear@0 209 EnsureCapacity( _size+count );
nuclear@0 210 T* ret = &_mem[_size];
nuclear@0 211 _size += count;
nuclear@0 212 return ret;
nuclear@0 213 }
nuclear@0 214
nuclear@0 215 T Pop() {
nuclear@0 216 return _mem[--_size];
nuclear@0 217 }
nuclear@0 218
nuclear@0 219 void PopArr( int count ) {
nuclear@0 220 TIXMLASSERT( _size >= count );
nuclear@0 221 _size -= count;
nuclear@0 222 }
nuclear@0 223
nuclear@0 224 bool Empty() const {
nuclear@0 225 return _size == 0;
nuclear@0 226 }
nuclear@0 227
nuclear@0 228 T& operator[](int i) {
nuclear@0 229 TIXMLASSERT( i>= 0 && i < _size );
nuclear@0 230 return _mem[i];
nuclear@0 231 }
nuclear@0 232
nuclear@0 233 const T& operator[](int i) const {
nuclear@0 234 TIXMLASSERT( i>= 0 && i < _size );
nuclear@0 235 return _mem[i];
nuclear@0 236 }
nuclear@0 237
nuclear@0 238 int Size() const {
nuclear@0 239 return _size;
nuclear@0 240 }
nuclear@0 241
nuclear@0 242 int Capacity() const {
nuclear@0 243 return _allocated;
nuclear@0 244 }
nuclear@0 245
nuclear@0 246 const T* Mem() const {
nuclear@0 247 return _mem;
nuclear@0 248 }
nuclear@0 249
nuclear@0 250 T* Mem() {
nuclear@0 251 return _mem;
nuclear@0 252 }
nuclear@0 253
nuclear@0 254 private:
nuclear@0 255 void EnsureCapacity( int cap ) {
nuclear@0 256 if ( cap > _allocated ) {
nuclear@0 257 int newAllocated = cap * 2;
nuclear@0 258 T* newMem = new T[newAllocated];
nuclear@0 259 memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs
nuclear@0 260 if ( _mem != _pool ) {
nuclear@0 261 delete [] _mem;
nuclear@0 262 }
nuclear@0 263 _mem = newMem;
nuclear@0 264 _allocated = newAllocated;
nuclear@0 265 }
nuclear@0 266 }
nuclear@0 267
nuclear@0 268 T* _mem;
nuclear@0 269 T _pool[INIT];
nuclear@0 270 int _allocated; // objects allocated
nuclear@0 271 int _size; // number objects in use
nuclear@0 272 };
nuclear@0 273
nuclear@0 274
nuclear@0 275 /*
nuclear@0 276 Parent virtual class of a pool for fast allocation
nuclear@0 277 and deallocation of objects.
nuclear@0 278 */
nuclear@0 279 class MemPool
nuclear@0 280 {
nuclear@0 281 public:
nuclear@0 282 MemPool() {}
nuclear@0 283 virtual ~MemPool() {}
nuclear@0 284
nuclear@0 285 virtual int ItemSize() const = 0;
nuclear@0 286 virtual void* Alloc() = 0;
nuclear@0 287 virtual void Free( void* ) = 0;
nuclear@0 288 virtual void SetTracked() = 0;
nuclear@0 289 };
nuclear@0 290
nuclear@0 291
nuclear@0 292 /*
nuclear@0 293 Template child class to create pools of the correct type.
nuclear@0 294 */
nuclear@0 295 template< int SIZE >
nuclear@0 296 class MemPoolT : public MemPool
nuclear@0 297 {
nuclear@0 298 public:
nuclear@0 299 MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {}
nuclear@0 300 ~MemPoolT() {
nuclear@0 301 // Delete the blocks.
nuclear@0 302 for( int i=0; i<_blockPtrs.Size(); ++i ) {
nuclear@0 303 delete _blockPtrs[i];
nuclear@0 304 }
nuclear@0 305 }
nuclear@0 306
nuclear@0 307 virtual int ItemSize() const {
nuclear@0 308 return SIZE;
nuclear@0 309 }
nuclear@0 310 int CurrentAllocs() const {
nuclear@0 311 return _currentAllocs;
nuclear@0 312 }
nuclear@0 313
nuclear@0 314 virtual void* Alloc() {
nuclear@0 315 if ( !_root ) {
nuclear@0 316 // Need a new block.
nuclear@0 317 Block* block = new Block();
nuclear@0 318 _blockPtrs.Push( block );
nuclear@0 319
nuclear@0 320 for( int i=0; i<COUNT-1; ++i ) {
nuclear@0 321 block->chunk[i].next = &block->chunk[i+1];
nuclear@0 322 }
nuclear@0 323 block->chunk[COUNT-1].next = 0;
nuclear@0 324 _root = block->chunk;
nuclear@0 325 }
nuclear@0 326 void* result = _root;
nuclear@0 327 _root = _root->next;
nuclear@0 328
nuclear@0 329 ++_currentAllocs;
nuclear@0 330 if ( _currentAllocs > _maxAllocs ) {
nuclear@0 331 _maxAllocs = _currentAllocs;
nuclear@0 332 }
nuclear@0 333 _nAllocs++;
nuclear@0 334 _nUntracked++;
nuclear@0 335 return result;
nuclear@0 336 }
nuclear@0 337 virtual void Free( void* mem ) {
nuclear@0 338 if ( !mem ) {
nuclear@0 339 return;
nuclear@0 340 }
nuclear@0 341 --_currentAllocs;
nuclear@0 342 Chunk* chunk = (Chunk*)mem;
nuclear@0 343 #ifdef DEBUG
nuclear@0 344 memset( chunk, 0xfe, sizeof(Chunk) );
nuclear@0 345 #endif
nuclear@0 346 chunk->next = _root;
nuclear@0 347 _root = chunk;
nuclear@0 348 }
nuclear@0 349 void Trace( const char* name ) {
nuclear@0 350 printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
nuclear@0 351 name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() );
nuclear@0 352 }
nuclear@0 353
nuclear@0 354 void SetTracked() {
nuclear@0 355 _nUntracked--;
nuclear@0 356 }
nuclear@0 357
nuclear@0 358 int Untracked() const {
nuclear@0 359 return _nUntracked;
nuclear@0 360 }
nuclear@0 361
nuclear@0 362 enum { COUNT = 1024/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private
nuclear@0 363
nuclear@0 364 private:
nuclear@0 365 union Chunk {
nuclear@0 366 Chunk* next;
nuclear@0 367 char mem[SIZE];
nuclear@0 368 };
nuclear@0 369 struct Block {
nuclear@0 370 Chunk chunk[COUNT];
nuclear@0 371 };
nuclear@0 372 DynArray< Block*, 10 > _blockPtrs;
nuclear@0 373 Chunk* _root;
nuclear@0 374
nuclear@0 375 int _currentAllocs;
nuclear@0 376 int _nAllocs;
nuclear@0 377 int _maxAllocs;
nuclear@0 378 int _nUntracked;
nuclear@0 379 };
nuclear@0 380
nuclear@0 381
nuclear@0 382
nuclear@0 383 /**
nuclear@0 384 Implements the interface to the "Visitor pattern" (see the Accept() method.)
nuclear@0 385 If you call the Accept() method, it requires being passed a XMLVisitor
nuclear@0 386 class to handle callbacks. For nodes that contain other nodes (Document, Element)
nuclear@0 387 you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
nuclear@0 388 are simply called with Visit().
nuclear@0 389
nuclear@0 390 If you return 'true' from a Visit method, recursive parsing will continue. If you return
nuclear@0 391 false, <b>no children of this node or its sibilings</b> will be visited.
nuclear@0 392
nuclear@0 393 All flavors of Visit methods have a default implementation that returns 'true' (continue
nuclear@0 394 visiting). You need to only override methods that are interesting to you.
nuclear@0 395
nuclear@0 396 Generally Accept() is called on the TiXmlDocument, although all nodes support visiting.
nuclear@0 397
nuclear@0 398 You should never change the document from a callback.
nuclear@0 399
nuclear@0 400 @sa XMLNode::Accept()
nuclear@0 401 */
nuclear@0 402 class XMLVisitor
nuclear@0 403 {
nuclear@0 404 public:
nuclear@0 405 virtual ~XMLVisitor() {}
nuclear@0 406
nuclear@0 407 /// Visit a document.
nuclear@0 408 virtual bool VisitEnter( const XMLDocument& /*doc*/ ) {
nuclear@0 409 return true;
nuclear@0 410 }
nuclear@0 411 /// Visit a document.
nuclear@0 412 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
nuclear@0 413 return true;
nuclear@0 414 }
nuclear@0 415
nuclear@0 416 /// Visit an element.
nuclear@0 417 virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) {
nuclear@0 418 return true;
nuclear@0 419 }
nuclear@0 420 /// Visit an element.
nuclear@0 421 virtual bool VisitExit( const XMLElement& /*element*/ ) {
nuclear@0 422 return true;
nuclear@0 423 }
nuclear@0 424
nuclear@0 425 /// Visit a declaration.
nuclear@0 426 virtual bool Visit( const XMLDeclaration& /*declaration*/ ) {
nuclear@0 427 return true;
nuclear@0 428 }
nuclear@0 429 /// Visit a text node.
nuclear@0 430 virtual bool Visit( const XMLText& /*text*/ ) {
nuclear@0 431 return true;
nuclear@0 432 }
nuclear@0 433 /// Visit a comment node.
nuclear@0 434 virtual bool Visit( const XMLComment& /*comment*/ ) {
nuclear@0 435 return true;
nuclear@0 436 }
nuclear@0 437 /// Visit an unknown node.
nuclear@0 438 virtual bool Visit( const XMLUnknown& /*unknown*/ ) {
nuclear@0 439 return true;
nuclear@0 440 }
nuclear@0 441 };
nuclear@0 442
nuclear@0 443
nuclear@0 444 /*
nuclear@0 445 Utility functionality.
nuclear@0 446 */
nuclear@0 447 class XMLUtil
nuclear@0 448 {
nuclear@0 449 public:
nuclear@0 450 // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
nuclear@0 451 // correct, but simple, and usually works.
nuclear@0 452 static const char* SkipWhiteSpace( const char* p ) {
nuclear@0 453 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<const unsigned char*>(p) ) ) {
nuclear@0 454 ++p;
nuclear@0 455 }
nuclear@0 456 return p;
nuclear@0 457 }
nuclear@0 458 static char* SkipWhiteSpace( char* p ) {
nuclear@0 459 while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast<unsigned char*>(p) ) ) {
nuclear@0 460 ++p;
nuclear@0 461 }
nuclear@0 462 return p;
nuclear@0 463 }
nuclear@0 464 static bool IsWhiteSpace( char p ) {
nuclear@0 465 return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
nuclear@0 466 }
nuclear@0 467
nuclear@0 468 inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) {
nuclear@0 469 int n = 0;
nuclear@0 470 if ( p == q ) {
nuclear@0 471 return true;
nuclear@0 472 }
nuclear@0 473 while( *p && *q && *p == *q && n<nChar ) {
nuclear@0 474 ++p;
nuclear@0 475 ++q;
nuclear@0 476 ++n;
nuclear@0 477 }
nuclear@0 478 if ( (n == nChar) || ( *p == 0 && *q == 0 ) ) {
nuclear@0 479 return true;
nuclear@0 480 }
nuclear@0 481 return false;
nuclear@0 482 }
nuclear@0 483 inline static int IsUTF8Continuation( const char p ) {
nuclear@0 484 return p & 0x80;
nuclear@0 485 }
nuclear@0 486 inline static int IsAlphaNum( unsigned char anyByte ) {
nuclear@0 487 return ( anyByte < 128 ) ? isalnum( anyByte ) : 1;
nuclear@0 488 }
nuclear@0 489 inline static int IsAlpha( unsigned char anyByte ) {
nuclear@0 490 return ( anyByte < 128 ) ? isalpha( anyByte ) : 1;
nuclear@0 491 }
nuclear@0 492
nuclear@0 493 static const char* ReadBOM( const char* p, bool* hasBOM );
nuclear@0 494 // p is the starting location,
nuclear@0 495 // the UTF-8 value of the entity will be placed in value, and length filled in.
nuclear@0 496 static const char* GetCharacterRef( const char* p, char* value, int* length );
nuclear@0 497 static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
nuclear@0 498
nuclear@0 499 // converts primitive types to strings
nuclear@0 500 static void ToStr( int v, char* buffer, int bufferSize );
nuclear@0 501 static void ToStr( unsigned v, char* buffer, int bufferSize );
nuclear@0 502 static void ToStr( bool v, char* buffer, int bufferSize );
nuclear@0 503 static void ToStr( float v, char* buffer, int bufferSize );
nuclear@0 504 static void ToStr( double v, char* buffer, int bufferSize );
nuclear@0 505
nuclear@0 506 // converts strings to primitive types
nuclear@0 507 static bool ToInt( const char* str, int* value );
nuclear@0 508 static bool ToUnsigned( const char* str, unsigned* value );
nuclear@0 509 static bool ToBool( const char* str, bool* value );
nuclear@0 510 static bool ToFloat( const char* str, float* value );
nuclear@0 511 static bool ToDouble( const char* str, double* value );
nuclear@0 512 };
nuclear@0 513
nuclear@0 514
nuclear@0 515 /** XMLNode is a base class for every object that is in the
nuclear@0 516 XML Document Object Model (DOM), except XMLAttributes.
nuclear@0 517 Nodes have siblings, a parent, and children which can
nuclear@0 518 be navigated. A node is always in a XMLDocument.
nuclear@0 519 The type of a XMLNode can be queried, and it can
nuclear@0 520 be cast to its more defined type.
nuclear@0 521
nuclear@0 522 A XMLDocument allocates memory for all its Nodes.
nuclear@0 523 When the XMLDocument gets deleted, all its Nodes
nuclear@0 524 will also be deleted.
nuclear@0 525
nuclear@0 526 @verbatim
nuclear@0 527 A Document can contain: Element (container or leaf)
nuclear@0 528 Comment (leaf)
nuclear@0 529 Unknown (leaf)
nuclear@0 530 Declaration( leaf )
nuclear@0 531
nuclear@0 532 An Element can contain: Element (container or leaf)
nuclear@0 533 Text (leaf)
nuclear@0 534 Attributes (not on tree)
nuclear@0 535 Comment (leaf)
nuclear@0 536 Unknown (leaf)
nuclear@0 537
nuclear@0 538 @endverbatim
nuclear@0 539 */
nuclear@0 540 class XMLNode
nuclear@0 541 {
nuclear@0 542 friend class XMLDocument;
nuclear@0 543 friend class XMLElement;
nuclear@0 544 public:
nuclear@0 545
nuclear@0 546 /// Get the XMLDocument that owns this XMLNode.
nuclear@0 547 const XMLDocument* GetDocument() const {
nuclear@0 548 return _document;
nuclear@0 549 }
nuclear@0 550 /// Get the XMLDocument that owns this XMLNode.
nuclear@0 551 XMLDocument* GetDocument() {
nuclear@0 552 return _document;
nuclear@0 553 }
nuclear@0 554
nuclear@0 555 /// Safely cast to an Element, or null.
nuclear@0 556 virtual XMLElement* ToElement() {
nuclear@0 557 return 0;
nuclear@0 558 }
nuclear@0 559 /// Safely cast to Text, or null.
nuclear@0 560 virtual XMLText* ToText() {
nuclear@0 561 return 0;
nuclear@0 562 }
nuclear@0 563 /// Safely cast to a Comment, or null.
nuclear@0 564 virtual XMLComment* ToComment() {
nuclear@0 565 return 0;
nuclear@0 566 }
nuclear@0 567 /// Safely cast to a Document, or null.
nuclear@0 568 virtual XMLDocument* ToDocument() {
nuclear@0 569 return 0;
nuclear@0 570 }
nuclear@0 571 /// Safely cast to a Declaration, or null.
nuclear@0 572 virtual XMLDeclaration* ToDeclaration() {
nuclear@0 573 return 0;
nuclear@0 574 }
nuclear@0 575 /// Safely cast to an Unknown, or null.
nuclear@0 576 virtual XMLUnknown* ToUnknown() {
nuclear@0 577 return 0;
nuclear@0 578 }
nuclear@0 579
nuclear@0 580 virtual const XMLElement* ToElement() const {
nuclear@0 581 return 0;
nuclear@0 582 }
nuclear@0 583 virtual const XMLText* ToText() const {
nuclear@0 584 return 0;
nuclear@0 585 }
nuclear@0 586 virtual const XMLComment* ToComment() const {
nuclear@0 587 return 0;
nuclear@0 588 }
nuclear@0 589 virtual const XMLDocument* ToDocument() const {
nuclear@0 590 return 0;
nuclear@0 591 }
nuclear@0 592 virtual const XMLDeclaration* ToDeclaration() const {
nuclear@0 593 return 0;
nuclear@0 594 }
nuclear@0 595 virtual const XMLUnknown* ToUnknown() const {
nuclear@0 596 return 0;
nuclear@0 597 }
nuclear@0 598
nuclear@0 599 /** The meaning of 'value' changes for the specific type.
nuclear@0 600 @verbatim
nuclear@0 601 Document: empty
nuclear@0 602 Element: name of the element
nuclear@0 603 Comment: the comment text
nuclear@0 604 Unknown: the tag contents
nuclear@0 605 Text: the text string
nuclear@0 606 @endverbatim
nuclear@0 607 */
nuclear@0 608 const char* Value() const {
nuclear@0 609 return _value.GetStr();
nuclear@0 610 }
nuclear@0 611
nuclear@0 612 /** Set the Value of an XML node.
nuclear@0 613 @sa Value()
nuclear@0 614 */
nuclear@0 615 void SetValue( const char* val, bool staticMem=false );
nuclear@0 616
nuclear@0 617 /// Get the parent of this node on the DOM.
nuclear@0 618 const XMLNode* Parent() const {
nuclear@0 619 return _parent;
nuclear@0 620 }
nuclear@0 621
nuclear@0 622 XMLNode* Parent() {
nuclear@0 623 return _parent;
nuclear@0 624 }
nuclear@0 625
nuclear@0 626 /// Returns true if this node has no children.
nuclear@0 627 bool NoChildren() const {
nuclear@0 628 return !_firstChild;
nuclear@0 629 }
nuclear@0 630
nuclear@0 631 /// Get the first child node, or null if none exists.
nuclear@0 632 const XMLNode* FirstChild() const {
nuclear@0 633 return _firstChild;
nuclear@0 634 }
nuclear@0 635
nuclear@0 636 XMLNode* FirstChild() {
nuclear@0 637 return _firstChild;
nuclear@0 638 }
nuclear@0 639
nuclear@0 640 /** Get the first child element, or optionally the first child
nuclear@0 641 element with the specified name.
nuclear@0 642 */
nuclear@0 643 const XMLElement* FirstChildElement( const char* value=0 ) const;
nuclear@0 644
nuclear@0 645 XMLElement* FirstChildElement( const char* value=0 ) {
nuclear@0 646 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->FirstChildElement( value ));
nuclear@0 647 }
nuclear@0 648
nuclear@0 649 /// Get the last child node, or null if none exists.
nuclear@0 650 const XMLNode* LastChild() const {
nuclear@0 651 return _lastChild;
nuclear@0 652 }
nuclear@0 653
nuclear@0 654 XMLNode* LastChild() {
nuclear@0 655 return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->LastChild() );
nuclear@0 656 }
nuclear@0 657
nuclear@0 658 /** Get the last child element or optionally the last child
nuclear@0 659 element with the specified name.
nuclear@0 660 */
nuclear@0 661 const XMLElement* LastChildElement( const char* value=0 ) const;
nuclear@0 662
nuclear@0 663 XMLElement* LastChildElement( const char* value=0 ) {
nuclear@0 664 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->LastChildElement(value) );
nuclear@0 665 }
nuclear@0 666
nuclear@0 667 /// Get the previous (left) sibling node of this node.
nuclear@0 668 const XMLNode* PreviousSibling() const {
nuclear@0 669 return _prev;
nuclear@0 670 }
nuclear@0 671
nuclear@0 672 XMLNode* PreviousSibling() {
nuclear@0 673 return _prev;
nuclear@0 674 }
nuclear@0 675
nuclear@0 676 /// Get the previous (left) sibling element of this node, with an opitionally supplied name.
nuclear@0 677 const XMLElement* PreviousSiblingElement( const char* value=0 ) const ;
nuclear@0 678
nuclear@0 679 XMLElement* PreviousSiblingElement( const char* value=0 ) {
nuclear@0 680 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->PreviousSiblingElement( value ) );
nuclear@0 681 }
nuclear@0 682
nuclear@0 683 /// Get the next (right) sibling node of this node.
nuclear@0 684 const XMLNode* NextSibling() const {
nuclear@0 685 return _next;
nuclear@0 686 }
nuclear@0 687
nuclear@0 688 XMLNode* NextSibling() {
nuclear@0 689 return _next;
nuclear@0 690 }
nuclear@0 691
nuclear@0 692 /// Get the next (right) sibling element of this node, with an opitionally supplied name.
nuclear@0 693 const XMLElement* NextSiblingElement( const char* value=0 ) const;
nuclear@0 694
nuclear@0 695 XMLElement* NextSiblingElement( const char* value=0 ) {
nuclear@0 696 return const_cast<XMLElement*>(const_cast<const XMLNode*>(this)->NextSiblingElement( value ) );
nuclear@0 697 }
nuclear@0 698
nuclear@0 699 /**
nuclear@0 700 Add a child node as the last (right) child.
nuclear@0 701 */
nuclear@0 702 XMLNode* InsertEndChild( XMLNode* addThis );
nuclear@0 703
nuclear@0 704 XMLNode* LinkEndChild( XMLNode* addThis ) {
nuclear@0 705 return InsertEndChild( addThis );
nuclear@0 706 }
nuclear@0 707 /**
nuclear@0 708 Add a child node as the first (left) child.
nuclear@0 709 */
nuclear@0 710 XMLNode* InsertFirstChild( XMLNode* addThis );
nuclear@0 711 /**
nuclear@0 712 Add a node after the specified child node.
nuclear@0 713 */
nuclear@0 714 XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis );
nuclear@0 715
nuclear@0 716 /**
nuclear@0 717 Delete all the children of this node.
nuclear@0 718 */
nuclear@0 719 void DeleteChildren();
nuclear@0 720
nuclear@0 721 /**
nuclear@0 722 Delete a child of this node.
nuclear@0 723 */
nuclear@0 724 void DeleteChild( XMLNode* node );
nuclear@0 725
nuclear@0 726 /**
nuclear@0 727 Make a copy of this node, but not its children.
nuclear@0 728 You may pass in a Document pointer that will be
nuclear@0 729 the owner of the new Node. If the 'document' is
nuclear@0 730 null, then the node returned will be allocated
nuclear@0 731 from the current Document. (this->GetDocument())
nuclear@0 732
nuclear@0 733 Note: if called on a XMLDocument, this will return null.
nuclear@0 734 */
nuclear@0 735 virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0;
nuclear@0 736
nuclear@0 737 /**
nuclear@0 738 Test if 2 nodes are the same, but don't test children.
nuclear@0 739 The 2 nodes do not need to be in the same Document.
nuclear@0 740
nuclear@0 741 Note: if called on a XMLDocument, this will return false.
nuclear@0 742 */
nuclear@0 743 virtual bool ShallowEqual( const XMLNode* compare ) const = 0;
nuclear@0 744
nuclear@0 745 /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the
nuclear@0 746 XML tree will be conditionally visited and the host will be called back
nuclear@0 747 via the TiXmlVisitor interface.
nuclear@0 748
nuclear@0 749 This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse
nuclear@0 750 the XML for the callbacks, so the performance of TinyXML is unchanged by using this
nuclear@0 751 interface versus any other.)
nuclear@0 752
nuclear@0 753 The interface has been based on ideas from:
nuclear@0 754
nuclear@0 755 - http://www.saxproject.org/
nuclear@0 756 - http://c2.com/cgi/wiki?HierarchicalVisitorPattern
nuclear@0 757
nuclear@0 758 Which are both good references for "visiting".
nuclear@0 759
nuclear@0 760 An example of using Accept():
nuclear@0 761 @verbatim
nuclear@0 762 TiXmlPrinter printer;
nuclear@0 763 tinyxmlDoc.Accept( &printer );
nuclear@0 764 const char* xmlcstr = printer.CStr();
nuclear@0 765 @endverbatim
nuclear@0 766 */
nuclear@0 767 virtual bool Accept( XMLVisitor* visitor ) const = 0;
nuclear@0 768
nuclear@0 769 // internal
nuclear@0 770 virtual char* ParseDeep( char*, StrPair* );
nuclear@0 771
nuclear@0 772 protected:
nuclear@0 773 XMLNode( XMLDocument* );
nuclear@0 774 virtual ~XMLNode();
nuclear@0 775 XMLNode( const XMLNode& ); // not supported
nuclear@0 776 XMLNode& operator=( const XMLNode& ); // not supported
nuclear@0 777
nuclear@0 778 XMLDocument* _document;
nuclear@0 779 XMLNode* _parent;
nuclear@0 780 mutable StrPair _value;
nuclear@0 781
nuclear@0 782 XMLNode* _firstChild;
nuclear@0 783 XMLNode* _lastChild;
nuclear@0 784
nuclear@0 785 XMLNode* _prev;
nuclear@0 786 XMLNode* _next;
nuclear@0 787
nuclear@0 788 private:
nuclear@0 789 MemPool* _memPool;
nuclear@0 790 void Unlink( XMLNode* child );
nuclear@0 791 };
nuclear@0 792
nuclear@0 793
nuclear@0 794 /** XML text.
nuclear@0 795
nuclear@0 796 Note that a text node can have child element nodes, for example:
nuclear@0 797 @verbatim
nuclear@0 798 <root>This is <b>bold</b></root>
nuclear@0 799 @endverbatim
nuclear@0 800
nuclear@0 801 A text node can have 2 ways to output the next. "normal" output
nuclear@0 802 and CDATA. It will default to the mode it was parsed from the XML file and
nuclear@0 803 you generally want to leave it alone, but you can change the output mode with
nuclear@0 804 SetCDATA() and query it with CDATA().
nuclear@0 805 */
nuclear@0 806 class XMLText : public XMLNode
nuclear@0 807 {
nuclear@0 808 friend class XMLBase;
nuclear@0 809 friend class XMLDocument;
nuclear@0 810 public:
nuclear@0 811 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 812
nuclear@0 813 virtual XMLText* ToText() {
nuclear@0 814 return this;
nuclear@0 815 }
nuclear@0 816 virtual const XMLText* ToText() const {
nuclear@0 817 return this;
nuclear@0 818 }
nuclear@0 819
nuclear@0 820 /// Declare whether this should be CDATA or standard text.
nuclear@0 821 void SetCData( bool isCData ) {
nuclear@0 822 _isCData = isCData;
nuclear@0 823 }
nuclear@0 824 /// Returns true if this is a CDATA text element.
nuclear@0 825 bool CData() const {
nuclear@0 826 return _isCData;
nuclear@0 827 }
nuclear@0 828
nuclear@0 829 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 830 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 831 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 832
nuclear@0 833 protected:
nuclear@0 834 XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {}
nuclear@0 835 virtual ~XMLText() {}
nuclear@0 836 XMLText( const XMLText& ); // not supported
nuclear@0 837 XMLText& operator=( const XMLText& ); // not supported
nuclear@0 838
nuclear@0 839 private:
nuclear@0 840 bool _isCData;
nuclear@0 841 };
nuclear@0 842
nuclear@0 843
nuclear@0 844 /** An XML Comment. */
nuclear@0 845 class XMLComment : public XMLNode
nuclear@0 846 {
nuclear@0 847 friend class XMLDocument;
nuclear@0 848 public:
nuclear@0 849 virtual XMLComment* ToComment() {
nuclear@0 850 return this;
nuclear@0 851 }
nuclear@0 852 virtual const XMLComment* ToComment() const {
nuclear@0 853 return this;
nuclear@0 854 }
nuclear@0 855
nuclear@0 856 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 857
nuclear@0 858 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 859 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 860 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 861
nuclear@0 862 protected:
nuclear@0 863 XMLComment( XMLDocument* doc );
nuclear@0 864 virtual ~XMLComment();
nuclear@0 865 XMLComment( const XMLComment& ); // not supported
nuclear@0 866 XMLComment& operator=( const XMLComment& ); // not supported
nuclear@0 867
nuclear@0 868 private:
nuclear@0 869 };
nuclear@0 870
nuclear@0 871
nuclear@0 872 /** In correct XML the declaration is the first entry in the file.
nuclear@0 873 @verbatim
nuclear@0 874 <?xml version="1.0" standalone="yes"?>
nuclear@0 875 @endverbatim
nuclear@0 876
nuclear@0 877 TinyXML2 will happily read or write files without a declaration,
nuclear@0 878 however.
nuclear@0 879
nuclear@0 880 The text of the declaration isn't interpreted. It is parsed
nuclear@0 881 and written as a string.
nuclear@0 882 */
nuclear@0 883 class XMLDeclaration : public XMLNode
nuclear@0 884 {
nuclear@0 885 friend class XMLDocument;
nuclear@0 886 public:
nuclear@0 887 virtual XMLDeclaration* ToDeclaration() {
nuclear@0 888 return this;
nuclear@0 889 }
nuclear@0 890 virtual const XMLDeclaration* ToDeclaration() const {
nuclear@0 891 return this;
nuclear@0 892 }
nuclear@0 893
nuclear@0 894 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 895
nuclear@0 896 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 897 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 898 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 899
nuclear@0 900 protected:
nuclear@0 901 XMLDeclaration( XMLDocument* doc );
nuclear@0 902 virtual ~XMLDeclaration();
nuclear@0 903 XMLDeclaration( const XMLDeclaration& ); // not supported
nuclear@0 904 XMLDeclaration& operator=( const XMLDeclaration& ); // not supported
nuclear@0 905 };
nuclear@0 906
nuclear@0 907
nuclear@0 908 /** Any tag that tinyXml doesn't recognize is saved as an
nuclear@0 909 unknown. It is a tag of text, but should not be modified.
nuclear@0 910 It will be written back to the XML, unchanged, when the file
nuclear@0 911 is saved.
nuclear@0 912
nuclear@0 913 DTD tags get thrown into TiXmlUnknowns.
nuclear@0 914 */
nuclear@0 915 class XMLUnknown : public XMLNode
nuclear@0 916 {
nuclear@0 917 friend class XMLDocument;
nuclear@0 918 public:
nuclear@0 919 virtual XMLUnknown* ToUnknown() {
nuclear@0 920 return this;
nuclear@0 921 }
nuclear@0 922 virtual const XMLUnknown* ToUnknown() const {
nuclear@0 923 return this;
nuclear@0 924 }
nuclear@0 925
nuclear@0 926 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 927
nuclear@0 928 char* ParseDeep( char*, StrPair* endTag );
nuclear@0 929 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 930 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 931
nuclear@0 932 protected:
nuclear@0 933 XMLUnknown( XMLDocument* doc );
nuclear@0 934 virtual ~XMLUnknown();
nuclear@0 935 XMLUnknown( const XMLUnknown& ); // not supported
nuclear@0 936 XMLUnknown& operator=( const XMLUnknown& ); // not supported
nuclear@0 937 };
nuclear@0 938
nuclear@0 939
nuclear@0 940 enum XMLError {
nuclear@0 941 XML_NO_ERROR = 0,
nuclear@0 942 XML_SUCCESS = 0,
nuclear@0 943
nuclear@0 944 XML_NO_ATTRIBUTE,
nuclear@0 945 XML_WRONG_ATTRIBUTE_TYPE,
nuclear@0 946
nuclear@0 947 XML_ERROR_FILE_NOT_FOUND,
nuclear@0 948 XML_ERROR_FILE_COULD_NOT_BE_OPENED,
nuclear@0 949 XML_ERROR_FILE_READ_ERROR,
nuclear@0 950 XML_ERROR_ELEMENT_MISMATCH,
nuclear@0 951 XML_ERROR_PARSING_ELEMENT,
nuclear@0 952 XML_ERROR_PARSING_ATTRIBUTE,
nuclear@0 953 XML_ERROR_IDENTIFYING_TAG,
nuclear@0 954 XML_ERROR_PARSING_TEXT,
nuclear@0 955 XML_ERROR_PARSING_CDATA,
nuclear@0 956 XML_ERROR_PARSING_COMMENT,
nuclear@0 957 XML_ERROR_PARSING_DECLARATION,
nuclear@0 958 XML_ERROR_PARSING_UNKNOWN,
nuclear@0 959 XML_ERROR_EMPTY_DOCUMENT,
nuclear@0 960 XML_ERROR_MISMATCHED_ELEMENT,
nuclear@0 961 XML_ERROR_PARSING,
nuclear@0 962
nuclear@0 963 XML_CAN_NOT_CONVERT_TEXT,
nuclear@0 964 XML_NO_TEXT_NODE
nuclear@0 965 };
nuclear@0 966
nuclear@0 967
nuclear@0 968 /** An attribute is a name-value pair. Elements have an arbitrary
nuclear@0 969 number of attributes, each with a unique name.
nuclear@0 970
nuclear@0 971 @note The attributes are not XMLNodes. You may only query the
nuclear@0 972 Next() attribute in a list.
nuclear@0 973 */
nuclear@0 974 class XMLAttribute
nuclear@0 975 {
nuclear@0 976 friend class XMLElement;
nuclear@0 977 public:
nuclear@0 978 /// The name of the attribute.
nuclear@0 979 const char* Name() const {
nuclear@0 980 return _name.GetStr();
nuclear@0 981 }
nuclear@0 982 /// The value of the attribute.
nuclear@0 983 const char* Value() const {
nuclear@0 984 return _value.GetStr();
nuclear@0 985 }
nuclear@0 986 /// The next attribute in the list.
nuclear@0 987 const XMLAttribute* Next() const {
nuclear@0 988 return _next;
nuclear@0 989 }
nuclear@0 990
nuclear@0 991 /** IntAttribute interprets the attribute as an integer, and returns the value.
nuclear@0 992 If the value isn't an integer, 0 will be returned. There is no error checking;
nuclear@0 993 use QueryIntAttribute() if you need error checking.
nuclear@0 994 */
nuclear@0 995 int IntValue() const {
nuclear@0 996 int i=0;
nuclear@0 997 QueryIntValue( &i );
nuclear@0 998 return i;
nuclear@0 999 }
nuclear@0 1000 /// Query as an unsigned integer. See IntAttribute()
nuclear@0 1001 unsigned UnsignedValue() const {
nuclear@0 1002 unsigned i=0;
nuclear@0 1003 QueryUnsignedValue( &i );
nuclear@0 1004 return i;
nuclear@0 1005 }
nuclear@0 1006 /// Query as a boolean. See IntAttribute()
nuclear@0 1007 bool BoolValue() const {
nuclear@0 1008 bool b=false;
nuclear@0 1009 QueryBoolValue( &b );
nuclear@0 1010 return b;
nuclear@0 1011 }
nuclear@0 1012 /// Query as a double. See IntAttribute()
nuclear@0 1013 double DoubleValue() const {
nuclear@0 1014 double d=0;
nuclear@0 1015 QueryDoubleValue( &d );
nuclear@0 1016 return d;
nuclear@0 1017 }
nuclear@0 1018 /// Query as a float. See IntAttribute()
nuclear@0 1019 float FloatValue() const {
nuclear@0 1020 float f=0;
nuclear@0 1021 QueryFloatValue( &f );
nuclear@0 1022 return f;
nuclear@0 1023 }
nuclear@0 1024
nuclear@0 1025 /** QueryIntAttribute interprets the attribute as an integer, and returns the value
nuclear@0 1026 in the provided paremeter. The function will return XML_NO_ERROR on success,
nuclear@0 1027 and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful.
nuclear@0 1028 */
nuclear@0 1029 XMLError QueryIntValue( int* value ) const;
nuclear@0 1030 /// See QueryIntAttribute
nuclear@0 1031 XMLError QueryUnsignedValue( unsigned int* value ) const;
nuclear@0 1032 /// See QueryIntAttribute
nuclear@0 1033 XMLError QueryBoolValue( bool* value ) const;
nuclear@0 1034 /// See QueryIntAttribute
nuclear@0 1035 XMLError QueryDoubleValue( double* value ) const;
nuclear@0 1036 /// See QueryIntAttribute
nuclear@0 1037 XMLError QueryFloatValue( float* value ) const;
nuclear@0 1038
nuclear@0 1039 /// Set the attribute to a string value.
nuclear@0 1040 void SetAttribute( const char* value );
nuclear@0 1041 /// Set the attribute to value.
nuclear@0 1042 void SetAttribute( int value );
nuclear@0 1043 /// Set the attribute to value.
nuclear@0 1044 void SetAttribute( unsigned value );
nuclear@0 1045 /// Set the attribute to value.
nuclear@0 1046 void SetAttribute( bool value );
nuclear@0 1047 /// Set the attribute to value.
nuclear@0 1048 void SetAttribute( double value );
nuclear@0 1049 /// Set the attribute to value.
nuclear@0 1050 void SetAttribute( float value );
nuclear@0 1051
nuclear@0 1052 private:
nuclear@0 1053 enum { BUF_SIZE = 200 };
nuclear@0 1054
nuclear@0 1055 XMLAttribute() : _next( 0 ) {}
nuclear@0 1056 virtual ~XMLAttribute() {}
nuclear@0 1057
nuclear@0 1058 XMLAttribute( const XMLAttribute& ); // not supported
nuclear@0 1059 void operator=( const XMLAttribute& ); // not supported
nuclear@0 1060 void SetName( const char* name );
nuclear@0 1061
nuclear@0 1062 char* ParseDeep( char* p, bool processEntities );
nuclear@0 1063
nuclear@0 1064 mutable StrPair _name;
nuclear@0 1065 mutable StrPair _value;
nuclear@0 1066 XMLAttribute* _next;
nuclear@0 1067 MemPool* _memPool;
nuclear@0 1068 };
nuclear@0 1069
nuclear@0 1070
nuclear@0 1071 /** The element is a container class. It has a value, the element name,
nuclear@0 1072 and can contain other elements, text, comments, and unknowns.
nuclear@0 1073 Elements also contain an arbitrary number of attributes.
nuclear@0 1074 */
nuclear@0 1075 class XMLElement : public XMLNode
nuclear@0 1076 {
nuclear@0 1077 friend class XMLBase;
nuclear@0 1078 friend class XMLDocument;
nuclear@0 1079 public:
nuclear@0 1080 /// Get the name of an element (which is the Value() of the node.)
nuclear@0 1081 const char* Name() const {
nuclear@0 1082 return Value();
nuclear@0 1083 }
nuclear@0 1084 /// Set the name of the element.
nuclear@0 1085 void SetName( const char* str, bool staticMem=false ) {
nuclear@0 1086 SetValue( str, staticMem );
nuclear@0 1087 }
nuclear@0 1088
nuclear@0 1089 virtual XMLElement* ToElement() {
nuclear@0 1090 return this;
nuclear@0 1091 }
nuclear@0 1092 virtual const XMLElement* ToElement() const {
nuclear@0 1093 return this;
nuclear@0 1094 }
nuclear@0 1095 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 1096
nuclear@0 1097 /** Given an attribute name, Attribute() returns the value
nuclear@0 1098 for the attribute of that name, or null if none
nuclear@0 1099 exists. For example:
nuclear@0 1100
nuclear@0 1101 @verbatim
nuclear@0 1102 const char* value = ele->Attribute( "foo" );
nuclear@0 1103 @endverbatim
nuclear@0 1104
nuclear@0 1105 The 'value' parameter is normally null. However, if specified,
nuclear@0 1106 the attribute will only be returned if the 'name' and 'value'
nuclear@0 1107 match. This allow you to write code:
nuclear@0 1108
nuclear@0 1109 @verbatim
nuclear@0 1110 if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar();
nuclear@0 1111 @endverbatim
nuclear@0 1112
nuclear@0 1113 rather than:
nuclear@0 1114 @verbatim
nuclear@0 1115 if ( ele->Attribute( "foo" ) ) {
nuclear@0 1116 if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar();
nuclear@0 1117 }
nuclear@0 1118 @endverbatim
nuclear@0 1119 */
nuclear@0 1120 const char* Attribute( const char* name, const char* value=0 ) const;
nuclear@0 1121
nuclear@0 1122 /** Given an attribute name, IntAttribute() returns the value
nuclear@0 1123 of the attribute interpreted as an integer. 0 will be
nuclear@0 1124 returned if there is an error. For a method with error
nuclear@0 1125 checking, see QueryIntAttribute()
nuclear@0 1126 */
nuclear@0 1127 int IntAttribute( const char* name ) const {
nuclear@0 1128 int i=0;
nuclear@0 1129 QueryIntAttribute( name, &i );
nuclear@0 1130 return i;
nuclear@0 1131 }
nuclear@0 1132 /// See IntAttribute()
nuclear@0 1133 unsigned UnsignedAttribute( const char* name ) const {
nuclear@0 1134 unsigned i=0;
nuclear@0 1135 QueryUnsignedAttribute( name, &i );
nuclear@0 1136 return i;
nuclear@0 1137 }
nuclear@0 1138 /// See IntAttribute()
nuclear@0 1139 bool BoolAttribute( const char* name ) const {
nuclear@0 1140 bool b=false;
nuclear@0 1141 QueryBoolAttribute( name, &b );
nuclear@0 1142 return b;
nuclear@0 1143 }
nuclear@0 1144 /// See IntAttribute()
nuclear@0 1145 double DoubleAttribute( const char* name ) const {
nuclear@0 1146 double d=0;
nuclear@0 1147 QueryDoubleAttribute( name, &d );
nuclear@0 1148 return d;
nuclear@0 1149 }
nuclear@0 1150 /// See IntAttribute()
nuclear@0 1151 float FloatAttribute( const char* name ) const {
nuclear@0 1152 float f=0;
nuclear@0 1153 QueryFloatAttribute( name, &f );
nuclear@0 1154 return f;
nuclear@0 1155 }
nuclear@0 1156
nuclear@0 1157 /** Given an attribute name, QueryIntAttribute() returns
nuclear@0 1158 XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion
nuclear@0 1159 can't be performed, or XML_NO_ATTRIBUTE if the attribute
nuclear@0 1160 doesn't exist. If successful, the result of the conversion
nuclear@0 1161 will be written to 'value'. If not successful, nothing will
nuclear@0 1162 be written to 'value'. This allows you to provide default
nuclear@0 1163 value:
nuclear@0 1164
nuclear@0 1165 @verbatim
nuclear@0 1166 int value = 10;
nuclear@0 1167 QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10
nuclear@0 1168 @endverbatim
nuclear@0 1169 */
nuclear@0 1170 XMLError QueryIntAttribute( const char* name, int* value ) const {
nuclear@0 1171 const XMLAttribute* a = FindAttribute( name );
nuclear@0 1172 if ( !a ) {
nuclear@0 1173 return XML_NO_ATTRIBUTE;
nuclear@0 1174 }
nuclear@0 1175 return a->QueryIntValue( value );
nuclear@0 1176 }
nuclear@0 1177 /// See QueryIntAttribute()
nuclear@0 1178 XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const {
nuclear@0 1179 const XMLAttribute* a = FindAttribute( name );
nuclear@0 1180 if ( !a ) {
nuclear@0 1181 return XML_NO_ATTRIBUTE;
nuclear@0 1182 }
nuclear@0 1183 return a->QueryUnsignedValue( value );
nuclear@0 1184 }
nuclear@0 1185 /// See QueryIntAttribute()
nuclear@0 1186 XMLError QueryBoolAttribute( const char* name, bool* value ) const {
nuclear@0 1187 const XMLAttribute* a = FindAttribute( name );
nuclear@0 1188 if ( !a ) {
nuclear@0 1189 return XML_NO_ATTRIBUTE;
nuclear@0 1190 }
nuclear@0 1191 return a->QueryBoolValue( value );
nuclear@0 1192 }
nuclear@0 1193 /// See QueryIntAttribute()
nuclear@0 1194 XMLError QueryDoubleAttribute( const char* name, double* value ) const {
nuclear@0 1195 const XMLAttribute* a = FindAttribute( name );
nuclear@0 1196 if ( !a ) {
nuclear@0 1197 return XML_NO_ATTRIBUTE;
nuclear@0 1198 }
nuclear@0 1199 return a->QueryDoubleValue( value );
nuclear@0 1200 }
nuclear@0 1201 /// See QueryIntAttribute()
nuclear@0 1202 XMLError QueryFloatAttribute( const char* name, float* value ) const {
nuclear@0 1203 const XMLAttribute* a = FindAttribute( name );
nuclear@0 1204 if ( !a ) {
nuclear@0 1205 return XML_NO_ATTRIBUTE;
nuclear@0 1206 }
nuclear@0 1207 return a->QueryFloatValue( value );
nuclear@0 1208 }
nuclear@0 1209
nuclear@0 1210 /// Sets the named attribute to value.
nuclear@0 1211 void SetAttribute( const char* name, const char* value ) {
nuclear@0 1212 XMLAttribute* a = FindOrCreateAttribute( name );
nuclear@0 1213 a->SetAttribute( value );
nuclear@0 1214 }
nuclear@0 1215 /// Sets the named attribute to value.
nuclear@0 1216 void SetAttribute( const char* name, int value ) {
nuclear@0 1217 XMLAttribute* a = FindOrCreateAttribute( name );
nuclear@0 1218 a->SetAttribute( value );
nuclear@0 1219 }
nuclear@0 1220 /// Sets the named attribute to value.
nuclear@0 1221 void SetAttribute( const char* name, unsigned value ) {
nuclear@0 1222 XMLAttribute* a = FindOrCreateAttribute( name );
nuclear@0 1223 a->SetAttribute( value );
nuclear@0 1224 }
nuclear@0 1225 /// Sets the named attribute to value.
nuclear@0 1226 void SetAttribute( const char* name, bool value ) {
nuclear@0 1227 XMLAttribute* a = FindOrCreateAttribute( name );
nuclear@0 1228 a->SetAttribute( value );
nuclear@0 1229 }
nuclear@0 1230 /// Sets the named attribute to value.
nuclear@0 1231 void SetAttribute( const char* name, double value ) {
nuclear@0 1232 XMLAttribute* a = FindOrCreateAttribute( name );
nuclear@0 1233 a->SetAttribute( value );
nuclear@0 1234 }
nuclear@0 1235
nuclear@0 1236 /**
nuclear@0 1237 Delete an attribute.
nuclear@0 1238 */
nuclear@0 1239 void DeleteAttribute( const char* name );
nuclear@0 1240
nuclear@0 1241 /// Return the first attribute in the list.
nuclear@0 1242 const XMLAttribute* FirstAttribute() const {
nuclear@0 1243 return _rootAttribute;
nuclear@0 1244 }
nuclear@0 1245 /// Query a specific attribute in the list.
nuclear@0 1246 const XMLAttribute* FindAttribute( const char* name ) const;
nuclear@0 1247
nuclear@0 1248 /** Convenience function for easy access to the text inside an element. Although easy
nuclear@0 1249 and concise, GetText() is limited compared to getting the TiXmlText child
nuclear@0 1250 and accessing it directly.
nuclear@0 1251
nuclear@0 1252 If the first child of 'this' is a TiXmlText, the GetText()
nuclear@0 1253 returns the character string of the Text node, else null is returned.
nuclear@0 1254
nuclear@0 1255 This is a convenient method for getting the text of simple contained text:
nuclear@0 1256 @verbatim
nuclear@0 1257 <foo>This is text</foo>
nuclear@0 1258 const char* str = fooElement->GetText();
nuclear@0 1259 @endverbatim
nuclear@0 1260
nuclear@0 1261 'str' will be a pointer to "This is text".
nuclear@0 1262
nuclear@0 1263 Note that this function can be misleading. If the element foo was created from
nuclear@0 1264 this XML:
nuclear@0 1265 @verbatim
nuclear@0 1266 <foo><b>This is text</b></foo>
nuclear@0 1267 @endverbatim
nuclear@0 1268
nuclear@0 1269 then the value of str would be null. The first child node isn't a text node, it is
nuclear@0 1270 another element. From this XML:
nuclear@0 1271 @verbatim
nuclear@0 1272 <foo>This is <b>text</b></foo>
nuclear@0 1273 @endverbatim
nuclear@0 1274 GetText() will return "This is ".
nuclear@0 1275 */
nuclear@0 1276 const char* GetText() const;
nuclear@0 1277
nuclear@0 1278 /**
nuclear@0 1279 Convenience method to query the value of a child text node. This is probably best
nuclear@0 1280 shown by example. Given you have a document is this form:
nuclear@0 1281 @verbatim
nuclear@0 1282 <point>
nuclear@0 1283 <x>1</x>
nuclear@0 1284 <y>1.4</y>
nuclear@0 1285 </point>
nuclear@0 1286 @endverbatim
nuclear@0 1287
nuclear@0 1288 The QueryIntText() and similar functions provide a safe and easier way to get to the
nuclear@0 1289 "value" of x and y.
nuclear@0 1290
nuclear@0 1291 @verbatim
nuclear@0 1292 int x = 0;
nuclear@0 1293 float y = 0; // types of x and y are contrived for example
nuclear@0 1294 const XMLElement* xElement = pointElement->FirstChildElement( "x" );
nuclear@0 1295 const XMLElement* yElement = pointElement->FirstChildElement( "y" );
nuclear@0 1296 xElement->QueryIntText( &x );
nuclear@0 1297 yElement->QueryFloatText( &y );
nuclear@0 1298 @endverbatim
nuclear@0 1299
nuclear@0 1300 @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted
nuclear@0 1301 to the requested type, and XML_NO_TEXT_NODE if there is no child text to query.
nuclear@0 1302
nuclear@0 1303 */
nuclear@0 1304 XMLError QueryIntText( int* ival ) const;
nuclear@0 1305 /// See QueryIntText()
nuclear@0 1306 XMLError QueryUnsignedText( unsigned* uval ) const;
nuclear@0 1307 /// See QueryIntText()
nuclear@0 1308 XMLError QueryBoolText( bool* bval ) const;
nuclear@0 1309 /// See QueryIntText()
nuclear@0 1310 XMLError QueryDoubleText( double* dval ) const;
nuclear@0 1311 /// See QueryIntText()
nuclear@0 1312 XMLError QueryFloatText( float* fval ) const;
nuclear@0 1313
nuclear@0 1314 // internal:
nuclear@0 1315 enum {
nuclear@0 1316 OPEN, // <foo>
nuclear@0 1317 CLOSED, // <foo/>
nuclear@0 1318 CLOSING // </foo>
nuclear@0 1319 };
nuclear@0 1320 int ClosingType() const {
nuclear@0 1321 return _closingType;
nuclear@0 1322 }
nuclear@0 1323 char* ParseDeep( char* p, StrPair* endTag );
nuclear@0 1324 virtual XMLNode* ShallowClone( XMLDocument* document ) const;
nuclear@0 1325 virtual bool ShallowEqual( const XMLNode* compare ) const;
nuclear@0 1326
nuclear@0 1327 private:
nuclear@0 1328 XMLElement( XMLDocument* doc );
nuclear@0 1329 virtual ~XMLElement();
nuclear@0 1330 XMLElement( const XMLElement& ); // not supported
nuclear@0 1331 void operator=( const XMLElement& ); // not supported
nuclear@0 1332
nuclear@0 1333 XMLAttribute* FindAttribute( const char* name );
nuclear@0 1334 XMLAttribute* FindOrCreateAttribute( const char* name );
nuclear@0 1335 //void LinkAttribute( XMLAttribute* attrib );
nuclear@0 1336 char* ParseAttributes( char* p );
nuclear@0 1337
nuclear@0 1338 int _closingType;
nuclear@0 1339 // The attribute list is ordered; there is no 'lastAttribute'
nuclear@0 1340 // because the list needs to be scanned for dupes before adding
nuclear@0 1341 // a new attribute.
nuclear@0 1342 XMLAttribute* _rootAttribute;
nuclear@0 1343 };
nuclear@0 1344
nuclear@0 1345
nuclear@0 1346 enum Whitespace {
nuclear@0 1347 PRESERVE_WHITESPACE,
nuclear@0 1348 COLLAPSE_WHITESPACE
nuclear@0 1349 };
nuclear@0 1350
nuclear@0 1351
nuclear@0 1352 /** A Document binds together all the functionality.
nuclear@0 1353 It can be saved, loaded, and printed to the screen.
nuclear@0 1354 All Nodes are connected and allocated to a Document.
nuclear@0 1355 If the Document is deleted, all its Nodes are also deleted.
nuclear@0 1356 */
nuclear@0 1357 class XMLDocument : public XMLNode
nuclear@0 1358 {
nuclear@0 1359 friend class XMLElement;
nuclear@0 1360 public:
nuclear@0 1361 /// constructor
nuclear@0 1362 XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE );
nuclear@0 1363 ~XMLDocument();
nuclear@0 1364
nuclear@0 1365 virtual XMLDocument* ToDocument() {
nuclear@0 1366 return this;
nuclear@0 1367 }
nuclear@0 1368 virtual const XMLDocument* ToDocument() const {
nuclear@0 1369 return this;
nuclear@0 1370 }
nuclear@0 1371
nuclear@0 1372 /**
nuclear@0 1373 Parse an XML file from a character string.
nuclear@0 1374 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1375 an errorID.
nuclear@0 1376
nuclear@0 1377 You may optionally pass in the 'nBytes', which is
nuclear@0 1378 the number of bytes which will be parsed. If not
nuclear@0 1379 specified, TinyXML will assume 'xml' points to a
nuclear@0 1380 null terminated string.
nuclear@0 1381 */
nuclear@0 1382 XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) );
nuclear@0 1383
nuclear@0 1384 /**
nuclear@0 1385 Load an XML file from disk.
nuclear@0 1386 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1387 an errorID.
nuclear@0 1388 */
nuclear@0 1389 XMLError LoadFile( const char* filename );
nuclear@0 1390
nuclear@0 1391 /**
nuclear@0 1392 Load an XML file from disk. You are responsible
nuclear@0 1393 for providing and closing the FILE*.
nuclear@0 1394
nuclear@0 1395 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1396 an errorID.
nuclear@0 1397 */
nuclear@0 1398 XMLError LoadFile( FILE* );
nuclear@0 1399
nuclear@0 1400 /**
nuclear@0 1401 Save the XML file to disk.
nuclear@0 1402 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1403 an errorID.
nuclear@0 1404 */
nuclear@0 1405 XMLError SaveFile( const char* filename, bool compact = false );
nuclear@0 1406
nuclear@0 1407 /**
nuclear@0 1408 Save the XML file to disk. You are responsible
nuclear@0 1409 for providing and closing the FILE*.
nuclear@0 1410
nuclear@0 1411 Returns XML_NO_ERROR (0) on success, or
nuclear@0 1412 an errorID.
nuclear@0 1413 */
nuclear@0 1414 XMLError SaveFile( FILE* fp, bool compact = false );
nuclear@0 1415
nuclear@0 1416 bool ProcessEntities() const {
nuclear@0 1417 return _processEntities;
nuclear@0 1418 }
nuclear@0 1419 Whitespace WhitespaceMode() const {
nuclear@0 1420 return _whitespace;
nuclear@0 1421 }
nuclear@0 1422
nuclear@0 1423 /**
nuclear@0 1424 Returns true if this document has a leading Byte Order Mark of UTF8.
nuclear@0 1425 */
nuclear@0 1426 bool HasBOM() const {
nuclear@0 1427 return _writeBOM;
nuclear@0 1428 }
nuclear@0 1429 /** Sets whether to write the BOM when writing the file.
nuclear@0 1430 */
nuclear@0 1431 void SetBOM( bool useBOM ) {
nuclear@0 1432 _writeBOM = useBOM;
nuclear@0 1433 }
nuclear@0 1434
nuclear@0 1435 /** Return the root element of DOM. Equivalent to FirstChildElement().
nuclear@0 1436 To get the first node, use FirstChild().
nuclear@0 1437 */
nuclear@0 1438 XMLElement* RootElement() {
nuclear@0 1439 return FirstChildElement();
nuclear@0 1440 }
nuclear@0 1441 const XMLElement* RootElement() const {
nuclear@0 1442 return FirstChildElement();
nuclear@0 1443 }
nuclear@0 1444
nuclear@0 1445 /** Print the Document. If the Printer is not provided, it will
nuclear@0 1446 print to stdout. If you provide Printer, this can print to a file:
nuclear@0 1447 @verbatim
nuclear@0 1448 XMLPrinter printer( fp );
nuclear@0 1449 doc.Print( &printer );
nuclear@0 1450 @endverbatim
nuclear@0 1451
nuclear@0 1452 Or you can use a printer to print to memory:
nuclear@0 1453 @verbatim
nuclear@0 1454 XMLPrinter printer;
nuclear@0 1455 doc->Print( &printer );
nuclear@0 1456 // printer.CStr() has a const char* to the XML
nuclear@0 1457 @endverbatim
nuclear@0 1458 */
nuclear@0 1459 void Print( XMLPrinter* streamer=0 );
nuclear@0 1460 virtual bool Accept( XMLVisitor* visitor ) const;
nuclear@0 1461
nuclear@0 1462 /**
nuclear@0 1463 Create a new Element associated with
nuclear@0 1464 this Document. The memory for the Element
nuclear@0 1465 is managed by the Document.
nuclear@0 1466 */
nuclear@0 1467 XMLElement* NewElement( const char* name );
nuclear@0 1468 /**
nuclear@0 1469 Create a new Comment associated with
nuclear@0 1470 this Document. The memory for the Comment
nuclear@0 1471 is managed by the Document.
nuclear@0 1472 */
nuclear@0 1473 XMLComment* NewComment( const char* comment );
nuclear@0 1474 /**
nuclear@0 1475 Create a new Text associated with
nuclear@0 1476 this Document. The memory for the Text
nuclear@0 1477 is managed by the Document.
nuclear@0 1478 */
nuclear@0 1479 XMLText* NewText( const char* text );
nuclear@0 1480 /**
nuclear@0 1481 Create a new Declaration associated with
nuclear@0 1482 this Document. The memory for the object
nuclear@0 1483 is managed by the Document.
nuclear@0 1484
nuclear@0 1485 If the 'text' param is null, the standard
nuclear@0 1486 declaration is used.:
nuclear@0 1487 @verbatim
nuclear@0 1488 <?xml version="1.0" encoding="UTF-8"?>
nuclear@0 1489 @endverbatim
nuclear@0 1490 */
nuclear@0 1491 XMLDeclaration* NewDeclaration( const char* text=0 );
nuclear@0 1492 /**
nuclear@0 1493 Create a new Unknown associated with
nuclear@0 1494 this Document. The memory forthe object
nuclear@0 1495 is managed by the Document.
nuclear@0 1496 */
nuclear@0 1497 XMLUnknown* NewUnknown( const char* text );
nuclear@0 1498
nuclear@0 1499 /**
nuclear@0 1500 Delete a node associated with this document.
nuclear@0 1501 It will be unlinked from the DOM.
nuclear@0 1502 */
nuclear@0 1503 void DeleteNode( XMLNode* node ) {
nuclear@0 1504 node->_parent->DeleteChild( node );
nuclear@0 1505 }
nuclear@0 1506
nuclear@0 1507 void SetError( XMLError error, const char* str1, const char* str2 );
nuclear@0 1508
nuclear@0 1509 /// Return true if there was an error parsing the document.
nuclear@0 1510 bool Error() const {
nuclear@0 1511 return _errorID != XML_NO_ERROR;
nuclear@0 1512 }
nuclear@0 1513 /// Return the errorID.
nuclear@0 1514 XMLError ErrorID() const {
nuclear@0 1515 return _errorID;
nuclear@0 1516 }
nuclear@0 1517 /// Return a possibly helpful diagnostic location or string.
nuclear@0 1518 const char* GetErrorStr1() const {
nuclear@0 1519 return _errorStr1;
nuclear@0 1520 }
nuclear@0 1521 /// Return a possibly helpful secondary diagnostic location or string.
nuclear@0 1522 const char* GetErrorStr2() const {
nuclear@0 1523 return _errorStr2;
nuclear@0 1524 }
nuclear@0 1525 /// If there is an error, print it to stdout.
nuclear@0 1526 void PrintError() const;
nuclear@0 1527
nuclear@0 1528 // internal
nuclear@0 1529 char* Identify( char* p, XMLNode** node );
nuclear@0 1530
nuclear@0 1531 virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const {
nuclear@0 1532 return 0;
nuclear@0 1533 }
nuclear@0 1534 virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const {
nuclear@0 1535 return false;
nuclear@0 1536 }
nuclear@0 1537
nuclear@0 1538 private:
nuclear@0 1539 XMLDocument( const XMLDocument& ); // not supported
nuclear@0 1540 void operator=( const XMLDocument& ); // not supported
nuclear@0 1541 void InitDocument();
nuclear@0 1542
nuclear@0 1543 bool _writeBOM;
nuclear@0 1544 bool _processEntities;
nuclear@0 1545 XMLError _errorID;
nuclear@0 1546 Whitespace _whitespace;
nuclear@0 1547 const char* _errorStr1;
nuclear@0 1548 const char* _errorStr2;
nuclear@0 1549 char* _charBuffer;
nuclear@0 1550
nuclear@0 1551 MemPoolT< sizeof(XMLElement) > _elementPool;
nuclear@0 1552 MemPoolT< sizeof(XMLAttribute) > _attributePool;
nuclear@0 1553 MemPoolT< sizeof(XMLText) > _textPool;
nuclear@0 1554 MemPoolT< sizeof(XMLComment) > _commentPool;
nuclear@0 1555 };
nuclear@0 1556
nuclear@0 1557
nuclear@0 1558 /**
nuclear@0 1559 A XMLHandle is a class that wraps a node pointer with null checks; this is
nuclear@0 1560 an incredibly useful thing. Note that XMLHandle is not part of the TinyXML
nuclear@0 1561 DOM structure. It is a separate utility class.
nuclear@0 1562
nuclear@0 1563 Take an example:
nuclear@0 1564 @verbatim
nuclear@0 1565 <Document>
nuclear@0 1566 <Element attributeA = "valueA">
nuclear@0 1567 <Child attributeB = "value1" />
nuclear@0 1568 <Child attributeB = "value2" />
nuclear@0 1569 </Element>
nuclear@0 1570 </Document>
nuclear@0 1571 @endverbatim
nuclear@0 1572
nuclear@0 1573 Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
nuclear@0 1574 easy to write a *lot* of code that looks like:
nuclear@0 1575
nuclear@0 1576 @verbatim
nuclear@0 1577 XMLElement* root = document.FirstChildElement( "Document" );
nuclear@0 1578 if ( root )
nuclear@0 1579 {
nuclear@0 1580 XMLElement* element = root->FirstChildElement( "Element" );
nuclear@0 1581 if ( element )
nuclear@0 1582 {
nuclear@0 1583 XMLElement* child = element->FirstChildElement( "Child" );
nuclear@0 1584 if ( child )
nuclear@0 1585 {
nuclear@0 1586 XMLElement* child2 = child->NextSiblingElement( "Child" );
nuclear@0 1587 if ( child2 )
nuclear@0 1588 {
nuclear@0 1589 // Finally do something useful.
nuclear@0 1590 @endverbatim
nuclear@0 1591
nuclear@0 1592 And that doesn't even cover "else" cases. XMLHandle addresses the verbosity
nuclear@0 1593 of such code. A XMLHandle checks for null pointers so it is perfectly safe
nuclear@0 1594 and correct to use:
nuclear@0 1595
nuclear@0 1596 @verbatim
nuclear@0 1597 XMLHandle docHandle( &document );
nuclear@0 1598 XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement();
nuclear@0 1599 if ( child2 )
nuclear@0 1600 {
nuclear@0 1601 // do something useful
nuclear@0 1602 @endverbatim
nuclear@0 1603
nuclear@0 1604 Which is MUCH more concise and useful.
nuclear@0 1605
nuclear@0 1606 It is also safe to copy handles - internally they are nothing more than node pointers.
nuclear@0 1607 @verbatim
nuclear@0 1608 XMLHandle handleCopy = handle;
nuclear@0 1609 @endverbatim
nuclear@0 1610
nuclear@0 1611 See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects.
nuclear@0 1612 */
nuclear@0 1613 class XMLHandle
nuclear@0 1614 {
nuclear@0 1615 public:
nuclear@0 1616 /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
nuclear@0 1617 XMLHandle( XMLNode* node ) {
nuclear@0 1618 _node = node;
nuclear@0 1619 }
nuclear@0 1620 /// Create a handle from a node.
nuclear@0 1621 XMLHandle( XMLNode& node ) {
nuclear@0 1622 _node = &node;
nuclear@0 1623 }
nuclear@0 1624 /// Copy constructor
nuclear@0 1625 XMLHandle( const XMLHandle& ref ) {
nuclear@0 1626 _node = ref._node;
nuclear@0 1627 }
nuclear@0 1628 /// Assignment
nuclear@0 1629 XMLHandle& operator=( const XMLHandle& ref ) {
nuclear@0 1630 _node = ref._node;
nuclear@0 1631 return *this;
nuclear@0 1632 }
nuclear@0 1633
nuclear@0 1634 /// Get the first child of this handle.
nuclear@0 1635 XMLHandle FirstChild() {
nuclear@0 1636 return XMLHandle( _node ? _node->FirstChild() : 0 );
nuclear@0 1637 }
nuclear@0 1638 /// Get the first child element of this handle.
nuclear@0 1639 XMLHandle FirstChildElement( const char* value=0 ) {
nuclear@0 1640 return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 );
nuclear@0 1641 }
nuclear@0 1642 /// Get the last child of this handle.
nuclear@0 1643 XMLHandle LastChild() {
nuclear@0 1644 return XMLHandle( _node ? _node->LastChild() : 0 );
nuclear@0 1645 }
nuclear@0 1646 /// Get the last child element of this handle.
nuclear@0 1647 XMLHandle LastChildElement( const char* _value=0 ) {
nuclear@0 1648 return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 );
nuclear@0 1649 }
nuclear@0 1650 /// Get the previous sibling of this handle.
nuclear@0 1651 XMLHandle PreviousSibling() {
nuclear@0 1652 return XMLHandle( _node ? _node->PreviousSibling() : 0 );
nuclear@0 1653 }
nuclear@0 1654 /// Get the previous sibling element of this handle.
nuclear@0 1655 XMLHandle PreviousSiblingElement( const char* _value=0 ) {
nuclear@0 1656 return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
nuclear@0 1657 }
nuclear@0 1658 /// Get the next sibling of this handle.
nuclear@0 1659 XMLHandle NextSibling() {
nuclear@0 1660 return XMLHandle( _node ? _node->NextSibling() : 0 );
nuclear@0 1661 }
nuclear@0 1662 /// Get the next sibling element of this handle.
nuclear@0 1663 XMLHandle NextSiblingElement( const char* _value=0 ) {
nuclear@0 1664 return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
nuclear@0 1665 }
nuclear@0 1666
nuclear@0 1667 /// Safe cast to XMLNode. This can return null.
nuclear@0 1668 XMLNode* ToNode() {
nuclear@0 1669 return _node;
nuclear@0 1670 }
nuclear@0 1671 /// Safe cast to XMLElement. This can return null.
nuclear@0 1672 XMLElement* ToElement() {
nuclear@0 1673 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
nuclear@0 1674 }
nuclear@0 1675 /// Safe cast to XMLText. This can return null.
nuclear@0 1676 XMLText* ToText() {
nuclear@0 1677 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
nuclear@0 1678 }
nuclear@0 1679 /// Safe cast to XMLUnknown. This can return null.
nuclear@0 1680 XMLUnknown* ToUnknown() {
nuclear@0 1681 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
nuclear@0 1682 }
nuclear@0 1683 /// Safe cast to XMLDeclaration. This can return null.
nuclear@0 1684 XMLDeclaration* ToDeclaration() {
nuclear@0 1685 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
nuclear@0 1686 }
nuclear@0 1687
nuclear@0 1688 private:
nuclear@0 1689 XMLNode* _node;
nuclear@0 1690 };
nuclear@0 1691
nuclear@0 1692
nuclear@0 1693 /**
nuclear@0 1694 A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the
nuclear@0 1695 same in all regards, except for the 'const' qualifiers. See XMLHandle for API.
nuclear@0 1696 */
nuclear@0 1697 class XMLConstHandle
nuclear@0 1698 {
nuclear@0 1699 public:
nuclear@0 1700 XMLConstHandle( const XMLNode* node ) {
nuclear@0 1701 _node = node;
nuclear@0 1702 }
nuclear@0 1703 XMLConstHandle( const XMLNode& node ) {
nuclear@0 1704 _node = &node;
nuclear@0 1705 }
nuclear@0 1706 XMLConstHandle( const XMLConstHandle& ref ) {
nuclear@0 1707 _node = ref._node;
nuclear@0 1708 }
nuclear@0 1709
nuclear@0 1710 XMLConstHandle& operator=( const XMLConstHandle& ref ) {
nuclear@0 1711 _node = ref._node;
nuclear@0 1712 return *this;
nuclear@0 1713 }
nuclear@0 1714
nuclear@0 1715 const XMLConstHandle FirstChild() const {
nuclear@0 1716 return XMLConstHandle( _node ? _node->FirstChild() : 0 );
nuclear@0 1717 }
nuclear@0 1718 const XMLConstHandle FirstChildElement( const char* value=0 ) const {
nuclear@0 1719 return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 );
nuclear@0 1720 }
nuclear@0 1721 const XMLConstHandle LastChild() const {
nuclear@0 1722 return XMLConstHandle( _node ? _node->LastChild() : 0 );
nuclear@0 1723 }
nuclear@0 1724 const XMLConstHandle LastChildElement( const char* _value=0 ) const {
nuclear@0 1725 return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 );
nuclear@0 1726 }
nuclear@0 1727 const XMLConstHandle PreviousSibling() const {
nuclear@0 1728 return XMLConstHandle( _node ? _node->PreviousSibling() : 0 );
nuclear@0 1729 }
nuclear@0 1730 const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const {
nuclear@0 1731 return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 );
nuclear@0 1732 }
nuclear@0 1733 const XMLConstHandle NextSibling() const {
nuclear@0 1734 return XMLConstHandle( _node ? _node->NextSibling() : 0 );
nuclear@0 1735 }
nuclear@0 1736 const XMLConstHandle NextSiblingElement( const char* _value=0 ) const {
nuclear@0 1737 return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 );
nuclear@0 1738 }
nuclear@0 1739
nuclear@0 1740
nuclear@0 1741 const XMLNode* ToNode() const {
nuclear@0 1742 return _node;
nuclear@0 1743 }
nuclear@0 1744 const XMLElement* ToElement() const {
nuclear@0 1745 return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 );
nuclear@0 1746 }
nuclear@0 1747 const XMLText* ToText() const {
nuclear@0 1748 return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 );
nuclear@0 1749 }
nuclear@0 1750 const XMLUnknown* ToUnknown() const {
nuclear@0 1751 return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 );
nuclear@0 1752 }
nuclear@0 1753 const XMLDeclaration* ToDeclaration() const {
nuclear@0 1754 return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 );
nuclear@0 1755 }
nuclear@0 1756
nuclear@0 1757 private:
nuclear@0 1758 const XMLNode* _node;
nuclear@0 1759 };
nuclear@0 1760
nuclear@0 1761
nuclear@0 1762 /**
nuclear@0 1763 Printing functionality. The XMLPrinter gives you more
nuclear@0 1764 options than the XMLDocument::Print() method.
nuclear@0 1765
nuclear@0 1766 It can:
nuclear@0 1767 -# Print to memory.
nuclear@0 1768 -# Print to a file you provide.
nuclear@0 1769 -# Print XML without a XMLDocument.
nuclear@0 1770
nuclear@0 1771 Print to Memory
nuclear@0 1772
nuclear@0 1773 @verbatim
nuclear@0 1774 XMLPrinter printer;
nuclear@0 1775 doc->Print( &printer );
nuclear@0 1776 SomeFunction( printer.CStr() );
nuclear@0 1777 @endverbatim
nuclear@0 1778
nuclear@0 1779 Print to a File
nuclear@0 1780
nuclear@0 1781 You provide the file pointer.
nuclear@0 1782 @verbatim
nuclear@0 1783 XMLPrinter printer( fp );
nuclear@0 1784 doc.Print( &printer );
nuclear@0 1785 @endverbatim
nuclear@0 1786
nuclear@0 1787 Print without a XMLDocument
nuclear@0 1788
nuclear@0 1789 When loading, an XML parser is very useful. However, sometimes
nuclear@0 1790 when saving, it just gets in the way. The code is often set up
nuclear@0 1791 for streaming, and constructing the DOM is just overhead.
nuclear@0 1792
nuclear@0 1793 The Printer supports the streaming case. The following code
nuclear@0 1794 prints out a trivially simple XML file without ever creating
nuclear@0 1795 an XML document.
nuclear@0 1796
nuclear@0 1797 @verbatim
nuclear@0 1798 XMLPrinter printer( fp );
nuclear@0 1799 printer.OpenElement( "foo" );
nuclear@0 1800 printer.PushAttribute( "foo", "bar" );
nuclear@0 1801 printer.CloseElement();
nuclear@0 1802 @endverbatim
nuclear@0 1803 */
nuclear@0 1804 class XMLPrinter : public XMLVisitor
nuclear@0 1805 {
nuclear@0 1806 public:
nuclear@0 1807 /** Construct the printer. If the FILE* is specified,
nuclear@0 1808 this will print to the FILE. Else it will print
nuclear@0 1809 to memory, and the result is available in CStr().
nuclear@0 1810 If 'compact' is set to true, then output is created
nuclear@0 1811 with only required whitespace and newlines.
nuclear@0 1812 */
nuclear@0 1813 XMLPrinter( FILE* file=0, bool compact = false );
nuclear@0 1814 ~XMLPrinter() {}
nuclear@0 1815
nuclear@0 1816 /** If streaming, write the BOM and declaration. */
nuclear@0 1817 void PushHeader( bool writeBOM, bool writeDeclaration );
nuclear@0 1818 /** If streaming, start writing an element.
nuclear@0 1819 The element must be closed with CloseElement()
nuclear@0 1820 */
nuclear@0 1821 void OpenElement( const char* name );
nuclear@0 1822 /// If streaming, add an attribute to an open element.
nuclear@0 1823 void PushAttribute( const char* name, const char* value );
nuclear@0 1824 void PushAttribute( const char* name, int value );
nuclear@0 1825 void PushAttribute( const char* name, unsigned value );
nuclear@0 1826 void PushAttribute( const char* name, bool value );
nuclear@0 1827 void PushAttribute( const char* name, double value );
nuclear@0 1828 /// If streaming, close the Element.
nuclear@0 1829 void CloseElement();
nuclear@0 1830
nuclear@0 1831 /// Add a text node.
nuclear@0 1832 void PushText( const char* text, bool cdata=false );
nuclear@0 1833 /// Add a text node from an integer.
nuclear@0 1834 void PushText( int value );
nuclear@0 1835 /// Add a text node from an unsigned.
nuclear@0 1836 void PushText( unsigned value );
nuclear@0 1837 /// Add a text node from a bool.
nuclear@0 1838 void PushText( bool value );
nuclear@0 1839 /// Add a text node from a float.
nuclear@0 1840 void PushText( float value );
nuclear@0 1841 /// Add a text node from a double.
nuclear@0 1842 void PushText( double value );
nuclear@0 1843
nuclear@0 1844 /// Add a comment
nuclear@0 1845 void PushComment( const char* comment );
nuclear@0 1846
nuclear@0 1847 void PushDeclaration( const char* value );
nuclear@0 1848 void PushUnknown( const char* value );
nuclear@0 1849
nuclear@0 1850 virtual bool VisitEnter( const XMLDocument& /*doc*/ );
nuclear@0 1851 virtual bool VisitExit( const XMLDocument& /*doc*/ ) {
nuclear@0 1852 return true;
nuclear@0 1853 }
nuclear@0 1854
nuclear@0 1855 virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute );
nuclear@0 1856 virtual bool VisitExit( const XMLElement& element );
nuclear@0 1857
nuclear@0 1858 virtual bool Visit( const XMLText& text );
nuclear@0 1859 virtual bool Visit( const XMLComment& comment );
nuclear@0 1860 virtual bool Visit( const XMLDeclaration& declaration );
nuclear@0 1861 virtual bool Visit( const XMLUnknown& unknown );
nuclear@0 1862
nuclear@0 1863 /**
nuclear@0 1864 If in print to memory mode, return a pointer to
nuclear@0 1865 the XML file in memory.
nuclear@0 1866 */
nuclear@0 1867 const char* CStr() const {
nuclear@0 1868 return _buffer.Mem();
nuclear@0 1869 }
nuclear@0 1870 /**
nuclear@0 1871 If in print to memory mode, return the size
nuclear@0 1872 of the XML file in memory. (Note the size returned
nuclear@0 1873 includes the terminating null.)
nuclear@0 1874 */
nuclear@0 1875 int CStrSize() const {
nuclear@0 1876 return _buffer.Size();
nuclear@0 1877 }
nuclear@0 1878
nuclear@0 1879 private:
nuclear@0 1880 void SealElement();
nuclear@0 1881 void PrintSpace( int depth );
nuclear@0 1882 void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities.
nuclear@0 1883 void Print( const char* format, ... );
nuclear@0 1884
nuclear@0 1885 bool _elementJustOpened;
nuclear@0 1886 bool _firstElement;
nuclear@0 1887 FILE* _fp;
nuclear@0 1888 int _depth;
nuclear@0 1889 int _textDepth;
nuclear@0 1890 bool _processEntities;
nuclear@0 1891 bool _compactMode;
nuclear@0 1892
nuclear@0 1893 enum {
nuclear@0 1894 ENTITY_RANGE = 64,
nuclear@0 1895 BUF_SIZE = 200
nuclear@0 1896 };
nuclear@0 1897 bool _entityFlag[ENTITY_RANGE];
nuclear@0 1898 bool _restrictedEntityFlag[ENTITY_RANGE];
nuclear@0 1899
nuclear@0 1900 DynArray< const char*, 10 > _stack;
nuclear@0 1901 DynArray< char, 20 > _buffer;
nuclear@0 1902 #ifdef _MSC_VER
nuclear@0 1903 DynArray< char, 20 > _accumulator;
nuclear@0 1904 #endif
nuclear@0 1905 };
nuclear@0 1906
nuclear@0 1907
nuclear@0 1908 } // tinyxml2
nuclear@0 1909
nuclear@0 1910
nuclear@0 1911 #endif // TINYXML2_INCLUDED