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 
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  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 
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 
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 
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 
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 
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 
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 
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 
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 
1399 {
1400  if (XMLUtil::ToInt64(Value(), value)) {
1401  return XML_SUCCESS;
1402  }
1403  return XML_WRONG_ATTRIBUTE_TYPE;
1404 }
1405 
1406 
1408 {
1409  if ( XMLUtil::ToBool( Value(), value )) {
1410  return XML_SUCCESS;
1411  }
1412  return XML_WRONG_ATTRIBUTE_TYPE;
1413 }
1414 
1415 
1417 {
1418  if ( XMLUtil::ToFloat( Value(), value )) {
1419  return XML_SUCCESS;
1420  }
1421  return XML_WRONG_ATTRIBUTE_TYPE;
1422 }
1423 
1424 
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 
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 
1457 {
1458  char buf[BUF_SIZE];
1459  XMLUtil::ToStr(v, buf, BUF_SIZE);
1460  _value.SetStr(buf);
1461 }
1462 
1463 
1464 
1466 {
1467  char buf[BUF_SIZE];
1468  XMLUtil::ToStr( v, buf, BUF_SIZE );
1469  _value.SetStr( buf );
1470 }
1471 
1473 {
1474  char buf[BUF_SIZE];
1475  XMLUtil::ToStr( v, buf, BUF_SIZE );
1476  _value.SetStr( buf );
1477 }
1478 
1480 {
1481  char buf[BUF_SIZE];
1482  XMLUtil::ToStr( v, buf, BUF_SIZE );
1483  _value.SetStr( buf );
1484 }
1485 
1486 
1487 // --------- XMLElement ---------- //
1489  _closingType( OPEN ),
1490  _rootAttribute( 0 )
1491 {
1492 }
1493 
1494 
1496 {
1497  while( _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 
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 
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 
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 
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 
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 
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 
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 );
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 
1865 {
1866  if ( attribute == 0 ) {
1867  return;
1868  }
1869  MemPool* pool = attribute->_memPool;
1870  attribute->~XMLAttribute();
1871  pool->Free( attribute );
1872 }
1873 
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 == '/' ) {
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 
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'
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  "UNUSED_XML_ERROR_ELEMENT_MISMATCH",
1981  "XML_ERROR_PARSING_ELEMENT",
1982  "XML_ERROR_PARSING_ATTRIBUTE",
1983  "UNUSED_XML_ERROR_IDENTIFYING_TAG",
1984  "XML_ERROR_PARSING_TEXT",
1985  "XML_ERROR_PARSING_CDATA",
1986  "XML_ERROR_PARSING_COMMENT",
1987  "XML_ERROR_PARSING_DECLARATION",
1988  "XML_ERROR_PARSING_UNKNOWN",
1989  "XML_ERROR_EMPTY_DOCUMENT",
1990  "XML_ERROR_MISMATCHED_ELEMENT",
1991  "XML_ERROR_PARSING",
1992  "XML_CAN_NOT_CONVERT_TEXT",
1993  "XML_NO_TEXT_NODE",
1994  "XML_ELEMENT_DEPTH_EXCEEDED"
1995 };
1996 
1997 
1998 XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :
1999  XMLNode( 0 ),
2000  _writeBOM( false ),
2001  _processEntities( processEntities ),
2002  _errorID(XML_SUCCESS),
2003  _whitespaceMode( whitespaceMode ),
2004  _errorStr(),
2005  _errorLineNum( 0 ),
2006  _charBuffer( 0 ),
2007  _parseCurLineNum( 0 ),
2008  _parsingDepth(0),
2009  _unlinked(),
2010  _elementPool(),
2011  _attributePool(),
2012  _textPool(),
2013  _commentPool()
2014 {
2015  // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
2016  _document = this;
2017 }
2018 
2019 
2021 {
2022  Clear();
2023 }
2024 
2025 
2027 {
2028  TIXMLASSERT(node);
2029  TIXMLASSERT(node->_parent == 0);
2030 
2031  for (int i = 0; i < _unlinked.Size(); ++i) {
2032  if (node == _unlinked[i]) {
2033  _unlinked.SwapRemove(i);
2034  break;
2035  }
2036  }
2037 }
2038 
2040 {
2041  DeleteChildren();
2042  while( _unlinked.Size()) {
2043  DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete.
2044  }
2045 
2046 #ifdef TINYXML2_DEBUG
2047  const bool hadError = Error();
2048 #endif
2049  ClearError();
2050 
2051  delete [] _charBuffer;
2052  _charBuffer = 0;
2053  _parsingDepth = 0;
2054 
2055 #if 0
2056  _textPool.Trace( "text" );
2057  _elementPool.Trace( "element" );
2058  _commentPool.Trace( "comment" );
2059  _attributePool.Trace( "attribute" );
2060 #endif
2061 
2062 #ifdef TINYXML2_DEBUG
2063  if ( !hadError ) {
2064  TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
2065  TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
2066  TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
2067  TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
2068  }
2069 #endif
2070 }
2071 
2072 
2074 {
2075  TIXMLASSERT(target);
2076  if (target == this) {
2077  return; // technically success - a no-op.
2078  }
2079 
2080  target->Clear();
2081  for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {
2082  target->InsertEndChild(node->DeepClone(target));
2083  }
2084 }
2085 
2087 {
2088  XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
2089  ele->SetName( name );
2090  return ele;
2091 }
2092 
2093 
2095 {
2096  XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );
2097  comment->SetValue( str );
2098  return comment;
2099 }
2100 
2101 
2102 XMLText* XMLDocument::NewText( const char* str )
2103 {
2104  XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
2105  text->SetValue( str );
2106  return text;
2107 }
2108 
2109 
2111 {
2112  XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
2113  dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
2114  return dec;
2115 }
2116 
2117 
2119 {
2120  XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );
2121  unk->SetValue( str );
2122  return unk;
2123 }
2124 
2125 static FILE* callfopen( const char* filepath, const char* mode )
2126 {
2127  TIXMLASSERT( filepath );
2128  TIXMLASSERT( mode );
2129 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
2130  FILE* fp = 0;
2131  errno_t err = fopen_s( &fp, filepath, mode );
2132  if ( err ) {
2133  return 0;
2134  }
2135 #else
2136  FILE* fp = fopen( filepath, mode );
2137 #endif
2138  return fp;
2139 }
2140 
2142  TIXMLASSERT( node );
2143  TIXMLASSERT(node->_document == this );
2144  if (node->_parent) {
2145  node->_parent->DeleteChild( node );
2146  }
2147  else {
2148  // Isn't in the tree.
2149  // Use the parent delete.
2150  // Also, we need to mark it tracked: we 'know'
2151  // it was never used.
2152  node->_memPool->SetTracked();
2153  // Call the static XMLNode version:
2154  XMLNode::DeleteNode(node);
2155  }
2156 }
2157 
2158 
2159 XMLError XMLDocument::LoadFile( const char* filename )
2160 {
2161  if ( !filename ) {
2162  TIXMLASSERT( false );
2163  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2164  return _errorID;
2165  }
2166 
2167  Clear();
2168  FILE* fp = callfopen( filename, "rb" );
2169  if ( !fp ) {
2170  SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename );
2171  return _errorID;
2172  }
2173  LoadFile( fp );
2174  fclose( fp );
2175  return _errorID;
2176 }
2177 
2178 // This is likely overengineered template art to have a check that unsigned long value incremented
2179 // by one still fits into size_t. If size_t type is larger than unsigned long type
2180 // (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit
2181 // -Wtype-limits warning. This piece makes the compiler select code with a check when a check
2182 // is useful and code with no check when a check is redundant depending on how size_t and unsigned long
2183 // types sizes relate to each other.
2184 template
2185 <bool = (sizeof(unsigned long) >= sizeof(size_t))>
2187  static bool Fits( unsigned long value )
2188  {
2189  return value < (size_t)-1;
2190  }
2191 };
2192 
2193 template <>
2195  static bool Fits( unsigned long )
2196  {
2197  return true;
2198  }
2199 };
2200 
2202 {
2203  Clear();
2204 
2205  fseek( fp, 0, SEEK_SET );
2206  if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
2208  return _errorID;
2209  }
2210 
2211  fseek( fp, 0, SEEK_END );
2212  const long filelength = ftell( fp );
2213  fseek( fp, 0, SEEK_SET );
2214  if ( filelength == -1L ) {
2216  return _errorID;
2217  }
2218  TIXMLASSERT( filelength >= 0 );
2219 
2220  if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {
2221  // Cannot handle files which won't fit in buffer together with null terminator
2223  return _errorID;
2224  }
2225 
2226  if ( filelength == 0 ) {
2228  return _errorID;
2229  }
2230 
2231  const size_t size = filelength;
2232  TIXMLASSERT( _charBuffer == 0 );
2233  _charBuffer = new char[size+1];
2234  size_t read = fread( _charBuffer, 1, size, fp );
2235  if ( read != size ) {
2237  return _errorID;
2238  }
2239 
2240  _charBuffer[size] = 0;
2241 
2242  Parse();
2243  return _errorID;
2244 }
2245 
2246 
2247 XMLError XMLDocument::SaveFile( const char* filename, bool compact )
2248 {
2249  if ( !filename ) {
2250  TIXMLASSERT( false );
2251  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2252  return _errorID;
2253  }
2254 
2255  FILE* fp = callfopen( filename, "w" );
2256  if ( !fp ) {
2257  SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename );
2258  return _errorID;
2259  }
2260  SaveFile(fp, compact);
2261  fclose( fp );
2262  return _errorID;
2263 }
2264 
2265 
2266 XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
2267 {
2268  // Clear any error from the last save, otherwise it will get reported
2269  // for *this* call.
2270  ClearError();
2271  XMLPrinter stream( fp, compact );
2272  Print( &stream );
2273  return _errorID;
2274 }
2275 
2276 
2277 XMLError XMLDocument::Parse( const char* p, size_t len )
2278 {
2279  Clear();
2280 
2281  if ( len == 0 || !p || !*p ) {
2283  return _errorID;
2284  }
2285  if ( len == (size_t)(-1) ) {
2286  len = strlen( p );
2287  }
2288  TIXMLASSERT( _charBuffer == 0 );
2289  _charBuffer = new char[ len+1 ];
2290  memcpy( _charBuffer, p, len );
2291  _charBuffer[len] = 0;
2292 
2293  Parse();
2294  if ( Error() ) {
2295  // clean up now essentially dangling memory.
2296  // and the parse fail can put objects in the
2297  // pools that are dead and inaccessible.
2298  DeleteChildren();
2299  _elementPool.Clear();
2300  _attributePool.Clear();
2301  _textPool.Clear();
2302  _commentPool.Clear();
2303  }
2304  return _errorID;
2305 }
2306 
2307 
2308 void XMLDocument::Print( XMLPrinter* streamer ) const
2309 {
2310  if ( streamer ) {
2311  Accept( streamer );
2312  }
2313  else {
2314  XMLPrinter stdoutStreamer( stdout );
2315  Accept( &stdoutStreamer );
2316  }
2317 }
2318 
2319 
2320 void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )
2321 {
2322  TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
2323  _errorID = error;
2324  _errorLineNum = lineNum;
2325  _errorStr.Reset();
2326 
2327  size_t BUFFER_SIZE = 1000;
2328  char* buffer = new char[BUFFER_SIZE];
2329 
2330  TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
2331 
2332  if (format) {
2333  size_t len = strlen(buffer);
2334  TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": ");
2335  len = strlen(buffer);
2336 
2337  va_list va;
2338  va_start(va, format);
2339  TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);
2340  va_end(va);
2341  }
2342  _errorStr.SetStr(buffer);
2343  delete[] buffer;
2344 }
2345 
2346 
2347 /*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)
2348 {
2349  TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );
2350  const char* errorName = _errorNames[errorID];
2351  TIXMLASSERT( errorName && errorName[0] );
2352  return errorName;
2353 }
2354 
2355 const char* XMLDocument::ErrorStr() const
2356 {
2357  return _errorStr.Empty() ? "" : _errorStr.GetStr();
2358 }
2359 
2360 
2362 {
2363  printf("%s\n", ErrorStr());
2364 }
2365 
2366 const char* XMLDocument::ErrorName() const
2367 {
2368  return ErrorIDToName(_errorID);
2369 }
2370 
2372 {
2373  TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
2375  _parseCurLineNum = 1;
2376  _parseLineNum = 1;
2377  char* p = _charBuffer;
2379  p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
2380  if ( !*p ) {
2382  return;
2383  }
2384  ParseDeep(p, 0, &_parseCurLineNum );
2385 }
2386 
2388 {
2389  _parsingDepth++;
2391  SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." );
2392  }
2393 }
2394 
2396 {
2398  --_parsingDepth;
2399 }
2400 
2401 XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
2402  _elementJustOpened( false ),
2403  _stack(),
2404  _firstElement( true ),
2405  _fp( file ),
2406  _depth( depth ),
2407  _textDepth( -1 ),
2408  _processEntities( true ),
2409  _compactMode( compact ),
2410  _buffer()
2411 {
2412  for( int i=0; i<ENTITY_RANGE; ++i ) {
2413  _entityFlag[i] = false;
2414  _restrictedEntityFlag[i] = false;
2415  }
2416  for( int i=0; i<NUM_ENTITIES; ++i ) {
2417  const char entityValue = entities[i].value;
2418  const unsigned char flagIndex = (unsigned char)entityValue;
2419  TIXMLASSERT( flagIndex < ENTITY_RANGE );
2420  _entityFlag[flagIndex] = true;
2421  }
2422  _restrictedEntityFlag[(unsigned char)'&'] = true;
2423  _restrictedEntityFlag[(unsigned char)'<'] = true;
2424  _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
2425  _buffer.Push( 0 );
2426 }
2427 
2428 
2429 void XMLPrinter::Print( const char* format, ... )
2430 {
2431  va_list va;
2432  va_start( va, format );
2433 
2434  if ( _fp ) {
2435  vfprintf( _fp, format, va );
2436  }
2437  else {
2438  const int len = TIXML_VSCPRINTF( format, va );
2439  // Close out and re-start the va-args
2440  va_end( va );
2441  TIXMLASSERT( len >= 0 );
2442  va_start( va, format );
2443  TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
2444  char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
2445  TIXML_VSNPRINTF( p, len+1, format, va );
2446  }
2447  va_end( va );
2448 }
2449 
2450 
2451 void XMLPrinter::Write( const char* data, size_t size )
2452 {
2453  if ( _fp ) {
2454  fwrite ( data , sizeof(char), size, _fp);
2455  }
2456  else {
2457  char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator.
2458  memcpy( p, data, size );
2459  p[size] = 0;
2460  }
2461 }
2462 
2463 
2464 void XMLPrinter::Putc( char ch )
2465 {
2466  if ( _fp ) {
2467  fputc ( ch, _fp);
2468  }
2469  else {
2470  char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator.
2471  p[0] = ch;
2472  p[1] = 0;
2473  }
2474 }
2475 
2476 
2477 void XMLPrinter::PrintSpace( int depth )
2478 {
2479  for( int i=0; i<depth; ++i ) {
2480  Write( " " );
2481  }
2482 }
2483 
2484 
2485 void XMLPrinter::PrintString( const char* p, bool restricted )
2486 {
2487  // Look for runs of bytes between entities to print.
2488  const char* q = p;
2489 
2490  if ( _processEntities ) {
2491  const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
2492  while ( *q ) {
2493  TIXMLASSERT( p <= q );
2494  // Remember, char is sometimes signed. (How many times has that bitten me?)
2495  if ( *q > 0 && *q < ENTITY_RANGE ) {
2496  // Check for entities. If one is found, flush
2497  // the stream up until the entity, write the
2498  // entity, and keep looking.
2499  if ( flag[(unsigned char)(*q)] ) {
2500  while ( p < q ) {
2501  const size_t delta = q - p;
2502  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2503  Write( p, toPrint );
2504  p += toPrint;
2505  }
2506  bool entityPatternPrinted = false;
2507  for( int i=0; i<NUM_ENTITIES; ++i ) {
2508  if ( entities[i].value == *q ) {
2509  Putc( '&' );
2510  Write( entities[i].pattern, entities[i].length );
2511  Putc( ';' );
2512  entityPatternPrinted = true;
2513  break;
2514  }
2515  }
2516  if ( !entityPatternPrinted ) {
2517  // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
2518  TIXMLASSERT( false );
2519  }
2520  ++p;
2521  }
2522  }
2523  ++q;
2524  TIXMLASSERT( p <= q );
2525  }
2526  }
2527  // Flush the remaining string. This will be the entire
2528  // string if an entity wasn't found.
2529  TIXMLASSERT( p <= q );
2530  if ( !_processEntities || ( p < q ) ) {
2531  const size_t delta = q - p;
2532  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2533  Write( p, toPrint );
2534  }
2535 }
2536 
2537 
2538 void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
2539 {
2540  if ( writeBOM ) {
2541  static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
2542  Write( reinterpret_cast< const char* >( bom ) );
2543  }
2544  if ( writeDec ) {
2545  PushDeclaration( "xml version=\"1.0\"" );
2546  }
2547 }
2548 
2549 
2550 void XMLPrinter::OpenElement( const char* name, bool compactMode )
2551 {
2553  _stack.Push( name );
2554 
2555  if ( _textDepth < 0 && !_firstElement && !compactMode ) {
2556  Putc( '\n' );
2557  }
2558  if ( !compactMode ) {
2559  PrintSpace( _depth );
2560  }
2561 
2562  Write ( "<" );
2563  Write ( name );
2564 
2565  _elementJustOpened = true;
2566  _firstElement = false;
2567  ++_depth;
2568 }
2569 
2570 
2571 void XMLPrinter::PushAttribute( const char* name, const char* value )
2572 {
2574  Putc ( ' ' );
2575  Write( name );
2576  Write( "=\"" );
2577  PrintString( value, false );
2578  Putc ( '\"' );
2579 }
2580 
2581 
2582 void XMLPrinter::PushAttribute( const char* name, int v )
2583 {
2584  char buf[BUF_SIZE];
2585  XMLUtil::ToStr( v, buf, BUF_SIZE );
2586  PushAttribute( name, buf );
2587 }
2588 
2589 
2590 void XMLPrinter::PushAttribute( const char* name, unsigned v )
2591 {
2592  char buf[BUF_SIZE];
2593  XMLUtil::ToStr( v, buf, BUF_SIZE );
2594  PushAttribute( name, buf );
2595 }
2596 
2597 
2598 void XMLPrinter::PushAttribute(const char* name, int64_t v)
2599 {
2600  char buf[BUF_SIZE];
2601  XMLUtil::ToStr(v, buf, BUF_SIZE);
2602  PushAttribute(name, buf);
2603 }
2604 
2605 
2606 void XMLPrinter::PushAttribute( const char* name, bool v )
2607 {
2608  char buf[BUF_SIZE];
2609  XMLUtil::ToStr( v, buf, BUF_SIZE );
2610  PushAttribute( name, buf );
2611 }
2612 
2613 
2614 void XMLPrinter::PushAttribute( const char* name, double v )
2615 {
2616  char buf[BUF_SIZE];
2617  XMLUtil::ToStr( v, buf, BUF_SIZE );
2618  PushAttribute( name, buf );
2619 }
2620 
2621 
2622 void XMLPrinter::CloseElement( bool compactMode )
2623 {
2624  --_depth;
2625  const char* name = _stack.Pop();
2626 
2627  if ( _elementJustOpened ) {
2628  Write( "/>" );
2629  }
2630  else {
2631  if ( _textDepth < 0 && !compactMode) {
2632  Putc( '\n' );
2633  PrintSpace( _depth );
2634  }
2635  Write ( "</" );
2636  Write ( name );
2637  Write ( ">" );
2638  }
2639 
2640  if ( _textDepth == _depth ) {
2641  _textDepth = -1;
2642  }
2643  if ( _depth == 0 && !compactMode) {
2644  Putc( '\n' );
2645  }
2646  _elementJustOpened = false;
2647 }
2648 
2649 
2651 {
2652  if ( !_elementJustOpened ) {
2653  return;
2654  }
2655  _elementJustOpened = false;
2656  Putc( '>' );
2657 }
2658 
2659 
2660 void XMLPrinter::PushText( const char* text, bool cdata )
2661 {
2662  _textDepth = _depth-1;
2663 
2665  if ( cdata ) {
2666  Write( "<![CDATA[" );
2667  Write( text );
2668  Write( "]]>" );
2669  }
2670  else {
2671  PrintString( text, true );
2672  }
2673 }
2674 
2675 void XMLPrinter::PushText( int64_t value )
2676 {
2677  char buf[BUF_SIZE];
2678  XMLUtil::ToStr( value, buf, BUF_SIZE );
2679  PushText( buf, false );
2680 }
2681 
2682 void XMLPrinter::PushText( int value )
2683 {
2684  char buf[BUF_SIZE];
2685  XMLUtil::ToStr( value, buf, BUF_SIZE );
2686  PushText( buf, false );
2687 }
2688 
2689 
2690 void XMLPrinter::PushText( unsigned value )
2691 {
2692  char buf[BUF_SIZE];
2693  XMLUtil::ToStr( value, buf, BUF_SIZE );
2694  PushText( buf, false );
2695 }
2696 
2697 
2698 void XMLPrinter::PushText( bool value )
2699 {
2700  char buf[BUF_SIZE];
2701  XMLUtil::ToStr( value, buf, BUF_SIZE );
2702  PushText( buf, false );
2703 }
2704 
2705 
2706 void XMLPrinter::PushText( float value )
2707 {
2708  char buf[BUF_SIZE];
2709  XMLUtil::ToStr( value, buf, BUF_SIZE );
2710  PushText( buf, false );
2711 }
2712 
2713 
2714 void XMLPrinter::PushText( double value )
2715 {
2716  char buf[BUF_SIZE];
2717  XMLUtil::ToStr( value, buf, BUF_SIZE );
2718  PushText( buf, false );
2719 }
2720 
2721 
2722 void XMLPrinter::PushComment( const char* comment )
2723 {
2725  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2726  Putc( '\n' );
2727  PrintSpace( _depth );
2728  }
2729  _firstElement = false;
2730 
2731  Write( "<!--" );
2732  Write( comment );
2733  Write( "-->" );
2734 }
2735 
2736 
2737 void XMLPrinter::PushDeclaration( const char* value )
2738 {
2740  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2741  Putc( '\n' );
2742  PrintSpace( _depth );
2743  }
2744  _firstElement = false;
2745 
2746  Write( "<?" );
2747  Write( value );
2748  Write( "?>" );
2749 }
2750 
2751 
2752 void XMLPrinter::PushUnknown( const char* value )
2753 {
2755  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2756  Putc( '\n' );
2757  PrintSpace( _depth );
2758  }
2759  _firstElement = false;
2760 
2761  Write( "<!" );
2762  Write( value );
2763  Putc( '>' );
2764 }
2765 
2766 
2768 {
2770  if ( doc.HasBOM() ) {
2771  PushHeader( true, false );
2772  }
2773  return true;
2774 }
2775 
2776 
2777 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
2778 {
2779  const XMLElement* parentElem = 0;
2780  if ( element.Parent() ) {
2781  parentElem = element.Parent()->ToElement();
2782  }
2783  const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
2784  OpenElement( element.Name(), compactMode );
2785  while ( attribute ) {
2786  PushAttribute( attribute->Name(), attribute->Value() );
2787  attribute = attribute->Next();
2788  }
2789  return true;
2790 }
2791 
2792 
2793 bool XMLPrinter::VisitExit( const XMLElement& element )
2794 {
2795  CloseElement( CompactMode(element) );
2796  return true;
2797 }
2798 
2799 
2800 bool XMLPrinter::Visit( const XMLText& text )
2801 {
2802  PushText( text.Value(), text.CData() );
2803  return true;
2804 }
2805 
2806 
2807 bool XMLPrinter::Visit( const XMLComment& comment )
2808 {
2809  PushComment( comment.Value() );
2810  return true;
2811 }
2812 
2813 bool XMLPrinter::Visit( const XMLDeclaration& declaration )
2814 {
2815  PushDeclaration( declaration.Value() );
2816  return true;
2817 }
2818 
2819 
2820 bool XMLPrinter::Visit( const XMLUnknown& unknown )
2821 {
2822  PushUnknown( unknown.Value() );
2823  return true;
2824 }
2825 
2826 } // namespace tinyxml2
XMLText * NewText(const char *text)
Definition: tinyxml2.cpp:2102
virtual bool Visit(const XMLText &text)
Visit a text node.
Definition: tinyxml2.cpp:2800
XMLNode(XMLDocument *)
Definition: tinyxml2.cpp:742
char * ParseAttributes(char *p, int *curLineNumPtr)
Definition: tinyxml2.cpp:1805
void CollapseWhitespace()
Definition: tinyxml2.cpp:238
const T * data(const std::vector< T, Alloc > &v)
Definition: flatbuffers.h:709
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1816
static const char LINE_FEED
Definition: tinyxml2.cpp:104
void SetText(const char *inText)
Definition: tinyxml2.cpp:1579
void SealElementIfJustOpened()
Definition: tinyxml2.cpp:2650
void Push(T t)
Definition: tinyxml2.h:215
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:940
static void ToStr(int v, char *buffer, int bufferSize)
Definition: tinyxml2.cpp:552
XMLAttribute * FindOrCreateAttribute(const char *name)
Definition: tinyxml2.cpp:1758
const XMLElement * ToElementWithName(const char *name) const
Definition: tinyxml2.cpp:1121
XMLError QueryIntValue(int *value) const
Definition: tinyxml2.cpp:1380
unsigned UnsignedAttribute(const char *name, unsigned defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1535
XMLError QueryUnsignedAttribute(const char *name, unsigned int *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1326
static const char * GetCharacterRef(const char *p, char *value, int *length)
Definition: tinyxml2.cpp:456
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:690
static const unsigned char TIXML_UTF_LEAD_0
Definition: tinyxml2.cpp:115
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2159
void PushComment(const char *comment)
Add a comment.
Definition: tinyxml2.cpp:2722
T * PushArr(int count)
Definition: tinyxml2.h:222
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1416
static const Entity entities[NUM_ENTITIES]
Definition: tinyxml2.cpp:129
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1183
static raw_event_t * buffer
Definition: minitrace.cpp:54
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1213
void SetError(XMLError error, int lineNum, const char *format,...)
Definition: tinyxml2.cpp:2320
XMLAttribute * _rootAttribute
Definition: tinyxml2.h:1635
MemPoolT< sizeof(XMLAttribute) > _attributePool
Definition: tinyxml2.h:1887
ElementClosingType ClosingType() const
Definition: tinyxml2.h:1606
virtual ~XMLAttribute()
Definition: tinyxml2.h:1220
virtual XMLNode * ShallowClone(XMLDocument *document) const =0
static bool ToFloat(const char *str, float *value)
Definition: tinyxml2.cpp:627
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1888
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
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:686
static FILE * file
Definition: minitrace.cpp:59
XMLError QueryBoolText(bool *bval) const
See QueryIntText()
Definition: tinyxml2.cpp:1677
XMLError QueryInt64Value(int64_t *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1398
XMLNode * _lastChild
Definition: tinyxml2.h:946
void PushHeader(bool writeBOM, bool writeDeclaration)
Definition: tinyxml2.cpp:2538
static const char * SkipWhiteSpace(const char *p, int *curLineNumPtr)
Definition: tinyxml2.h:546
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:995
void Unlink(XMLNode *child)
Definition: tinyxml2.cpp:804
void PushDeclaration(const char *value)
Definition: tinyxml2.cpp:2737
virtual void Free(void *)=0
void PrintError() const
A (trivial) utility function that prints the ErrorStr() to stdout.
Definition: tinyxml2.cpp:2361
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1202
static bool IsNameChar(unsigned char ch)
Definition: tinyxml2.h:579
XMLNode * DeepClone(XMLDocument *target) const
Definition: tinyxml2.cpp:781
static bool IsWhiteSpace(char p)
Definition: tinyxml2.h:564
static const char * ReadBOM(const char *p, bool *hasBOM)
Definition: tinyxml2.cpp:385
void TransferTo(StrPair *other)
Definition: tinyxml2.cpp:144
XMLNode * _next
Definition: tinyxml2.h:949
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 Putc(char ch)
Definition: tinyxml2.cpp:2464
const XMLAttribute * FindAttribute(const char *name) const
Query a specific attribute in the list.
Definition: tinyxml2.cpp:1505
char * ParseDeep(char *p, bool processEntities, int *curLineNumPtr)
Definition: tinyxml2.cpp:1346
int IntAttribute(const char *name, int defaultValue=0) const
Definition: tinyxml2.cpp:1528
static const char DOUBLE_QUOTE
Definition: tinyxml2.cpp:109
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:755
XMLNode * _firstChild
Definition: tinyxml2.h:945
static const char * _errorNames[XML_ERROR_COUNT]
Definition: tinyxml2.h:1891
static bool ToBool(const char *str, bool *value)
Definition: tinyxml2.cpp:608
XMLAttribute * CreateAttribute()
Definition: tinyxml2.cpp:1874
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:481
char * ParseName(char *in)
Definition: tinyxml2.cpp:218
const char * Value() const
The value of the attribute.
Definition: tinyxml2.cpp:1341
double DoubleAttribute(const char *name, double defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1556
void SetAttribute(const char *value)
Set the attribute to a string value.
Definition: tinyxml2.cpp:1434
XMLError QueryFloatAttribute(const char *name, float *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1360
XMLNode * _parent
Definition: tinyxml2.h:941
MemPool * _memPool
Definition: tinyxml2.h:954
void Print(const char *format,...)
Definition: tinyxml2.cpp:2429
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1175
XMLPrinter(FILE *file=0, bool compact=false, int depth=0)
Definition: tinyxml2.cpp:2401
int64_t Int64Text(int64_t defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1729
static const char * writeBoolTrue
Definition: tinyxml2.h:630
void Clear()
Clear the document, resetting it to the initial state.
Definition: tinyxml2.cpp:2039
void MarkInUse(XMLNode *)
Definition: tinyxml2.cpp:2026
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1422
XMLError QueryDoubleText(double *dval) const
See QueryIntText()
Definition: tinyxml2.cpp:1690
int IntText(int defaultValue=0) const
Definition: tinyxml2.cpp:1715
void DeleteChildren()
Definition: tinyxml2.cpp:794
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2086
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1164
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1425
XMLError QueryInt64Attribute(const char *name, int64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1335
bool ProcessEntities() const
Definition: tinyxml2.h:1722
DynArray< char, 20 > _buffer
Definition: tinyxml2.h:2292
void DeepCopy(XMLDocument *target) const
Definition: tinyxml2.cpp:2073
static const unsigned char TIXML_UTF_LEAD_2
Definition: tinyxml2.cpp:117
static bool ToInt(const char *str, int *value)
Definition: tinyxml2.cpp:592
void SetName(const char *name)
Definition: tinyxml2.cpp:1374
static const char * ErrorIDToName(XMLError errorID)
Definition: tinyxml2.cpp:2347
static void SetBoolSerialization(const char *writeTrue, const char *writeFalse)
Definition: tinyxml2.cpp:375
double DoubleText(double defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1743
float FloatAttribute(const char *name, float defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1563
float FloatText(float defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1750
bool BoolText(bool defaultValue=false) const
See QueryIntText()
Definition: tinyxml2.cpp:1736
unsigned UnsignedText(unsigned defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1722
#define TIXML_VSNPRINTF
Definition: tinyxml2.cpp:93
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:2247
static bool ToUnsigned(const char *str, unsigned *value)
Definition: tinyxml2.cpp:600
const XMLNode * Parent() const
Get the parent of this node on the DOM.
Definition: tinyxml2.h:741
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2660
XMLAttribute * _next
Definition: tinyxml2.h:1231
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1140
static int TIXML_VSCPRINTF(const char *format, va_list va)
Definition: tinyxml2.cpp:94
XMLError QueryDoubleAttribute(const char *name, double *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1352
static const char CARRIAGE_RETURN
Definition: tinyxml2.cpp:106
void SetName(const char *str, bool staticMem=false)
Set the name of the element.
Definition: tinyxml2.h:1249
XMLComment * NewComment(const char *comment)
Definition: tinyxml2.cpp:2094
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2622
const char * ErrorStr() const
Definition: tinyxml2.cpp:2355
static bool ToInt64(const char *str, int64_t *value)
Definition: tinyxml2.cpp:645
StrPair _value
Definition: tinyxml2.h:942
void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:2141
virtual void SetTracked()=0
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1516
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.cpp:2767
static bool ToDouble(const char *str, double *value)
Definition: tinyxml2.cpp:636
XMLComment(XMLDocument *doc)
Definition: tinyxml2.cpp:1192
MemPoolT< sizeof(XMLComment) > _commentPool
Definition: tinyxml2.h:1889
#define TIXML_SNPRINTF
Definition: tinyxml2.cpp:92
const char * Name() const
The name of the attribute.
Definition: tinyxml2.cpp:1336
const char * GetText() const
Definition: tinyxml2.cpp:1570
XMLError QueryIntText(int *ival) const
Definition: tinyxml2.cpp:1638
static bool Fits(unsigned long value)
Definition: tinyxml2.cpp:2187
const char * GetStr()
Definition: tinyxml2.cpp:267
static const char SINGLE_QUOTE
Definition: tinyxml2.cpp:108
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2222
void OpenElement(const char *name, bool compactMode=false)
Definition: tinyxml2.cpp:2550
void SetStr(const char *str, int flags=0)
Definition: tinyxml2.cpp:180
int Size() const
Definition: tinyxml2.h:261
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1262
void SetCData(bool isCData)
Declare whether this should be CDATA or standard text.
Definition: tinyxml2.h:991
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1328
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1137
XMLDeclaration(XMLDocument *doc)
Definition: tinyxml2.cpp:1240
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:871
char * ParseText(char *in, const char *endTag, int strFlags, int *curLineNumPtr)
Definition: tinyxml2.cpp:193
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:667
XMLElement(XMLDocument *doc)
Definition: tinyxml2.cpp:1488
XMLError QueryInt64Text(int64_t *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1664
void Write(const char *data, size_t size)
Definition: tinyxml2.cpp:2451
virtual XMLUnknown * ToUnknown()
Safely cast to an Unknown, or null.
Definition: tinyxml2.h:698
char * Identify(char *p, XMLNode **node)
Definition: tinyxml2.cpp:656
ElementClosingType _closingType
Definition: tinyxml2.h:1631
static bool StringEqual(const char *p, const char *q, int nChar=INT_MAX)
Definition: tinyxml2.h:586
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1320
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1251
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1310
void InsertChildPreamble(XMLNode *insertThis) const
Definition: tinyxml2.cpp:1107
const char * Value() const
Definition: tinyxml2.cpp:763
static void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:1092
XMLError QueryFloatText(float *fval) const
See QueryIntText()
Definition: tinyxml2.cpp:1703
void SetValue(const char *val, bool staticMem=false)
Definition: tinyxml2.cpp:771
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1299
XMLError QueryUnsignedText(unsigned *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1651
static const int NUM_ENTITIES
Definition: tinyxml2.cpp:128
void PushUnknown(const char *value)
Definition: tinyxml2.cpp:2752
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1281
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2571
virtual ~XMLNode()
Definition: tinyxml2.cpp:755
#define TIXMLASSERT(x)
Definition: tinyxml2.h:86
DynArray< const char *, 10 > _stack
Definition: tinyxml2.h:2273
XMLError QueryIntAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1317
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
Definition: tinyxml2.cpp:403
bool BoolAttribute(const char *name, bool defaultValue=false) const
See IntAttribute()
Definition: tinyxml2.cpp:1549
void DeleteAttribute(const char *name)
Definition: tinyxml2.cpp:1786
void PrintString(const char *, bool restrictedEntitySet)
Definition: tinyxml2.cpp:2485
DynArray< XMLNode *, 10 > _unlinked
Definition: tinyxml2.h:1884
const XMLElement * LastChildElement(const char *name=0) const
Definition: tinyxml2.cpp:952
const char * pattern
Definition: tinyxml2.cpp:123
XMLUnknown(XMLDocument *doc)
Definition: tinyxml2.cpp:1289
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1389
static bool IsNameStartChar(unsigned char ch)
Definition: tinyxml2.h:568
void DeleteChild(XMLNode *node)
Definition: tinyxml2.cpp:828
XMLDocument * _document
Definition: tinyxml2.h:940
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:682
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1917
XMLError QueryBoolAttribute(const char *name, bool *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1344
bool HasBOM() const
Definition: tinyxml2.h:1732
virtual char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:988
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:726
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1231
static const char CR
Definition: tinyxml2.cpp:107
virtual void PrintSpace(int depth)
Definition: tinyxml2.cpp:2477
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1223
XMLUnknown * NewUnknown(const char *text)
Definition: tinyxml2.cpp:2118
virtual bool CompactMode(const XMLElement &)
Definition: tinyxml2.h:2260
MemPoolT< sizeof(XMLText) > _textPool
Definition: tinyxml2.h:1888
XMLDeclaration * NewDeclaration(const char *text=0)
Definition: tinyxml2.cpp:2110
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:750
MemPoolT< sizeof(XMLElement) > _elementPool
Definition: tinyxml2.h:1886
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1465
static const char * writeBoolFalse
Definition: tinyxml2.h:631
static const char LF
Definition: tinyxml2.cpp:105
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1272
virtual bool Visit(const XMLDeclaration &)
Visit a declaration.
Definition: tinyxml2.h:495
bool _restrictedEntityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2290
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:477
XMLNode * _prev
Definition: tinyxml2.h:948
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2308
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1407
Whitespace WhitespaceMode() const
Definition: tinyxml2.h:1725
XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
Definition: tinyxml2.cpp:902
#define TIXML_SSCANF
Definition: tinyxml2.cpp:100
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:694
static const unsigned char TIXML_UTF_LEAD_1
Definition: tinyxml2.cpp:116
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:678
const char * ErrorName() const
Definition: tinyxml2.cpp:2366
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1956
static FILE * callfopen(const char *filepath, const char *mode)
Definition: tinyxml2.cpp:2125
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:841
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:807
static const int TINYXML2_MAX_ELEMENT_DEPTH
Definition: tinyxml2.h:106
bool _entityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2289
int64_t Int64Attribute(const char *name, int64_t defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1542
bool Empty() const
Definition: tinyxml2.h:155
XMLDocument(bool processEntities=true, Whitespace whitespaceMode=PRESERVE_WHITESPACE)
constructor
Definition: tinyxml2.cpp:1998
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1245
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1930
void SetInternedStr(const char *str)
Definition: tinyxml2.h:159


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sun Feb 3 2019 03:14:32