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 
25 
26 #include <new> // yes, this one new style header, is in the Android SDK.
27 #if defined(ANDROID_NDK) || 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->_flags == 0 );
153  TIXMLASSERT( other->_start == 0 );
154  TIXMLASSERT( other->_end == 0 );
155 
156  other->Reset();
157 
158  other->_flags = _flags;
159  other->_start = _start;
160  other->_end = _end;
161 
162  _flags = 0;
163  _start = 0;
164  _end = 0;
165 }
166 
168 {
169  if ( _flags & NEEDS_DELETE ) {
170  delete [] _start;
171  }
172  _flags = 0;
173  _start = 0;
174  _end = 0;
175 }
176 
177 
178 void StrPair::SetStr( const char* str, int flags )
179 {
180  Reset();
181  size_t len = strlen( str );
182  TIXMLASSERT( _start == 0 );
183  _start = new char[ len+1 ];
184  memcpy( _start, str, len+1 );
185  _end = _start + len;
186  _flags = flags | NEEDS_DELETE;
187 }
188 
189 
190 char* StrPair::ParseText( char* p, const char* endTag, int strFlags )
191 {
192  TIXMLASSERT( endTag && *endTag );
193 
194  char* start = p;
195  char endChar = *endTag;
196  size_t length = strlen( endTag );
197 
198  // Inner loop of text parsing.
199  while ( *p ) {
200  if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
201  Set( start, p, strFlags );
202  return p + length;
203  }
204  ++p;
205  }
206  return 0;
207 }
208 
209 
210 char* StrPair::ParseName( char* p )
211 {
212  if ( !p || !(*p) ) {
213  return 0;
214  }
215  if ( !XMLUtil::IsNameStartChar( *p ) ) {
216  return 0;
217  }
218 
219  char* const start = p;
220  ++p;
221  while ( *p && XMLUtil::IsNameChar( *p ) ) {
222  ++p;
223  }
224 
225  Set( start, p, 0 );
226  return p;
227 }
228 
229 
231 {
232  // Adjusting _start would cause undefined behavior on delete[]
233  TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );
234  // Trim leading space.
235  _start = XMLUtil::SkipWhiteSpace( _start );
236 
237  if ( *_start ) {
238  char* p = _start; // the read pointer
239  char* q = _start; // the write pointer
240 
241  while( *p ) {
242  if ( XMLUtil::IsWhiteSpace( *p )) {
243  p = XMLUtil::SkipWhiteSpace( p );
244  if ( *p == 0 ) {
245  break; // don't write to q; this trims the trailing space.
246  }
247  *q = ' ';
248  ++q;
249  }
250  *q = *p;
251  ++q;
252  ++p;
253  }
254  *q = 0;
255  }
256 }
257 
258 
259 const char* StrPair::GetStr()
260 {
261  TIXMLASSERT( _start );
262  TIXMLASSERT( _end );
263  if ( _flags & NEEDS_FLUSH ) {
264  *_end = 0;
265  _flags ^= NEEDS_FLUSH;
266 
267  if ( _flags ) {
268  char* p = _start; // the read pointer
269  char* q = _start; // the write pointer
270 
271  while( p < _end ) {
272  if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
273  // CR-LF pair becomes LF
274  // CR alone becomes LF
275  // LF-CR becomes LF
276  if ( *(p+1) == LF ) {
277  p += 2;
278  }
279  else {
280  ++p;
281  }
282  *q++ = LF;
283  }
284  else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
285  if ( *(p+1) == CR ) {
286  p += 2;
287  }
288  else {
289  ++p;
290  }
291  *q++ = LF;
292  }
293  else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
294  // Entities handled by tinyXML2:
295  // - special entities in the entity table [in/out]
296  // - numeric character reference [in]
297  // &#20013; or &#x4e2d;
298 
299  if ( *(p+1) == '#' ) {
300  const int buflen = 10;
301  char buf[buflen] = { 0 };
302  int len = 0;
303  char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
304  if ( adjusted == 0 ) {
305  *q = *p;
306  ++p;
307  ++q;
308  }
309  else {
310  TIXMLASSERT( 0 <= len && len <= buflen );
311  TIXMLASSERT( q + len <= adjusted );
312  p = adjusted;
313  memcpy( q, buf, len );
314  q += len;
315  }
316  }
317  else {
318  bool entityFound = false;
319  for( int i = 0; i < NUM_ENTITIES; ++i ) {
320  const Entity& entity = entities[i];
321  if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
322  && *( p + entity.length + 1 ) == ';' ) {
323  // Found an entity - convert.
324  *q = entity.value;
325  ++q;
326  p += entity.length + 2;
327  entityFound = true;
328  break;
329  }
330  }
331  if ( !entityFound ) {
332  // fixme: treat as error?
333  ++p;
334  ++q;
335  }
336  }
337  }
338  else {
339  *q = *p;
340  ++p;
341  ++q;
342  }
343  }
344  *q = 0;
345  }
346  // The loop below has plenty going on, and this
347  // is a less useful mode. Break it out.
348  if ( _flags & NEEDS_WHITESPACE_COLLAPSING ) {
349  CollapseWhitespace();
350  }
351  _flags = (_flags & NEEDS_DELETE);
352  }
353  TIXMLASSERT( _start );
354  return _start;
355 }
356 
357 
358 
359 
360 // --------- XMLUtil ----------- //
361 
362 const char* XMLUtil::ReadBOM( const char* p, bool* bom )
363 {
364  TIXMLASSERT( p );
365  TIXMLASSERT( bom );
366  *bom = false;
367  const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
368  // Check for BOM:
369  if ( *(pu+0) == TIXML_UTF_LEAD_0
370  && *(pu+1) == TIXML_UTF_LEAD_1
371  && *(pu+2) == TIXML_UTF_LEAD_2 ) {
372  *bom = true;
373  p += 3;
374  }
375  TIXMLASSERT( p );
376  return p;
377 }
378 
379 
380 void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
381 {
382  const unsigned long BYTE_MASK = 0xBF;
383  const unsigned long BYTE_MARK = 0x80;
384  const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
385 
386  if (input < 0x80) {
387  *length = 1;
388  }
389  else if ( input < 0x800 ) {
390  *length = 2;
391  }
392  else if ( input < 0x10000 ) {
393  *length = 3;
394  }
395  else if ( input < 0x200000 ) {
396  *length = 4;
397  }
398  else {
399  *length = 0; // This code won't convert this correctly anyway.
400  return;
401  }
402 
403  output += *length;
404 
405  // Scary scary fall throughs.
406  switch (*length) {
407  case 4:
408  --output;
409  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
410  input >>= 6;
411  case 3:
412  --output;
413  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
414  input >>= 6;
415  case 2:
416  --output;
417  *output = (char)((input | BYTE_MARK) & BYTE_MASK);
418  input >>= 6;
419  case 1:
420  --output;
421  *output = (char)(input | FIRST_BYTE_MARK[*length]);
422  break;
423  default:
424  TIXMLASSERT( false );
425  }
426 }
427 
428 
429 const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
430 {
431  // Presume an entity, and pull it out.
432  *length = 0;
433 
434  if ( *(p+1) == '#' && *(p+2) ) {
435  unsigned long ucs = 0;
436  TIXMLASSERT( sizeof( ucs ) >= 4 );
437  ptrdiff_t delta = 0;
438  unsigned mult = 1;
439  static const char SEMICOLON = ';';
440 
441  if ( *(p+2) == 'x' ) {
442  // Hexadecimal.
443  const char* q = p+3;
444  if ( !(*q) ) {
445  return 0;
446  }
447 
448  q = strchr( q, SEMICOLON );
449 
450  if ( !q ) {
451  return 0;
452  }
453  TIXMLASSERT( *q == SEMICOLON );
454 
455  delta = q-p;
456  --q;
457 
458  while ( *q != 'x' ) {
459  unsigned int digit = 0;
460 
461  if ( *q >= '0' && *q <= '9' ) {
462  digit = *q - '0';
463  }
464  else if ( *q >= 'a' && *q <= 'f' ) {
465  digit = *q - 'a' + 10;
466  }
467  else if ( *q >= 'A' && *q <= 'F' ) {
468  digit = *q - 'A' + 10;
469  }
470  else {
471  return 0;
472  }
473  TIXMLASSERT( digit >= 0 && digit < 16);
474  TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
475  const unsigned int digitScaled = mult * digit;
476  TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
477  ucs += digitScaled;
478  TIXMLASSERT( mult <= UINT_MAX / 16 );
479  mult *= 16;
480  --q;
481  }
482  }
483  else {
484  // Decimal.
485  const char* q = p+2;
486  if ( !(*q) ) {
487  return 0;
488  }
489 
490  q = strchr( q, SEMICOLON );
491 
492  if ( !q ) {
493  return 0;
494  }
495  TIXMLASSERT( *q == SEMICOLON );
496 
497  delta = q-p;
498  --q;
499 
500  while ( *q != '#' ) {
501  if ( *q >= '0' && *q <= '9' ) {
502  const unsigned int digit = *q - '0';
503  TIXMLASSERT( digit >= 0 && digit < 10);
504  TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
505  const unsigned int digitScaled = mult * digit;
506  TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
507  ucs += digitScaled;
508  }
509  else {
510  return 0;
511  }
512  TIXMLASSERT( mult <= UINT_MAX / 10 );
513  mult *= 10;
514  --q;
515  }
516  }
517  // convert the UCS to UTF-8
518  ConvertUTF32ToUTF8( ucs, value, length );
519  return p + delta + 1;
520  }
521  return p+1;
522 }
523 
524 
525 void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
526 {
527  TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
528 }
529 
530 
531 void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
532 {
533  TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
534 }
535 
536 
537 void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
538 {
539  TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 );
540 }
541 
542 /*
543  ToStr() of a number is a very tricky topic.
544  https://github.com/leethomason/tinyxml2/issues/106
545 */
546 void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
547 {
548  TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );
549 }
550 
551 
552 void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
553 {
554  TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );
555 }
556 
557 
558 bool XMLUtil::ToInt( const char* str, int* value )
559 {
560  if ( TIXML_SSCANF( str, "%d", value ) == 1 ) {
561  return true;
562  }
563  return false;
564 }
565 
566 bool XMLUtil::ToUnsigned( const char* str, unsigned *value )
567 {
568  if ( TIXML_SSCANF( str, "%u", value ) == 1 ) {
569  return true;
570  }
571  return false;
572 }
573 
574 bool XMLUtil::ToBool( const char* str, bool* value )
575 {
576  int ival = 0;
577  if ( ToInt( str, &ival )) {
578  *value = (ival==0) ? false : true;
579  return true;
580  }
581  if ( StringEqual( str, "true" ) ) {
582  *value = true;
583  return true;
584  }
585  else if ( StringEqual( str, "false" ) ) {
586  *value = false;
587  return true;
588  }
589  return false;
590 }
591 
592 
593 bool XMLUtil::ToFloat( const char* str, float* value )
594 {
595  if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
596  return true;
597  }
598  return false;
599 }
600 
601 bool XMLUtil::ToDouble( const char* str, double* value )
602 {
603  if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
604  return true;
605  }
606  return false;
607 }
608 
609 
610 char* XMLDocument::Identify( char* p, XMLNode** node )
611 {
612  TIXMLASSERT( node );
613  TIXMLASSERT( p );
614  char* const start = p;
615  p = XMLUtil::SkipWhiteSpace( p );
616  if( !*p ) {
617  *node = 0;
618  TIXMLASSERT( p );
619  return p;
620  }
621 
622  // These strings define the matching patterns:
623  static const char* xmlHeader = { "<?" };
624  static const char* commentHeader = { "<!--" };
625  static const char* cdataHeader = { "<![CDATA[" };
626  static const char* dtdHeader = { "<!" };
627  static const char* elementHeader = { "<" }; // and a header for everything else; check last.
628 
629  static const int xmlHeaderLen = 2;
630  static const int commentHeaderLen = 4;
631  static const int cdataHeaderLen = 9;
632  static const int dtdHeaderLen = 2;
633  static const int elementHeaderLen = 1;
634 
635  TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
636  TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
637  XMLNode* returnNode = 0;
638  if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
639  TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );
640  returnNode = new (_commentPool.Alloc()) XMLDeclaration( this );
641  returnNode->_memPool = &_commentPool;
642  p += xmlHeaderLen;
643  }
644  else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
645  TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() );
646  returnNode = new (_commentPool.Alloc()) XMLComment( this );
647  returnNode->_memPool = &_commentPool;
648  p += commentHeaderLen;
649  }
650  else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
651  TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );
652  XMLText* text = new (_textPool.Alloc()) XMLText( this );
653  returnNode = text;
654  returnNode->_memPool = &_textPool;
655  p += cdataHeaderLen;
656  text->SetCData( true );
657  }
658  else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
659  TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() );
660  returnNode = new (_commentPool.Alloc()) XMLUnknown( this );
661  returnNode->_memPool = &_commentPool;
662  p += dtdHeaderLen;
663  }
664  else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
665  TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() );
666  returnNode = new (_elementPool.Alloc()) XMLElement( this );
667  returnNode->_memPool = &_elementPool;
668  p += elementHeaderLen;
669  }
670  else {
671  TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );
672  returnNode = new (_textPool.Alloc()) XMLText( this );
673  returnNode->_memPool = &_textPool;
674  p = start; // Back it up, all the text counts.
675  }
676 
677  TIXMLASSERT( returnNode );
678  TIXMLASSERT( p );
679  *node = returnNode;
680  return p;
681 }
682 
683 
684 bool XMLDocument::Accept( XMLVisitor* visitor ) const
685 {
686  TIXMLASSERT( visitor );
687  if ( visitor->VisitEnter( *this ) ) {
688  for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
689  if ( !node->Accept( visitor ) ) {
690  break;
691  }
692  }
693  }
694  return visitor->VisitExit( *this );
695 }
696 
697 
698 // --------- XMLNode ----------- //
699 
701  _document( doc ),
702  _parent( 0 ),
703  _firstChild( 0 ), _lastChild( 0 ),
704  _prev( 0 ), _next( 0 ),
705  _memPool( 0 )
706 {
707 }
708 
709 
711 {
712  DeleteChildren();
713  if ( _parent ) {
714  _parent->Unlink( this );
715  }
716 }
717 
718 const char* XMLNode::Value() const
719 {
720  // Catch an edge case: XMLDocuments don't have a a Value. Carefully return nullptr.
721  if ( this->ToDocument() )
722  return 0;
723  return _value.GetStr();
724 }
725 
726 void XMLNode::SetValue( const char* str, bool staticMem )
727 {
728  if ( staticMem ) {
729  _value.SetInternedStr( str );
730  }
731  else {
732  _value.SetStr( str );
733  }
734 }
735 
736 
738 {
739  while( _firstChild ) {
742  XMLNode* node = _firstChild;
743  Unlink( node );
744 
745  DeleteNode( node );
746  }
747  _firstChild = _lastChild = 0;
748 }
749 
750 
751 void XMLNode::Unlink( XMLNode* child )
752 {
753  TIXMLASSERT( child );
754  TIXMLASSERT( child->_document == _document );
755  TIXMLASSERT( child->_parent == this );
756  if ( child == _firstChild ) {
758  }
759  if ( child == _lastChild ) {
761  }
762 
763  if ( child->_prev ) {
764  child->_prev->_next = child->_next;
765  }
766  if ( child->_next ) {
767  child->_next->_prev = child->_prev;
768  }
769  child->_parent = 0;
770 }
771 
772 
774 {
775  TIXMLASSERT( node );
776  TIXMLASSERT( node->_document == _document );
777  TIXMLASSERT( node->_parent == this );
778  DeleteNode( node );
779 }
780 
781 
783 {
784  TIXMLASSERT( addThis );
785  if ( addThis->_document != _document ) {
786  TIXMLASSERT( false );
787  return 0;
788  }
789  InsertChildPreamble( addThis );
790 
791  if ( _lastChild ) {
793  TIXMLASSERT( _lastChild->_next == 0 );
794  _lastChild->_next = addThis;
795  addThis->_prev = _lastChild;
796  _lastChild = addThis;
797 
798  addThis->_next = 0;
799  }
800  else {
801  TIXMLASSERT( _firstChild == 0 );
802  _firstChild = _lastChild = addThis;
803 
804  addThis->_prev = 0;
805  addThis->_next = 0;
806  }
807  addThis->_parent = this;
808  return addThis;
809 }
810 
811 
813 {
814  TIXMLASSERT( addThis );
815  if ( addThis->_document != _document ) {
816  TIXMLASSERT( false );
817  return 0;
818  }
819  InsertChildPreamble( addThis );
820 
821  if ( _firstChild ) {
823  TIXMLASSERT( _firstChild->_prev == 0 );
824 
825  _firstChild->_prev = addThis;
826  addThis->_next = _firstChild;
827  _firstChild = addThis;
828 
829  addThis->_prev = 0;
830  }
831  else {
832  TIXMLASSERT( _lastChild == 0 );
833  _firstChild = _lastChild = addThis;
834 
835  addThis->_prev = 0;
836  addThis->_next = 0;
837  }
838  addThis->_parent = this;
839  return addThis;
840 }
841 
842 
844 {
845  TIXMLASSERT( addThis );
846  if ( addThis->_document != _document ) {
847  TIXMLASSERT( false );
848  return 0;
849  }
850 
851  TIXMLASSERT( afterThis );
852 
853  if ( afterThis->_parent != this ) {
854  TIXMLASSERT( false );
855  return 0;
856  }
857 
858  if ( afterThis->_next == 0 ) {
859  // The last node or the only node.
860  return InsertEndChild( addThis );
861  }
862  InsertChildPreamble( addThis );
863  addThis->_prev = afterThis;
864  addThis->_next = afterThis->_next;
865  afterThis->_next->_prev = addThis;
866  afterThis->_next = addThis;
867  addThis->_parent = this;
868  return addThis;
869 }
870 
871 
872 
873 
874 const XMLElement* XMLNode::FirstChildElement( const char* name ) const
875 {
876  for( const XMLNode* node = _firstChild; node; node = node->_next ) {
877  const XMLElement* element = node->ToElement();
878  if ( element ) {
879  if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
880  return element;
881  }
882  }
883  }
884  return 0;
885 }
886 
887 
888 const XMLElement* XMLNode::LastChildElement( const char* name ) const
889 {
890  for( const XMLNode* node = _lastChild; node; node = node->_prev ) {
891  const XMLElement* element = node->ToElement();
892  if ( element ) {
893  if ( !name || XMLUtil::StringEqual( element->Name(), name ) ) {
894  return element;
895  }
896  }
897  }
898  return 0;
899 }
900 
901 
902 const XMLElement* XMLNode::NextSiblingElement( const char* name ) const
903 {
904  for( const XMLNode* node = _next; node; node = node->_next ) {
905  const XMLElement* element = node->ToElement();
906  if ( element
907  && (!name || XMLUtil::StringEqual( name, element->Name() ))) {
908  return element;
909  }
910  }
911  return 0;
912 }
913 
914 
915 const XMLElement* XMLNode::PreviousSiblingElement( const char* name ) const
916 {
917  for( const XMLNode* node = _prev; node; node = node->_prev ) {
918  const XMLElement* element = node->ToElement();
919  if ( element
920  && (!name || XMLUtil::StringEqual( name, element->Name() ))) {
921  return element;
922  }
923  }
924  return 0;
925 }
926 
927 
928 char* XMLNode::ParseDeep( char* p, StrPair* parentEnd )
929 {
930  // This is a recursive method, but thinking about it "at the current level"
931  // it is a pretty simple flat list:
932  // <foo/>
933  // <!-- comment -->
934  //
935  // With a special case:
936  // <foo>
937  // </foo>
938  // <!-- comment -->
939  //
940  // Where the closing element (/foo) *must* be the next thing after the opening
941  // element, and the names must match. BUT the tricky bit is that the closing
942  // element will be read by the child.
943  //
944  // 'endTag' is the end tag for this node, it is returned by a call to a child.
945  // 'parentEnd' is the end tag for the parent, which is filled in and returned.
946 
947  while( p && *p ) {
948  XMLNode* node = 0;
949 
950  p = _document->Identify( p, &node );
951  if ( node == 0 ) {
952  break;
953  }
954 
955  StrPair endTag;
956  p = node->ParseDeep( p, &endTag );
957  if ( !p ) {
958  DeleteNode( node );
959  if ( !_document->Error() ) {
961  }
962  break;
963  }
964 
965  XMLDeclaration* decl = node->ToDeclaration();
966  if ( decl ) {
967  // A declaration can only be the first child of a document.
968  // Set error, if document already has children.
969  if ( !_document->NoChildren() ) {
971  DeleteNode( decl );
972  break;
973  }
974  }
975 
976  XMLElement* ele = node->ToElement();
977  if ( ele ) {
978  // We read the end tag. Return it to the parent.
979  if ( ele->ClosingType() == XMLElement::CLOSING ) {
980  if ( parentEnd ) {
981  ele->_value.TransferTo( parentEnd );
982  }
983  node->_memPool->SetTracked(); // created and then immediately deleted.
984  DeleteNode( node );
985  return p;
986  }
987 
988  // Handle an end tag returned to this level.
989  // And handle a bunch of annoying errors.
990  bool mismatch = false;
991  if ( endTag.Empty() ) {
992  if ( ele->ClosingType() == XMLElement::OPEN ) {
993  mismatch = true;
994  }
995  }
996  else {
997  if ( ele->ClosingType() != XMLElement::OPEN ) {
998  mismatch = true;
999  }
1000  else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {
1001  mismatch = true;
1002  }
1003  }
1004  if ( mismatch ) {
1006  DeleteNode( node );
1007  break;
1008  }
1009  }
1010  InsertEndChild( node );
1011  }
1012  return 0;
1013 }
1014 
1016 {
1017  if ( node == 0 ) {
1018  return;
1019  }
1020  MemPool* pool = node->_memPool;
1021  node->~XMLNode();
1022  pool->Free( node );
1023 }
1024 
1025 void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
1026 {
1027  TIXMLASSERT( insertThis );
1028  TIXMLASSERT( insertThis->_document == _document );
1029 
1030  if ( insertThis->_parent )
1031  insertThis->_parent->Unlink( insertThis );
1032  else
1033  insertThis->_memPool->SetTracked();
1034 }
1035 
1036 // --------- XMLText ---------- //
1037 char* XMLText::ParseDeep( char* p, StrPair* )
1038 {
1039  const char* start = p;
1040  if ( this->CData() ) {
1042  if ( !p ) {
1044  }
1045  return p;
1046  }
1047  else {
1051  }
1052 
1053  p = _value.ParseText( p, "<", flags );
1054  if ( p && *p ) {
1055  return p-1;
1056  }
1057  if ( !p ) {
1059  }
1060  }
1061  return 0;
1062 }
1063 
1064 
1066 {
1067  if ( !doc ) {
1068  doc = _document;
1069  }
1070  XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?
1071  text->SetCData( this->CData() );
1072  return text;
1073 }
1074 
1075 
1076 bool XMLText::ShallowEqual( const XMLNode* compare ) const
1077 {
1078  const XMLText* text = compare->ToText();
1079  return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );
1080 }
1081 
1082 
1083 bool XMLText::Accept( XMLVisitor* visitor ) const
1084 {
1085  TIXMLASSERT( visitor );
1086  return visitor->Visit( *this );
1087 }
1088 
1089 
1090 // --------- XMLComment ---------- //
1091 
1093 {
1094 }
1095 
1096 
1098 {
1099 }
1100 
1101 
1102 char* XMLComment::ParseDeep( char* p, StrPair* )
1103 {
1104  // Comment parses as text.
1105  const char* start = p;
1106  p = _value.ParseText( p, "-->", StrPair::COMMENT );
1107  if ( p == 0 ) {
1109  }
1110  return p;
1111 }
1112 
1113 
1115 {
1116  if ( !doc ) {
1117  doc = _document;
1118  }
1119  XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?
1120  return comment;
1121 }
1122 
1123 
1124 bool XMLComment::ShallowEqual( const XMLNode* compare ) const
1125 {
1126  TIXMLASSERT( compare );
1127  const XMLComment* comment = compare->ToComment();
1128  return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));
1129 }
1130 
1131 
1132 bool XMLComment::Accept( XMLVisitor* visitor ) const
1133 {
1134  TIXMLASSERT( visitor );
1135  return visitor->Visit( *this );
1136 }
1137 
1138 
1139 // --------- XMLDeclaration ---------- //
1140 
1142 {
1143 }
1144 
1145 
1147 {
1148  //printf( "~XMLDeclaration\n" );
1149 }
1150 
1151 
1153 {
1154  // Declaration parses as text.
1155  const char* start = p;
1157  if ( p == 0 ) {
1159  }
1160  return p;
1161 }
1162 
1163 
1165 {
1166  if ( !doc ) {
1167  doc = _document;
1168  }
1169  XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?
1170  return dec;
1171 }
1172 
1173 
1174 bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const
1175 {
1176  TIXMLASSERT( compare );
1177  const XMLDeclaration* declaration = compare->ToDeclaration();
1178  return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));
1179 }
1180 
1181 
1182 
1183 bool XMLDeclaration::Accept( XMLVisitor* visitor ) const
1184 {
1185  TIXMLASSERT( visitor );
1186  return visitor->Visit( *this );
1187 }
1188 
1189 // --------- XMLUnknown ---------- //
1190 
1192 {
1193 }
1194 
1195 
1197 {
1198 }
1199 
1200 
1201 char* XMLUnknown::ParseDeep( char* p, StrPair* )
1202 {
1203  // Unknown parses as text.
1204  const char* start = p;
1205 
1207  if ( !p ) {
1209  }
1210  return p;
1211 }
1212 
1213 
1215 {
1216  if ( !doc ) {
1217  doc = _document;
1218  }
1219  XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?
1220  return text;
1221 }
1222 
1223 
1224 bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const
1225 {
1226  TIXMLASSERT( compare );
1227  const XMLUnknown* unknown = compare->ToUnknown();
1228  return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));
1229 }
1230 
1231 
1232 bool XMLUnknown::Accept( XMLVisitor* visitor ) const
1233 {
1234  TIXMLASSERT( visitor );
1235  return visitor->Visit( *this );
1236 }
1237 
1238 // --------- XMLAttribute ---------- //
1239 
1240 const char* XMLAttribute::Name() const
1241 {
1242  return _name.GetStr();
1243 }
1244 
1245 const char* XMLAttribute::Value() const
1246 {
1247  return _value.GetStr();
1248 }
1249 
1250 char* XMLAttribute::ParseDeep( char* p, bool processEntities )
1251 {
1252  // Parse using the name rules: bug fix, was using ParseText before
1253  p = _name.ParseName( p );
1254  if ( !p || !*p ) {
1255  return 0;
1256  }
1257 
1258  // Skip white space before =
1259  p = XMLUtil::SkipWhiteSpace( p );
1260  if ( *p != '=' ) {
1261  return 0;
1262  }
1263 
1264  ++p; // move up to opening quote
1265  p = XMLUtil::SkipWhiteSpace( p );
1266  if ( *p != '\"' && *p != '\'' ) {
1267  return 0;
1268  }
1269 
1270  char endTag[2] = { *p, 0 };
1271  ++p; // move past opening quote
1272 
1274  return p;
1275 }
1276 
1277 
1278 void XMLAttribute::SetName( const char* n )
1279 {
1280  _name.SetStr( n );
1281 }
1282 
1283 
1285 {
1286  if ( XMLUtil::ToInt( Value(), value )) {
1287  return XML_NO_ERROR;
1288  }
1289  return XML_WRONG_ATTRIBUTE_TYPE;
1290 }
1291 
1292 
1293 XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
1294 {
1295  if ( XMLUtil::ToUnsigned( Value(), value )) {
1296  return XML_NO_ERROR;
1297  }
1298  return XML_WRONG_ATTRIBUTE_TYPE;
1299 }
1300 
1301 
1303 {
1304  if ( XMLUtil::ToBool( Value(), value )) {
1305  return XML_NO_ERROR;
1306  }
1307  return XML_WRONG_ATTRIBUTE_TYPE;
1308 }
1309 
1310 
1312 {
1313  if ( XMLUtil::ToFloat( Value(), value )) {
1314  return XML_NO_ERROR;
1315  }
1316  return XML_WRONG_ATTRIBUTE_TYPE;
1317 }
1318 
1319 
1321 {
1322  if ( XMLUtil::ToDouble( Value(), value )) {
1323  return XML_NO_ERROR;
1324  }
1325  return XML_WRONG_ATTRIBUTE_TYPE;
1326 }
1327 
1328 
1329 void XMLAttribute::SetAttribute( const char* v )
1330 {
1331  _value.SetStr( v );
1332 }
1333 
1334 
1336 {
1337  char buf[BUF_SIZE];
1338  XMLUtil::ToStr( v, buf, BUF_SIZE );
1339  _value.SetStr( buf );
1340 }
1341 
1342 
1343 void XMLAttribute::SetAttribute( unsigned v )
1344 {
1345  char buf[BUF_SIZE];
1346  XMLUtil::ToStr( v, buf, BUF_SIZE );
1347  _value.SetStr( buf );
1348 }
1349 
1350 
1352 {
1353  char buf[BUF_SIZE];
1354  XMLUtil::ToStr( v, buf, BUF_SIZE );
1355  _value.SetStr( buf );
1356 }
1357 
1359 {
1360  char buf[BUF_SIZE];
1361  XMLUtil::ToStr( v, buf, BUF_SIZE );
1362  _value.SetStr( buf );
1363 }
1364 
1366 {
1367  char buf[BUF_SIZE];
1368  XMLUtil::ToStr( v, buf, BUF_SIZE );
1369  _value.SetStr( buf );
1370 }
1371 
1372 
1373 // --------- XMLElement ---------- //
1375  _closingType( 0 ),
1376  _rootAttribute( 0 )
1377 {
1378 }
1379 
1380 
1382 {
1383  while( _rootAttribute ) {
1386  _rootAttribute = next;
1387  }
1388 }
1389 
1390 
1391 const XMLAttribute* XMLElement::FindAttribute( const char* name ) const
1392 {
1393  for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {
1394  if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1395  return a;
1396  }
1397  }
1398  return 0;
1399 }
1400 
1401 
1402 const char* XMLElement::Attribute( const char* name, const char* value ) const
1403 {
1404  const XMLAttribute* a = FindAttribute( name );
1405  if ( !a ) {
1406  return 0;
1407  }
1408  if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
1409  return a->Value();
1410  }
1411  return 0;
1412 }
1413 
1414 
1415 const char* XMLElement::GetText() const
1416 {
1417  if ( FirstChild() && FirstChild()->ToText() ) {
1418  return FirstChild()->Value();
1419  }
1420  return 0;
1421 }
1422 
1423 
1424 void XMLElement::SetText( const char* inText )
1425 {
1426  if ( FirstChild() && FirstChild()->ToText() )
1427  FirstChild()->SetValue( inText );
1428  else {
1429  XMLText* theText = GetDocument()->NewText( inText );
1430  InsertFirstChild( theText );
1431  }
1432 }
1433 
1434 
1435 void XMLElement::SetText( int v )
1436 {
1437  char buf[BUF_SIZE];
1438  XMLUtil::ToStr( v, buf, BUF_SIZE );
1439  SetText( buf );
1440 }
1441 
1442 
1443 void XMLElement::SetText( unsigned v )
1444 {
1445  char buf[BUF_SIZE];
1446  XMLUtil::ToStr( v, buf, BUF_SIZE );
1447  SetText( buf );
1448 }
1449 
1450 
1451 void XMLElement::SetText( bool v )
1452 {
1453  char buf[BUF_SIZE];
1454  XMLUtil::ToStr( v, buf, BUF_SIZE );
1455  SetText( buf );
1456 }
1457 
1458 
1459 void XMLElement::SetText( float v )
1460 {
1461  char buf[BUF_SIZE];
1462  XMLUtil::ToStr( v, buf, BUF_SIZE );
1463  SetText( buf );
1464 }
1465 
1466 
1467 void XMLElement::SetText( double v )
1468 {
1469  char buf[BUF_SIZE];
1470  XMLUtil::ToStr( v, buf, BUF_SIZE );
1471  SetText( buf );
1472 }
1473 
1474 
1476 {
1477  if ( FirstChild() && FirstChild()->ToText() ) {
1478  const char* t = FirstChild()->Value();
1479  if ( XMLUtil::ToInt( t, ival ) ) {
1480  return XML_SUCCESS;
1481  }
1482  return XML_CAN_NOT_CONVERT_TEXT;
1483  }
1484  return XML_NO_TEXT_NODE;
1485 }
1486 
1487 
1489 {
1490  if ( FirstChild() && FirstChild()->ToText() ) {
1491  const char* t = FirstChild()->Value();
1492  if ( XMLUtil::ToUnsigned( t, uval ) ) {
1493  return XML_SUCCESS;
1494  }
1495  return XML_CAN_NOT_CONVERT_TEXT;
1496  }
1497  return XML_NO_TEXT_NODE;
1498 }
1499 
1500 
1502 {
1503  if ( FirstChild() && FirstChild()->ToText() ) {
1504  const char* t = FirstChild()->Value();
1505  if ( XMLUtil::ToBool( t, bval ) ) {
1506  return XML_SUCCESS;
1507  }
1508  return XML_CAN_NOT_CONVERT_TEXT;
1509  }
1510  return XML_NO_TEXT_NODE;
1511 }
1512 
1513 
1515 {
1516  if ( FirstChild() && FirstChild()->ToText() ) {
1517  const char* t = FirstChild()->Value();
1518  if ( XMLUtil::ToDouble( t, dval ) ) {
1519  return XML_SUCCESS;
1520  }
1521  return XML_CAN_NOT_CONVERT_TEXT;
1522  }
1523  return XML_NO_TEXT_NODE;
1524 }
1525 
1526 
1528 {
1529  if ( FirstChild() && FirstChild()->ToText() ) {
1530  const char* t = FirstChild()->Value();
1531  if ( XMLUtil::ToFloat( t, fval ) ) {
1532  return XML_SUCCESS;
1533  }
1534  return XML_CAN_NOT_CONVERT_TEXT;
1535  }
1536  return XML_NO_TEXT_NODE;
1537 }
1538 
1539 
1540 
1542 {
1543  XMLAttribute* last = 0;
1544  XMLAttribute* attrib = 0;
1545  for( attrib = _rootAttribute;
1546  attrib;
1547  last = attrib, attrib = attrib->_next ) {
1548  if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1549  break;
1550  }
1551  }
1552  if ( !attrib ) {
1553  TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
1554  attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1555  attrib->_memPool = &_document->_attributePool;
1556  if ( last ) {
1557  last->_next = attrib;
1558  }
1559  else {
1560  _rootAttribute = attrib;
1561  }
1562  attrib->SetName( name );
1563  attrib->_memPool->SetTracked(); // always created and linked.
1564  }
1565  return attrib;
1566 }
1567 
1568 
1569 void XMLElement::DeleteAttribute( const char* name )
1570 {
1571  XMLAttribute* prev = 0;
1572  for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
1573  if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1574  if ( prev ) {
1575  prev->_next = a->_next;
1576  }
1577  else {
1578  _rootAttribute = a->_next;
1579  }
1580  DeleteAttribute( a );
1581  break;
1582  }
1583  prev = a;
1584  }
1585 }
1586 
1587 
1589 {
1590  const char* start = p;
1591  XMLAttribute* prevAttribute = 0;
1592 
1593  // Read the attributes.
1594  while( p ) {
1595  p = XMLUtil::SkipWhiteSpace( p );
1596  if ( !(*p) ) {
1598  return 0;
1599  }
1600 
1601  // attribute.
1602  if (XMLUtil::IsNameStartChar( *p ) ) {
1603  TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
1604  XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
1605  attrib->_memPool = &_document->_attributePool;
1606  attrib->_memPool->SetTracked();
1607 
1608  p = attrib->ParseDeep( p, _document->ProcessEntities() );
1609  if ( !p || Attribute( attrib->Name() ) ) {
1610  DeleteAttribute( attrib );
1612  return 0;
1613  }
1614  // There is a minor bug here: if the attribute in the source xml
1615  // document is duplicated, it will not be detected and the
1616  // attribute will be doubly added. However, tracking the 'prevAttribute'
1617  // avoids re-scanning the attribute list. Preferring performance for
1618  // now, may reconsider in the future.
1619  if ( prevAttribute ) {
1620  prevAttribute->_next = attrib;
1621  }
1622  else {
1623  _rootAttribute = attrib;
1624  }
1625  prevAttribute = attrib;
1626  }
1627  // end of the tag
1628  else if ( *p == '>' ) {
1629  ++p;
1630  break;
1631  }
1632  // end of the tag
1633  else if ( *p == '/' && *(p+1) == '>' ) {
1634  _closingType = CLOSED;
1635  return p+2; // done; sealed element.
1636  }
1637  else {
1639  return 0;
1640  }
1641  }
1642  return p;
1643 }
1644 
1646 {
1647  if ( attribute == 0 ) {
1648  return;
1649  }
1650  MemPool* pool = attribute->_memPool;
1651  attribute->~XMLAttribute();
1652  pool->Free( attribute );
1653 }
1654 
1655 //
1656 // <ele></ele>
1657 // <ele>foo<b>bar</b></ele>
1658 //
1659 char* XMLElement::ParseDeep( char* p, StrPair* strPair )
1660 {
1661  // Read the element name.
1662  p = XMLUtil::SkipWhiteSpace( p );
1663 
1664  // The closing element is the </element> form. It is
1665  // parsed just like a regular element then deleted from
1666  // the DOM.
1667  if ( *p == '/' ) {
1669  ++p;
1670  }
1671 
1672  p = _value.ParseName( p );
1673  if ( _value.Empty() ) {
1674  return 0;
1675  }
1676 
1677  p = ParseAttributes( p );
1678  if ( !p || !*p || _closingType ) {
1679  return p;
1680  }
1681 
1682  p = XMLNode::ParseDeep( p, strPair );
1683  return p;
1684 }
1685 
1686 
1687 
1689 {
1690  if ( !doc ) {
1691  doc = _document;
1692  }
1693  XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?
1694  for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
1695  element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?
1696  }
1697  return element;
1698 }
1699 
1700 
1701 bool XMLElement::ShallowEqual( const XMLNode* compare ) const
1702 {
1703  TIXMLASSERT( compare );
1704  const XMLElement* other = compare->ToElement();
1705  if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {
1706 
1707  const XMLAttribute* a=FirstAttribute();
1708  const XMLAttribute* b=other->FirstAttribute();
1709 
1710  while ( a && b ) {
1711  if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
1712  return false;
1713  }
1714  a = a->Next();
1715  b = b->Next();
1716  }
1717  if ( a || b ) {
1718  // different count
1719  return false;
1720  }
1721  return true;
1722  }
1723  return false;
1724 }
1725 
1726 
1727 bool XMLElement::Accept( XMLVisitor* visitor ) const
1728 {
1729  TIXMLASSERT( visitor );
1730  if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
1731  for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
1732  if ( !node->Accept( visitor ) ) {
1733  break;
1734  }
1735  }
1736  }
1737  return visitor->VisitExit( *this );
1738 }
1739 
1740 
1741 // --------- XMLDocument ----------- //
1742 
1743 // Warning: List must match 'enum XMLError'
1745  "XML_SUCCESS",
1746  "XML_NO_ATTRIBUTE",
1747  "XML_WRONG_ATTRIBUTE_TYPE",
1748  "XML_ERROR_FILE_NOT_FOUND",
1749  "XML_ERROR_FILE_COULD_NOT_BE_OPENED",
1750  "XML_ERROR_FILE_READ_ERROR",
1751  "XML_ERROR_ELEMENT_MISMATCH",
1752  "XML_ERROR_PARSING_ELEMENT",
1753  "XML_ERROR_PARSING_ATTRIBUTE",
1754  "XML_ERROR_IDENTIFYING_TAG",
1755  "XML_ERROR_PARSING_TEXT",
1756  "XML_ERROR_PARSING_CDATA",
1757  "XML_ERROR_PARSING_COMMENT",
1758  "XML_ERROR_PARSING_DECLARATION",
1759  "XML_ERROR_PARSING_UNKNOWN",
1760  "XML_ERROR_EMPTY_DOCUMENT",
1761  "XML_ERROR_MISMATCHED_ELEMENT",
1762  "XML_ERROR_PARSING",
1763  "XML_CAN_NOT_CONVERT_TEXT",
1764  "XML_NO_TEXT_NODE"
1765 };
1766 
1767 
1768 XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) :
1769  XMLNode( 0 ),
1770  _writeBOM( false ),
1771  _processEntities( processEntities ),
1772  _errorID( XML_NO_ERROR ),
1773  _whitespace( whitespace ),
1774  _errorStr1( 0 ),
1775  _errorStr2( 0 ),
1776  _charBuffer( 0 )
1777 {
1778  // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
1779  _document = this;
1780 }
1781 
1782 
1784 {
1785  Clear();
1786 }
1787 
1788 
1790 {
1791  DeleteChildren();
1792 
1793 #ifdef DEBUG
1794  const bool hadError = Error();
1795 #endif
1797  _errorStr1 = 0;
1798  _errorStr2 = 0;
1799 
1800  delete [] _charBuffer;
1801  _charBuffer = 0;
1802 
1803 #if 0
1804  _textPool.Trace( "text" );
1805  _elementPool.Trace( "element" );
1806  _commentPool.Trace( "comment" );
1807  _attributePool.Trace( "attribute" );
1808 #endif
1809 
1810 #ifdef DEBUG
1811  if ( !hadError ) {
1812  TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
1813  TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
1814  TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
1815  TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
1816  }
1817 #endif
1818 }
1819 
1820 
1822 {
1823  TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() );
1824  XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this );
1825  ele->_memPool = &_elementPool;
1826  ele->SetName( name );
1827  return ele;
1828 }
1829 
1830 
1832 {
1833  TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() );
1834  XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this );
1835  comment->_memPool = &_commentPool;
1836  comment->SetValue( str );
1837  return comment;
1838 }
1839 
1840 
1841 XMLText* XMLDocument::NewText( const char* str )
1842 {
1843  TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() );
1844  XMLText* text = new (_textPool.Alloc()) XMLText( this );
1845  text->_memPool = &_textPool;
1846  text->SetValue( str );
1847  return text;
1848 }
1849 
1850 
1852 {
1853  TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() );
1854  XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this );
1855  dec->_memPool = &_commentPool;
1856  dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
1857  return dec;
1858 }
1859 
1860 
1862 {
1863  TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() );
1864  XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this );
1865  unk->_memPool = &_commentPool;
1866  unk->SetValue( str );
1867  return unk;
1868 }
1869 
1870 static FILE* callfopen( const char* filepath, const char* mode )
1871 {
1872  TIXMLASSERT( filepath );
1873  TIXMLASSERT( mode );
1874 #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
1875  FILE* fp = 0;
1876  errno_t err = fopen_s( &fp, filepath, mode );
1877  if ( err ) {
1878  return 0;
1879  }
1880 #else
1881  FILE* fp = fopen( filepath, mode );
1882 #endif
1883  return fp;
1884 }
1885 
1887  TIXMLASSERT( node );
1888  TIXMLASSERT(node->_document == this );
1889  if (node->_parent) {
1890  node->_parent->DeleteChild( node );
1891  }
1892  else {
1893  // Isn't in the tree.
1894  // Use the parent delete.
1895  // Also, we need to mark it tracked: we 'know'
1896  // it was never used.
1897  node->_memPool->SetTracked();
1898  // Call the static XMLNode version:
1899  XMLNode::DeleteNode(node);
1900  }
1901 }
1902 
1903 
1904 XMLError XMLDocument::LoadFile( const char* filename )
1905 {
1906  Clear();
1907  FILE* fp = callfopen( filename, "rb" );
1908  if ( !fp ) {
1909  SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 );
1910  return _errorID;
1911  }
1912  LoadFile( fp );
1913  fclose( fp );
1914  return _errorID;
1915 }
1916 
1917 // This is likely overengineered template art to have a check that unsigned long value incremented
1918 // by one still fits into size_t. If size_t type is larger than unsigned long type
1919 // (x86_64-w64-mingw32 target) then the check is redundant and gcc and clang emit
1920 // -Wtype-limits warning. This piece makes the compiler select code with a check when a check
1921 // is useful and code with no check when a check is redundant depending on how size_t and unsigned long
1922 // types sizes relate to each other.
1923 template
1924 <bool = (sizeof(unsigned long) >= sizeof(size_t))>
1926  static bool Fits( unsigned long value )
1927  {
1928  return value < (size_t)-1;
1929  }
1930 };
1931 
1932 template <>
1933 bool LongFitsIntoSizeTMinusOne<false>::Fits( unsigned long /*value*/ )
1934 {
1935  return true;
1936 }
1937 
1939 {
1940  Clear();
1941 
1942  fseek( fp, 0, SEEK_SET );
1943  if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
1945  return _errorID;
1946  }
1947 
1948  fseek( fp, 0, SEEK_END );
1949  const long filelength = ftell( fp );
1950  fseek( fp, 0, SEEK_SET );
1951  if ( filelength == -1L ) {
1953  return _errorID;
1954  }
1955 
1956  if ( !LongFitsIntoSizeTMinusOne<>::Fits( filelength ) ) {
1957  // Cannot handle files which won't fit in buffer together with null terminator
1959  return _errorID;
1960  }
1961 
1962  if ( filelength == 0 ) {
1964  return _errorID;
1965  }
1966 
1967  const size_t size = filelength;
1968  TIXMLASSERT( _charBuffer == 0 );
1969  _charBuffer = new char[size+1];
1970  size_t read = fread( _charBuffer, 1, size, fp );
1971  if ( read != size ) {
1973  return _errorID;
1974  }
1975 
1976  _charBuffer[size] = 0;
1977 
1978  Parse();
1979  return _errorID;
1980 }
1981 
1982 
1983 XMLError XMLDocument::SaveFile( const char* filename, bool compact )
1984 {
1985  FILE* fp = callfopen( filename, "w" );
1986  if ( !fp ) {
1988  return _errorID;
1989  }
1990  SaveFile(fp, compact);
1991  fclose( fp );
1992  return _errorID;
1993 }
1994 
1995 
1996 XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
1997 {
1998  // Clear any error from the last save, otherwise it will get reported
1999  // for *this* call.
2000  SetError( XML_NO_ERROR, 0, 0 );
2001  XMLPrinter stream( fp, compact );
2002  Print( &stream );
2003  return _errorID;
2004 }
2005 
2006 
2007 XMLError XMLDocument::Parse( const char* p, size_t len )
2008 {
2009  Clear();
2010 
2011  if ( len == 0 || !p || !*p ) {
2013  return _errorID;
2014  }
2015  if ( len == (size_t)(-1) ) {
2016  len = strlen( p );
2017  }
2018  TIXMLASSERT( _charBuffer == 0 );
2019  _charBuffer = new char[ len+1 ];
2020  memcpy( _charBuffer, p, len );
2021  _charBuffer[len] = 0;
2022 
2023  Parse();
2024  if ( Error() ) {
2025  // clean up now essentially dangling memory.
2026  // and the parse fail can put objects in the
2027  // pools that are dead and inaccessible.
2028  DeleteChildren();
2029  _elementPool.Clear();
2030  _attributePool.Clear();
2031  _textPool.Clear();
2032  _commentPool.Clear();
2033  }
2034  return _errorID;
2035 }
2036 
2037 
2038 void XMLDocument::Print( XMLPrinter* streamer ) const
2039 {
2040  if ( streamer ) {
2041  Accept( streamer );
2042  }
2043  else {
2044  XMLPrinter stdoutStreamer( stdout );
2045  Accept( &stdoutStreamer );
2046  }
2047 }
2048 
2049 
2050 void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 )
2051 {
2052  TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
2053  _errorID = error;
2054  _errorStr1 = str1;
2055  _errorStr2 = str2;
2056 }
2057 
2058 const char* XMLDocument::ErrorName() const
2059 {
2061  const char* errorName = _errorNames[_errorID];
2062  TIXMLASSERT( errorName && errorName[0] );
2063  return errorName;
2064 }
2065 
2067 {
2068  if ( Error() ) {
2069  static const int LEN = 20;
2070  char buf1[LEN] = { 0 };
2071  char buf2[LEN] = { 0 };
2072 
2073  if ( _errorStr1 ) {
2074  TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 );
2075  }
2076  if ( _errorStr2 ) {
2077  TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 );
2078  }
2079 
2080  // Should check INT_MIN <= _errorID && _errorId <= INT_MAX, but that
2081  // causes a clang "always true" -Wtautological-constant-out-of-range-compare warning
2082  TIXMLASSERT( 0 <= _errorID && XML_ERROR_COUNT - 1 <= INT_MAX );
2083  printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n",
2084  static_cast<int>( _errorID ), ErrorName(), buf1, buf2 );
2085  }
2086 }
2087 
2089 {
2090  TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
2092  char* p = _charBuffer;
2093  p = XMLUtil::SkipWhiteSpace( p );
2094  p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
2095  if ( !*p ) {
2097  return;
2098  }
2099  ParseDeep(p, 0 );
2100 }
2101 
2102 XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
2103  _elementJustOpened( false ),
2104  _firstElement( true ),
2105  _fp( file ),
2106  _depth( depth ),
2107  _textDepth( -1 ),
2108  _processEntities( true ),
2109  _compactMode( compact )
2110 {
2111  for( int i=0; i<ENTITY_RANGE; ++i ) {
2112  _entityFlag[i] = false;
2113  _restrictedEntityFlag[i] = false;
2114  }
2115  for( int i=0; i<NUM_ENTITIES; ++i ) {
2116  const char entityValue = entities[i].value;
2117  TIXMLASSERT( 0 <= entityValue && entityValue < ENTITY_RANGE );
2118  _entityFlag[ (unsigned char)entityValue ] = true;
2119  }
2120  _restrictedEntityFlag[(unsigned char)'&'] = true;
2121  _restrictedEntityFlag[(unsigned char)'<'] = true;
2122  _restrictedEntityFlag[(unsigned char)'>'] = true; // not required, but consistency is nice
2123  _buffer.Push( 0 );
2124 }
2125 
2126 
2127 void XMLPrinter::Print( const char* format, ... )
2128 {
2129  va_list va;
2130  va_start( va, format );
2131 
2132  if ( _fp ) {
2133  vfprintf( _fp, format, va );
2134  }
2135  else {
2136  const int len = TIXML_VSCPRINTF( format, va );
2137  // Close out and re-start the va-args
2138  va_end( va );
2139  TIXMLASSERT( len >= 0 );
2140  va_start( va, format );
2141  TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
2142  char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
2143  TIXML_VSNPRINTF( p, len+1, format, va );
2144  }
2145  va_end( va );
2146 }
2147 
2148 
2149 void XMLPrinter::PrintSpace( int depth )
2150 {
2151  for( int i=0; i<depth; ++i ) {
2152  Print( " " );
2153  }
2154 }
2155 
2156 
2157 void XMLPrinter::PrintString( const char* p, bool restricted )
2158 {
2159  // Look for runs of bytes between entities to print.
2160  const char* q = p;
2161 
2162  if ( _processEntities ) {
2163  const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
2164  while ( *q ) {
2165  TIXMLASSERT( p <= q );
2166  // Remember, char is sometimes signed. (How many times has that bitten me?)
2167  if ( *q > 0 && *q < ENTITY_RANGE ) {
2168  // Check for entities. If one is found, flush
2169  // the stream up until the entity, write the
2170  // entity, and keep looking.
2171  if ( flag[(unsigned char)(*q)] ) {
2172  while ( p < q ) {
2173  const size_t delta = q - p;
2174  // %.*s accepts type int as "precision"
2175  const int toPrint = ( INT_MAX < delta ) ? INT_MAX : (int)delta;
2176  Print( "%.*s", toPrint, p );
2177  p += toPrint;
2178  }
2179  bool entityPatternPrinted = false;
2180  for( int i=0; i<NUM_ENTITIES; ++i ) {
2181  if ( entities[i].value == *q ) {
2182  Print( "&%s;", entities[i].pattern );
2183  entityPatternPrinted = true;
2184  break;
2185  }
2186  }
2187  if ( !entityPatternPrinted ) {
2188  // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
2189  TIXMLASSERT( false );
2190  }
2191  ++p;
2192  }
2193  }
2194  ++q;
2195  TIXMLASSERT( p <= q );
2196  }
2197  }
2198  // Flush the remaining string. This will be the entire
2199  // string if an entity wasn't found.
2200  TIXMLASSERT( p <= q );
2201  if ( !_processEntities || ( p < q ) ) {
2202  Print( "%s", p );
2203  }
2204 }
2205 
2206 
2207 void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
2208 {
2209  if ( writeBOM ) {
2210  static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
2211  Print( "%s", bom );
2212  }
2213  if ( writeDec ) {
2214  PushDeclaration( "xml version=\"1.0\"" );
2215  }
2216 }
2217 
2218 
2219 void XMLPrinter::OpenElement( const char* name, bool compactMode )
2220 {
2222  _stack.Push( name );
2223 
2224  if ( _textDepth < 0 && !_firstElement && !compactMode ) {
2225  Print( "\n" );
2226  }
2227  if ( !compactMode ) {
2228  PrintSpace( _depth );
2229  }
2230 
2231  Print( "<%s", name );
2232  _elementJustOpened = true;
2233  _firstElement = false;
2234  ++_depth;
2235 }
2236 
2237 
2238 void XMLPrinter::PushAttribute( const char* name, const char* value )
2239 {
2241  Print( " %s=\"", name );
2242  PrintString( value, false );
2243  Print( "\"" );
2244 }
2245 
2246 
2247 void XMLPrinter::PushAttribute( const char* name, int v )
2248 {
2249  char buf[BUF_SIZE];
2250  XMLUtil::ToStr( v, buf, BUF_SIZE );
2251  PushAttribute( name, buf );
2252 }
2253 
2254 
2255 void XMLPrinter::PushAttribute( const char* name, unsigned v )
2256 {
2257  char buf[BUF_SIZE];
2258  XMLUtil::ToStr( v, buf, BUF_SIZE );
2259  PushAttribute( name, buf );
2260 }
2261 
2262 
2263 void XMLPrinter::PushAttribute( const char* name, bool v )
2264 {
2265  char buf[BUF_SIZE];
2266  XMLUtil::ToStr( v, buf, BUF_SIZE );
2267  PushAttribute( name, buf );
2268 }
2269 
2270 
2271 void XMLPrinter::PushAttribute( const char* name, double v )
2272 {
2273  char buf[BUF_SIZE];
2274  XMLUtil::ToStr( v, buf, BUF_SIZE );
2275  PushAttribute( name, buf );
2276 }
2277 
2278 
2279 void XMLPrinter::CloseElement( bool compactMode )
2280 {
2281  --_depth;
2282  const char* name = _stack.Pop();
2283 
2284  if ( _elementJustOpened ) {
2285  Print( "/>" );
2286  }
2287  else {
2288  if ( _textDepth < 0 && !compactMode) {
2289  Print( "\n" );
2290  PrintSpace( _depth );
2291  }
2292  Print( "</%s>", name );
2293  }
2294 
2295  if ( _textDepth == _depth ) {
2296  _textDepth = -1;
2297  }
2298  if ( _depth == 0 && !compactMode) {
2299  Print( "\n" );
2300  }
2301  _elementJustOpened = false;
2302 }
2303 
2304 
2306 {
2307  if ( !_elementJustOpened ) {
2308  return;
2309  }
2310  _elementJustOpened = false;
2311  Print( ">" );
2312 }
2313 
2314 
2315 void XMLPrinter::PushText( const char* text, bool cdata )
2316 {
2317  _textDepth = _depth-1;
2318 
2320  if ( cdata ) {
2321  Print( "<![CDATA[%s]]>", text );
2322  }
2323  else {
2324  PrintString( text, true );
2325  }
2326 }
2327 
2328 void XMLPrinter::PushText( int value )
2329 {
2330  char buf[BUF_SIZE];
2331  XMLUtil::ToStr( value, buf, BUF_SIZE );
2332  PushText( buf, false );
2333 }
2334 
2335 
2336 void XMLPrinter::PushText( unsigned value )
2337 {
2338  char buf[BUF_SIZE];
2339  XMLUtil::ToStr( value, buf, BUF_SIZE );
2340  PushText( buf, false );
2341 }
2342 
2343 
2344 void XMLPrinter::PushText( bool value )
2345 {
2346  char buf[BUF_SIZE];
2347  XMLUtil::ToStr( value, buf, BUF_SIZE );
2348  PushText( buf, false );
2349 }
2350 
2351 
2352 void XMLPrinter::PushText( float value )
2353 {
2354  char buf[BUF_SIZE];
2355  XMLUtil::ToStr( value, buf, BUF_SIZE );
2356  PushText( buf, false );
2357 }
2358 
2359 
2360 void XMLPrinter::PushText( double value )
2361 {
2362  char buf[BUF_SIZE];
2363  XMLUtil::ToStr( value, buf, BUF_SIZE );
2364  PushText( buf, false );
2365 }
2366 
2367 
2368 void XMLPrinter::PushComment( const char* comment )
2369 {
2371  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2372  Print( "\n" );
2373  PrintSpace( _depth );
2374  }
2375  _firstElement = false;
2376  Print( "<!--%s-->", comment );
2377 }
2378 
2379 
2380 void XMLPrinter::PushDeclaration( const char* value )
2381 {
2383  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2384  Print( "\n" );
2385  PrintSpace( _depth );
2386  }
2387  _firstElement = false;
2388  Print( "<?%s?>", value );
2389 }
2390 
2391 
2392 void XMLPrinter::PushUnknown( const char* value )
2393 {
2395  if ( _textDepth < 0 && !_firstElement && !_compactMode) {
2396  Print( "\n" );
2397  PrintSpace( _depth );
2398  }
2399  _firstElement = false;
2400  Print( "<!%s>", value );
2401 }
2402 
2403 
2405 {
2407  if ( doc.HasBOM() ) {
2408  PushHeader( true, false );
2409  }
2410  return true;
2411 }
2412 
2413 
2414 bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
2415 {
2416  const XMLElement* parentElem = 0;
2417  if ( element.Parent() ) {
2418  parentElem = element.Parent()->ToElement();
2419  }
2420  const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
2421  OpenElement( element.Name(), compactMode );
2422  while ( attribute ) {
2423  PushAttribute( attribute->Name(), attribute->Value() );
2424  attribute = attribute->Next();
2425  }
2426  return true;
2427 }
2428 
2429 
2430 bool XMLPrinter::VisitExit( const XMLElement& element )
2431 {
2432  CloseElement( CompactMode(element) );
2433  return true;
2434 }
2435 
2436 
2437 bool XMLPrinter::Visit( const XMLText& text )
2438 {
2439  PushText( text.Value(), text.CData() );
2440  return true;
2441 }
2442 
2443 
2444 bool XMLPrinter::Visit( const XMLComment& comment )
2445 {
2446  PushComment( comment.Value() );
2447  return true;
2448 }
2449 
2450 bool XMLPrinter::Visit( const XMLDeclaration& declaration )
2451 {
2452  PushDeclaration( declaration.Value() );
2453  return true;
2454 }
2455 
2456 
2457 bool XMLPrinter::Visit( const XMLUnknown& unknown )
2458 {
2459  PushUnknown( unknown.Value() );
2460  return true;
2461 }
2462 
2463 } // namespace tinyxml2
2464 
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:1167
XMLText * NewText(const char *text)
Definition: tinyxml2.cpp:1841
virtual bool Visit(const XMLText &text)
Visit a text node.
Definition: tinyxml2.cpp:2437
XMLNode(XMLDocument *)
Definition: tinyxml2.cpp:700
void SetError(XMLError error, const char *str1, const char *str2)
Definition: tinyxml2.cpp:2050
void CollapseWhitespace()
Definition: tinyxml2.cpp:230
const char * _errorStr1
Definition: tinyxml2.h:1728
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1687
static const char LINE_FEED
Definition: tinyxml2.cpp:104
void SetText(const char *inText)
Definition: tinyxml2.cpp:1424
void SealElementIfJustOpened()
Definition: tinyxml2.cpp:2305
void Push(T t)
Definition: tinyxml2.h:204
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:874
static void ToStr(int v, char *buffer, int bufferSize)
Definition: tinyxml2.cpp:525
XMLAttribute * FindOrCreateAttribute(const char *name)
Definition: tinyxml2.cpp:1541
XMLError QueryIntValue(int *value) const
Definition: tinyxml2.cpp:1284
static const char * GetCharacterRef(const char *p, char *value, int *length)
Definition: tinyxml2.cpp:429
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:653
ROSCPP_DECL void start()
static const unsigned char TIXML_UTF_LEAD_0
Definition: tinyxml2.cpp:115
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:1904
void PushComment(const char *comment)
Add a comment.
Definition: tinyxml2.cpp:2368
T * PushArr(int count)
Definition: tinyxml2.h:210
char * ParseDeep(char *p, StrPair *endTag)
Definition: tinyxml2.cpp:1659
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1311
static const Entity entities[NUM_ENTITIES]
Definition: tinyxml2.cpp:129
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1083
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1114
XMLAttribute * _rootAttribute
Definition: tinyxml2.h:1515
MemPoolT< sizeof(XMLAttribute) > _attributePool
Definition: tinyxml2.h:1733
static const char * SkipWhiteSpace(const char *p)
Definition: tinyxml2.h:520
virtual ~XMLAttribute()
Definition: tinyxml2.h:1134
static bool ToFloat(const char *str, float *value)
Definition: tinyxml2.cpp:593
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:902
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:649
char * ParseDeep(char *, StrPair *endTag)
Definition: tinyxml2.cpp:1037
XMLError QueryBoolText(bool *bval) const
See QueryIntText()
Definition: tinyxml2.cpp:1501
XMLNode * _lastChild
Definition: tinyxml2.h:876
void PushHeader(bool writeBOM, bool writeDeclaration)
Definition: tinyxml2.cpp:2207
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:923
void Unlink(XMLNode *child)
Definition: tinyxml2.cpp:751
void PushDeclaration(const char *value)
Definition: tinyxml2.cpp:2380
virtual void Free(void *)=0
void PrintError() const
If there is an error, print it to stdout.
Definition: tinyxml2.cpp:2066
int ClosingType() const
Definition: tinyxml2.h:1487
static bool IsNameChar(unsigned char ch)
Definition: tinyxml2.h:549
static bool IsWhiteSpace(char p)
Definition: tinyxml2.h:534
static const char * ReadBOM(const char *p, bool *hasBOM)
Definition: tinyxml2.cpp:362
void TransferTo(StrPair *other)
Definition: tinyxml2.cpp:144
char * ParseDeep(char *p, bool processEntities)
Definition: tinyxml2.cpp:1250
XMLNode * _next
Definition: tinyxml2.h:879
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:915
const XMLAttribute * FindAttribute(const char *name) const
Query a specific attribute in the list.
Definition: tinyxml2.cpp:1391
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:715
XMLNode * _firstChild
Definition: tinyxml2.h:875
static const char * _errorNames[XML_ERROR_COUNT]
Definition: tinyxml2.h:1737
static bool ToBool(const char *str, bool *value)
Definition: tinyxml2.cpp:574
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:455
char * ParseName(char *in)
Definition: tinyxml2.cpp:210
const char * Value() const
The value of the attribute.
Definition: tinyxml2.cpp:1245
void SetAttribute(const char *value)
Set the attribute to a string value.
Definition: tinyxml2.cpp:1329
XMLNode * _parent
Definition: tinyxml2.h:872
MemPool * _memPool
Definition: tinyxml2.h:882
void Print(const char *format,...)
Definition: tinyxml2.cpp:2127
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1076
XMLPrinter(FILE *file=0, bool compact=false, int depth=0)
Definition: tinyxml2.cpp:2102
void Clear()
Clear the document, resetting it to the initial state.
Definition: tinyxml2.cpp:1789
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1327
virtual char * ParseDeep(char *, StrPair *)
Definition: tinyxml2.cpp:928
XMLError QueryDoubleText(double *dval) const
See QueryIntText()
Definition: tinyxml2.cpp:1514
void DeleteChildren()
Definition: tinyxml2.cpp:737
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:1821
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1065
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1320
bool ProcessEntities() const
Definition: tinyxml2.h:1595
DynArray< char, 20 > _buffer
Definition: tinyxml2.h:2102
_fp
static const unsigned char TIXML_UTF_LEAD_2
Definition: tinyxml2.cpp:117
char * ParseDeep(char *, StrPair *endTag)
Definition: tinyxml2.cpp:1152
static bool ToInt(const char *str, int *value)
Definition: tinyxml2.cpp:558
void SetName(const char *name)
Definition: tinyxml2.cpp:1278
#define TIXML_VSNPRINTF
Definition: tinyxml2.cpp:93
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:1983
static bool ToUnsigned(const char *str, unsigned *value)
Definition: tinyxml2.cpp:566
const XMLNode * Parent() const
Get the parent of this node on the DOM.
Definition: tinyxml2.h:701
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2315
XMLAttribute * _next
Definition: tinyxml2.h:1144
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1065
static int TIXML_VSCPRINTF(const char *format, va_list va)
Definition: tinyxml2.cpp:94
static const char CARRIAGE_RETURN
Definition: tinyxml2.cpp:106
XMLComment * NewComment(const char *comment)
Definition: tinyxml2.cpp:1831
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2279
StrPair _value
Definition: tinyxml2.h:873
void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:1886
virtual void SetTracked()=0
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1402
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.cpp:2404
static bool ToDouble(const char *str, double *value)
Definition: tinyxml2.cpp:601
XMLComment(XMLDocument *doc)
Definition: tinyxml2.cpp:1092
MemPoolT< sizeof(XMLComment) > _commentPool
Definition: tinyxml2.h:1735
#define TIXML_SNPRINTF
Definition: tinyxml2.cpp:92
const char * Name() const
The name of the attribute.
Definition: tinyxml2.cpp:1240
const char * GetText() const
Definition: tinyxml2.cpp:1415
XMLError QueryIntText(int *ival) const
Definition: tinyxml2.cpp:1475
static bool Fits(unsigned long value)
Definition: tinyxml2.cpp:1926
const char * GetStr()
Definition: tinyxml2.cpp:259
static const char SINGLE_QUOTE
Definition: tinyxml2.cpp:108
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2036
void OpenElement(const char *name, bool compactMode=false)
Definition: tinyxml2.cpp:2219
void SetStr(const char *str, int flags=0)
Definition: tinyxml2.cpp:178
int Size() const
Definition: tinyxml2.h:248
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1164
char * ParseDeep(char *, StrPair *endTag)
Definition: tinyxml2.cpp:1102
void SetCData(bool isCData)
Declare whether this should be CDATA or standard text.
Definition: tinyxml2.h:919
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1232
XMLDeclaration(XMLDocument *doc)
Definition: tinyxml2.cpp:1141
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:812
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:630
XMLElement(XMLDocument *doc)
Definition: tinyxml2.cpp:1374
char * ParseAttributes(char *p)
Definition: tinyxml2.cpp:1588
XMLDocument(bool processEntities=true, Whitespace=PRESERVE_WHITESPACE)
constructor
Definition: tinyxml2.cpp:1768
virtual XMLUnknown * ToUnknown()
Safely cast to an Unknown, or null.
Definition: tinyxml2.h:661
char * Identify(char *p, XMLNode **node)
Definition: tinyxml2.cpp:610
static bool StringEqual(const char *p, const char *q, int nChar=INT_MAX)
Definition: tinyxml2.h:556
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1224
const char * _errorStr2
Definition: tinyxml2.h:1729
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1214
void InsertChildPreamble(XMLNode *insertThis) const
Definition: tinyxml2.cpp:1025
const char * Value() const
Definition: tinyxml2.cpp:718
static void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:1015
XMLError QueryFloatText(float *fval) const
See QueryIntText()
Definition: tinyxml2.cpp:1527
void SetValue(const char *val, bool staticMem=false)
Definition: tinyxml2.cpp:726
XMLError QueryUnsignedText(unsigned *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1488
static const int NUM_ENTITIES
Definition: tinyxml2.cpp:128
void PushUnknown(const char *value)
Definition: tinyxml2.cpp:2392
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1183
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2238
virtual ~XMLNode()
Definition: tinyxml2.cpp:710
#define TIXMLASSERT(x)
Definition: tinyxml2.h:88
DynArray< const char *, 10 > _stack
Definition: tinyxml2.h:2083
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
Definition: tinyxml2.cpp:380
void DeleteAttribute(const char *name)
Definition: tinyxml2.cpp:1569
void PrintString(const char *, bool restrictedEntitySet)
Definition: tinyxml2.cpp:2157
const XMLElement * LastChildElement(const char *name=0) const
Definition: tinyxml2.cpp:888
const char * pattern
Definition: tinyxml2.cpp:123
XMLUnknown(XMLDocument *doc)
Definition: tinyxml2.cpp:1191
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1293
static bool IsNameStartChar(unsigned char ch)
Definition: tinyxml2.h:538
void DeleteChild(XMLNode *node)
Definition: tinyxml2.cpp:773
XMLDocument * _document
Definition: tinyxml2.h:871
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:645
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1688
bool HasBOM() const
Definition: tinyxml2.h:1605
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:684
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1132
static const char CR
Definition: tinyxml2.cpp:107
virtual void PrintSpace(int depth)
Definition: tinyxml2.cpp:2149
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1124
XMLUnknown * NewUnknown(const char *text)
Definition: tinyxml2.cpp:1861
virtual bool CompactMode(const XMLElement &)
Definition: tinyxml2.h:2073
MemPoolT< sizeof(XMLText) > _textPool
Definition: tinyxml2.h:1734
char * ParseDeep(char *, StrPair *endTag)
Definition: tinyxml2.cpp:1201
XMLDeclaration * NewDeclaration(const char *text=0)
Definition: tinyxml2.cpp:1851
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:710
MemPoolT< sizeof(XMLElement) > _elementPool
Definition: tinyxml2.h:1732
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1363
static const char LF
Definition: tinyxml2.cpp:105
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1174
virtual bool Visit(const XMLDeclaration &)
Visit a declaration.
Definition: tinyxml2.h:469
friend class XMLElement
Definition: tinyxml2.h:1532
bool _restrictedEntityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2100
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:451
XMLNode * _prev
Definition: tinyxml2.h:878
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2038
char * ParseText(char *in, const char *endTag, int strFlags)
Definition: tinyxml2.cpp:190
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1302
Whitespace WhitespaceMode() const
Definition: tinyxml2.h:1598
XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
Definition: tinyxml2.cpp:843
#define TIXML_SSCANF
Definition: tinyxml2.cpp:100
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:657
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:641
const char * ErrorName() const
Definition: tinyxml2.cpp:2058
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1727
static FILE * callfopen(const char *filepath, const char *mode)
Definition: tinyxml2.cpp:1870
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:782
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:767
bool _entityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2099
bool Empty() const
Definition: tinyxml2.h:144
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1159
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1701
void SetInternedStr(const char *str)
Definition: tinyxml2.h:148


denso_robot_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Mon Jun 10 2019 13:12:27