Openholo  v5.0
Open Source Digital Holographic Library
tinyxml2.cpp
Go to the documentation of this file.
1 /*
2 Original code by Lee Thomason (www.grinninglizard.com)
3 
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any
6 damages arising from the use of this software.
7 
8 Permission is granted to anyone to use this software for any
9 purpose, including commercial applications, and to alter it and
10 redistribute it freely, subject to the following restrictions:
11 
12 1. The origin of this software must not be misrepresented; you must
13 not claim that you wrote the original software. If you use this
14 software in a product, an acknowledgment in the product documentation
15 would be appreciated but is not required.
16 
17 2. Altered source versions must be plainly marked as such, and
18 must not be misrepresented as being the original software.
19 
20 3. This notice may not be removed or altered from any source
21 distribution.
22 */
23 
24 #include "tinyxml2.h"
25 
26 #include <new> // yes, this one new style header, is in the Android SDK.
27 #if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
28 # include <stddef.h>
29 # include <stdarg.h>
30 #else
31 # include <cstddef>
32 # include <cstdarg>
33 #endif
34 
35 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
36  // Microsoft Visual Studio, version 2005 and higher. Not WinCE.
37  /*int _snprintf_s(
38  char *buffer,
39  size_t sizeOfBuffer,
40  size_t count,
41  const char *format [,
42  argument] ...
43  );*/
44  static inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... )
45  {
46  va_list va;
47  va_start( va, format );
48  int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
49  va_end( va );
50  return result;
51  }
52 
53  static inline int TIXML_VSNPRINTF( char* buffer, size_t size, const char* format, va_list va )
54  {
55  int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va );
56  return result;
57  }
58 
59  #define TIXML_VSCPRINTF _vscprintf
60  #define TIXML_SSCANF sscanf_s
61 #elif defined _MSC_VER
62  // Microsoft Visual Studio 2003 and earlier or WinCE
63  #define TIXML_SNPRINTF _snprintf
64  #define TIXML_VSNPRINTF _vsnprintf
65  #define TIXML_SSCANF sscanf
66  #if (_MSC_VER < 1400 ) && (!defined WINCE)
67  // Microsoft Visual Studio 2003 and not WinCE.
68  #define TIXML_VSCPRINTF _vscprintf // VS2003's C runtime has this, but VC6 C runtime or WinCE SDK doesn't have.
69  #else
70  // Microsoft Visual Studio 2003 and earlier or WinCE.
71  static inline int TIXML_VSCPRINTF( const char* format, va_list va )
72  {
73  int len = 512;
74  for (;;) {
75  len = len*2;
76  char* str = new char[len]();
77  const int required = _vsnprintf(str, len, format, va);
78  delete[] str;
79  if ( required != -1 ) {
80  TIXMLASSERT( required >= 0 );
81  len = required;
82  break;
83  }
84  }
85  TIXMLASSERT( len >= 0 );
86  return len;
87  }
88  #endif
89 #else
90  // GCC version 3 and higher
91  //#warning( "Using sn* functions." )
92  #define TIXML_SNPRINTF snprintf
93  #define TIXML_VSNPRINTF vsnprintf
94  static inline int TIXML_VSCPRINTF( const char* format, va_list va )
95  {
96  int len = vsnprintf( 0, 0, format, va );
97  TIXMLASSERT( len >= 0 );
98  return len;
99  }
100  #define TIXML_SSCANF sscanf
101 #endif
102 
103 
104 static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF
105 static const char LF = LINE_FEED;
106 static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out
107 static const char CR = CARRIAGE_RETURN;
108 static const char SINGLE_QUOTE = '\'';
109 static const char DOUBLE_QUOTE = '\"';
110 
111 // Bunch of unicode info at:
112 // http://www.unicode.org/faq/utf_bom.html
113 // ef bb bf (Microsoft "lead bytes") - designates UTF-8
114 
115 static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
116 static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
117 static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
118 
119 namespace tinyxml2
120 {
121 
122 struct Entity {
123  const char* pattern;
124  int length;
125  char value;
126 };
127 
128 static const int NUM_ENTITIES = 5;
129 static const Entity entities[NUM_ENTITIES] = {
130  { "quot", 4, DOUBLE_QUOTE },
131  { "amp", 3, '&' },
132  { "apos", 4, SINGLE_QUOTE },
133  { "lt", 2, '<' },
134  { "gt", 2, '>' }
135 };
136 
137 
139 {
140  Reset();
141 }
142 
143 
144 void StrPair::TransferTo( StrPair* other )
145 {
146  if ( this == other ) {
147  return;
148  }
149  // This in effect implements the assignment operator by "moving"
150  // ownership (as in auto_ptr).
151 
152  TIXMLASSERT( other != 0 );
153  TIXMLASSERT( other->_flags == 0 );
154  TIXMLASSERT( other->_start == 0 );
155  TIXMLASSERT( other->_end == 0 );
156 
157  other->Reset();
158 
159  other->_flags = _flags;
160  other->_start = _start;
161  other->_end = _end;
162 
163  _flags = 0;
164  _start = 0;
165  _end = 0;
166 }
167 
168 
169 void StrPair::Reset()
170 {
171  if ( _flags & NEEDS_DELETE ) {
172  delete [] _start;
173  }
174  _flags = 0;
175  _start = 0;
176  _end = 0;
177 }
178 
179 
180 void StrPair::SetStr( const char* str, int flags )
181 {
182  TIXMLASSERT( str );
183  Reset();
184  size_t len = strlen( str );
185  TIXMLASSERT( _start == 0 );
186  _start = new char[ len+1 ];
187  memcpy( _start, str, len+1 );
188  _end = _start + len;
189  _flags = flags | NEEDS_DELETE;
190 }
191 
192 
193 char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr )
194 {
195  TIXMLASSERT( p );
196  TIXMLASSERT( endTag && *endTag );
197  TIXMLASSERT(curLineNumPtr);
198 
199  char* start = p;
200  char endChar = *endTag;
201  size_t length = strlen( endTag );
202 
203  // Inner loop of text parsing.
204  while ( *p ) {
205  if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
206  Set( start, p, strFlags );
207  return p + length;
208  } else if (*p == '\n') {
209  ++(*curLineNumPtr);
210  }
211  ++p;
212  TIXMLASSERT( p );
213  }
214  return 0;
215 }
216 
217 
218 char* StrPair::ParseName( char* p )
219 {
220  if ( !p || !(*p) ) {
221  return 0;
222  }
223  if ( !XMLUtil::IsNameStartChar( *p ) ) {
224  return 0;
225  }
226 
227  char* const start = p;
228  ++p;
229  while ( *p && XMLUtil::IsNameChar( *p ) ) {
230  ++p;
231  }
232 
233  Set( start, p, 0 );
234  return p;
235 }
236 
237 
238 void StrPair::CollapseWhitespace()
239 {
240  // Adjusting _start would cause undefined behavior on delete[]
241  TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );
242  // Trim leading space.
243  _start = XMLUtil::SkipWhiteSpace( _start, 0 );
244 
245  if ( *_start ) {
246  const char* p = _start; // the read pointer
247  char* q = _start; // the write pointer
248 
249  while( *p ) {
250  if ( XMLUtil::IsWhiteSpace( *p )) {
251  p = XMLUtil::SkipWhiteSpace( p, 0 );
252  if ( *p == 0 ) {
253  break; // don't write to q; this trims the trailing space.
254  }
255  *q = ' ';
256  ++q;
257  }
258  *q = *p;
259  ++q;
260  ++p;
261  }
262  *q = 0;
263  }
264 }
265 
266 
267 const char* StrPair::GetStr()
268 {
269  TIXMLASSERT( _start );
270  TIXMLASSERT( _end );
271  if ( _flags & NEEDS_FLUSH ) {
272  *_end = 0;
273  _flags ^= NEEDS_FLUSH;
274 
275  if ( _flags ) {
276  const char* p = _start; // the read pointer
277  char* q = _start; // the write pointer
278 
279  while( p < _end ) {
280  if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
281  // CR-LF pair becomes LF
282  // CR alone becomes LF
283  // LF-CR becomes LF
284  if ( *(p+1) == LF ) {
285  p += 2;
286  }
287  else {
288  ++p;
289  }
290  *q = LF;
291  ++q;
292  }
293  else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
294  if ( *(p+1) == CR ) {
295  p += 2;
296  }
297  else {
298  ++p;
299  }
300  *q = LF;
301  ++q;
302  }
303  else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
304  // Entities handled by tinyXML2:
305  // - special entities in the entity table [in/out]
306  // - numeric character reference [in]
307  // &#20013; or &#x4e2d;
308 
309  if ( *(p+1) == '#' ) {
310  const int buflen = 10;
311  char buf[buflen] = { 0 };
312  int len = 0;
313  char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
314  if ( adjusted == 0 ) {
315  *q = *p;
316  ++p;
317  ++q;
318  }
319  else {
320  TIXMLASSERT( 0 <= len && len <= buflen );
321  TIXMLASSERT( q + len <= adjusted );
322  p = adjusted;
323  memcpy( q, buf, len );
324  q += len;
325  }
326  }
327  else {
328  bool entityFound = false;
329  for( int i = 0; i < NUM_ENTITIES; ++i ) {
330  const Entity& entity = entities[i];
331  if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
332  && *( p + entity.length + 1 ) == ';' ) {
333  // Found an entity - convert.
334  *q = entity.value;
335  ++q;
336  p += entity.length + 2;
337  entityFound = true;
338  break;
339  }
340  }
341  if ( !entityFound ) {
342  // fixme: treat as error?
343  ++p;
344  ++q;
345  }
346  }
347  }
348  else {
349  *q = *p;
350  ++p;
351  ++q;
352  }
353  }
354  *q = 0;
355  }
356  // The loop below has plenty going on, and this
357  // is a less useful mode. Break it out.
358  if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {
359  CollapseWhitespace();
360  }
361  _flags = (_flags & NEEDS_DELETE);
362  }
363  TIXMLASSERT( _start );
364  return _start;
365 }
366 
367 
368 
369 
370 // --------- XMLUtil ----------- //
371 
372 const char* XMLUtil::writeBoolTrue = "true";
373 const char* XMLUtil::writeBoolFalse = "false";
374 
375 void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse)
376 {
377  static const char* defTrue = "true";
378  static const char* defFalse = "false";
379 
380  writeBoolTrue = (writeTrue) ? writeTrue : defTrue;
381  writeBoolFalse = (writeFalse) ? writeFalse : defFalse;
382 }
383 
384 
385 const char* XMLUtil::ReadBOM( const char* p, bool* bom )
386 {
387  TIXMLASSERT( p );
388  TIXMLASSERT( bom );
389  *bom = false;
390  const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
391  // Check for BOM:
392  if ( *(pu+0) == TIXML_UTF_LEAD_0
393  && *(pu+1) == TIXML_UTF_LEAD_1
394  && *(pu+2) == TIXML_UTF_LEAD_2 ) {
395  *bom = true;
396  p += 3;
397  }
398  TIXMLASSERT( p );
399  return p;
400 }
401 
402 
403 void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
404 {
405  const unsigned long BYTE_MASK = 0xBF;
406  const unsigned long BYTE_MARK = 0x80;
407  const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
408 
409  if (input < 0x80) {
410  *length = 1;
411  }
412  else if ( input < 0x800 ) {
413  *length = 2;
414  }
415  else if ( input < 0x10000 ) {
416  *length = 3;
417  }
418  else if ( input < 0x200000 ) {
419  *length = 4;
420  }
421  else {
422  *length = 0; // This code won't convert this correctly anyway.
423  return;
424  }
425 
426  output += *length;
427 
428  // Scary scary fall throughs are annotated with carefully designed comments
429  // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc
430  switch (*length) {
431  case 4:
432  --output;
433  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
434  input >>= 6;
435  //fall through
436  case 3:
437  --output;
438  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
439  input >>= 6;
440  //fall through
441  case 2:
442  --output;
443  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
444  input >>= 6;
445  //fall through
446  case 1:
447  --output;
448  *output = (char)(input | FIRST_BYTE_MARK[*length]);
449  break;
450  default:
451  TIXMLASSERT( false );
452  }
453 }
454 
455 
456 const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
457 {
458  // Presume an entity, and pull it out.
459  *length = 0;
460 
461  if ( *(p+1) == '#' && *(p+2) ) {
462  unsigned long ucs = 0;
463  TIXMLASSERT( sizeof( ucs ) >= 4 );
464  ptrdiff_t delta = 0;
465  unsigned mult = 1;
466  static const char SEMICOLON = ';';
467 
468  if ( *(p+2) == 'x' ) {
469  // Hexadecimal.
470  const char* q = p+3;
471  if ( !(*q) ) {
472  return 0;
473  }
474 
475  q = strchr( q, SEMICOLON );
476 
477  if ( !q ) {
478  return 0;
479  }
480  TIXMLASSERT( *q == SEMICOLON );
481 
482  delta = q-p;
483  --q;
484 
485  while ( *q != 'x' ) {
486  unsigned int digit = 0;
487 
488  if ( *q >= '0' && *q <= '9' ) {
489  digit = *q - '0';
490  }
491  else if ( *q >= 'a' && *q <= 'f' ) {
492  digit = *q - 'a' + 10;
493  }
494  else if ( *q >= 'A' && *q <= 'F' ) {
495  digit = *q - 'A' + 10;
496  }
497  else {
498  return 0;
499  }
500  TIXMLASSERT( digit < 16 );
501  TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
502  const unsigned int digitScaled = mult * digit;
503  TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
504  ucs += digitScaled;
505  TIXMLASSERT( mult <= UINT_MAX / 16 );
506  mult *= 16;
507  --q;
508  }
509  }
510  else {
511  // Decimal.
512  const char* q = p+2;
513  if ( !(*q) ) {
514  return 0;
515  }
516 
517  q = strchr( q, SEMICOLON );
518 
519  if ( !q ) {
520  return 0;
521  }
522  TIXMLASSERT( *q == SEMICOLON );
523 
524  delta = q-p;
525  --q;
526 
527  while ( *q != '#' ) {
528  if ( *q >= '0' && *q <= '9' ) {
529  const unsigned int digit = *q - '0';
530  TIXMLASSERT( digit < 10 );
531  TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
532  const unsigned int digitScaled = mult * digit;
533  TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
534  ucs += digitScaled;
535  }
536  else {
537  return 0;
538  }
539  TIXMLASSERT( mult <= UINT_MAX / 10 );
540  mult *= 10;
541  --q;
542  }
543  }
544  // convert the UCS to UTF-8
545  ConvertUTF32ToUTF8( ucs, value, length );
546  return p + delta + 1;
547  }
548  return p+1;
549 }
550 
551 
552 void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
553 {
554  TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
555 }
556 
557 
558 void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
559 {
560  TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
561 }
562 
563 
564 void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
565 {
566  TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse);
567 }
568 
569 /*
570  ToStr() of a number is a very tricky topic.
571  https://github.com/leethomason/tinyxml2/issues/106
572 */
573 void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
574 {
575  TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );
576 }
577 
578 
579 void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
580 {
581  TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );
582 }
583 
584 
585 void XMLUtil::ToStr(int64_t v, char* buffer, int bufferSize)
586 {
587  // horrible syntax trick to make the compiler happy about %lld
588  TIXML_SNPRINTF(buffer, bufferSize, "%lld", (long long)v);
589 }
590 
591 
592 bool XMLUtil::ToInt( const char* str, int* value )
593 {
594  if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
595  return true;
596  }
597  return false;
598 }
599 
600 bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
601 {
602  if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
603  return true;
604  }
605  return false;
606 }
607 
608 bool XMLUtil::ToBool( const char* str, bool* value )
609 {
610  int ival = 0;
611  if ( ToInt( str, &ival )) {
612  *value = (ival==0) ? false : true;
613  return true;
614  }
615  if ( StringEqual( str, "true" ) ) {
616  *value = true;
617  return true;
618  }
619  else if ( StringEqual( str, "false" ) ) {
620  *value = false;
621  return true;
622  }
623  return false;
624 }
625 
626 
627 bool XMLUtil::ToFloat( const char* str, float* value )
628 {
629  if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
630  return true;
631  }
632  return false;
633 }
634 
635 
636 bool XMLUtil::ToDouble( const char* str, double* value )
637 {
638  if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
639  return true;
640  }
641  return false;
642 }
643 
644 
645 bool XMLUtil::ToInt64(const char* str, int64_t* value)
646 {
647  long long v = 0; // horrible syntax trick to make the compiler happy about %lld
648  if (TIXML_SSCANF(str, "%lld", &v) == 1) {
649  *value = (int64_t)v;
650  return true;
651  }
652  return false;
653 }
654 
655 
656 char* XMLDocument::Identify( char* p, XMLNode** node )
657 {
658  TIXMLASSERT( node );
659  TIXMLASSERT( p );
660  char* const start = p;
661  int const startLine = _parseCurLineNum;
662  p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );
663  if( !*p ) {
664  *node = 0;
665  TIXMLASSERT( p );
666  return p;
667  }
668 
669  // These strings define the matching patterns:
670  static const char* xmlHeader = { "<?" };
671  static const char* commentHeader = { "<!--" };
672  static const char* cdataHeader = { "<![CDATA[" };
673  static const char* dtdHeader = { "<!" };
674  static const char* elementHeader = { "<" }; // and a header for everything else; check last.
675 
676  static const int xmlHeaderLen = 2;
677  static const int commentHeaderLen = 4;
678  static const int cdataHeaderLen = 9;
679  static const int dtdHeaderLen = 2;
680  static const int elementHeaderLen = 1;
681 
682  TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
683  TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
684  XMLNode* returnNode = 0;
685  if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
686  returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
687  returnNode->_parseLineNum = _parseCurLineNum;
688  p += xmlHeaderLen;
689  }
690  else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
691  returnNode = CreateUnlinkedNode<XMLComment>( _commentPool );
692  returnNode->_parseLineNum = _parseCurLineNum;
693  p += commentHeaderLen;
694  }
695  else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
696  XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
697  returnNode = text;
698  returnNode->_parseLineNum = _parseCurLineNum;
699  p += cdataHeaderLen;
700  text->SetCData( true );
701  }
702  else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
703  returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool );
704  returnNode->_parseLineNum = _parseCurLineNum;
705  p += dtdHeaderLen;
706  }
707  else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
708  returnNode = CreateUnlinkedNode<XMLElement>( _elementPool );
709  returnNode->_parseLineNum = _parseCurLineNum;
710  p += elementHeaderLen;
711  }
712  else {
713  returnNode = CreateUnlinkedNode<XMLText>( _textPool );
714  returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character
715  p = start; // Back it up, all the text counts.
716  _parseCurLineNum = startLine;
717  }
718 
719  TIXMLASSERT( returnNode );
720  TIXMLASSERT( p );
721  *node = returnNode;
722  return p;
723 }
724 
725 
726 bool XMLDocument::Accept( XMLVisitor* visitor ) const
727 {
728  TIXMLASSERT( visitor );
729  if ( visitor->VisitEnter( *this ) ) {
730  for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
731  if ( !node->Accept( visitor ) ) {
732  break;
733  }
734  }
735  }
736  return visitor->VisitExit( *this );
737 }
738 
739 
740 // --------- XMLNode ----------- //
741 
742 XMLNode::XMLNode( XMLDocument* doc ) :
743  _document( doc ),
744  _parent( 0 ),
745  _value(),
746  _parseLineNum( 0 ),
747  _firstChild( 0 ), _lastChild( 0 ),
748  _prev( 0 ), _next( 0 ),
749  _userData( 0 ),
750  _memPool( 0 )
751 {
752 }
753 
754 
756 {
757  DeleteChildren();
758  if ( _parent ) {
759  _parent->Unlink( this );
760  }
761 }
762 
763 const char* XMLNode::Value() const
764 {
765  // Edge case: XMLDocuments don't have a Value. Return null.
766  if ( this->ToDocument() )
767  return 0;
768  return _value.GetStr();
769 }
770 
771 void XMLNode::SetValue( const char* str, bool staticMem )
772 {
773  if ( staticMem ) {
774  _value.SetInternedStr( str );
775  }
776  else {
777  _value.SetStr( str );
778  }
779 }
780 
781 XMLNode* XMLNode::DeepClone(XMLDocument* target) const
782 {
783  XMLNode* clone = this->ShallowClone(target);
784  if (!clone) return 0;
785 
786  for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) {
787  XMLNode* childClone = child->DeepClone(target);
788  TIXMLASSERT(childClone);
789  clone->InsertEndChild(childClone);
790  }
791  return clone;
792 }
793 
795 {
796  while( _firstChild ) {
799  }
800  _firstChild = _lastChild = 0;
801 }
802 
803 
804 void XMLNode::Unlink( XMLNode* child )
805 {
806  TIXMLASSERT( child );
807  TIXMLASSERT( child->_document == _document );
808  TIXMLASSERT( child->_parent == this );
809  if ( child == _firstChild ) {
811  }
812  if ( child == _lastChild ) {
814  }
815 
816  if ( child->_prev ) {
817  child->_prev->_next = child->_next;
818  }
819  if ( child->_next ) {
820  child->_next->_prev = child->_prev;
821  }
822  child->_next = 0;
823  child->_prev = 0;
824  child->_parent = 0;
825 }
826 
827 
828 void XMLNode::DeleteChild( XMLNode* node )
829 {
830  TIXMLASSERT( node );
831  TIXMLASSERT( node->_document == _document );
832  TIXMLASSERT( node->_parent == this );
833  Unlink( node );
834  TIXMLASSERT(node->_prev == 0);
835  TIXMLASSERT(node->_next == 0);
836  TIXMLASSERT(node->_parent == 0);
837  DeleteNode( node );
838 }
839 
840 
841 XMLNode* XMLNode::InsertEndChild( XMLNode* addThis )
842 {
843  TIXMLASSERT( addThis );
844  if ( addThis->_document != _document ) {
845  TIXMLASSERT( false );
846  return 0;
847  }
848  InsertChildPreamble( addThis );
849 
850  if ( _lastChild ) {
852  TIXMLASSERT( _lastChild->_next == 0 );
853  _lastChild->_next = addThis;
854  addThis->_prev = _lastChild;
855  _lastChild = addThis;
856 
857  addThis->_next = 0;
858  }
859  else {
860  TIXMLASSERT( _firstChild == 0 );
861  _firstChild = _lastChild = addThis;
862 
863  addThis->_prev = 0;
864  addThis->_next = 0;
865  }
866  addThis->_parent = this;
867  return addThis;
868 }
869 
870 
871 XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis )
872 {
873  TIXMLASSERT( addThis );
874  if ( addThis->_document != _document ) {
875  TIXMLASSERT( false );
876  return 0;
877  }
878  InsertChildPreamble( addThis );
879 
880  if ( _firstChild ) {
882  TIXMLASSERT( _firstChild->_prev == 0 );
883 
884  _firstChild->_prev = addThis;
885  addThis->_next = _firstChild;
886  _firstChild = addThis;
887 
888  addThis->_prev = 0;
889  }
890  else {
891  TIXMLASSERT( _lastChild == 0 );
892  _firstChild = _lastChild = addThis;
893 
894  addThis->_prev = 0;
895  addThis->_next = 0;
896  }
897  addThis->_parent = this;
898  return addThis;
899 }
900 
901 
902 XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis )
903 {
904  TIXMLASSERT( addThis );
905  if ( addThis->_document != _document ) {
906  TIXMLASSERT( false );
907  return 0;
908  }
909 
910  TIXMLASSERT( afterThis );
911 
912  if ( afterThis->_parent != this ) {
913  TIXMLASSERT( false );
914  return 0;
915  }
916  if ( afterThis == addThis ) {
917  // Current state: BeforeThis -> AddThis -> OneAfterAddThis
918  // Now AddThis must disappear from it's location and then
919  // reappear between BeforeThis and OneAfterAddThis.
920  // So just leave it where it is.
921  return addThis;
922  }
923 
924  if ( afterThis->_next == 0 ) {
925  // The last node or the only node.
926  return InsertEndChild( addThis );
927  }
928  InsertChildPreamble( addThis );
929  addThis->_prev = afterThis;
930  addThis->_next = afterThis->_next;
931  afterThis->_next->_prev = addThis;
932  afterThis->_next = addThis;
933  addThis->_parent = this;
934  return addThis;
935 }
936 
937 
938 
939 
940 const XMLElement* XMLNode::FirstChildElement( const char* name ) const
941 {
942  for( const XMLNode* node = _firstChild; node; node = node->_next ) {
943  const XMLElement* element = node->ToElementWithName( name );
944  if ( element ) {
945  return element;
946  }
947  }
948  return 0;
949 }
950 
951 
952 const XMLElement* XMLNode::LastChildElement( const char* name ) const
953 {
954  for( const XMLNode* node = _lastChild; node; node = node->_prev ) {
955  const XMLElement* element = node->ToElementWithName( name );
956  if ( element ) {
957  return element;
958  }
959  }
960  return 0;
961 }
962 
963 
964 const XMLElement* XMLNode::NextSiblingElement( const char* name ) const
965 {
966  for( const XMLNode* node = _next; node; node = node->_next ) {
967  const XMLElement* element = node->ToElementWithName( name );
968  if ( element ) {
969  return element;
970  }
971  }
972  return 0;
973 }
974 
975 
976 const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const
977 {
978  for( const XMLNode* node = _prev; node; node = node->_prev ) {
979  const XMLElement* element = node->ToElementWithName( name );
980  if ( element ) {
981  return element;
982  }
983  }
984  return 0;
985 }
986 
987 
988 char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
989 {
990  // This is a recursive method, but thinking about it "at the current level"
991  // it is a pretty simple flat list:
992  // <foo/>
993  // <!-- comment -->
994  //
995  // With a special case:
996  // <foo>
997  // </foo>
998  // <!-- comment -->
999  //
1000  // Where the closing element (/foo) *must* be the next thing after the opening
1001  // element, and the names must match. BUT the tricky bit is that the closing
1002  // element will be read by the child.
1003  //
1004  // 'endTag' is the end tag for this node, it is returned by a call to a child.
1005  // 'parentEnd' is the end tag for the parent, which is filled in and returned.
1006 
1007  XMLDocument::DepthTracker tracker(_document);
1008  if (_document->Error())
1009  return 0;
1010 
1011  while( p && *p ) {
1012  XMLNode* node = 0;
1013 
1014  p = _document->Identify( p, &node );
1015  TIXMLASSERT( p );
1016  if ( node == 0 ) {
1017  break;
1018  }
1019 
1020  int initialLineNum = node->_parseLineNum;
1021 
1022  StrPair endTag;
1023  p = node->ParseDeep( p, &endTag, curLineNumPtr );
1024  if ( !p ) {
1025  DeleteNode( node );
1026  if ( !_document->Error() ) {
1027  _document->SetError( XML_ERROR_PARSING, initialLineNum, 0);
1028  }
1029  break;
1030  }
1031 
1032  XMLDeclaration* decl = node->ToDeclaration();
1033  if ( decl ) {
1034  // Declarations are only allowed at document level
1035  bool wellLocated = ( ToDocument() != 0 );
1036  if ( wellLocated ) {
1037  // Multiple declarations are allowed but all declarations
1038  // must occur before anything else
1039  for ( const XMLNode* existingNode = _document->FirstChild(); existingNode; existingNode = existingNode->NextSibling() ) {
1040  if ( !existingNode->ToDeclaration() ) {
1041  wellLocated = false;
1042  break;
1043  }
1044  }
1045  }
1046  if ( !wellLocated ) {
1047  _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());
1048  DeleteNode( node );
1049  break;
1050  }
1051  }
1052 
1053  XMLElement* ele = node->ToElement();
1054  if ( ele ) {
1055  // We read the end tag. Return it to the parent.
1056  if ( ele->ClosingType() == XMLElement::CLOSING ) {
1057  if ( parentEndTag ) {
1058  ele->_value.TransferTo( parentEndTag );
1059  }
1060  node->_memPool->SetTracked(); // created and then immediately deleted.
1061  DeleteNode( node );
1062  return p;
1063  }
1064 
1065  // Handle an end tag returned to this level.
1066  // And handle a bunch of annoying errors.
1067  bool mismatch = false;
1068  if ( endTag.Empty() ) {
1069  if ( ele->ClosingType() == XMLElement::OPEN ) {
1070  mismatch = true;
1071  }
1072  }
1073  else {
1074  if ( ele->ClosingType() != XMLElement::OPEN ) {
1075  mismatch = true;
1076  }
1077  else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {
1078  mismatch = true;
1079  }
1080  }
1081  if ( mismatch ) {
1082  _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());
1083  DeleteNode( node );
1084  break;
1085  }
1086  }
1087  InsertEndChild( node );
1088  }
1089  return 0;
1090 }
1091 
1092 /*static*/ void XMLNode::DeleteNode( XMLNode* node )
1093 {
1094  if ( node == 0 ) {
1095  return;
1096  }
1097  TIXMLASSERT(node->_document);
1098  if (!node->ToDocument()) {
1099  node->_document->MarkInUse(node);
1100  }
1101 
1102  MemPool* pool = node->_memPool;
1103  node->~XMLNode();
1104  pool->Free( node );
1105 }
1106 
1107 void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
1108 {
1109  TIXMLASSERT( insertThis );
1110  TIXMLASSERT( insertThis->_document == _document );
1111 
1112  if (insertThis->_parent) {
1113  insertThis->_parent->Unlink( insertThis );
1114  }
1115  else {
1116  insertThis->_document->MarkInUse(insertThis);
1117  insertThis->_memPool->SetTracked();
1118  }
1119 }
1120 
1121 const XMLElement* XMLNode::ToElementWithName( const char* name ) const
1122 {
1123  const XMLElement* element = this->ToElement();
1124  if ( element == 0 ) {
1125  return 0;
1126  }
1127  if ( name == 0 ) {
1128  return element;
1129  }
1130  if ( XMLUtil::StringEqual( element->Name(), name ) ) {
1131  return element;
1132  }
1133  return 0;
1134 }
1135 
1136 // --------- XMLText ---------- //
1137 char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1138 {
1139  if ( this->CData() ) {
1140  p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1141  if ( !p ) {
1143  }
1144  return p;
1145  }
1146  else {
1150  }
1151 
1152  p = _value.ParseText( p, "<", flags, curLineNumPtr );
1153  if ( p && *p ) {
1154  return p-1;
1155  }
1156  if ( !p ) {
1158  }
1159  }
1160  return 0;
1161 }
1162 
1163 
1164 XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const
1165 {
1166  if ( !doc ) {
1167  doc = _document;
1168  }
1169  XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?
1170  text->SetCData( this->CData() );
1171  return text;
1172 }
1173 
1174 
1175 bool XMLText::ShallowEqual( const XMLNode* compare ) const
1176 {
1177  TIXMLASSERT( compare );
1178  const XMLText* text = compare->ToText();
1179  return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );
1180 }
1181 
1182 
1183 bool XMLText::Accept( XMLVisitor* visitor ) const
1184 {
1185  TIXMLASSERT( visitor );
1186  return visitor->Visit( *this );
1187 }
1188 
1189 
1190 // --------- XMLComment ---------- //
1191 
1192 XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc )
1193 {
1194 }
1195 
1196 
1198 {
1199 }
1200 
1201 
1202 char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1203 {
1204  // Comment parses as text.
1205  p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr );
1206  if ( p == 0 ) {
1208  }
1209  return p;
1210 }
1211 
1212 
1213 XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const
1214 {
1215  if ( !doc ) {
1216  doc = _document;
1217  }
1218  XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?
1219  return comment;
1220 }
1221 
1222 
1223 bool XMLComment::ShallowEqual( const XMLNode* compare ) const
1224 {
1225  TIXMLASSERT( compare );
1226  const XMLComment* comment = compare->ToComment();
1227  return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));
1228 }
1229 
1230 
1231 bool XMLComment::Accept( XMLVisitor* visitor ) const
1232 {
1233  TIXMLASSERT( visitor );
1234  return visitor->Visit( *this );
1235 }
1236 
1237 
1238 // --------- XMLDeclaration ---------- //
1239 
1240 XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc )
1241 {
1242 }
1243 
1244 
1246 {
1247  //printf( "~XMLDeclaration\n" );
1248 }
1249 
1250 
1251 char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1252 {
1253  // Declaration parses as text.
1254  p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1255  if ( p == 0 ) {
1257  }
1258  return p;
1259 }
1260 
1261 
1262 XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const
1263 {
1264  if ( !doc ) {
1265  doc = _document;
1266  }
1267  XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?
1268  return dec;
1269 }
1270 
1271 
1272 bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
1273 {
1274  TIXMLASSERT( compare );
1275  const XMLDeclaration* declaration = compare->ToDeclaration();
1276  return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));
1277 }
1278 
1279 
1280 
1281 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
1282 {
1283  TIXMLASSERT( visitor );
1284  return visitor->Visit( *this );
1285 }
1286 
1287 // --------- XMLUnknown ---------- //
1288 
1289 XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc )
1290 {
1291 }
1292 
1293 
1295 {
1296 }
1297 
1298 
1299 char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1300 {
1301  // Unknown parses as text.
1302  p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1303  if ( !p ) {
1305  }
1306  return p;
1307 }
1308 
1309 
1310 XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const
1311 {
1312  if ( !doc ) {
1313  doc = _document;
1314  }
1315  XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?
1316  return text;
1317 }
1318 
1319 
1320 bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
1321 {
1322  TIXMLASSERT( compare );
1323  const XMLUnknown* unknown = compare->ToUnknown();
1324  return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));
1325 }
1326 
1327 
1328 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
1329 {
1330  TIXMLASSERT( visitor );
1331  return visitor->Visit( *this );
1332 }
1333 
1334 // --------- XMLAttribute ---------- //
1335 
1336 const char* XMLAttribute::Name() const
1337 {
1338  return _name.GetStr();
1339 }
1340 
1341 const char* XMLAttribute::Value() const
1342 {
1343  return _value.GetStr();
1344 }
1345 
1346 char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )
1347 {
1348  // Parse using the name rules: bug fix, was using ParseText before
1349  p = _name.ParseName( p );
1350  if ( !p || !*p ) {
1351  return 0;
1352  }
1353 
1354  // Skip white space before =
1355  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1356  if ( *p != '=' ) {
1357  return 0;
1358  }
1359 
1360  ++p; // move up to opening quote
1361  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1362  if ( *p != '\"' && *p != '\'' ) {
1363  return 0;
1364  }
1365 
1366  char endTag[2] = { *p, 0 };
1367  ++p; // move past opening quote
1368 
1369  p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );
1370  return p;
1371 }
1372 
1373 
1374 void XMLAttribute::SetName( const char* n )
1375 {
1376  _name.SetStr( n );
1377 }
1378 
1379 
1380 XMLError XMLAttribute::QueryIntValue( int* value ) const
1381 {
1382  if ( XMLUtil::ToInt( Value(), value )) {
1383  return XML_SUCCESS;
1384  }
1385  return XML_WRONG_ATTRIBUTE_TYPE;
1386 }
1387 
1388 
1389 XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
1390 {
1391  if ( XMLUtil::ToUnsigned( Value(), value )) {
1392  return XML_SUCCESS;
1393  }
1394  return XML_WRONG_ATTRIBUTE_TYPE;
1395 }
1396 
1397 
1398 XMLError XMLAttribute::QueryInt64Value(int64_t* value) const
1399 {
1400  if (XMLUtil::ToInt64(Value(), value)) {
1401  return XML_SUCCESS;
1402  }
1403  return XML_WRONG_ATTRIBUTE_TYPE;
1404 }
1405 
1406 
1407 XMLError XMLAttribute::QueryBoolValue( bool* value ) const
1408 {
1409  if ( XMLUtil::ToBool( Value(), value )) {
1410  return XML_SUCCESS;
1411  }
1412  return XML_WRONG_ATTRIBUTE_TYPE;
1413 }
1414 
1415 
1416 XMLError XMLAttribute::QueryFloatValue( float* value ) const
1417 {
1418  if ( XMLUtil::ToFloat( Value(), value )) {
1419  return XML_SUCCESS;
1420  }
1421  return XML_WRONG_ATTRIBUTE_TYPE;
1422 }
1423 
1424 
1425 XMLError XMLAttribute::QueryDoubleValue( double* value ) const
1426 {
1427  if ( XMLUtil::ToDouble( Value(), value )) {
1428  return XML_SUCCESS;
1429  }
1430  return XML_WRONG_ATTRIBUTE_TYPE;
1431 }
1432 
1433 
1434 void XMLAttribute::SetAttribute( const char* v )
1435 {
1436  _value.SetStr( v );
1437 }
1438 
1439 
1440 void XMLAttribute::SetAttribute( int v )
1441 {
1442  char buf[BUF_SIZE];
1443  XMLUtil::ToStr( v, buf, BUF_SIZE );
1444  _value.SetStr( buf );
1445 }
1446 
1447 
1448 void XMLAttribute::SetAttribute( unsigned v )
1449 {
1450  char buf[BUF_SIZE];
1451  XMLUtil::ToStr( v, buf, BUF_SIZE );
1452  _value.SetStr( buf );
1453 }
1454 
1455 
1456 void XMLAttribute::SetAttribute(int64_t v)
1457 {
1458  char buf[BUF_SIZE];
1459  XMLUtil::ToStr(v, buf, BUF_SIZE);
1460  _value.SetStr(buf);
1461 }
1462 
1463 
1464 
1465 void XMLAttribute::SetAttribute( bool v )
1466 {
1467  char buf[BUF_SIZE];
1468  XMLUtil::ToStr( v, buf, BUF_SIZE );
1469  _value.SetStr( buf );
1470 }
1471 
1472 void XMLAttribute::SetAttribute( double v )
1473 {
1474  char buf[BUF_SIZE];
1475  XMLUtil::ToStr( v, buf, BUF_SIZE );
1476  _value.SetStr( buf );
1477 }
1478 
1479 void XMLAttribute::SetAttribute( float v )
1480 {
1481  char buf[BUF_SIZE];
1482  XMLUtil::ToStr( v, buf, BUF_SIZE );
1483  _value.SetStr( buf );
1484 }
1485 
1486 
1487 // --------- XMLElement ---------- //
1488 XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ),
1489  _closingType( OPEN ),
1490  _rootAttribute( 0 )
1491 {
1492 }
1493 
1494 
1495 XMLElement::~XMLElement()
1496 {
1497  while( _rootAttribute ) {
1498  XMLAttribute* next = _rootAttribute->_next;
1499  DeleteAttribute( _rootAttribute );
1500  _rootAttribute = next;
1501  }
1502 }
1503 
1504 
1505 const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
1506 {
1507  for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {
1508  if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1509  return a;
1510  }
1511  }
1512  return 0;
1513 }
1514 
1515 
1516 const char* XMLElement::Attribute( const char* name, const char* value ) const
1517 {
1518  const XMLAttribute* a = FindAttribute( name );
1519  if ( !a ) {
1520  return 0;
1521  }
1522  if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
1523  return a->Value();
1524  }
1525  return 0;
1526 }
1527 
1528 int XMLElement::IntAttribute(const char* name, int defaultValue) const
1529 {
1530  int i = defaultValue;
1531  QueryIntAttribute(name, &i);
1532  return i;
1533 }
1534 
1535 unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const
1536 {
1537  unsigned i = defaultValue;
1538  QueryUnsignedAttribute(name, &i);
1539  return i;
1540 }
1541 
1542 int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const
1543 {
1544  int64_t i = defaultValue;
1545  QueryInt64Attribute(name, &i);
1546  return i;
1547 }
1548 
1549 bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const
1550 {
1551  bool b = defaultValue;
1552  QueryBoolAttribute(name, &b);
1553  return b;
1554 }
1555 
1556 double XMLElement::DoubleAttribute(const char* name, double defaultValue) const
1557 {
1558  double d = defaultValue;
1559  QueryDoubleAttribute(name, &d);
1560  return d;
1561 }
1562 
1563 float XMLElement::FloatAttribute(const char* name, float defaultValue) const
1564 {
1565  float f = defaultValue;
1566  QueryFloatAttribute(name, &f);
1567  return f;
1568 }
1569 
1570 const char* XMLElement::GetText() const
1571 {
1572  if ( FirstChild() && FirstChild()->ToText() ) {
1573  return FirstChild()->Value();
1574  }
1575  return 0;
1576 }
1577 
1578 
1579 void XMLElement::SetText( const char* inText )
1580 {
1581  if ( FirstChild() && FirstChild()->ToText() )
1582  FirstChild()->SetValue( inText );
1583  else {
1584  XMLText* theText = GetDocument()->NewText( inText );
1585  InsertFirstChild( theText );
1586  }
1587 }
1588 
1589 
1590 void XMLElement::SetText( int v )
1591 {
1592  char buf[BUF_SIZE];
1593  XMLUtil::ToStr( v, buf, BUF_SIZE );
1594  SetText( buf );
1595 }
1596 
1597 
1598 void XMLElement::SetText( unsigned v )
1599 {
1600  char buf[BUF_SIZE];
1601  XMLUtil::ToStr( v, buf, BUF_SIZE );
1602  SetText( buf );
1603 }
1604 
1605 
1606 void XMLElement::SetText(int64_t v)
1607 {
1608  char buf[BUF_SIZE];
1609  XMLUtil::ToStr(v, buf, BUF_SIZE);
1610  SetText(buf);
1611 }
1612 
1613 
1614 void XMLElement::SetText( bool v )
1615 {
1616  char buf[BUF_SIZE];
1617  XMLUtil::ToStr( v, buf, BUF_SIZE );
1618  SetText( buf );
1619 }
1620 
1621 
1622 void XMLElement::SetText( float v )
1623 {
1624  char buf[BUF_SIZE];
1625  XMLUtil::ToStr( v, buf, BUF_SIZE );
1626  SetText( buf );
1627 }
1628 
1629 
1630 void XMLElement::SetText( double v )
1631 {
1632  char buf[BUF_SIZE];
1633  XMLUtil::ToStr( v, buf, BUF_SIZE );
1634  SetText( buf );
1635 }
1636 
1637 
1638 XMLError XMLElement::QueryIntText( int* ival ) const
1639 {
1640  if ( FirstChild() && FirstChild()->ToText() ) {
1641  const char* t = FirstChild()->Value();
1642  if ( XMLUtil::ToInt( t, ival ) ) {
1643  return XML_SUCCESS;
1644  }
1645  return XML_CAN_NOT_CONVERT_TEXT;
1646  }
1647  return XML_NO_TEXT_NODE;
1648 }
1649 
1650 
1651 XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const
1652 {
1653  if ( FirstChild() && FirstChild()->ToText() ) {
1654  const char* t = FirstChild()->Value();
1655  if ( XMLUtil::ToUnsigned( t, uval ) ) {
1656  return XML_SUCCESS;
1657  }
1658  return XML_CAN_NOT_CONVERT_TEXT;
1659  }
1660  return XML_NO_TEXT_NODE;
1661 }
1662 
1663 
1664 XMLError XMLElement::QueryInt64Text(int64_t* ival) const
1665 {
1666  if (FirstChild() && FirstChild()->ToText()) {
1667  const char* t = FirstChild()->Value();
1668  if (XMLUtil::ToInt64(t, ival)) {
1669  return XML_SUCCESS;
1670  }
1671  return XML_CAN_NOT_CONVERT_TEXT;
1672  }
1673  return XML_NO_TEXT_NODE;
1674 }
1675 
1676 
1677 XMLError XMLElement::QueryBoolText( bool* bval ) const
1678 {
1679  if ( FirstChild() && FirstChild()->ToText() ) {
1680  const char* t = FirstChild()->Value();
1681  if ( XMLUtil::ToBool( t, bval ) ) {
1682  return XML_SUCCESS;
1683  }
1684  return XML_CAN_NOT_CONVERT_TEXT;
1685  }
1686  return XML_NO_TEXT_NODE;
1687 }
1688 
1689 
1690 XMLError XMLElement::QueryDoubleText( double* dval ) const
1691 {
1692  if ( FirstChild() && FirstChild()->ToText() ) {
1693  const char* t = FirstChild()->Value();
1694  if ( XMLUtil::ToDouble( t, dval ) ) {
1695  return XML_SUCCESS;
1696  }
1697  return XML_CAN_NOT_CONVERT_TEXT;
1698  }
1699  return XML_NO_TEXT_NODE;
1700 }
1701 
1702 
1703 XMLError XMLElement::QueryFloatText( float* fval ) const
1704 {
1705  if ( FirstChild() && FirstChild()->ToText() ) {
1706  const char* t = FirstChild()->Value();
1707  if ( XMLUtil::ToFloat( t, fval ) ) {
1708  return XML_SUCCESS;
1709  }
1710  return XML_CAN_NOT_CONVERT_TEXT;
1711  }
1712  return XML_NO_TEXT_NODE;
1713 }
1714 
1715 int XMLElement::IntText(int defaultValue) const
1716 {
1717  int i = defaultValue;
1718  QueryIntText(&i);
1719  return i;
1720 }
1721 
1722 unsigned XMLElement::UnsignedText(unsigned defaultValue) const
1723 {
1724  unsigned i = defaultValue;
1725  QueryUnsignedText(&i);
1726  return i;
1727 }
1728 
1729 int64_t XMLElement::Int64Text(int64_t defaultValue) const
1730 {
1731  int64_t i = defaultValue;
1732  QueryInt64Text(&i);
1733  return i;
1734 }
1735 
1736 bool XMLElement::BoolText(bool defaultValue) const
1737 {
1738  bool b = defaultValue;
1739  QueryBoolText(&b);
1740  return b;
1741 }
1742 
1743 double XMLElement::DoubleText(double defaultValue) const
1744 {
1745  double d = defaultValue;
1746  QueryDoubleText(&d);
1747  return d;
1748 }
1749 
1750 float XMLElement::FloatText(float defaultValue) const
1751 {
1752  float f = defaultValue;
1753  QueryFloatText(&f);
1754  return f;
1755 }
1756 
1757 
1758 XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name )
1759 {
1760  XMLAttribute* last = 0;
1761  XMLAttribute* attrib = 0;
1762  for( attrib = _rootAttribute;
1763  attrib;
1764  last = attrib, attrib = attrib->_next ) {
1765  if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1766  break;
1767  }
1768  }
1769  if ( !attrib ) {
1770  attrib = CreateAttribute();
1771  TIXMLASSERT( attrib );
1772  if ( last ) {
1773  TIXMLASSERT( last->_next == 0 );
1774  last->_next = attrib;
1775  }
1776  else {
1777  TIXMLASSERT( _rootAttribute == 0 );
1778  _rootAttribute = attrib;
1779  }
1780  attrib->SetName( name );
1781  }
1782  return attrib;
1783 }
1784 
1785 
1786 void XMLElement::DeleteAttribute( const char* name )
1787 {
1788  XMLAttribute* prev = 0;
1789  for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
1790  if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1791  if ( prev ) {
1792  prev->_next = a->_next;
1793  }
1794  else {
1795  _rootAttribute = a->_next;
1796  }
1797  DeleteAttribute( a );
1798  break;
1799  }
1800  prev = a;
1801  }
1802 }
1803 
1804 
1805 char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
1806 {
1807  XMLAttribute* prevAttribute = 0;
1808 
1809  // Read the attributes.
1810  while( p ) {
1811  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1812  if ( !(*p) ) {
1813  _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() );
1814  return 0;
1815  }
1816 
1817  // attribute.
1818  if (XMLUtil::IsNameStartChar( *p ) ) {
1819  XMLAttribute* attrib = CreateAttribute();
1820  TIXMLASSERT( attrib );
1821  attrib->_parseLineNum = _document->_parseCurLineNum;
1822 
1823  int attrLineNum = attrib->_parseLineNum;
1824 
1825  p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );
1826  if ( !p || Attribute( attrib->Name() ) ) {
1827  DeleteAttribute( attrib );
1828  _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() );
1829  return 0;
1830  }
1831  // There is a minor bug here: if the attribute in the source xml
1832  // document is duplicated, it will not be detected and the
1833  // attribute will be doubly added. However, tracking the 'prevAttribute'
1834  // avoids re-scanning the attribute list. Preferring performance for
1835  // now, may reconsider in the future.
1836  if ( prevAttribute ) {
1837  TIXMLASSERT( prevAttribute->_next == 0 );
1838  prevAttribute->_next = attrib;
1839  }
1840  else {
1841  TIXMLASSERT( _rootAttribute == 0 );
1842  _rootAttribute = attrib;
1843  }
1844  prevAttribute = attrib;
1845  }
1846  // end of the tag
1847  else if ( *p == '>' ) {
1848  ++p;
1849  break;
1850  }
1851  // end of the tag
1852  else if ( *p == '/' && *(p+1) == '>' ) {
1853  _closingType = CLOSED;
1854  return p+2; // done; sealed element.
1855  }
1856  else {
1858  return 0;
1859  }
1860  }
1861  return p;
1862 }
1863 
1864 void XMLElement::DeleteAttribute( XMLAttribute* attribute )
1865 {
1866  if ( attribute == 0 ) {
1867  return;
1868  }
1869  MemPool* pool = attribute->_memPool;
1870  attribute->~XMLAttribute();
1871  pool->Free( attribute );
1872 }
1873 
1874 XMLAttribute* XMLElement::CreateAttribute()
1875 {
1876  TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
1877  XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1878  TIXMLASSERT( attrib );
1879  attrib->_memPool = &_document->_attributePool;
1880  attrib->_memPool->SetTracked();
1881  return attrib;
1882 }
1883 
1884 //
1885 // <ele></ele>
1886 // <ele>foo<b>bar</b></ele>
1887 //
1888 char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
1889 {
1890  // Read the element name.
1891  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1892 
1893  // The closing element is the </element> form. It is
1894  // parsed just like a regular element then deleted from
1895  // the DOM.
1896  if ( *p == '/' ) {
1897  _closingType = CLOSING;
1898  ++p;
1899  }
1900 
1901  p = _value.ParseName( p );
1902  if ( _value.Empty() ) {
1903  return 0;
1904  }
1905 
1906  p = ParseAttributes( p, curLineNumPtr );
1907  if ( !p || !*p || _closingType != OPEN ) {
1908  return p;
1909  }
1910 
1911  p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr );
1912  return p;
1913 }
1914 
1915 
1916 
1917 XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const
1918 {
1919  if ( !doc ) {
1920  doc = _document;
1921  }
1922  XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?
1923  for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
1924  element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?
1925  }
1926  return element;
1927 }
1928 
1929 
1930 bool XMLElement::ShallowEqual( const XMLNode* compare ) const
1931 {
1932  TIXMLASSERT( compare );
1933  const XMLElement* other = compare->ToElement();
1934  if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {
1935 
1936  const XMLAttribute* a=FirstAttribute();
1937  const XMLAttribute* b=other->FirstAttribute();
1938 
1939  while ( a && b ) {
1940  if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
1941  return false;
1942  }
1943  a = a->Next();
1944  b = b->Next();
1945  }
1946  if ( a || b ) {
1947  // different count
1948  return false;
1949  }
1950  return true;
1951  }
1952  return false;
1953 }
1954 
1955 
1956 bool XMLElement::Accept( XMLVisitor* visitor ) const
1957 {
1958  TIXMLASSERT( visitor );
1959  if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
1960  for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
1961  if ( !node->Accept( visitor ) ) {
1962  break;
1963  }
1964  }
1965  }
1966  return visitor->VisitExit( *this );
1967 }
1968 
1969 
1970 // --------- XMLDocument ----------- //
1971 
1972 // Warning: List must match 'enum XMLError'
1973 const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = {
1974  "XML_SUCCESS",
1975  "XML_NO_ATTRIBUTE",
1976  "XML_WRONG_ATTRIBUTE_TYPE",
1977  "XML_ERROR_FILE_NOT_FOUND",
1978  "XML_ERROR_FILE_COULD_NOT_BE_OPENED",
1979  "XML_ERROR_FILE_READ_ERROR",
1980  "XML_ERROR_PARSING_ELEMENT",
1981  "XML_ERROR_PARSING_ATTRIBUTE",
1982  "XML_ERROR_PARSING_TEXT",
1983  "XML_ERROR_PARSING_CDATA",
1984  "XML_ERROR_PARSING_COMMENT",
1985  "XML_ERROR_PARSING_DECLARATION",
1986  "XML_ERROR_PARSING_UNKNOWN",
1987  "XML_ERROR_EMPTY_DOCUMENT",
1988  "XML_ERROR_MISMATCHED_ELEMENT",
1989  "XML_ERROR_PARSING",
1990  "XML_CAN_NOT_CONVERT_TEXT",
1991  "XML_NO_TEXT_NODE",
1992  "XML_ELEMENT_DEPTH_EXCEEDED"
1993 };
1994 
1995 
1996 XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :
1997  XMLNode( 0 ),
1998  _writeBOM( false ),
1999  _processEntities( processEntities ),
2000  _errorID(XML_SUCCESS),
2001  _whitespaceMode( whitespaceMode ),
2002  _errorStr(),
2003  _errorLineNum( 0 ),
2004  _charBuffer( 0 ),
2005  _parseCurLineNum( 0 ),
2006  _parsingDepth(0),
2007  _unlinked(),
2008  _elementPool(),
2009  _attributePool(),
2010  _textPool(),
2011  _commentPool()
2012 {
2013  // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
2014  _document = this;
2015 }
2016 
2017 
2019 {
2020  Clear();
2021 }
2022 
2023 
2024 void XMLDocument::MarkInUse(XMLNode* node)
2025 {
2026  TIXMLASSERT(node);
2027  TIXMLASSERT(node->_parent == 0);
2028 
2029  for (int i = 0; i < _unlinked.Size(); ++i) {
2030  if (node == _unlinked[i]) {
2031  _unlinked.SwapRemove(i);
2032  break;
2033  }
2034  }
2035 }
2036 
2037 void XMLDocument::Clear()
2038 {
2039  DeleteChildren();
2040  while( _unlinked.Size()) {
2041  DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete.
2042  }
2043 
2044 #ifdef TINYXML2_DEBUG
2045  const bool hadError = Error();
2046 #endif
2047  ClearError();
2048 
2049  delete [] _charBuffer;
2050  _charBuffer = 0;
2051  _parsingDepth = 0;
2052 
2053 #ifdef TINYXML2_DEBUG
2054  if ( !hadError ) {
2055  TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
2056  TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
2057  TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
2058  TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
2059  }
2060 #endif
2061 }
2062 
2063 
2064 void XMLDocument::DeepCopy(XMLDocument* target) const
2065 {
2066  TIXMLASSERT(target);
2067  if (target == this) {
2068  return; // technically success - a no-op.
2069  }
2070 
2071  target->Clear();
2072  for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {
2073  target->InsertEndChild(node->DeepClone(target));
2074  }
2075 }
2076 
2077 XMLElement* XMLDocument::NewElement( const char* name )
2078 {
2079  XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
2080  ele->SetName( name );
2081  return ele;
2082 }
2083 
2084 
2085 XMLComment* XMLDocument::NewComment( const char* str )
2086 {
2087  XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );
2088  comment->SetValue( str );
2089  return comment;
2090 }
2091 
2092 
2093 XMLText* XMLDocument::NewText( const char* str )
2094 {
2095  XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
2096  text->SetValue( str );
2097  return text;
2098 }
2099 
2100 
2101 XMLDeclaration* XMLDocument::NewDeclaration( const char* str )
2102 {
2103  XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
2104  dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
2105  return dec;
2106 }
2107 
2108 
2109 XMLUnknown* XMLDocument::NewUnknown( const char* str )
2110 {
2111  XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );
2112  unk->SetValue( str );
2113  return unk;
2114 }
2115 
2116 static FILE* callfopen( const char* filepath, const char* mode )
2117 {
2118  TIXMLASSERT( filepath );
2119  TIXMLASSERT( mode );
2120 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
2121  FILE* fp = 0;
2122  errno_t err = fopen_s( &fp, filepath, mode );
2123  if ( err ) {
2124  return 0;
2125  }
2126 #else
2127  FILE* fp = fopen( filepath, mode );
2128 #endif
2129  return fp;
2130 }
2131 
2132 void XMLDocument::DeleteNode( XMLNode* node ) {
2133  TIXMLASSERT( node );
2134  TIXMLASSERT(node->_document == this );
2135  if (node->_parent) {
2136  node->_parent->DeleteChild( node );
2137  }
2138  else {
2139  // Isn't in the tree.
2140  // Use the parent delete.
2141  // Also, we need to mark it tracked: we 'know'
2142  // it was never used.
2143  node->_memPool->SetTracked();
2144  // Call the static XMLNode version:
2145  XMLNode::DeleteNode(node);
2146  }
2147 }
2148 
2149 
2150 XMLError XMLDocument::LoadFile( const char* filename )
2151 {
2152  if ( !filename ) {
2153  TIXMLASSERT( false );
2154  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2155  return _errorID;
2156  }
2157 
2158  Clear();
2159  FILE* fp = callfopen( filename, "rb" );
2160  if ( !fp ) {
2161  SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename );
2162  return _errorID;
2163  }
2164  LoadFile( fp );
2165  fclose( fp );
2166  return _errorID;
2167 }
2168 
2169 // This is likely overengineered template art to have a check that unsigned long value incremented
2170 // by one still fits into size_t. If size_t type is larger than unsigned long type
2171 // (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit
2172 // -Wtype-limits warning. This piece makes the compiler select code with a check when a check
2173 // is useful and code with no check when a check is redundant depending on how size_t and unsigned long
2174 // types sizes relate to each other.
2175 template
2176 <bool = (sizeof(unsigned long) >= sizeof(size_t))>
2177 struct LongFitsIntoSizeTMinusOne {
2178  static bool Fits( unsigned long value )
2179  {
2180  return value < (size_t)-1;
2181  }
2182 };
2183 
2184 template <>
2185 struct LongFitsIntoSizeTMinusOne<false> {
2186  static bool Fits( unsigned long )
2187  {
2188  return true;
2189  }
2190 };
2191 
2192 XMLError XMLDocument::LoadFile( FILE* fp )
2193 {
2194  Clear();
2195 
2196  fseek( fp, 0, SEEK_SET );
2197  if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
2198  SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
2199  return _errorID;
2200  }
2201 
2202  fseek( fp, 0, SEEK_END );
2203  const long filelength = ftell( fp );
2204  fseek( fp, 0, SEEK_SET );
2205  if ( filelength == -1L ) {
2206  SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
2207  return _errorID;
2208  }
2209  TIXMLASSERT( filelength >= 0 );
2210 
2211  if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {
2212  // Cannot handle files which won't fit in buffer together with null terminator
2213  SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
2214  return _errorID;
2215  }
2216 
2217  if ( filelength == 0 ) {
2218  SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
2219  return _errorID;
2220  }
2221 
2222  const size_t size = filelength;
2223  TIXMLASSERT( _charBuffer == 0 );
2224  _charBuffer = new char[size+1];
2225  size_t read = fread( _charBuffer, 1, size, fp );
2226  if ( read != size ) {
2227  SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 );
2228  return _errorID;
2229  }
2230 
2231  _charBuffer[size] = 0;
2232 
2233  Parse();
2234  return _errorID;
2235 }
2236 
2237 
2238 XMLError XMLDocument::SaveFile( const char* filename, bool compact )
2239 {
2240  if ( !filename ) {
2241  TIXMLASSERT( false );
2242  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2243  return _errorID;
2244  }
2245 
2246  FILE* fp = callfopen( filename, "w" );
2247  if ( !fp ) {
2248  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename );
2249  return _errorID;
2250  }
2251  SaveFile(fp, compact);
2252  fclose( fp );
2253  return _errorID;
2254 }
2255 
2256 
2257 XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
2258 {
2259  // Clear any error from the last save, otherwise it will get reported
2260  // for *this* call.
2261  ClearError();
2262  XMLPrinter stream( fp, compact );
2263  Print( &stream );
2264  return _errorID;
2265 }
2266 
2267 
2268 XMLError XMLDocument::Parse( const char* p, size_t len )
2269 {
2270  Clear();
2271 
2272  if ( len == 0 || !p || !*p ) {
2273  SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
2274  return _errorID;
2275  }
2276  if ( len == (size_t)(-1) ) {
2277  len = strlen( p );
2278  }
2279  TIXMLASSERT( _charBuffer == 0 );
2280  _charBuffer = new char[ len+1 ];
2281  memcpy( _charBuffer, p, len );
2282  _charBuffer[len] = 0;
2283 
2284  Parse();
2285  if ( Error() ) {
2286  // clean up now essentially dangling memory.
2287  // and the parse fail can put objects in the
2288  // pools that are dead and inaccessible.
2289  DeleteChildren();
2290  _elementPool.Clear();
2291  _attributePool.Clear();
2292  _textPool.Clear();
2293  _commentPool.Clear();
2294  }
2295  return _errorID;
2296 }
2297 
2298 
2299 void XMLDocument::Print( XMLPrinter* streamer ) const
2300 {
2301  if ( streamer ) {
2302  Accept( streamer );
2303  }
2304  else {
2305  XMLPrinter stdoutStreamer( stdout );
2306  Accept( &stdoutStreamer );
2307  }
2308 }
2309 
2310 
2311 void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )
2312 {
2313  TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
2314  _errorID = error;
2315  _errorLineNum = lineNum;
2316  _errorStr.Reset();
2317 
2318  size_t BUFFER_SIZE = 1000;
2319  char* buffer = new char[BUFFER_SIZE];
2320 
2321  TIXMLASSERT(sizeof(error) <= sizeof(int));
2322  TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
2323 
2324  if (format) {
2325  size_t len = strlen(buffer);
2326  TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": ");
2327  len = strlen(buffer);
2328 
2329  va_list va;
2330  va_start(va, format);
2331  TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);
2332  va_end(va);
2333  }
2334  _errorStr.SetStr(buffer);
2335  delete[] buffer;
2336 }
2337 
2338 
2339 /*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)
2340 {
2341  TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );
2342  const char* errorName = _errorNames[errorID];
2343  TIXMLASSERT( errorName && errorName[0] );
2344  return errorName;
2345 }
2346 
2347 const char* XMLDocument::ErrorStr() const
2348 {
2349  return _errorStr.Empty() ? "" : _errorStr.GetStr();
2350 }
2351 
2352 
2353 void XMLDocument::PrintError() const
2354 {
2355  printf("%s\n", ErrorStr());
2356 }
2357 
2358 const char* XMLDocument::ErrorName() const
2359 {
2360  return ErrorIDToName(_errorID);
2361 }
2362 
2363 void XMLDocument::Parse()
2364 {
2365  TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
2366  TIXMLASSERT( _charBuffer );
2367  _parseCurLineNum = 1;
2368  _parseLineNum = 1;
2369  char* p = _charBuffer;
2370  p = XMLUtil::SkipWhiteSpace( p, &_parseCurLineNum );
2371  p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
2372  if ( !*p ) {
2373  SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 );
2374  return;
2375  }
2376  ParseDeep(p, 0, &_parseCurLineNum );
2377 }
2378 
2379 void XMLDocument::PushDepth()
2380 {
2381  _parsingDepth++;
2382  if (_parsingDepth == TINYXML2_MAX_ELEMENT_DEPTH) {
2383  SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." );
2384  }
2385 }
2386 
2387 void XMLDocument::PopDepth()
2388 {
2389  TIXMLASSERT(_parsingDepth > 0);
2390  --_parsingDepth;
2391 }
2392 
2393 XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
2394  _elementJustOpened( false ),
2395  _stack(),
2396  _firstElement( true ),
2397  _fp( file ),
2398  _depth( depth ),
2399  _textDepth( -1 ),
2400  _processEntities( true ),
2401  _compactMode( compact ),
2402  _buffer()
2403 {
2404  for( int i=0; i<ENTITY_RANGE; ++i ) {
2405  _entityFlag[i] = false;
2406  _restrictedEntityFlag[i] = false;
2407  }
2408  for( int i=0; i<NUM_ENTITIES; ++i ) {
2409  const char entityValue = entities[i].value;
2410  const unsigned char flagIndex = (unsigned char)entityValue;
2411  TIXMLASSERT( flagIndex < ENTITY_RANGE );
2412  _entityFlag[flagIndex] = true;
2413  }
2414  _restrictedEntityFlag[(unsigned char)'&'] = true;
2415  _restrictedEntityFlag[(unsigned char)'<'] = true;
2416  _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
2417  _buffer.Push( 0 );
2418 }
2419 
2420 
2421 void XMLPrinter::Print( const char* format, ... )
2422 {
2423  va_list va;
2424  va_start( va, format );
2425 
2426  if ( _fp ) {
2427  vfprintf( _fp, format, va );
2428  }
2429  else {
2430  const int len = TIXML_VSCPRINTF( format, va );
2431  // Close out and re-start the va-args
2432  va_end( va );
2433  TIXMLASSERT( len >= 0 );
2434  va_start( va, format );
2435  TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
2436  char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
2437  TIXML_VSNPRINTF( p, len+1, format, va );
2438  }
2439  va_end( va );
2440 }
2441 
2442 
2443 void XMLPrinter::Write( const char* data, size_t size )
2444 {
2445  if ( _fp ) {
2446  fwrite ( data , sizeof(char), size, _fp);
2447  }
2448  else {
2449  char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator.
2450  memcpy( p, data, size );
2451  p[size] = 0;
2452  }
2453 }
2454 
2455 
2456 void XMLPrinter::Putc( char ch )
2457 {
2458  if ( _fp ) {
2459  fputc ( ch, _fp);
2460  }
2461  else {
2462  char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator.
2463  p[0] = ch;
2464  p[1] = 0;
2465  }
2466 }
2467 
2468 
2469 void XMLPrinter::PrintSpace( int depth )
2470 {
2471  for( int i=0; i<depth; ++i ) {
2472  Write( " " );
2473  }
2474 }
2475 
2476 
2477 void XMLPrinter::PrintString( const char* p, bool restricted )
2478 {
2479  // Look for runs of bytes between entities to print.
2480  const char* q = p;
2481 
2482  if ( _processEntities ) {
2483  const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
2484  while ( *q ) {
2485  TIXMLASSERT( p <= q );
2486  // Remember, char is sometimes signed. (How many times has that bitten me?)
2487  if ( *q > 0 && *q < ENTITY_RANGE ) {
2488  // Check for entities. If one is found, flush
2489  // the stream up until the entity, write the
2490  // entity, and keep looking.
2491  if ( flag[(unsigned char)(*q)] ) {
2492  while ( p < q ) {
2493  const size_t delta = q - p;
2494  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2495  Write( p, toPrint );
2496  p += toPrint;
2497  }
2498  bool entityPatternPrinted = false;
2499  for( int i=0; i<NUM_ENTITIES; ++i ) {
2500  if ( entities[i].value == *q ) {
2501  Putc( '&' );
2502  Write( entities[i].pattern, entities[i].length );
2503  Putc( ';' );
2504  entityPatternPrinted = true;
2505  break;
2506  }
2507  }
2508  if ( !entityPatternPrinted ) {
2509  // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
2510  TIXMLASSERT( false );
2511  }
2512  ++p;
2513  }
2514  }
2515  ++q;
2516  TIXMLASSERT( p <= q );
2517  }
2518  // Flush the remaining string. This will be the entire
2519  // string if an entity wasn't found.
2520  if ( p < q ) {
2521  const size_t delta = q - p;
2522  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2523  Write( p, toPrint );
2524  }
2525  }
2526  else {
2527  Write( p );
2528  }
2529 }
2530 
2531 
2532 void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
2533 {
2534  if ( writeBOM ) {
2535  static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
2536  Write( reinterpret_cast< const char* >( bom ) );
2537  }
2538  if ( writeDec ) {
2539  PushDeclaration( "xml version=\"1.0\"" );
2540  }
2541 }
2542 
2543 
2544 void XMLPrinter::OpenElement( const char* name, bool compactMode )
2545 {
2547  _stack.Push( name );
2548 
2549  if ( _textDepth < 0 && !_firstElement && !compactMode ) {
2550  Putc( '\n' );
2551  }
2552  if ( !compactMode ) {
2553  PrintSpace( _depth );
2554  }
2555 
2556  Write ( "<" );
2557  Write ( name );
2558 
2559  _elementJustOpened = true;
2560  _firstElement = false;
2561  ++_depth;
2562 }
2563 
2564 
2565 void XMLPrinter::PushAttribute( const char* name, const char* value )
2566 {
2568  Putc ( ' ' );
2569  Write( name );
2570  Write( "=\"" );
2571  PrintString( value, false );
2572  Putc ( '\"' );
2573 }
2574 
2575 
2576 void XMLPrinter::PushAttribute( const char* name, int v )
2577 {
2578  char buf[BUF_SIZE];
2579  XMLUtil::ToStr( v, buf, BUF_SIZE );
2580  PushAttribute( name, buf );
2581 }
2582 
2583 
2584 void XMLPrinter::PushAttribute( const char* name, unsigned v )
2585 {
2586  char buf[BUF_SIZE];
2587  XMLUtil::ToStr( v, buf, BUF_SIZE );
2588  PushAttribute( name, buf );
2589 }
2590 
2591 
2592 void XMLPrinter::PushAttribute(const char* name, int64_t v)
2593 {
2594  char buf[BUF_SIZE];
2595  XMLUtil::ToStr(v, buf, BUF_SIZE);
2596  PushAttribute(name, buf);
2597 }
2598 
2599 
2600 void XMLPrinter::PushAttribute( const char* name, bool v )
2601 {
2602  char buf[BUF_SIZE];
2603  XMLUtil::ToStr( v, buf, BUF_SIZE );
2604  PushAttribute( name, buf );
2605 }
2606 
2607 
2608 void XMLPrinter::PushAttribute( const char* name, double v )
2609 {
2610  char buf[BUF_SIZE];
2611  XMLUtil::ToStr( v, buf, BUF_SIZE );
2612  PushAttribute( name, buf );
2613 }
2614 
2615 
2616 void XMLPrinter::CloseElement( bool compactMode )
2617 {
2618  --_depth;
2619  const char* name = _stack.Pop();
2620 
2621  if ( _elementJustOpened ) {
2622  Write( "/>" );
2623  }
2624  else {
2625  if ( _textDepth < 0 && !compactMode) {
2626  Putc( '\n' );
2627  PrintSpace( _depth );
2628  }
2629  Write ( "</" );
2630  Write ( name );
2631  Write ( ">" );
2632  }
2633 
2634  if ( _textDepth == _depth ) {
2635  _textDepth = -1;
2636  }
2637  if ( _depth == 0 && !compactMode) {
2638  Putc( '\n' );
2639  }
2640  _elementJustOpened = false;
2641 }
2642 
2643 
2645 {
2646  if ( !_elementJustOpened ) {
2647  return;
2648  }
2649  _elementJustOpened = false;
2650  Putc( '>' );
2651 }
2652 
2653 
2654 void XMLPrinter::PushText( const char* text, bool cdata )
2655 {
2656  _textDepth = _depth-1;
2657 
2659  if ( cdata ) {
2660  Write( "<![CDATA[" );
2661  Write( text );
2662  Write( "]]>" );
2663  }
2664  else {
2665  PrintString( text, true );
2666  }
2667 }
2668 
2669 void XMLPrinter::PushText( int64_t value )
2670 {
2671  char buf[BUF_SIZE];
2672  XMLUtil::ToStr( value, buf, BUF_SIZE );
2673  PushText( buf, false );
2674 }
2675 
2676 void XMLPrinter::PushText( int value )
2677 {
2678  char buf[BUF_SIZE];
2679  XMLUtil::ToStr( value, buf, BUF_SIZE );
2680  PushText( buf, false );
2681 }
2682 
2683 
2684 void XMLPrinter::PushText( unsigned value )
2685 {
2686  char buf[BUF_SIZE];
2687  XMLUtil::ToStr( value, buf, BUF_SIZE );
2688  PushText( buf, false );
2689 }
2690 
2691 
2692 void XMLPrinter::PushText( bool value )
2693 {
2694  char buf[BUF_SIZE];
2695  XMLUtil::ToStr( value, buf, BUF_SIZE );
2696  PushText( buf, false );
2697 }
2698 
2699 
2700 void XMLPrinter::PushText( float value )
2701 {
2702  char buf[BUF_SIZE];
2703  XMLUtil::ToStr( value, buf, BUF_SIZE );
2704  PushText( buf, false );
2705 }
2706 
2707 
2708 void XMLPrinter::PushText( double value )
2709 {
2710  char buf[BUF_SIZE];
2711  XMLUtil::ToStr( value, buf, BUF_SIZE );
2712  PushText( buf, false );
2713 }
2714 
2715 
2716 void XMLPrinter::PushComment( const char* comment )
2717 {
2719  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2720  Putc( '\n' );
2721  PrintSpace( _depth );
2722  }
2723  _firstElement = false;
2724 
2725  Write( "<!--" );
2726  Write( comment );
2727  Write( "-->" );
2728 }
2729 
2730 
2731 void XMLPrinter::PushDeclaration( const char* value )
2732 {
2734  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2735  Putc( '\n' );
2736  PrintSpace( _depth );
2737  }
2738  _firstElement = false;
2739 
2740  Write( "<?" );
2741  Write( value );
2742  Write( "?>" );
2743 }
2744 
2745 
2746 void XMLPrinter::PushUnknown( const char* value )
2747 {
2749  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2750  Putc( '\n' );
2751  PrintSpace( _depth );
2752  }
2753  _firstElement = false;
2754 
2755  Write( "<!" );
2756  Write( value );
2757  Putc( '>' );
2758 }
2759 
2760 
2761 bool XMLPrinter::VisitEnter( const XMLDocument& doc )
2762 {
2763  _processEntities = doc.ProcessEntities();
2764  if ( doc.HasBOM() ) {
2765  PushHeader( true, false );
2766  }
2767  return true;
2768 }
2769 
2770 
2771 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
2772 {
2773  const XMLElement* parentElem = 0;
2774  if ( element.Parent() ) {
2775  parentElem = element.Parent()->ToElement();
2776  }
2777  const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
2778  OpenElement( element.Name(), compactMode );
2779  while ( attribute ) {
2780  PushAttribute( attribute->Name(), attribute->Value() );
2781  attribute = attribute->Next();
2782  }
2783  return true;
2784 }
2785 
2786 
2787 bool XMLPrinter::VisitExit( const XMLElement& element )
2788 {
2789  CloseElement( CompactMode(element) );
2790  return true;
2791 }
2792 
2793 
2794 bool XMLPrinter::Visit( const XMLText& text )
2795 {
2796  PushText( text.Value(), text.CData() );
2797  return true;
2798 }
2799 
2800 
2801 bool XMLPrinter::Visit( const XMLComment& comment )
2802 {
2803  PushComment( comment.Value() );
2804  return true;
2805 }
2806 
2807 bool XMLPrinter::Visit( const XMLDeclaration& declaration )
2808 {
2809  PushDeclaration( declaration.Value() );
2810  return true;
2811 }
2812 
2813 
2814 bool XMLPrinter::Visit( const XMLUnknown& unknown )
2815 {
2816  PushUnknown( unknown.Value() );
2817  return true;
2818 }
2819 
2820 } // namespace tinyxml2
void SetValue(const char *val, bool staticMem=false)
Definition: tinyxml2.cpp:771
XMLError QueryInt64Attribute(const char *name, int64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1341
XMLError QueryIntValue(int *value) const
Definition: tinyxml2.cpp:1380
static const char * GetCharacterRef(const char *p, char *value, int *length)
Definition: tinyxml2.cpp:456
XMLComment(XMLDocument *doc)
Definition: tinyxml2.cpp:1192
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1137
XMLError QueryBoolAttribute(const char *name, bool *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1350
#define TIXMLASSERT(x)
Definition: tinyxml2.h:94
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2565
unsigned UnsignedAttribute(const char *name, unsigned defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1535
void SetInternedStr(const char *str)
Definition: tinyxml2.h:167
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:841
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1416
XMLText(XMLDocument *doc)
Definition: tinyxml2.h:1009
int IntAttribute(const char *name, int defaultValue=0) const
Definition: tinyxml2.cpp:1528
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2616
bool Empty() const
Definition: tinyxml2.h:163
static bool ToInt(const char *str, int *value)
Definition: tinyxml2.cpp:592
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1202
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:726
virtual bool Visit(const XMLText &text)
Visit a text node.
Definition: tinyxml2.cpp:2794
virtual bool CompactMode(const XMLElement &)
Definition: tinyxml2.h:2262
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:684
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:688
virtual ~XMLNode()
Definition: tinyxml2.cpp:755
XMLDocument * _document
Definition: tinyxml2.h:946
Whitespace WhitespaceMode() const
Definition: tinyxml2.h:1727
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1516
void Putc(char ch)
Definition: tinyxml2.cpp:2456
XMLText * NewText(const char *text)
Definition: tinyxml2.cpp:2093
void PushHeader(bool writeBOM, bool writeDeclaration)
Definition: tinyxml2.cpp:2532
static const char * SkipWhiteSpace(const char *p, int *curLineNumPtr)
Definition: tinyxml2.h:552
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1310
XMLError QueryUnsignedAttribute(const char *name, unsigned int *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1332
static bool ToInt64(const char *str, int64_t *value)
Definition: tinyxml2.cpp:645
void DeleteChildren()
Definition: tinyxml2.cpp:794
XMLComment * NewComment(const char *comment)
Definition: tinyxml2.cpp:2085
int64_t Int64Text(int64_t defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1729
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1272
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1251
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:813
XMLError QueryIntText(int *ival) const
Definition: tinyxml2.cpp:1638
int Size() const
Definition: tinyxml2.h:269
#define TIXML_SNPRINTF
Definition: tinyxml2.cpp:92
XMLNode * _firstChild
Definition: tinyxml2.h:951
static bool StringEqual(const char *p, const char *q, int nChar=INT_MAX)
Definition: tinyxml2.h:592
static bool ToUnsigned(const char *str, unsigned *value)
Definition: tinyxml2.cpp:600
const char * ErrorName() const
Definition: tinyxml2.cpp:2358
XMLError QueryBoolText(bool *bval) const
See QueryIntText()
Definition: tinyxml2.cpp:1677
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1956
static void SetBoolSerialization(const char *writeTrue, const char *writeFalse)
Definition: tinyxml2.cpp:375
static void ToStr(int v, char *buffer, int bufferSize)
Definition: tinyxml2.cpp:552
void Write(const char *data, size_t size)
Definition: tinyxml2.cpp:2443
friend class XMLDeclaration
Definition: tinyxml2.h:1660
friend class XMLUnknown
Definition: tinyxml2.h:1661
static const char * ReadBOM(const char *p, bool *hasBOM)
Definition: tinyxml2.cpp:385
XMLError QueryUnsignedText(unsigned *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1651
XMLUnknown(XMLDocument *doc)
Definition: tinyxml2.cpp:1289
void OpenElement(const char *name, bool compactMode=false)
Definition: tinyxml2.cpp:2544
static bool IsNameChar(unsigned char ch)
Definition: tinyxml2.h:585
XMLError QueryFloatAttribute(const char *name, float *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1366
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1389
XMLNode(XMLDocument *)
Definition: tinyxml2.cpp:742
void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:2132
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:761
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1328
static const char * ErrorIDToName(XMLError errorID)
Definition: tinyxml2.cpp:2339
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1262
void DeleteChild(XMLNode *node)
Definition: tinyxml2.cpp:828
void PushComment(const char *comment)
Add a comment.
Definition: tinyxml2.cpp:2716
virtual void PrintSpace(int depth)
Definition: tinyxml2.cpp:2469
friend class XMLElement
Definition: tinyxml2.h:669
void Push(T t)
Definition: tinyxml2.h:223
int IntText(int defaultValue=0) const
Definition: tinyxml2.cpp:1715
XMLError QueryDoubleAttribute(const char *name, double *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1358
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.cpp:2761
const char * GetStr()
Definition: tinyxml2.cpp:267
XMLNode * _lastChild
Definition: tinyxml2.h:952
XMLError QueryInt64Value(int64_t *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1398
float FloatText(float defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1750
char * Identify(char *p, XMLNode **node)
Definition: tinyxml2.cpp:656
XMLNode * DeepClone(XMLDocument *target) const
Definition: tinyxml2.cpp:781
void Set(char *start, char *end, int flags)
Definition: tinyxml2.h:152
XMLError QueryInt64Text(int64_t *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1664
const XMLElement * NextSiblingElement(const char *name=0) const
Get the next (right) sibling element of this node, with an optionally supplied name.
Definition: tinyxml2.cpp:964
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:1001
bool BoolText(bool defaultValue=false) const
See QueryIntText()
Definition: tinyxml2.cpp:1736
const char * Name() const
The name of the attribute.
Definition: tinyxml2.cpp:1336
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1930
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2224
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1213
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1888
return true
Definition: Openholo.cpp:434
fclose(infile)
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1320
char * ParseName(char *in)
Definition: tinyxml2.cpp:218
friend class XMLText
Definition: tinyxml2.h:1658
void MarkInUse(XMLNode *)
Definition: tinyxml2.cpp:2024
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1299
const char * Value() const
Definition: tinyxml2.cpp:763
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1818
static bool ToFloat(const char *str, float *value)
Definition: tinyxml2.cpp:627
const XMLElement * LastChildElement(const char *name=0) const
Definition: tinyxml2.cpp:952
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1231
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2654
XMLNode * _parent
Definition: tinyxml2.h:947
double DoubleText(double defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1743
static bool Fits(unsigned long value)
Definition: tinyxml2.cpp:2178
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1183
void SealElementIfJustOpened()
Definition: tinyxml2.cpp:2644
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:696
static bool ToDouble(const char *str, double *value)
Definition: tinyxml2.cpp:636
T * PushArr(int count)
Definition: tinyxml2.h:230
double DoubleAttribute(const char *name, double defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1556
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2077
#define TIXML_SSCANF
Definition: tinyxml2.cpp:100
void PushUnknown(const char *value)
Definition: tinyxml2.cpp:2746
int64_t Int64Attribute(const char *name, int64_t defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1542
const char * GetText() const
Definition: tinyxml2.cpp:1570
void SetAttribute(const char *value)
Set the attribute to a string value.
Definition: tinyxml2.cpp:1434
static bool IsWhiteSpace(char p)
Definition: tinyxml2.h:570
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:2238
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1175
unsigned UnsignedText(unsigned defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1722
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1251
virtual char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:988
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
Definition: tinyxml2.cpp:403
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1425
void TransferTo(StrPair *other)
Definition: tinyxml2.cpp:144
void Clear()
Clear the document, resetting it to the initial state.
Definition: tinyxml2.cpp:2037
void PrintError() const
A (trivial) utility function that prints the ErrorStr() to stdout.
Definition: tinyxml2.cpp:2353
static bool IsNameStartChar(unsigned char ch)
Definition: tinyxml2.h:574
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1407
XMLNode * _next
Definition: tinyxml2.h:955
XMLDeclaration * NewDeclaration(const char *text=0)
Definition: tinyxml2.cpp:2101
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2150
const char * ErrorStr() const
Definition: tinyxml2.cpp:2347
XMLUnknown * NewUnknown(const char *text)
Definition: tinyxml2.cpp:2109
float FloatAttribute(const char *name, float defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1563
XMLError QueryDoubleText(double *dval) const
See QueryIntText()
Definition: tinyxml2.cpp:1690
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2299
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1164
const char * Value() const
The value of the attribute.
Definition: tinyxml2.cpp:1341
XMLError Parse(const char *xml, size_t nBytes=(size_t)(-1))
Definition: tinyxml2.cpp:2268
XMLDeclaration(XMLDocument *doc)
Definition: tinyxml2.cpp:1240
XMLNode * _prev
Definition: tinyxml2.h:954
friend class XMLNode
Definition: tinyxml2.h:1657
const XMLAttribute * FindAttribute(const char *name) const
Query a specific attribute in the list.
Definition: tinyxml2.cpp:1505
void Print(const char *format,...)
Definition: tinyxml2.cpp:2421
friend class XMLComment
Definition: tinyxml2.h:1659
XMLError QueryIntAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1323
XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
Definition: tinyxml2.cpp:902
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1917
StrPair _value
Definition: tinyxml2.h:948
void DeleteAttribute(const char *name)
Definition: tinyxml2.cpp:1786
char * ParseText(char *in, const char *endTag, int strFlags, int *curLineNumPtr)
Definition: tinyxml2.cpp:193
static bool ToBool(const char *str, bool *value)
Definition: tinyxml2.cpp:608
DynArray< const char *, 10 > _stack
Definition: tinyxml2.h:2275
void DeepCopy(XMLDocument *target) const
Definition: tinyxml2.cpp:2064
XMLPrinter(FILE *file=0, bool compact=false, int depth=0)
Definition: tinyxml2.cpp:2393
void SetText(const char *inText)
Definition: tinyxml2.cpp:1579
const char * pattern
Definition: tinyxml2.cpp:123
bool BoolAttribute(const char *name, bool defaultValue=false) const
See IntAttribute()
Definition: tinyxml2.cpp:1549
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1146
void PushDeclaration(const char *value)
Definition: tinyxml2.cpp:2731
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:756
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1281
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:673
bool ProcessEntities() const
Definition: tinyxml2.h:1724
#define TIXML_VSNPRINTF
Definition: tinyxml2.cpp:93
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
void SetStr(const char *str, int flags=0)
Definition: tinyxml2.cpp:180
friend class XMLElement
Definition: tinyxml2.h:1654
XMLError QueryFloatText(float *fval) const
See QueryIntText()
Definition: tinyxml2.cpp:1703
XMLDocument(bool processEntities=true, Whitespace whitespaceMode=PRESERVE_WHITESPACE)
constructor
Definition: tinyxml2.cpp:1996
const XMLElement * PreviousSiblingElement(const char *name=0) const
Get the previous (left) sibling element of this node, with an optionally supplied name...
Definition: tinyxml2.cpp:976
virtual XMLNode * ShallowClone(XMLDocument *document) const =0
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:871
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1471
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1223