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 BT_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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  //
1036  // Multiple declarations are allowed but all declarations
1037  // must occur before anything else.
1038  //
1039  // Optimized due to a security test case. If the first node is
1040  // a declaration, and the last node is a declaration, then only
1041  // declarations have so far been addded.
1042  bool wellLocated = false;
1043 
1044  if (ToDocument()) {
1045  if (FirstChild()) {
1046  wellLocated =
1047  FirstChild() &&
1048  FirstChild()->ToDeclaration() &&
1049  LastChild() &&
1050  LastChild()->ToDeclaration();
1051  }
1052  else {
1053  wellLocated = true;
1054  }
1055  }
1056  if ( !wellLocated ) {
1057  _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());
1058  DeleteNode( node );
1059  break;
1060  }
1061  }
1062 
1063  XMLElement* ele = node->ToElement();
1064  if ( ele ) {
1065  // We read the end tag. Return it to the parent.
1066  if ( ele->ClosingType() == XMLElement::CLOSING ) {
1067  if ( parentEndTag ) {
1068  ele->_value.TransferTo( parentEndTag );
1069  }
1070  node->_memPool->SetTracked(); // created and then immediately deleted.
1071  DeleteNode( node );
1072  return p;
1073  }
1074 
1075  // Handle an end tag returned to this level.
1076  // And handle a bunch of annoying errors.
1077  bool mismatch = false;
1078  if ( endTag.Empty() ) {
1079  if ( ele->ClosingType() == XMLElement::OPEN ) {
1080  mismatch = true;
1081  }
1082  }
1083  else {
1084  if ( ele->ClosingType() != XMLElement::OPEN ) {
1085  mismatch = true;
1086  }
1087  else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {
1088  mismatch = true;
1089  }
1090  }
1091  if ( mismatch ) {
1092  _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());
1093  DeleteNode( node );
1094  break;
1095  }
1096  }
1097  InsertEndChild( node );
1098  }
1099  return 0;
1100 }
1101 
1102 /*static*/ void XMLNode::DeleteNode( XMLNode* node )
1103 {
1104  if ( node == 0 ) {
1105  return;
1106  }
1107  TIXMLASSERT(node->_document);
1108  if (!node->ToDocument()) {
1109  node->_document->MarkInUse(node);
1110  }
1111 
1112  MemPool* pool = node->_memPool;
1113  node->~XMLNode();
1114  pool->Free( node );
1115 }
1116 
1117 void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
1118 {
1119  TIXMLASSERT( insertThis );
1120  TIXMLASSERT( insertThis->_document == _document );
1121 
1122  if (insertThis->_parent) {
1123  insertThis->_parent->Unlink( insertThis );
1124  }
1125  else {
1126  insertThis->_document->MarkInUse(insertThis);
1127  insertThis->_memPool->SetTracked();
1128  }
1129 }
1130 
1131 const XMLElement* XMLNode::ToElementWithName( const char* name ) const
1132 {
1133  const XMLElement* element = this->ToElement();
1134  if ( element == 0 ) {
1135  return 0;
1136  }
1137  if ( name == 0 ) {
1138  return element;
1139  }
1140  if ( XMLUtil::StringEqual( element->Name(), name ) ) {
1141  return element;
1142  }
1143  return 0;
1144 }
1145 
1146 // --------- XMLText ---------- //
1147 char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1148 {
1149  if ( this->CData() ) {
1150  p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1151  if ( !p ) {
1153  }
1154  return p;
1155  }
1156  else {
1160  }
1161 
1162  p = _value.ParseText( p, "<", flags, curLineNumPtr );
1163  if ( p && *p ) {
1164  return p-1;
1165  }
1166  if ( !p ) {
1168  }
1169  }
1170  return 0;
1171 }
1172 
1173 
1175 {
1176  if ( !doc ) {
1177  doc = _document;
1178  }
1179  XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?
1180  text->SetCData( this->CData() );
1181  return text;
1182 }
1183 
1184 
1185 bool XMLText::ShallowEqual( const XMLNode* compare ) const
1186 {
1187  TIXMLASSERT( compare );
1188  const XMLText* text = compare->ToText();
1189  return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );
1190 }
1191 
1192 
1193 bool XMLText::Accept( XMLVisitor* visitor ) const
1194 {
1195  TIXMLASSERT( visitor );
1196  return visitor->Visit( *this );
1197 }
1198 
1199 
1200 // --------- XMLComment ---------- //
1201 
1203 {
1204 }
1205 
1206 
1208 {
1209 }
1210 
1211 
1212 char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1213 {
1214  // Comment parses as text.
1215  p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr );
1216  if ( p == 0 ) {
1218  }
1219  return p;
1220 }
1221 
1222 
1224 {
1225  if ( !doc ) {
1226  doc = _document;
1227  }
1228  XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?
1229  return comment;
1230 }
1231 
1232 
1233 bool XMLComment::ShallowEqual( const XMLNode* compare ) const
1234 {
1235  TIXMLASSERT( compare );
1236  const XMLComment* comment = compare->ToComment();
1237  return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));
1238 }
1239 
1240 
1241 bool XMLComment::Accept( XMLVisitor* visitor ) const
1242 {
1243  TIXMLASSERT( visitor );
1244  return visitor->Visit( *this );
1245 }
1246 
1247 
1248 // --------- XMLDeclaration ---------- //
1249 
1251 {
1252 }
1253 
1254 
1256 {
1257  //printf( "~XMLDeclaration\n" );
1258 }
1259 
1260 
1261 char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1262 {
1263  // Declaration parses as text.
1264  p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1265  if ( p == 0 ) {
1267  }
1268  return p;
1269 }
1270 
1271 
1273 {
1274  if ( !doc ) {
1275  doc = _document;
1276  }
1277  XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?
1278  return dec;
1279 }
1280 
1281 
1282 bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
1283 {
1284  TIXMLASSERT( compare );
1285  const XMLDeclaration* declaration = compare->ToDeclaration();
1286  return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));
1287 }
1288 
1289 
1290 
1291 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
1292 {
1293  TIXMLASSERT( visitor );
1294  return visitor->Visit( *this );
1295 }
1296 
1297 // --------- XMLUnknown ---------- //
1298 
1300 {
1301 }
1302 
1303 
1305 {
1306 }
1307 
1308 
1309 char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1310 {
1311  // Unknown parses as text.
1312  p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1313  if ( !p ) {
1315  }
1316  return p;
1317 }
1318 
1319 
1321 {
1322  if ( !doc ) {
1323  doc = _document;
1324  }
1325  XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?
1326  return text;
1327 }
1328 
1329 
1330 bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
1331 {
1332  TIXMLASSERT( compare );
1333  const XMLUnknown* unknown = compare->ToUnknown();
1334  return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));
1335 }
1336 
1337 
1338 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
1339 {
1340  TIXMLASSERT( visitor );
1341  return visitor->Visit( *this );
1342 }
1343 
1344 // --------- XMLAttribute ---------- //
1345 
1346 const char* XMLAttribute::Name() const
1347 {
1348  return _name.GetStr();
1349 }
1350 
1351 const char* XMLAttribute::Value() const
1352 {
1353  return _value.GetStr();
1354 }
1355 
1356 char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )
1357 {
1358  // Parse using the name rules: bug fix, was using ParseText before
1359  p = _name.ParseName( p );
1360  if ( !p || !*p ) {
1361  return 0;
1362  }
1363 
1364  // Skip white space before =
1365  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1366  if ( *p != '=' ) {
1367  return 0;
1368  }
1369 
1370  ++p; // move up to opening quote
1371  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1372  if ( *p != '\"' && *p != '\'' ) {
1373  return 0;
1374  }
1375 
1376  char endTag[2] = { *p, 0 };
1377  ++p; // move past opening quote
1378 
1379  p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );
1380  return p;
1381 }
1382 
1383 
1384 void XMLAttribute::SetName( const char* n )
1385 {
1386  _name.SetStr( n );
1387 }
1388 
1389 
1391 {
1392  if ( XMLUtil::ToInt( Value(), value )) {
1393  return XML_SUCCESS;
1394  }
1395  return XML_WRONG_ATTRIBUTE_TYPE;
1396 }
1397 
1398 
1399 XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
1400 {
1401  if ( XMLUtil::ToUnsigned( Value(), value )) {
1402  return XML_SUCCESS;
1403  }
1404  return XML_WRONG_ATTRIBUTE_TYPE;
1405 }
1406 
1407 
1409 {
1410  if (XMLUtil::ToInt64(Value(), value)) {
1411  return XML_SUCCESS;
1412  }
1413  return XML_WRONG_ATTRIBUTE_TYPE;
1414 }
1415 
1416 
1418 {
1419  if ( XMLUtil::ToBool( Value(), value )) {
1420  return XML_SUCCESS;
1421  }
1422  return XML_WRONG_ATTRIBUTE_TYPE;
1423 }
1424 
1425 
1427 {
1428  if ( XMLUtil::ToFloat( Value(), value )) {
1429  return XML_SUCCESS;
1430  }
1431  return XML_WRONG_ATTRIBUTE_TYPE;
1432 }
1433 
1434 
1436 {
1437  if ( XMLUtil::ToDouble( Value(), value )) {
1438  return XML_SUCCESS;
1439  }
1440  return XML_WRONG_ATTRIBUTE_TYPE;
1441 }
1442 
1443 
1444 void XMLAttribute::SetAttribute( const char* v )
1445 {
1446  _value.SetStr( v );
1447 }
1448 
1449 
1451 {
1452  char buf[BUF_SIZE];
1453  XMLUtil::ToStr( v, buf, BUF_SIZE );
1454  _value.SetStr( buf );
1455 }
1456 
1457 
1458 void XMLAttribute::SetAttribute( unsigned v )
1459 {
1460  char buf[BUF_SIZE];
1461  XMLUtil::ToStr( v, buf, BUF_SIZE );
1462  _value.SetStr( buf );
1463 }
1464 
1465 
1467 {
1468  char buf[BUF_SIZE];
1469  XMLUtil::ToStr(v, buf, BUF_SIZE);
1470  _value.SetStr(buf);
1471 }
1472 
1473 
1474 
1476 {
1477  char buf[BUF_SIZE];
1478  XMLUtil::ToStr( v, buf, BUF_SIZE );
1479  _value.SetStr( buf );
1480 }
1481 
1483 {
1484  char buf[BUF_SIZE];
1485  XMLUtil::ToStr( v, buf, BUF_SIZE );
1486  _value.SetStr( buf );
1487 }
1488 
1490 {
1491  char buf[BUF_SIZE];
1492  XMLUtil::ToStr( v, buf, BUF_SIZE );
1493  _value.SetStr( buf );
1494 }
1495 
1496 
1497 // --------- XMLElement ---------- //
1499  _closingType( OPEN ),
1500  _rootAttribute( 0 )
1501 {
1502 }
1503 
1504 
1506 {
1507  while( _rootAttribute ) {
1510  _rootAttribute = next;
1511  }
1512 }
1513 
1514 
1515 const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
1516 {
1517  for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {
1518  if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1519  return a;
1520  }
1521  }
1522  return 0;
1523 }
1524 
1525 
1526 const char* XMLElement::Attribute( const char* name, const char* value ) const
1527 {
1528  const XMLAttribute* a = FindAttribute( name );
1529  if ( !a ) {
1530  return 0;
1531  }
1532  if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
1533  return a->Value();
1534  }
1535  return 0;
1536 }
1537 
1538 int XMLElement::IntAttribute(const char* name, int defaultValue) const
1539 {
1540  int i = defaultValue;
1541  QueryIntAttribute(name, &i);
1542  return i;
1543 }
1544 
1545 unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const
1546 {
1547  unsigned i = defaultValue;
1548  QueryUnsignedAttribute(name, &i);
1549  return i;
1550 }
1551 
1552 int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const
1553 {
1554  int64_t i = defaultValue;
1555  QueryInt64Attribute(name, &i);
1556  return i;
1557 }
1558 
1559 bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const
1560 {
1561  bool b = defaultValue;
1562  QueryBoolAttribute(name, &b);
1563  return b;
1564 }
1565 
1566 double XMLElement::DoubleAttribute(const char* name, double defaultValue) const
1567 {
1568  double d = defaultValue;
1569  QueryDoubleAttribute(name, &d);
1570  return d;
1571 }
1572 
1573 float XMLElement::FloatAttribute(const char* name, float defaultValue) const
1574 {
1575  float f = defaultValue;
1576  QueryFloatAttribute(name, &f);
1577  return f;
1578 }
1579 
1580 const char* XMLElement::GetText() const
1581 {
1582  if ( FirstChild() && FirstChild()->ToText() ) {
1583  return FirstChild()->Value();
1584  }
1585  return 0;
1586 }
1587 
1588 
1589 void XMLElement::SetText( const char* inText )
1590 {
1591  if ( FirstChild() && FirstChild()->ToText() )
1592  FirstChild()->SetValue( inText );
1593  else {
1594  XMLText* theText = GetDocument()->NewText( inText );
1595  InsertFirstChild( theText );
1596  }
1597 }
1598 
1599 
1600 void XMLElement::SetText( int v )
1601 {
1602  char buf[BUF_SIZE];
1603  XMLUtil::ToStr( v, buf, BUF_SIZE );
1604  SetText( buf );
1605 }
1606 
1607 
1608 void XMLElement::SetText( unsigned v )
1609 {
1610  char buf[BUF_SIZE];
1611  XMLUtil::ToStr( v, buf, BUF_SIZE );
1612  SetText( buf );
1613 }
1614 
1615 
1616 void XMLElement::SetText(int64_t v)
1617 {
1618  char buf[BUF_SIZE];
1619  XMLUtil::ToStr(v, buf, BUF_SIZE);
1620  SetText(buf);
1621 }
1622 
1623 
1624 void XMLElement::SetText( bool v )
1625 {
1626  char buf[BUF_SIZE];
1627  XMLUtil::ToStr( v, buf, BUF_SIZE );
1628  SetText( buf );
1629 }
1630 
1631 
1632 void XMLElement::SetText( float v )
1633 {
1634  char buf[BUF_SIZE];
1635  XMLUtil::ToStr( v, buf, BUF_SIZE );
1636  SetText( buf );
1637 }
1638 
1639 
1640 void XMLElement::SetText( double v )
1641 {
1642  char buf[BUF_SIZE];
1643  XMLUtil::ToStr( v, buf, BUF_SIZE );
1644  SetText( buf );
1645 }
1646 
1647 
1649 {
1650  if ( FirstChild() && FirstChild()->ToText() ) {
1651  const char* t = FirstChild()->Value();
1652  if ( XMLUtil::ToInt( t, ival ) ) {
1653  return XML_SUCCESS;
1654  }
1655  return XML_CAN_NOT_CONVERT_TEXT;
1656  }
1657  return XML_NO_TEXT_NODE;
1658 }
1659 
1660 
1662 {
1663  if ( FirstChild() && FirstChild()->ToText() ) {
1664  const char* t = FirstChild()->Value();
1665  if ( XMLUtil::ToUnsigned( t, uval ) ) {
1666  return XML_SUCCESS;
1667  }
1668  return XML_CAN_NOT_CONVERT_TEXT;
1669  }
1670  return XML_NO_TEXT_NODE;
1671 }
1672 
1673 
1675 {
1676  if (FirstChild() && FirstChild()->ToText()) {
1677  const char* t = FirstChild()->Value();
1678  if (XMLUtil::ToInt64(t, ival)) {
1679  return XML_SUCCESS;
1680  }
1681  return XML_CAN_NOT_CONVERT_TEXT;
1682  }
1683  return XML_NO_TEXT_NODE;
1684 }
1685 
1686 
1688 {
1689  if ( FirstChild() && FirstChild()->ToText() ) {
1690  const char* t = FirstChild()->Value();
1691  if ( XMLUtil::ToBool( t, bval ) ) {
1692  return XML_SUCCESS;
1693  }
1694  return XML_CAN_NOT_CONVERT_TEXT;
1695  }
1696  return XML_NO_TEXT_NODE;
1697 }
1698 
1699 
1701 {
1702  if ( FirstChild() && FirstChild()->ToText() ) {
1703  const char* t = FirstChild()->Value();
1704  if ( XMLUtil::ToDouble( t, dval ) ) {
1705  return XML_SUCCESS;
1706  }
1707  return XML_CAN_NOT_CONVERT_TEXT;
1708  }
1709  return XML_NO_TEXT_NODE;
1710 }
1711 
1712 
1714 {
1715  if ( FirstChild() && FirstChild()->ToText() ) {
1716  const char* t = FirstChild()->Value();
1717  if ( XMLUtil::ToFloat( t, fval ) ) {
1718  return XML_SUCCESS;
1719  }
1720  return XML_CAN_NOT_CONVERT_TEXT;
1721  }
1722  return XML_NO_TEXT_NODE;
1723 }
1724 
1725 int XMLElement::IntText(int defaultValue) const
1726 {
1727  int i = defaultValue;
1728  QueryIntText(&i);
1729  return i;
1730 }
1731 
1732 unsigned XMLElement::UnsignedText(unsigned defaultValue) const
1733 {
1734  unsigned i = defaultValue;
1735  QueryUnsignedText(&i);
1736  return i;
1737 }
1738 
1739 int64_t XMLElement::Int64Text(int64_t defaultValue) const
1740 {
1741  int64_t i = defaultValue;
1742  QueryInt64Text(&i);
1743  return i;
1744 }
1745 
1746 bool XMLElement::BoolText(bool defaultValue) const
1747 {
1748  bool b = defaultValue;
1749  QueryBoolText(&b);
1750  return b;
1751 }
1752 
1753 double XMLElement::DoubleText(double defaultValue) const
1754 {
1755  double d = defaultValue;
1756  QueryDoubleText(&d);
1757  return d;
1758 }
1759 
1760 float XMLElement::FloatText(float defaultValue) const
1761 {
1762  float f = defaultValue;
1763  QueryFloatText(&f);
1764  return f;
1765 }
1766 
1767 
1769 {
1770  XMLAttribute* last = 0;
1771  XMLAttribute* attrib = 0;
1772  for( attrib = _rootAttribute;
1773  attrib;
1774  last = attrib, attrib = attrib->_next ) {
1775  if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1776  break;
1777  }
1778  }
1779  if ( !attrib ) {
1780  attrib = CreateAttribute();
1781  TIXMLASSERT( attrib );
1782  if ( last ) {
1783  TIXMLASSERT( last->_next == 0 );
1784  last->_next = attrib;
1785  }
1786  else {
1787  TIXMLASSERT( _rootAttribute == 0 );
1788  _rootAttribute = attrib;
1789  }
1790  attrib->SetName( name );
1791  }
1792  return attrib;
1793 }
1794 
1795 
1796 void XMLElement::DeleteAttribute( const char* name )
1797 {
1798  XMLAttribute* prev = 0;
1799  for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
1800  if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1801  if ( prev ) {
1802  prev->_next = a->_next;
1803  }
1804  else {
1805  _rootAttribute = a->_next;
1806  }
1807  DeleteAttribute( a );
1808  break;
1809  }
1810  prev = a;
1811  }
1812 }
1813 
1814 
1815 char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
1816 {
1817  XMLAttribute* prevAttribute = 0;
1818 
1819  // Read the attributes.
1820  while( p ) {
1821  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1822  if ( !(*p) ) {
1823  _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() );
1824  return 0;
1825  }
1826 
1827  // attribute.
1828  if (XMLUtil::IsNameStartChar( *p ) ) {
1829  XMLAttribute* attrib = CreateAttribute();
1830  TIXMLASSERT( attrib );
1832 
1833  int attrLineNum = attrib->_parseLineNum;
1834 
1835  p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );
1836  if ( !p || Attribute( attrib->Name() ) ) {
1837  DeleteAttribute( attrib );
1838  _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() );
1839  return 0;
1840  }
1841  // There is a minor bug here: if the attribute in the source xml
1842  // document is duplicated, it will not be detected and the
1843  // attribute will be doubly added. However, tracking the 'prevAttribute'
1844  // avoids re-scanning the attribute list. Preferring performance for
1845  // now, may reconsider in the future.
1846  if ( prevAttribute ) {
1847  TIXMLASSERT( prevAttribute->_next == 0 );
1848  prevAttribute->_next = attrib;
1849  }
1850  else {
1851  TIXMLASSERT( _rootAttribute == 0 );
1852  _rootAttribute = attrib;
1853  }
1854  prevAttribute = attrib;
1855  }
1856  // end of the tag
1857  else if ( *p == '>' ) {
1858  ++p;
1859  break;
1860  }
1861  // end of the tag
1862  else if ( *p == '/' && *(p+1) == '>' ) {
1863  _closingType = CLOSED;
1864  return p+2; // done; sealed element.
1865  }
1866  else {
1868  return 0;
1869  }
1870  }
1871  return p;
1872 }
1873 
1875 {
1876  if ( attribute == 0 ) {
1877  return;
1878  }
1879  MemPool* pool = attribute->_memPool;
1880  attribute->~XMLAttribute();
1881  pool->Free( attribute );
1882 }
1883 
1885 {
1886  TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
1887  XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1888  TIXMLASSERT( attrib );
1889  attrib->_memPool = &_document->_attributePool;
1890  attrib->_memPool->SetTracked();
1891  return attrib;
1892 }
1893 
1894 //
1895 // <ele></ele>
1896 // <ele>foo<b>bar</b></ele>
1897 //
1898 char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
1899 {
1900  // Read the element name.
1901  p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1902 
1903  // The closing element is the </element> form. It is
1904  // parsed just like a regular element then deleted from
1905  // the DOM.
1906  if ( *p == '/' ) {
1908  ++p;
1909  }
1910 
1911  p = _value.ParseName( p );
1912  if ( _value.Empty() ) {
1913  return 0;
1914  }
1915 
1916  p = ParseAttributes( p, curLineNumPtr );
1917  if ( !p || !*p || _closingType != OPEN ) {
1918  return p;
1919  }
1920 
1921  p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr );
1922  return p;
1923 }
1924 
1925 
1926 
1928 {
1929  if ( !doc ) {
1930  doc = _document;
1931  }
1932  XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?
1933  for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
1934  element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?
1935  }
1936  return element;
1937 }
1938 
1939 
1940 bool XMLElement::ShallowEqual( const XMLNode* compare ) const
1941 {
1942  TIXMLASSERT( compare );
1943  const XMLElement* other = compare->ToElement();
1944  if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {
1945 
1946  const XMLAttribute* a=FirstAttribute();
1947  const XMLAttribute* b=other->FirstAttribute();
1948 
1949  while ( a && b ) {
1950  if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
1951  return false;
1952  }
1953  a = a->Next();
1954  b = b->Next();
1955  }
1956  if ( a || b ) {
1957  // different count
1958  return false;
1959  }
1960  return true;
1961  }
1962  return false;
1963 }
1964 
1965 
1966 bool XMLElement::Accept( XMLVisitor* visitor ) const
1967 {
1968  TIXMLASSERT( visitor );
1969  if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
1970  for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
1971  if ( !node->Accept( visitor ) ) {
1972  break;
1973  }
1974  }
1975  }
1976  return visitor->VisitExit( *this );
1977 }
1978 
1979 
1980 // --------- XMLDocument ----------- //
1981 
1982 // Warning: List must match 'enum XMLError'
1984  "XML_SUCCESS",
1985  "XML_NO_ATTRIBUTE",
1986  "XML_WRONG_ATTRIBUTE_TYPE",
1987  "XML_ERROR_FILE_NOT_FOUND",
1988  "XML_ERROR_FILE_COULD_NOT_BE_OPENED",
1989  "XML_ERROR_FILE_READ_ERROR",
1990  "XML_ERROR_PARSING_ELEMENT",
1991  "XML_ERROR_PARSING_ATTRIBUTE",
1992  "XML_ERROR_PARSING_TEXT",
1993  "XML_ERROR_PARSING_CDATA",
1994  "XML_ERROR_PARSING_COMMENT",
1995  "XML_ERROR_PARSING_DECLARATION",
1996  "XML_ERROR_PARSING_UNKNOWN",
1997  "XML_ERROR_EMPTY_DOCUMENT",
1998  "XML_ERROR_MISMATCHED_ELEMENT",
1999  "XML_ERROR_PARSING",
2000  "XML_CAN_NOT_CONVERT_TEXT",
2001  "XML_NO_TEXT_NODE",
2002  "XML_ELEMENT_DEPTH_EXCEEDED"
2003 };
2004 
2005 
2006 XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :
2007  XMLNode( 0 ),
2008  _writeBOM( false ),
2009  _processEntities( processEntities ),
2010  _errorID(XML_SUCCESS),
2011  _whitespaceMode( whitespaceMode ),
2012  _errorStr(),
2013  _errorLineNum( 0 ),
2014  _charBuffer( 0 ),
2015  _parseCurLineNum( 0 ),
2016  _parsingDepth(0),
2017  _unlinked(),
2018  _elementPool(),
2019  _attributePool(),
2020  _textPool(),
2021  _commentPool()
2022 {
2023  // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
2024  _document = this;
2025 }
2026 
2027 
2029 {
2030  Clear();
2031 }
2032 
2033 
2035 {
2036  TIXMLASSERT(node);
2037  TIXMLASSERT(node->_parent == 0);
2038 
2039  for (int i = 0; i < _unlinked.Size(); ++i) {
2040  if (node == _unlinked[i]) {
2041  _unlinked.SwapRemove(i);
2042  break;
2043  }
2044  }
2045 }
2046 
2048 {
2049  DeleteChildren();
2050  while( _unlinked.Size()) {
2051  DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete.
2052  }
2053 
2054 #ifdef TINYXML2_DEBUG
2055  const bool hadError = Error();
2056 #endif
2057  ClearError();
2058 
2059  delete [] _charBuffer;
2060  _charBuffer = 0;
2061  _parsingDepth = 0;
2062 
2063 #if 0
2064  _textPool.Trace( "text" );
2065  _elementPool.Trace( "element" );
2066  _commentPool.Trace( "comment" );
2067  _attributePool.Trace( "attribute" );
2068 #endif
2069 
2070 #ifdef TINYXML2_DEBUG
2071  if ( !hadError ) {
2072  TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
2073  TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
2074  TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
2075  TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
2076  }
2077 #endif
2078 }
2079 
2080 
2082 {
2083  TIXMLASSERT(target);
2084  if (target == this) {
2085  return; // technically success - a no-op.
2086  }
2087 
2088  target->Clear();
2089  for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {
2090  target->InsertEndChild(node->DeepClone(target));
2091  }
2092 }
2093 
2095 {
2096  XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
2097  ele->SetName( name );
2098  return ele;
2099 }
2100 
2101 
2103 {
2104  XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );
2105  comment->SetValue( str );
2106  return comment;
2107 }
2108 
2109 
2110 XMLText* XMLDocument::NewText( const char* str )
2111 {
2112  XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
2113  text->SetValue( str );
2114  return text;
2115 }
2116 
2117 
2119 {
2120  XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
2121  dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
2122  return dec;
2123 }
2124 
2125 
2127 {
2128  XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );
2129  unk->SetValue( str );
2130  return unk;
2131 }
2132 
2133 static FILE* callfopen( const char* filepath, const char* mode )
2134 {
2135  TIXMLASSERT( filepath );
2136  TIXMLASSERT( mode );
2137 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
2138  FILE* fp = 0;
2139  errno_t err = fopen_s( &fp, filepath, mode );
2140  if ( err ) {
2141  return 0;
2142  }
2143 #else
2144  FILE* fp = fopen( filepath, mode );
2145 #endif
2146  return fp;
2147 }
2148 
2150  TIXMLASSERT( node );
2151  TIXMLASSERT(node->_document == this );
2152  if (node->_parent) {
2153  node->_parent->DeleteChild( node );
2154  }
2155  else {
2156  // Isn't in the tree.
2157  // Use the parent delete.
2158  // Also, we need to mark it tracked: we 'know'
2159  // it was never used.
2160  node->_memPool->SetTracked();
2161  // Call the static XMLNode version:
2162  XMLNode::DeleteNode(node);
2163  }
2164 }
2165 
2166 
2167 XMLError XMLDocument::LoadFile( const char* filename )
2168 {
2169  if ( !filename ) {
2170  TIXMLASSERT( false );
2171  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2172  return _errorID;
2173  }
2174 
2175  Clear();
2176  FILE* fp = callfopen( filename, "rb" );
2177  if ( !fp ) {
2178  SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename );
2179  return _errorID;
2180  }
2181  LoadFile( fp );
2182  fclose( fp );
2183  return _errorID;
2184 }
2185 
2186 // This is likely overengineered template art to have a check that unsigned long value incremented
2187 // by one still fits into size_t. If size_t type is larger than unsigned long type
2188 // (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit
2189 // -Wtype-limits warning. This piece makes the compiler select code with a check when a check
2190 // is useful and code with no check when a check is redundant depending on how size_t and unsigned long
2191 // types sizes relate to each other.
2192 template
2193 <bool = (sizeof(unsigned long) >= sizeof(size_t))>
2195  static bool Fits( unsigned long value )
2196  {
2197  return value < (size_t)-1;
2198  }
2199 };
2200 
2201 template <>
2203  static bool Fits( unsigned long )
2204  {
2205  return true;
2206  }
2207 };
2208 
2210 {
2211  Clear();
2212 
2213  fseek( fp, 0, SEEK_SET );
2214  if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
2216  return _errorID;
2217  }
2218 
2219  fseek( fp, 0, SEEK_END );
2220  const long filelength = ftell( fp );
2221  fseek( fp, 0, SEEK_SET );
2222  if ( filelength == -1L ) {
2224  return _errorID;
2225  }
2226  TIXMLASSERT( filelength >= 0 );
2227 
2228  if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {
2229  // Cannot handle files which won't fit in buffer together with null terminator
2231  return _errorID;
2232  }
2233 
2234  if ( filelength == 0 ) {
2236  return _errorID;
2237  }
2238 
2239  const size_t size = filelength;
2240  TIXMLASSERT( _charBuffer == 0 );
2241  _charBuffer = new char[size+1];
2242  size_t read = fread( _charBuffer, 1, size, fp );
2243  if ( read != size ) {
2245  return _errorID;
2246  }
2247 
2248  _charBuffer[size] = 0;
2249 
2250  Parse();
2251  return _errorID;
2252 }
2253 
2254 
2255 XMLError XMLDocument::SaveFile( const char* filename, bool compact )
2256 {
2257  if ( !filename ) {
2258  TIXMLASSERT( false );
2259  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2260  return _errorID;
2261  }
2262 
2263  FILE* fp = callfopen( filename, "w" );
2264  if ( !fp ) {
2265  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename );
2266  return _errorID;
2267  }
2268  SaveFile(fp, compact);
2269  fclose( fp );
2270  return _errorID;
2271 }
2272 
2273 
2274 XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
2275 {
2276  // Clear any error from the last save, otherwise it will get reported
2277  // for *this* call.
2278  ClearError();
2279  XMLPrinter stream( fp, compact );
2280  Print( &stream );
2281  return _errorID;
2282 }
2283 
2284 
2285 XMLError XMLDocument::Parse( const char* p, size_t len )
2286 {
2287  Clear();
2288 
2289  if ( len == 0 || !p || !*p ) {
2291  return _errorID;
2292  }
2293  if ( len == (size_t)(-1) ) {
2294  len = strlen( p );
2295  }
2296  TIXMLASSERT( _charBuffer == 0 );
2297  _charBuffer = new char[ len+1 ];
2298  memcpy( _charBuffer, p, len );
2299  _charBuffer[len] = 0;
2300 
2301  Parse();
2302  if ( Error() ) {
2303  // clean up now essentially dangling memory.
2304  // and the parse fail can put objects in the
2305  // pools that are dead and inaccessible.
2306  DeleteChildren();
2307  _elementPool.Clear();
2308  _attributePool.Clear();
2309  _textPool.Clear();
2310  _commentPool.Clear();
2311  }
2312  return _errorID;
2313 }
2314 
2315 
2316 void XMLDocument::Print( XMLPrinter* streamer ) const
2317 {
2318  if ( streamer ) {
2319  Accept( streamer );
2320  }
2321  else {
2322  XMLPrinter stdoutStreamer( stdout );
2323  Accept( &stdoutStreamer );
2324  }
2325 }
2326 
2327 
2328 void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )
2329 {
2330  TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
2331  _errorID = error;
2332  _errorLineNum = lineNum;
2333  _errorStr.Reset();
2334 
2335  size_t BUFFER_SIZE = 1000;
2336  char* buffer = new char[BUFFER_SIZE];
2337 
2338  TIXMLASSERT(sizeof(error) <= sizeof(int));
2339  TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
2340 
2341  if (format) {
2342  size_t len = strlen(buffer);
2343  TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": ");
2344  len = strlen(buffer);
2345 
2346  va_list va;
2347  va_start(va, format);
2348  TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);
2349  va_end(va);
2350  }
2351  _errorStr.SetStr(buffer);
2352  delete[] buffer;
2353 }
2354 
2355 
2356 /*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)
2357 {
2358  TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );
2359  const char* errorName = _errorNames[errorID];
2360  TIXMLASSERT( errorName && errorName[0] );
2361  return errorName;
2362 }
2363 
2364 const char* XMLDocument::ErrorStr() const
2365 {
2366  return _errorStr.Empty() ? "" : _errorStr.GetStr();
2367 }
2368 
2369 
2371 {
2372  printf("%s\n", ErrorStr());
2373 }
2374 
2375 const char* XMLDocument::ErrorName() const
2376 {
2377  return ErrorIDToName(_errorID);
2378 }
2379 
2381 {
2382  TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
2384  _parseCurLineNum = 1;
2385  _parseLineNum = 1;
2386  char* p = _charBuffer;
2388  p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
2389  if ( !*p ) {
2391  return;
2392  }
2393  ParseDeep(p, 0, &_parseCurLineNum );
2394 }
2395 
2397 {
2398  _parsingDepth++;
2400  SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." );
2401  }
2402 }
2403 
2405 {
2407  --_parsingDepth;
2408 }
2409 
2410 XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
2411  _elementJustOpened( false ),
2412  _stack(),
2413  _firstElement( true ),
2414  _fp( file ),
2415  _depth( depth ),
2416  _textDepth( -1 ),
2417  _processEntities( true ),
2418  _compactMode( compact ),
2419  _buffer()
2420 {
2421  for( int i=0; i<ENTITY_RANGE; ++i ) {
2422  _entityFlag[i] = false;
2423  _restrictedEntityFlag[i] = false;
2424  }
2425  for( int i=0; i<NUM_ENTITIES; ++i ) {
2426  const char entityValue = entities[i].value;
2427  const unsigned char flagIndex = (unsigned char)entityValue;
2428  TIXMLASSERT( flagIndex < ENTITY_RANGE );
2429  _entityFlag[flagIndex] = true;
2430  }
2431  _restrictedEntityFlag[(unsigned char)'&'] = true;
2432  _restrictedEntityFlag[(unsigned char)'<'] = true;
2433  _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
2434  _buffer.Push( 0 );
2435 }
2436 
2437 
2438 void XMLPrinter::Print( const char* format, ... )
2439 {
2440  va_list va;
2441  va_start( va, format );
2442 
2443  if ( _fp ) {
2444  vfprintf( _fp, format, va );
2445  }
2446  else {
2447  const int len = TIXML_VSCPRINTF( format, va );
2448  // Close out and re-start the va-args
2449  va_end( va );
2450  TIXMLASSERT( len >= 0 );
2451  va_start( va, format );
2452  TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
2453  char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
2454  TIXML_VSNPRINTF( p, len+1, format, va );
2455  }
2456  va_end( va );
2457 }
2458 
2459 
2460 void XMLPrinter::Write( const char* data, size_t size )
2461 {
2462  if ( _fp ) {
2463  fwrite ( data , sizeof(char), size, _fp);
2464  }
2465  else {
2466  char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator.
2467  memcpy( p, data, size );
2468  p[size] = 0;
2469  }
2470 }
2471 
2472 
2473 void XMLPrinter::Putc( char ch )
2474 {
2475  if ( _fp ) {
2476  fputc ( ch, _fp);
2477  }
2478  else {
2479  char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator.
2480  p[0] = ch;
2481  p[1] = 0;
2482  }
2483 }
2484 
2485 
2486 void XMLPrinter::PrintSpace( int depth )
2487 {
2488  for( int i=0; i<depth; ++i ) {
2489  Write( " " );
2490  }
2491 }
2492 
2493 
2494 void XMLPrinter::PrintString( const char* p, bool restricted )
2495 {
2496  // Look for runs of bytes between entities to print.
2497  const char* q = p;
2498 
2499  if ( _processEntities ) {
2500  const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
2501  while ( *q ) {
2502  TIXMLASSERT( p <= q );
2503  // Remember, char is sometimes signed. (How many times has that bitten me?)
2504  if ( *q > 0 && *q < ENTITY_RANGE ) {
2505  // Check for entities. If one is found, flush
2506  // the stream up until the entity, write the
2507  // entity, and keep looking.
2508  if ( flag[(unsigned char)(*q)] ) {
2509  while ( p < q ) {
2510  const size_t delta = q - p;
2511  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2512  Write( p, toPrint );
2513  p += toPrint;
2514  }
2515  bool entityPatternPrinted = false;
2516  for( int i=0; i<NUM_ENTITIES; ++i ) {
2517  if ( entities[i].value == *q ) {
2518  Putc( '&' );
2519  Write( entities[i].pattern, entities[i].length );
2520  Putc( ';' );
2521  entityPatternPrinted = true;
2522  break;
2523  }
2524  }
2525  if ( !entityPatternPrinted ) {
2526  // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
2527  TIXMLASSERT( false );
2528  }
2529  ++p;
2530  }
2531  }
2532  ++q;
2533  TIXMLASSERT( p <= q );
2534  }
2535  // Flush the remaining string. This will be the entire
2536  // string if an entity wasn't found.
2537  if ( p < q ) {
2538  const size_t delta = q - p;
2539  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2540  Write( p, toPrint );
2541  }
2542  }
2543  else {
2544  Write( p );
2545  }
2546 }
2547 
2548 
2549 void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
2550 {
2551  if ( writeBOM ) {
2552  static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
2553  Write( reinterpret_cast< const char* >( bom ) );
2554  }
2555  if ( writeDec ) {
2556  PushDeclaration( "xml version=\"1.0\"" );
2557  }
2558 }
2559 
2560 
2561 void XMLPrinter::OpenElement( const char* name, bool compactMode )
2562 {
2564  _stack.Push( name );
2565 
2566  if ( _textDepth < 0 && !_firstElement && !compactMode ) {
2567  Putc( '\n' );
2568  }
2569  if ( !compactMode ) {
2570  PrintSpace( _depth );
2571  }
2572 
2573  Write ( "<" );
2574  Write ( name );
2575 
2576  _elementJustOpened = true;
2577  _firstElement = false;
2578  ++_depth;
2579 }
2580 
2581 
2582 void XMLPrinter::PushAttribute( const char* name, const char* value )
2583 {
2585  Putc ( ' ' );
2586  Write( name );
2587  Write( "=\"" );
2588  PrintString( value, false );
2589  Putc ( '\"' );
2590 }
2591 
2592 
2593 void XMLPrinter::PushAttribute( const char* name, int v )
2594 {
2595  char buf[BUF_SIZE];
2596  XMLUtil::ToStr( v, buf, BUF_SIZE );
2597  PushAttribute( name, buf );
2598 }
2599 
2600 
2601 void XMLPrinter::PushAttribute( const char* name, unsigned v )
2602 {
2603  char buf[BUF_SIZE];
2604  XMLUtil::ToStr( v, buf, BUF_SIZE );
2605  PushAttribute( name, buf );
2606 }
2607 
2608 
2609 void XMLPrinter::PushAttribute(const char* name, int64_t v)
2610 {
2611  char buf[BUF_SIZE];
2612  XMLUtil::ToStr(v, buf, BUF_SIZE);
2613  PushAttribute(name, buf);
2614 }
2615 
2616 
2617 void XMLPrinter::PushAttribute( const char* name, bool v )
2618 {
2619  char buf[BUF_SIZE];
2620  XMLUtil::ToStr( v, buf, BUF_SIZE );
2621  PushAttribute( name, buf );
2622 }
2623 
2624 
2625 void XMLPrinter::PushAttribute( const char* name, double v )
2626 {
2627  char buf[BUF_SIZE];
2628  XMLUtil::ToStr( v, buf, BUF_SIZE );
2629  PushAttribute( name, buf );
2630 }
2631 
2632 
2633 void XMLPrinter::CloseElement( bool compactMode )
2634 {
2635  --_depth;
2636  const char* name = _stack.Pop();
2637 
2638  if ( _elementJustOpened ) {
2639  Write( "/>" );
2640  }
2641  else {
2642  if ( _textDepth < 0 && !compactMode) {
2643  Putc( '\n' );
2644  PrintSpace( _depth );
2645  }
2646  Write ( "</" );
2647  Write ( name );
2648  Write ( ">" );
2649  }
2650 
2651  if ( _textDepth == _depth ) {
2652  _textDepth = -1;
2653  }
2654  if ( _depth == 0 && !compactMode) {
2655  Putc( '\n' );
2656  }
2657  _elementJustOpened = false;
2658 }
2659 
2660 
2662 {
2663  if ( !_elementJustOpened ) {
2664  return;
2665  }
2666  _elementJustOpened = false;
2667  Putc( '>' );
2668 }
2669 
2670 
2671 void XMLPrinter::PushText( const char* text, bool cdata )
2672 {
2673  _textDepth = _depth-1;
2674 
2676  if ( cdata ) {
2677  Write( "<![CDATA[" );
2678  Write( text );
2679  Write( "]]>" );
2680  }
2681  else {
2682  PrintString( text, true );
2683  }
2684 }
2685 
2686 void XMLPrinter::PushText( int64_t value )
2687 {
2688  char buf[BUF_SIZE];
2689  XMLUtil::ToStr( value, buf, BUF_SIZE );
2690  PushText( buf, false );
2691 }
2692 
2693 void XMLPrinter::PushText( int value )
2694 {
2695  char buf[BUF_SIZE];
2696  XMLUtil::ToStr( value, buf, BUF_SIZE );
2697  PushText( buf, false );
2698 }
2699 
2700 
2701 void XMLPrinter::PushText( unsigned value )
2702 {
2703  char buf[BUF_SIZE];
2704  XMLUtil::ToStr( value, buf, BUF_SIZE );
2705  PushText( buf, false );
2706 }
2707 
2708 
2709 void XMLPrinter::PushText( bool value )
2710 {
2711  char buf[BUF_SIZE];
2712  XMLUtil::ToStr( value, buf, BUF_SIZE );
2713  PushText( buf, false );
2714 }
2715 
2716 
2717 void XMLPrinter::PushText( float value )
2718 {
2719  char buf[BUF_SIZE];
2720  XMLUtil::ToStr( value, buf, BUF_SIZE );
2721  PushText( buf, false );
2722 }
2723 
2724 
2725 void XMLPrinter::PushText( double value )
2726 {
2727  char buf[BUF_SIZE];
2728  XMLUtil::ToStr( value, buf, BUF_SIZE );
2729  PushText( buf, false );
2730 }
2731 
2732 
2733 void XMLPrinter::PushComment( const char* comment )
2734 {
2736  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2737  Putc( '\n' );
2738  PrintSpace( _depth );
2739  }
2740  _firstElement = false;
2741 
2742  Write( "<!--" );
2743  Write( comment );
2744  Write( "-->" );
2745 }
2746 
2747 
2748 void XMLPrinter::PushDeclaration( const char* value )
2749 {
2751  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2752  Putc( '\n' );
2753  PrintSpace( _depth );
2754  }
2755  _firstElement = false;
2756 
2757  Write( "<?" );
2758  Write( value );
2759  Write( "?>" );
2760 }
2761 
2762 
2763 void XMLPrinter::PushUnknown( const char* value )
2764 {
2766  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2767  Putc( '\n' );
2768  PrintSpace( _depth );
2769  }
2770  _firstElement = false;
2771 
2772  Write( "<!" );
2773  Write( value );
2774  Putc( '>' );
2775 }
2776 
2777 
2779 {
2781  if ( doc.HasBOM() ) {
2782  PushHeader( true, false );
2783  }
2784  return true;
2785 }
2786 
2787 
2788 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
2789 {
2790  const XMLElement* parentElem = 0;
2791  if ( element.Parent() ) {
2792  parentElem = element.Parent()->ToElement();
2793  }
2794  const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
2795  OpenElement( element.Name(), compactMode );
2796  while ( attribute ) {
2797  PushAttribute( attribute->Name(), attribute->Value() );
2798  attribute = attribute->Next();
2799  }
2800  return true;
2801 }
2802 
2803 
2804 bool XMLPrinter::VisitExit( const XMLElement& element )
2805 {
2806  CloseElement( CompactMode(element) );
2807  return true;
2808 }
2809 
2810 
2811 bool XMLPrinter::Visit( const XMLText& text )
2812 {
2813  PushText( text.Value(), text.CData() );
2814  return true;
2815 }
2816 
2817 
2818 bool XMLPrinter::Visit( const XMLComment& comment )
2819 {
2820  PushComment( comment.Value() );
2821  return true;
2822 }
2823 
2824 bool XMLPrinter::Visit( const XMLDeclaration& declaration )
2825 {
2826  PushDeclaration( declaration.Value() );
2827  return true;
2828 }
2829 
2830 
2831 bool XMLPrinter::Visit( const XMLUnknown& unknown )
2832 {
2833  PushUnknown( unknown.Value() );
2834  return true;
2835 }
2836 
2837 } // namespace tinyxml2
char * Identify(char *p, XMLNode **node)
Definition: tinyxml2.cpp:656
XMLError QueryUnsignedAttribute(const char *name, unsigned int *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1333
virtual XMLNode * ShallowClone(XMLDocument *document) const =0
static bool IsNameStartChar(unsigned char ch)
Definition: tinyxml2.h:575
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:693
void Print(const char *format,...)
Definition: tinyxml2.cpp:2438
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1174
const T * data(const std::vector< T, Alloc > &v)
Definition: flatbuffers.h:1108
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1338
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1330
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:814
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1429
static const char LINE_FEED
Definition: tinyxml2.cpp:104
XMLError QueryFloatAttribute(const char *name, float *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1367
XMLNode * _firstChild
Definition: tinyxml2.h:952
Whitespace WhitespaceMode() const
Definition: tinyxml2.h:1728
XMLPrinter(FILE *file=0, bool compact=false, int depth=0)
Definition: tinyxml2.cpp:2410
MemPool * _memPool
Definition: tinyxml2.h:961
XMLError QueryDoubleText(double *dval) const
See QueryIntText()
Definition: tinyxml2.cpp:1700
void PushComment(const char *comment)
Add a comment.
Definition: tinyxml2.cpp:2733
virtual void PrintSpace(int depth)
Definition: tinyxml2.cpp:2486
float FloatAttribute(const char *name, float defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1573
XMLDeclaration(XMLDocument *doc)
Definition: tinyxml2.cpp:1250
void PrintError() const
A (trivial) utility function that prints the ErrorStr() to stdout.
Definition: tinyxml2.cpp:2370
XMLError QueryIntAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1324
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1435
static const unsigned char TIXML_UTF_LEAD_0
Definition: tinyxml2.cpp:115
void PushDeclaration(const char *value)
Definition: tinyxml2.cpp:2748
void DeepCopy(XMLDocument *target) const
Definition: tinyxml2.cpp:2081
XMLAttribute * _next
Definition: tinyxml2.h:1238
static bool IsNameChar(unsigned char ch)
Definition: tinyxml2.h:586
DynArray< char, 20 > _buffer
Definition: tinyxml2.h:2295
void SetAttribute(const char *value)
Set the attribute to a string value.
Definition: tinyxml2.cpp:1444
const XMLNode * LastChild() const
Get the last child node, or null if none exists.
Definition: tinyxml2.h:780
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
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1261
virtual bool Visit(const XMLDeclaration &)
Visit a declaration.
Definition: tinyxml2.h:504
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2671
int64_t Int64Text(int64_t defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1739
static raw_event_t * buffer
Definition: minitrace.cpp:54
void PushHeader(bool writeBOM, bool writeDeclaration)
Definition: tinyxml2.cpp:2549
XMLError QueryFloatText(float *fval) const
See QueryIntText()
Definition: tinyxml2.cpp:1713
static bool ToInt64(const char *str, int64_t *value)
Definition: tinyxml2.cpp:645
static FILE * file
Definition: minitrace.cpp:59
const char * Value() const
Definition: tinyxml2.cpp:763
XMLDocument * _document
Definition: tinyxml2.h:947
void TransferTo(StrPair *other)
Definition: tinyxml2.cpp:144
const char * Value() const
The value of the attribute.
Definition: tinyxml2.cpp:1351
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1233
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1147
void MarkInUse(XMLNode *)
Definition: tinyxml2.cpp:2034
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2225
void SetStr(const char *str, int flags=0)
Definition: tinyxml2.cpp:180
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1309
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1320
const XMLNode * Parent() const
Get the parent of this node on the DOM.
Definition: tinyxml2.h:748
XMLComment(XMLDocument *doc)
Definition: tinyxml2.cpp:1202
virtual void SetTracked()=0
static const char DOUBLE_QUOTE
Definition: tinyxml2.cpp:109
XMLNode(XMLDocument *)
Definition: tinyxml2.cpp:742
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:871
const char * Name() const
The name of the attribute.
Definition: tinyxml2.cpp:1346
void Write(const char *data, size_t size)
Definition: tinyxml2.cpp:2460
XMLAttribute * FindOrCreateAttribute(const char *name)
Definition: tinyxml2.cpp:1768
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1185
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
virtual bool CompactMode(const XMLElement &)
Definition: tinyxml2.h:2263
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:490
bool ProcessEntities() const
Definition: tinyxml2.h:1725
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.cpp:2778
unsigned UnsignedAttribute(const char *name, unsigned defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1545
void DeleteAttribute(const char *name)
Definition: tinyxml2.cpp:1796
XMLDocument(bool processEntities=true, Whitespace whitespaceMode=PRESERVE_WHITESPACE)
constructor
Definition: tinyxml2.cpp:2006
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1417
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:486
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:762
virtual XMLUnknown * ToUnknown()
Safely cast to an Unknown, or null.
Definition: tinyxml2.h:705
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1898
static const Entity entities[NUM_ENTITIES]
Definition: tinyxml2.cpp:129
static const char * ErrorIDToName(XMLError errorID)
Definition: tinyxml2.cpp:2356
const XMLElement * ToElementWithName(const char *name) const
Definition: tinyxml2.cpp:1131
char * ParseText(char *in, const char *endTag, int strFlags, int *curLineNumPtr)
Definition: tinyxml2.cpp:193
XMLError QueryDoubleAttribute(const char *name, double *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1359
static const char * writeBoolFalse
Definition: tinyxml2.h:638
static bool StringEqual(const char *p, const char *q, int nChar=INT_MAX)
Definition: tinyxml2.h:593
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2094
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:726
void SetName(const char *str, bool staticMem=false)
Set the name of the element.
Definition: tinyxml2.h:1256
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:701
void SetText(const char *inText)
Definition: tinyxml2.cpp:1589
ElementClosingType _closingType
Definition: tinyxml2.h:1634
void SetCData(bool isCData)
Declare whether this should be CDATA or standard text.
Definition: tinyxml2.h:998
MemPoolT< sizeof(XMLText) > _textPool
Definition: tinyxml2.h:1891
static const unsigned char TIXML_UTF_LEAD_2
Definition: tinyxml2.cpp:117
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2167
virtual void Free(void *)=0
XMLElement(XMLDocument *doc)
Definition: tinyxml2.cpp:1498
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1272
#define TIXML_VSNPRINTF
Definition: tinyxml2.cpp:93
float FloatText(float defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1760
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1966
XMLError QueryInt64Value(int64_t *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1408
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:689
static bool ToBool(const char *str, bool *value)
Definition: tinyxml2.cpp:608
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1940
void SetError(XMLError error, int lineNum, const char *format,...)
Definition: tinyxml2.cpp:2328
static const char * writeBoolTrue
Definition: tinyxml2.h:637
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1193
static int TIXML_VSCPRINTF(const char *format, va_list va)
Definition: tinyxml2.cpp:94
bool Empty() const
Definition: tinyxml2.h:165
static const char CARRIAGE_RETURN
Definition: tinyxml2.cpp:106
bool HasBOM() const
Definition: tinyxml2.h:1735
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1819
T * PushArr(int count)
Definition: tinyxml2.h:232
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
void Clear()
Clear the document, resetting it to the initial state.
Definition: tinyxml2.cpp:2047
static void SetBoolSerialization(const char *writeTrue, const char *writeFalse)
Definition: tinyxml2.cpp:375
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:2255
static const char * SkipWhiteSpace(const char *p, int *curLineNumPtr)
Definition: tinyxml2.h:553
#define TIXML_SNPRINTF
Definition: tinyxml2.cpp:92
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1212
static const char * GetCharacterRef(const char *p, char *value, int *length)
Definition: tinyxml2.cpp:456
XMLNode * DeepClone(XMLDocument *target) const
Definition: tinyxml2.cpp:781
int Size() const
Definition: tinyxml2.h:271
XMLUnknown(XMLDocument *doc)
Definition: tinyxml2.cpp:1299
XMLNode * _lastChild
Definition: tinyxml2.h:953
static FILE * callfopen(const char *filepath, const char *mode)
Definition: tinyxml2.cpp:2133
static bool ToInt(const char *str, int *value)
Definition: tinyxml2.cpp:592
static const char SINGLE_QUOTE
Definition: tinyxml2.cpp:108
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2316
XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
Definition: tinyxml2.cpp:902
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1472
bool _entityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2292
char * ParseAttributes(char *p, int *curLineNumPtr)
Definition: tinyxml2.cpp:1815
XMLError QueryBoolText(bool *bval) const
See QueryIntText()
Definition: tinyxml2.cpp:1687
bool _restrictedEntityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2293
XMLComment * NewComment(const char *comment)
Definition: tinyxml2.cpp:2102
XMLError QueryInt64Attribute(const char *name, int64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1342
DynArray< XMLNode *, 10 > _unlinked
Definition: tinyxml2.h:1887
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1291
static bool ToFloat(const char *str, float *value)
Definition: tinyxml2.cpp:627
static bool ToDouble(const char *str, double *value)
Definition: tinyxml2.cpp:636
void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:2149
int64_t Int64Attribute(const char *name, int64_t defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1552
XMLText * NewText(const char *text)
Definition: tinyxml2.cpp:2110
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:674
XMLAttribute * _rootAttribute
Definition: tinyxml2.h:1638
void SetName(const char *name)
Definition: tinyxml2.cpp:1384
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1223
XMLAttribute * CreateAttribute()
Definition: tinyxml2.cpp:1884
char * ParseName(char *in)
Definition: tinyxml2.cpp:218
static bool ToUnsigned(const char *str, unsigned *value)
Definition: tinyxml2.cpp:600
void InsertChildPreamble(XMLNode *insertThis) const
Definition: tinyxml2.cpp:1117
ElementClosingType ClosingType() const
Definition: tinyxml2.h:1613
const char * GetStr()
Definition: tinyxml2.cpp:267
int IntText(int defaultValue=0) const
Definition: tinyxml2.cpp:1725
static void ToStr(int v, char *buffer, int bufferSize)
Definition: tinyxml2.cpp:552
XMLUnknown * NewUnknown(const char *text)
Definition: tinyxml2.cpp:2126
const XMLElement * LastChildElement(const char *name=0) const
Definition: tinyxml2.cpp:952
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2582
MemPoolT< sizeof(XMLAttribute) > _attributePool
Definition: tinyxml2.h:1890
int IntAttribute(const char *name, int defaultValue=0) const
Definition: tinyxml2.cpp:1538
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:685
#define TIXMLASSERT(x)
Definition: tinyxml2.h:94
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:697
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1426
XMLError QueryInt64Text(int64_t *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1674
XMLError QueryIntValue(int *value) const
Definition: tinyxml2.cpp:1390
virtual bool Visit(const XMLText &text)
Visit a text node.
Definition: tinyxml2.cpp:2811
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1147
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:1002
XMLDeclaration * NewDeclaration(const char *text=0)
Definition: tinyxml2.cpp:2118
XMLError QueryBoolAttribute(const char *name, bool *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1351
void PrintString(const char *, bool restrictedEntitySet)
Definition: tinyxml2.cpp:2494
XMLError QueryUnsignedText(unsigned *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1661
const char * GetText() const
Definition: tinyxml2.cpp:1580
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2633
DynArray< const char *, 10 > _stack
Definition: tinyxml2.h:2276
static const char * _errorNames[XML_ERROR_COUNT]
Definition: tinyxml2.h:1894
static bool IsWhiteSpace(char p)
Definition: tinyxml2.h:571
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1399
virtual char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:988
const char * ErrorStr() const
Definition: tinyxml2.cpp:2364
static const char CR
Definition: tinyxml2.cpp:107
void SetInternedStr(const char *str)
Definition: tinyxml2.h:169
void OpenElement(const char *name, bool compactMode=false)
Definition: tinyxml2.cpp:2561
const char * ErrorName() const
Definition: tinyxml2.cpp:2375
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1252
double DoubleAttribute(const char *name, double defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1566
XMLNode * _parent
Definition: tinyxml2.h:948
double DoubleText(double defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1753
static const char LF
Definition: tinyxml2.cpp:105
void DeleteChild(XMLNode *node)
Definition: tinyxml2.cpp:828
bool BoolText(bool defaultValue=false) const
See QueryIntText()
Definition: tinyxml2.cpp:1746
static const char * ReadBOM(const char *p, bool *hasBOM)
Definition: tinyxml2.cpp:385
void SetValue(const char *val, bool staticMem=false)
Definition: tinyxml2.cpp:771
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1526
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:757
XMLError QueryIntText(int *ival) const
Definition: tinyxml2.cpp:1648
bool BoolAttribute(const char *name, bool defaultValue=false) const
See IntAttribute()
Definition: tinyxml2.cpp:1559
#define TIXML_SSCANF
Definition: tinyxml2.cpp:100
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1927
static const unsigned char TIXML_UTF_LEAD_1
Definition: tinyxml2.cpp:116
void Unlink(XMLNode *child)
Definition: tinyxml2.cpp:804
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
Definition: tinyxml2.cpp:403
static const int NUM_ENTITIES
Definition: tinyxml2.cpp:128
static void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:1102
static const int TINYXML2_MAX_ELEMENT_DEPTH
Definition: tinyxml2.h:114
char * ParseDeep(char *p, bool processEntities, int *curLineNumPtr)
Definition: tinyxml2.cpp:1356
unsigned UnsignedText(unsigned defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1732
MemPoolT< sizeof(XMLElement) > _elementPool
Definition: tinyxml2.h:1889
static bool Fits(unsigned long value)
Definition: tinyxml2.cpp:2195
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1282
MemPoolT< sizeof(XMLComment) > _commentPool
Definition: tinyxml2.h:1892
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:841
const char * pattern
Definition: tinyxml2.cpp:123
const XMLAttribute * FindAttribute(const char *name) const
Query a specific attribute in the list.
Definition: tinyxml2.cpp:1515
void PushUnknown(const char *value)
Definition: tinyxml2.cpp:2763
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1241


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:25