Panda3D
tinyxml.cpp
1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12 
13 1. The origin of this software must not be misrepresented; you must
14 not claim that you wrote the original software. If you use this
15 software in a product, an acknowledgment in the product documentation
16 would be appreciated but is not required.
17 
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20 
21 3. This notice may not be removed or altered from any source
22 distribution.
23 */
24 
25 #include <ctype.h>
26 
27 #ifdef TIXML_USE_STL
28 #include <sstream>
29 #include <iostream>
30 #endif
31 #ifdef _WIN32
32 #include <windows.h>
33 #endif // _WIN32
34 
35 #include "tinyxml.h"
36 
37 FILE* TiXmlFOpen( const char* filename, const char* mode );
38 
39 bool TiXmlBase::condenseWhiteSpace = true;
40 
41 // Microsoft compiler security
42 FILE* TiXmlFOpen( const char* filename, const char* mode )
43 {
44  #if defined(_MSC_VER) && (_MSC_VER >= 1400 )
45  FILE* fp = nullptr;
46 
47  /* Addition by drwr for Windows wide-character support */
48  //errno_t err = fopen_s( &fp, filename, mode );
49  errno_t err = 1;
50  {
51  int size = MultiByteToWideChar(CP_UTF8, 0, filename, -1,
52  NULL, 0);
53  if (size > 0) {
54  wchar_t *buffer = new wchar_t[size];
55  int rc = MultiByteToWideChar(CP_UTF8, 0, filename, -1,
56  buffer, size);
57  if (rc != 0) {
58  buffer[size - 1] = 0;
59  err = _wfopen_s( &fp, buffer, mode[0] == 'w' ? L"w" : L"rb" );
60  }
61  delete[] buffer;
62  }
63  }
64  /* End wide-character addition */
65 
66  if ( !err && fp )
67  return fp;
68  return nullptr;
69  #else
70  return fopen( filename, mode );
71  #endif
72 }
73 
74 void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
75 {
76  int i=0;
77 
78  while( i<(int)str.length() )
79  {
80  unsigned char c = (unsigned char) str[i];
81 
82  if ( c == '&'
83  && i < ( (int)str.length() - 2 )
84  && str[i+1] == '#'
85  && str[i+2] == 'x' )
86  {
87  // Hexadecimal character reference.
88  // Pass through unchanged.
89  // &#xA9; -- copyright symbol, for example.
90  //
91  // The -1 is a bug fix from Rob Laveaux. It keeps
92  // an overflow from happening if there is no ';'.
93  // There are actually 2 ways to exit this loop -
94  // while fails (error case) and break (semicolon found).
95  // However, there is no mechanism (currently) for
96  // this function to return an error.
97  while ( i<(int)str.length()-1 )
98  {
99  outString->append( str.c_str() + i, 1 );
100  ++i;
101  if ( str[i] == ';' )
102  break;
103  }
104  }
105  else if ( c == '&' )
106  {
107  outString->append( entity[0].str, entity[0].strLength );
108  ++i;
109  }
110  else if ( c == '<' )
111  {
112  outString->append( entity[1].str, entity[1].strLength );
113  ++i;
114  }
115  else if ( c == '>' )
116  {
117  outString->append( entity[2].str, entity[2].strLength );
118  ++i;
119  }
120  else if ( c == '\"' )
121  {
122  outString->append( entity[3].str, entity[3].strLength );
123  ++i;
124  }
125  else if ( c == '\'' )
126  {
127  outString->append( entity[4].str, entity[4].strLength );
128  ++i;
129  }
130  else if ( c < 32 )
131  {
132  // Easy pass at non-alpha/numeric/symbol
133  // Below 32 is symbolic.
134  char buf[ 32 ];
135 
136  #if defined(TIXML_SNPRINTF)
137  TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
138  #else
139  sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
140  #endif
141 
142  //*ME: warning C4267: convert 'size_t' to 'int'
143  //*ME: Int-Cast to make compiler happy ...
144  outString->append( buf, (int)strlen( buf ) );
145  ++i;
146  }
147  else
148  {
149  //char realc = (char) c;
150  //outString->append( &realc, 1 );
151  *outString += (char) c; // somewhat more efficient function call.
152  ++i;
153  }
154  }
155 }
156 
157 
158 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
159 {
160  parent = nullptr;
161  type = _type;
162  firstChild = nullptr;
163  lastChild = nullptr;
164  prev = nullptr;
165  next = nullptr;
166 }
167 
168 
169 TiXmlNode::~TiXmlNode()
170 {
171  TiXmlNode* node = firstChild;
172  TiXmlNode* temp = nullptr;
173 
174  while ( node )
175  {
176  temp = node;
177  node = node->next;
178  delete temp;
179  }
180 }
181 
182 
183 void TiXmlNode::CopyTo( TiXmlNode* target ) const
184 {
185  target->SetValue (value.c_str() );
186  target->userData = userData;
187  target->location = location;
188 }
189 
190 
192 {
193  TiXmlNode* node = firstChild;
194  TiXmlNode* temp = nullptr;
195 
196  while ( node )
197  {
198  temp = node;
199  node = node->next;
200  delete temp;
201  }
202 
203  firstChild = nullptr;
204  lastChild = nullptr;
205 }
206 
207 
209 {
210  assert( node->parent == nullptr || node->parent == this );
211  assert( node->GetDocument() == nullptr || node->GetDocument() == this->GetDocument() );
212 
213  if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
214  {
215  delete node;
216  if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
217  return nullptr;
218  }
219 
220  node->parent = this;
221 
222  node->prev = lastChild;
223  node->next = nullptr;
224 
225  if ( lastChild )
226  lastChild->next = node;
227  else
228  firstChild = node; // it was an empty list.
229 
230  lastChild = node;
231  return node;
232 }
233 
234 
236 {
237  if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
238  {
239  if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
240  return nullptr;
241  }
242  TiXmlNode* node = addThis.Clone();
243  if ( !node )
244  return nullptr;
245 
246  return LinkEndChild( node );
247 }
248 
249 
251 {
252  if ( !beforeThis || beforeThis->parent != this ) {
253  return nullptr;
254  }
255  if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
256  {
257  if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
258  return nullptr;
259  }
260 
261  TiXmlNode* node = addThis.Clone();
262  if ( !node )
263  return nullptr;
264  node->parent = this;
265 
266  node->next = beforeThis;
267  node->prev = beforeThis->prev;
268  if ( beforeThis->prev )
269  {
270  beforeThis->prev->next = node;
271  }
272  else
273  {
274  assert( firstChild == beforeThis );
275  firstChild = node;
276  }
277  beforeThis->prev = node;
278  return node;
279 }
280 
281 
283 {
284  if ( !afterThis || afterThis->parent != this ) {
285  return nullptr;
286  }
287  if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
288  {
289  if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
290  return nullptr;
291  }
292 
293  TiXmlNode* node = addThis.Clone();
294  if ( !node )
295  return nullptr;
296  node->parent = this;
297 
298  node->prev = afterThis;
299  node->next = afterThis->next;
300  if ( afterThis->next )
301  {
302  afterThis->next->prev = node;
303  }
304  else
305  {
306  assert( lastChild == afterThis );
307  lastChild = node;
308  }
309  afterThis->next = node;
310  return node;
311 }
312 
313 
314 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
315 {
316  if ( !replaceThis )
317  return nullptr;
318 
319  if ( replaceThis->parent != this )
320  return nullptr;
321 
322  if ( withThis.ToDocument() ) {
323  // A document can never be a child. Thanks to Noam.
324  TiXmlDocument* document = GetDocument();
325  if ( document )
326  document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
327  return nullptr;
328  }
329 
330  TiXmlNode* node = withThis.Clone();
331  if ( !node )
332  return nullptr;
333 
334  node->next = replaceThis->next;
335  node->prev = replaceThis->prev;
336 
337  if ( replaceThis->next )
338  replaceThis->next->prev = node;
339  else
340  lastChild = node;
341 
342  if ( replaceThis->prev )
343  replaceThis->prev->next = node;
344  else
345  firstChild = node;
346 
347  delete replaceThis;
348  node->parent = this;
349  return node;
350 }
351 
352 
354 {
355  if ( !removeThis ) {
356  return false;
357  }
358 
359  if ( removeThis->parent != this )
360  {
361  assert( 0 );
362  return false;
363  }
364 
365  if ( removeThis->next )
366  removeThis->next->prev = removeThis->prev;
367  else
368  lastChild = removeThis->prev;
369 
370  if ( removeThis->prev )
371  removeThis->prev->next = removeThis->next;
372  else
373  firstChild = removeThis->next;
374 
375  delete removeThis;
376  return true;
377 }
378 
379 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
380 {
381  const TiXmlNode* node;
382  for ( node = firstChild; node; node = node->next )
383  {
384  if ( strcmp( node->Value(), _value ) == 0 )
385  return node;
386  }
387  return nullptr;
388 }
389 
390 
391 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
392 {
393  const TiXmlNode* node;
394  for ( node = lastChild; node; node = node->prev )
395  {
396  if ( strcmp( node->Value(), _value ) == 0 )
397  return node;
398  }
399  return nullptr;
400 }
401 
402 
403 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
404 {
405  if ( !previous )
406  {
407  return FirstChild();
408  }
409  else
410  {
411  assert( previous->parent == this );
412  return previous->NextSibling();
413  }
414 }
415 
416 
417 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
418 {
419  if ( !previous )
420  {
421  return FirstChild( val );
422  }
423  else
424  {
425  assert( previous->parent == this );
426  return previous->NextSibling( val );
427  }
428 }
429 
430 
431 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
432 {
433  const TiXmlNode* node;
434  for ( node = next; node; node = node->next )
435  {
436  if ( strcmp( node->Value(), _value ) == 0 )
437  return node;
438  }
439  return nullptr;
440 }
441 
442 
443 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
444 {
445  const TiXmlNode* node;
446  for ( node = prev; node; node = node->prev )
447  {
448  if ( strcmp( node->Value(), _value ) == 0 )
449  return node;
450  }
451  return nullptr;
452 }
453 
454 
455 void TiXmlElement::RemoveAttribute( const char * name )
456 {
457  #ifdef TIXML_USE_STL
458  TIXML_STRING str( name );
459  TiXmlAttribute* node = attributeSet.Find( str );
460  #else
461  TiXmlAttribute* node = attributeSet.Find( name );
462  #endif
463  if ( node )
464  {
465  attributeSet.Remove( node );
466  delete node;
467  }
468 }
469 
471 {
472  const TiXmlNode* node;
473 
474  for ( node = FirstChild();
475  node;
476  node = node->NextSibling() )
477  {
478  if ( node->ToElement() )
479  return node->ToElement();
480  }
481  return nullptr;
482 }
483 
484 
485 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
486 {
487  const TiXmlNode* node;
488 
489  for ( node = FirstChild( _value );
490  node;
491  node = node->NextSibling( _value ) )
492  {
493  if ( node->ToElement() )
494  return node->ToElement();
495  }
496  return nullptr;
497 }
498 
499 
501 {
502  const TiXmlNode* node;
503 
504  for ( node = NextSibling();
505  node;
506  node = node->NextSibling() )
507  {
508  if ( node->ToElement() )
509  return node->ToElement();
510  }
511  return nullptr;
512 }
513 
514 
515 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
516 {
517  const TiXmlNode* node;
518 
519  for ( node = NextSibling( _value );
520  node;
521  node = node->NextSibling( _value ) )
522  {
523  if ( node->ToElement() )
524  return node->ToElement();
525  }
526  return nullptr;
527 }
528 
529 
531 {
532  const TiXmlNode* node;
533 
534  for( node = this; node; node = node->parent )
535  {
536  if ( node->ToDocument() )
537  return node->ToDocument();
538  }
539  return nullptr;
540 }
541 
542 
543 TiXmlElement::TiXmlElement (const char * _value)
544  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
545 {
546  firstChild = lastChild = nullptr;
547  value = _value;
548 }
549 
550 
551 #ifdef TIXML_USE_STL
552 TiXmlElement::TiXmlElement( const std::string& _value )
553  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
554 {
555  firstChild = lastChild = nullptr;
556  value = _value;
557 }
558 #endif
559 
560 
562  : TiXmlNode( TiXmlNode::TINYXML_ELEMENT )
563 {
564  firstChild = lastChild = nullptr;
565  copy.CopyTo( this );
566 }
567 
568 
569 void TiXmlElement::operator=( const TiXmlElement& base )
570 {
571  ClearThis();
572  base.CopyTo( this );
573 }
574 
575 
576 TiXmlElement::~TiXmlElement()
577 {
578  ClearThis();
579 }
580 
581 
582 void TiXmlElement::ClearThis()
583 {
584  Clear();
585  while( attributeSet.First() )
586  {
587  TiXmlAttribute* node = attributeSet.First();
588  attributeSet.Remove( node );
589  delete node;
590  }
591 }
592 
593 
594 const char* TiXmlElement::Attribute( const char* name ) const
595 {
596  const TiXmlAttribute* node = attributeSet.Find( name );
597  if ( node )
598  return node->Value();
599  return nullptr;
600 }
601 
602 
603 #ifdef TIXML_USE_STL
604 const std::string* TiXmlElement::Attribute( const std::string& name ) const
605 {
606  const TiXmlAttribute* attrib = attributeSet.Find( name );
607  if ( attrib )
608  return &attrib->ValueStr();
609  return nullptr;
610 }
611 #endif
612 
613 
614 const char* TiXmlElement::Attribute( const char* name, int* i ) const
615 {
616  const TiXmlAttribute* attrib = attributeSet.Find( name );
617  const char* result = nullptr;
618 
619  if ( attrib ) {
620  result = attrib->Value();
621  if ( i ) {
622  attrib->QueryIntValue( i );
623  }
624  }
625  return result;
626 }
627 
628 
629 #ifdef TIXML_USE_STL
630 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
631 {
632  const TiXmlAttribute* attrib = attributeSet.Find( name );
633  const std::string* result = nullptr;
634 
635  if ( attrib ) {
636  result = &attrib->ValueStr();
637  if ( i ) {
638  attrib->QueryIntValue( i );
639  }
640  }
641  return result;
642 }
643 #endif
644 
645 
646 const char* TiXmlElement::Attribute( const char* name, double* d ) const
647 {
648  const TiXmlAttribute* attrib = attributeSet.Find( name );
649  const char* result = nullptr;
650 
651  if ( attrib ) {
652  result = attrib->Value();
653  if ( d ) {
654  attrib->QueryDoubleValue( d );
655  }
656  }
657  return result;
658 }
659 
660 
661 #ifdef TIXML_USE_STL
662 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
663 {
664  const TiXmlAttribute* attrib = attributeSet.Find( name );
665  const std::string* result = nullptr;
666 
667  if ( attrib ) {
668  result = &attrib->ValueStr();
669  if ( d ) {
670  attrib->QueryDoubleValue( d );
671  }
672  }
673  return result;
674 }
675 #endif
676 
677 
678 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
679 {
680  const TiXmlAttribute* attrib = attributeSet.Find( name );
681  if ( !attrib )
682  return TIXML_NO_ATTRIBUTE;
683  return attrib->QueryIntValue( ival );
684 }
685 
686 
687 #ifdef TIXML_USE_STL
688 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
689 {
690  const TiXmlAttribute* attrib = attributeSet.Find( name );
691  if ( !attrib )
692  return TIXML_NO_ATTRIBUTE;
693  return attrib->QueryIntValue( ival );
694 }
695 #endif
696 
697 
698 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
699 {
700  const TiXmlAttribute* attrib = attributeSet.Find( name );
701  if ( !attrib )
702  return TIXML_NO_ATTRIBUTE;
703  return attrib->QueryDoubleValue( dval );
704 }
705 
706 
707 #ifdef TIXML_USE_STL
708 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
709 {
710  const TiXmlAttribute* attrib = attributeSet.Find( name );
711  if ( !attrib )
712  return TIXML_NO_ATTRIBUTE;
713  return attrib->QueryDoubleValue( dval );
714 }
715 #endif
716 
717 
718 void TiXmlElement::SetAttribute( const char * name, int val )
719 {
720  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
721  if ( attrib ) {
722  attrib->SetIntValue( val );
723  }
724 }
725 
726 
727 #ifdef TIXML_USE_STL
728 void TiXmlElement::SetAttribute( const std::string& name, int val )
729 {
730  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
731  if ( attrib ) {
732  attrib->SetIntValue( val );
733  }
734 }
735 #endif
736 
737 
738 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
739 {
740  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
741  if ( attrib ) {
742  attrib->SetDoubleValue( val );
743  }
744 }
745 
746 
747 #ifdef TIXML_USE_STL
748 void TiXmlElement::SetDoubleAttribute( const std::string& name, double val )
749 {
750  TiXmlAttribute* attrib = attributeSet.FindOrCreate( name );
751  if ( attrib ) {
752  attrib->SetDoubleValue( val );
753  }
754 }
755 #endif
756 
757 
758 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
759 {
760  TiXmlAttribute* attrib = attributeSet.FindOrCreate( cname );
761  if ( attrib ) {
762  attrib->SetValue( cvalue );
763  }
764 }
765 
766 
767 #ifdef TIXML_USE_STL
768 void TiXmlElement::SetAttribute( const std::string& _name, const std::string& _value )
769 {
770  TiXmlAttribute* attrib = attributeSet.FindOrCreate( _name );
771  if ( attrib ) {
772  attrib->SetValue( _value );
773  }
774 }
775 #endif
776 
777 
778 void TiXmlElement::Print( FILE* cfile, int depth ) const
779 {
780  int i;
781  assert( cfile );
782  for ( i=0; i<depth; i++ ) {
783  fprintf( cfile, " " );
784  }
785 
786  fprintf( cfile, "<%s", value.c_str() );
787 
788  const TiXmlAttribute* attrib;
789  for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
790  {
791  fprintf( cfile, " " );
792  attrib->Print( cfile, depth );
793  }
794 
795  // There are 3 different formatting approaches:
796  // 1) An element without children is printed as a <foo /> node
797  // 2) An element with only a text child is printed as <foo> text </foo>
798  // 3) An element with children is printed on multiple lines.
799  TiXmlNode* node;
800  if ( !firstChild )
801  {
802  fprintf( cfile, " />" );
803  }
804  else if ( firstChild == lastChild && firstChild->ToText() )
805  {
806  fprintf( cfile, ">" );
807  firstChild->Print( cfile, depth + 1 );
808  fprintf( cfile, "</%s>", value.c_str() );
809  }
810  else
811  {
812  fprintf( cfile, ">" );
813 
814  for ( node = firstChild; node; node=node->NextSibling() )
815  {
816  if ( !node->ToText() )
817  {
818  fprintf( cfile, "\n" );
819  }
820  node->Print( cfile, depth+1 );
821  }
822  fprintf( cfile, "\n" );
823  for( i=0; i<depth; ++i ) {
824  fprintf( cfile, " " );
825  }
826  fprintf( cfile, "</%s>", value.c_str() );
827  }
828 }
829 
830 
831 void TiXmlElement::CopyTo( TiXmlElement* target ) const
832 {
833  // superclass:
834  TiXmlNode::CopyTo( target );
835 
836  // Element class:
837  // Clone the attributes, then clone the children.
838  const TiXmlAttribute* attribute = nullptr;
839  for( attribute = attributeSet.First();
840  attribute;
841  attribute = attribute->Next() )
842  {
843  target->SetAttribute( attribute->Name(), attribute->Value() );
844  }
845 
846  TiXmlNode* node = nullptr;
847  for ( node = firstChild; node; node = node->NextSibling() )
848  {
849  target->LinkEndChild( node->Clone() );
850  }
851 }
852 
853 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
854 {
855  if ( visitor->VisitEnter( *this, attributeSet.First() ) )
856  {
857  for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
858  {
859  if ( !node->Accept( visitor ) )
860  break;
861  }
862  }
863  return visitor->VisitExit( *this );
864 }
865 
866 
868 {
869  TiXmlElement* clone = new TiXmlElement( Value() );
870  if ( !clone )
871  return nullptr;
872 
873  CopyTo( clone );
874  return clone;
875 }
876 
877 
878 const char* TiXmlElement::GetText() const
879 {
880  const TiXmlNode* child = this->FirstChild();
881  if ( child ) {
882  const TiXmlText* childText = child->ToText();
883  if ( childText ) {
884  return childText->Value();
885  }
886  }
887  return nullptr;
888 }
889 
890 
892 {
893  tabsize = 4;
894  useMicrosoftBOM = false;
895  ClearError();
896 }
897 
898 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
899 {
900  tabsize = 4;
901  useMicrosoftBOM = false;
902  value = documentName;
903  ClearError();
904 }
905 
906 
907 #ifdef TIXML_USE_STL
908 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
909 {
910  tabsize = 4;
911  useMicrosoftBOM = false;
912  value = documentName;
913  ClearError();
914 }
915 #endif
916 
917 
918 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::TINYXML_DOCUMENT )
919 {
920  copy.CopyTo( this );
921 }
922 
923 
924 void TiXmlDocument::operator=( const TiXmlDocument& copy )
925 {
926  Clear();
927  copy.CopyTo( this );
928 }
929 
930 
931 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
932 {
933  return LoadFile( Value(), encoding );
934 }
935 
936 
938 {
939  return SaveFile( Value() );
940 }
941 
942 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
943 {
944  TIXML_STRING filename( _filename );
945  value = filename;
946 
947  // reading in binary mode so that tinyxml can normalize the EOL
948  FILE* file = TiXmlFOpen( value.c_str (), "rb" );
949 
950  if ( file )
951  {
952  bool result = LoadFile( file, encoding );
953  fclose( file );
954  return result;
955  }
956  else
957  {
958  SetError( TIXML_ERROR_OPENING_FILE, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
959  return false;
960  }
961 }
962 
963 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
964 {
965  if ( !file )
966  {
967  SetError( TIXML_ERROR_OPENING_FILE, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
968  return false;
969  }
970 
971  // Delete the existing data:
972  Clear();
973  location.Clear();
974 
975  // Get the file size, so we can pre-allocate the string. HUGE speed impact.
976  long length = 0;
977  fseek( file, 0, SEEK_END );
978  length = ftell( file );
979  fseek( file, 0, SEEK_SET );
980 
981  // Strange case, but good to handle up front.
982  if ( length <= 0 )
983  {
984  SetError( TIXML_ERROR_DOCUMENT_EMPTY, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
985  return false;
986  }
987 
988  // Subtle bug here. TinyXml did use fgets. But from the XML spec:
989  // 2.11 End-of-Line Handling
990  // <snip>
991  // <quote>
992  // ...the XML processor MUST behave as if it normalized all line breaks in external
993  // parsed entities (including the document entity) on input, before parsing, by translating
994  // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
995  // a single #xA character.
996  // </quote>
997  //
998  // It is not clear fgets does that, and certainly isn't clear it works cross platform.
999  // Generally, you expect fgets to translate from the convention of the OS to the c/unix
1000  // convention, and not work generally.
1001 
1002  /*
1003  while( fgets( buf, sizeof(buf), file ) )
1004  {
1005  data += buf;
1006  }
1007  */
1008 
1009  char* buf = new char[ length+1 ];
1010  buf[0] = 0;
1011 
1012  if ( fread( buf, length, 1, file ) != 1 ) {
1013  delete [] buf;
1014  SetError( TIXML_ERROR_OPENING_FILE, nullptr, nullptr, TIXML_ENCODING_UNKNOWN );
1015  return false;
1016  }
1017 
1018  // Process the buffer in place to normalize new lines. (See comment above.)
1019  // Copies from the 'p' to 'q' pointer, where p can advance faster if
1020  // a newline-carriage return is hit.
1021  //
1022  // Wikipedia:
1023  // Systems based on ASCII or a compatible character set use either LF (Line feed, '\n', 0x0A, 10 in decimal) or
1024  // CR (Carriage return, '\r', 0x0D, 13 in decimal) individually, or CR followed by LF (CR+LF, 0x0D 0x0A)...
1025  // * LF: Multics, Unix and Unix-like systems (GNU/Linux, AIX, Xenix, Mac OS X, FreeBSD, etc.), BeOS, Amiga, RISC OS, and others
1026  // * CR+LF: DEC RT-11 and most other early non-Unix, non-IBM OSes, CP/M, MP/M, DOS, OS/2, Microsoft Windows, Symbian OS
1027  // * CR: Commodore 8-bit machines, Apple II family, Mac OS up to version 9 and OS-9
1028 
1029  const char* p = buf; // the read head
1030  char* q = buf; // the write head
1031  const char CR = 0x0d;
1032  const char LF = 0x0a;
1033 
1034  buf[length] = 0;
1035  while( *p ) {
1036  assert( p < (buf+length) );
1037  assert( q <= (buf+length) );
1038  assert( q <= p );
1039 
1040  if ( *p == CR ) {
1041  *q++ = LF;
1042  p++;
1043  if ( *p == LF ) { // check for CR+LF (and skip LF)
1044  p++;
1045  }
1046  }
1047  else {
1048  *q++ = *p++;
1049  }
1050  }
1051  assert( q <= (buf+length) );
1052  *q = 0;
1053 
1054  Parse( buf, nullptr, encoding );
1055 
1056  delete [] buf;
1057  return !Error();
1058 }
1059 
1060 
1061 bool TiXmlDocument::SaveFile( const char * filename ) const
1062 {
1063  // The old c stuff lives on...
1064  FILE* fp = TiXmlFOpen( filename, "w" );
1065  if ( fp )
1066  {
1067  bool result = SaveFile( fp );
1068  fclose( fp );
1069  return result;
1070  }
1071  return false;
1072 }
1073 
1074 
1075 bool TiXmlDocument::SaveFile( FILE* fp ) const
1076 {
1077  if ( useMicrosoftBOM )
1078  {
1079  const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1080  const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1081  const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1082 
1083  fputc( TIXML_UTF_LEAD_0, fp );
1084  fputc( TIXML_UTF_LEAD_1, fp );
1085  fputc( TIXML_UTF_LEAD_2, fp );
1086  }
1087  Print( fp, 0 );
1088  return (ferror(fp) == 0);
1089 }
1090 
1091 
1092 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1093 {
1094  TiXmlNode::CopyTo( target );
1095 
1096  target->error = error;
1097  target->errorId = errorId;
1098  target->errorDesc = errorDesc;
1099  target->tabsize = tabsize;
1100  target->errorLocation = errorLocation;
1101  target->useMicrosoftBOM = useMicrosoftBOM;
1102 
1103  TiXmlNode* node = nullptr;
1104  for ( node = firstChild; node; node = node->NextSibling() )
1105  {
1106  target->LinkEndChild( node->Clone() );
1107  }
1108 }
1109 
1110 
1111 TiXmlNode* TiXmlDocument::Clone() const
1112 {
1113  TiXmlDocument* clone = new TiXmlDocument();
1114  if ( !clone )
1115  return nullptr;
1116 
1117  CopyTo( clone );
1118  return clone;
1119 }
1120 
1121 
1122 void TiXmlDocument::Print( FILE* cfile, int depth ) const
1123 {
1124  assert( cfile );
1125  for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1126  {
1127  node->Print( cfile, depth );
1128  fprintf( cfile, "\n" );
1129  }
1130 }
1131 
1132 
1133 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1134 {
1135  if ( visitor->VisitEnter( *this ) )
1136  {
1137  for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1138  {
1139  if ( !node->Accept( visitor ) )
1140  break;
1141  }
1142  }
1143  return visitor->VisitExit( *this );
1144 }
1145 
1146 
1148 {
1149  // We are using knowledge of the sentinel. The sentinel
1150  // have a value or name.
1151  if ( next->value.empty() && next->name.empty() )
1152  return nullptr;
1153  return next;
1154 }
1155 
1156 /*
1157 TiXmlAttribute* TiXmlAttribute::Next()
1158 {
1159  // We are using knowledge of the sentinel. The sentinel
1160  // have a value or name.
1161  if ( next->value.empty() && next->name.empty() )
1162  return 0;
1163  return next;
1164 }
1165 */
1166 
1168 {
1169  // We are using knowledge of the sentinel. The sentinel
1170  // have a value or name.
1171  if ( prev->value.empty() && prev->name.empty() )
1172  return nullptr;
1173  return prev;
1174 }
1175 
1176 /*
1177 TiXmlAttribute* TiXmlAttribute::Previous()
1178 {
1179  // We are using knowledge of the sentinel. The sentinel
1180  // have a value or name.
1181  if ( prev->value.empty() && prev->name.empty() )
1182  return 0;
1183  return prev;
1184 }
1185 */
1186 
1187 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1188 {
1189  TIXML_STRING n, v;
1190 
1191  EncodeString( name, &n );
1192  EncodeString( value, &v );
1193 
1194  if (value.find ('\"') == TIXML_STRING::npos) {
1195  if ( cfile ) {
1196  fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1197  }
1198  if ( str ) {
1199  (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1200  }
1201  }
1202  else {
1203  if ( cfile ) {
1204  fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1205  }
1206  if ( str ) {
1207  (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1208  }
1209  }
1210 }
1211 
1212 
1213 int TiXmlAttribute::QueryIntValue( int* ival ) const
1214 {
1215  if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1216  return TIXML_SUCCESS;
1217  return TIXML_WRONG_TYPE;
1218 }
1219 
1220 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1221 {
1222  if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1223  return TIXML_SUCCESS;
1224  return TIXML_WRONG_TYPE;
1225 }
1226 
1228 {
1229  char buf [64];
1230  #if defined(TIXML_SNPRINTF)
1231  TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1232  #else
1233  sprintf (buf, "%d", _value);
1234  #endif
1235  SetValue (buf);
1236 }
1237 
1238 void TiXmlAttribute::SetDoubleValue( double _value )
1239 {
1240  char buf [256];
1241  #if defined(TIXML_SNPRINTF)
1242  TIXML_SNPRINTF( buf, sizeof(buf), "%g", _value);
1243  #else
1244  sprintf (buf, "%g", _value);
1245  #endif
1246  SetValue (buf);
1247 }
1248 
1250 {
1251  return atoi (value.c_str ());
1252 }
1253 
1255 {
1256  return atof (value.c_str ());
1257 }
1258 
1259 
1260 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT )
1261 {
1262  copy.CopyTo( this );
1263 }
1264 
1265 
1266 void TiXmlComment::operator=( const TiXmlComment& base )
1267 {
1268  Clear();
1269  base.CopyTo( this );
1270 }
1271 
1272 
1273 void TiXmlComment::Print( FILE* cfile, int depth ) const
1274 {
1275  assert( cfile );
1276  for ( int i=0; i<depth; i++ )
1277  {
1278  fprintf( cfile, " " );
1279  }
1280  fprintf( cfile, "<!--%s-->", value.c_str() );
1281 }
1282 
1283 
1284 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1285 {
1286  TiXmlNode::CopyTo( target );
1287 }
1288 
1289 
1290 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1291 {
1292  return visitor->Visit( *this );
1293 }
1294 
1295 
1297 {
1298  TiXmlComment* clone = new TiXmlComment();
1299 
1300  if ( !clone )
1301  return nullptr;
1302 
1303  CopyTo( clone );
1304  return clone;
1305 }
1306 
1307 
1308 void TiXmlText::Print( FILE* cfile, int depth ) const
1309 {
1310  assert( cfile );
1311  if ( cdata )
1312  {
1313  int i;
1314  fprintf( cfile, "\n" );
1315  for ( i=0; i<depth; i++ ) {
1316  fprintf( cfile, " " );
1317  }
1318  fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1319  }
1320  else
1321  {
1322  TIXML_STRING buffer;
1323  EncodeString( value, &buffer );
1324  fprintf( cfile, "%s", buffer.c_str() );
1325  }
1326 }
1327 
1328 
1329 void TiXmlText::CopyTo( TiXmlText* target ) const
1330 {
1331  TiXmlNode::CopyTo( target );
1332  target->cdata = cdata;
1333 }
1334 
1335 
1336 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1337 {
1338  return visitor->Visit( *this );
1339 }
1340 
1341 
1342 TiXmlNode* TiXmlText::Clone() const
1343 {
1344  TiXmlText* clone = nullptr;
1345  clone = new TiXmlText( "" );
1346 
1347  if ( !clone )
1348  return nullptr;
1349 
1350  CopyTo( clone );
1351  return clone;
1352 }
1353 
1354 
1355 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1356  const char * _encoding,
1357  const char * _standalone )
1358  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1359 {
1360  version = _version;
1361  encoding = _encoding;
1362  standalone = _standalone;
1363 }
1364 
1365 
1366 #ifdef TIXML_USE_STL
1367 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1368  const std::string& _encoding,
1369  const std::string& _standalone )
1370  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1371 {
1372  version = _version;
1373  encoding = _encoding;
1374  standalone = _standalone;
1375 }
1376 #endif
1377 
1378 
1380  : TiXmlNode( TiXmlNode::TINYXML_DECLARATION )
1381 {
1382  copy.CopyTo( this );
1383 }
1384 
1385 
1386 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1387 {
1388  Clear();
1389  copy.CopyTo( this );
1390 }
1391 
1392 
1393 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1394 {
1395  if ( cfile ) fprintf( cfile, "<?xml " );
1396  if ( str ) (*str) += "<?xml ";
1397 
1398  if ( !version.empty() ) {
1399  if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1400  if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1401  }
1402  if ( !encoding.empty() ) {
1403  if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1404  if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1405  }
1406  if ( !standalone.empty() ) {
1407  if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1408  if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1409  }
1410  if ( cfile ) fprintf( cfile, "?>" );
1411  if ( str ) (*str) += "?>";
1412 }
1413 
1414 
1415 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1416 {
1417  TiXmlNode::CopyTo( target );
1418 
1419  target->version = version;
1420  target->encoding = encoding;
1421  target->standalone = standalone;
1422 }
1423 
1424 
1426 {
1427  return visitor->Visit( *this );
1428 }
1429 
1430 
1432 {
1433  TiXmlDeclaration* clone = new TiXmlDeclaration();
1434 
1435  if ( !clone )
1436  return nullptr;
1437 
1438  CopyTo( clone );
1439  return clone;
1440 }
1441 
1442 
1443 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1444 {
1445  for ( int i=0; i<depth; i++ )
1446  fprintf( cfile, " " );
1447  fprintf( cfile, "<%s>", value.c_str() );
1448 }
1449 
1450 
1451 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1452 {
1453  TiXmlNode::CopyTo( target );
1454 }
1455 
1456 
1457 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1458 {
1459  return visitor->Visit( *this );
1460 }
1461 
1462 
1464 {
1465  TiXmlUnknown* clone = new TiXmlUnknown();
1466 
1467  if ( !clone )
1468  return nullptr;
1469 
1470  CopyTo( clone );
1471  return clone;
1472 }
1473 
1474 
1475 TiXmlAttributeSet::TiXmlAttributeSet()
1476 {
1477  sentinel.next = &sentinel;
1478  sentinel.prev = &sentinel;
1479 }
1480 
1481 
1482 TiXmlAttributeSet::~TiXmlAttributeSet()
1483 {
1484  assert( sentinel.next == &sentinel );
1485  assert( sentinel.prev == &sentinel );
1486 }
1487 
1488 
1489 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1490 {
1491  #ifdef TIXML_USE_STL
1492  assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1493  #else
1494  assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1495  #endif
1496 
1497  addMe->next = &sentinel;
1498  addMe->prev = sentinel.prev;
1499 
1500  sentinel.prev->next = addMe;
1501  sentinel.prev = addMe;
1502 }
1503 
1504 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1505 {
1506  TiXmlAttribute* node;
1507 
1508  for( node = sentinel.next; node != &sentinel; node = node->next )
1509  {
1510  if ( node == removeMe )
1511  {
1512  node->prev->next = node->next;
1513  node->next->prev = node->prev;
1514  node->next = nullptr;
1515  node->prev = nullptr;
1516  return;
1517  }
1518  }
1519  assert( 0 ); // we tried to remove a non-linked attribute.
1520 }
1521 
1522 
1523 #ifdef TIXML_USE_STL
1524 TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1525 {
1526  for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1527  {
1528  if ( node->name == name )
1529  return node;
1530  }
1531  return nullptr;
1532 }
1533 
1534 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const std::string& _name )
1535 {
1536  TiXmlAttribute* attrib = Find( _name );
1537  if ( !attrib ) {
1538  attrib = new TiXmlAttribute();
1539  Add( attrib );
1540  attrib->SetName( _name );
1541  }
1542  return attrib;
1543 }
1544 #endif
1545 
1546 
1547 TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1548 {
1549  for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1550  {
1551  if ( strcmp( node->name.c_str(), name ) == 0 )
1552  return node;
1553  }
1554  return nullptr;
1555 }
1556 
1557 
1558 TiXmlAttribute* TiXmlAttributeSet::FindOrCreate( const char* _name )
1559 {
1560  TiXmlAttribute* attrib = Find( _name );
1561  if ( !attrib ) {
1562  attrib = new TiXmlAttribute();
1563  Add( attrib );
1564  attrib->SetName( _name );
1565  }
1566  return attrib;
1567 }
1568 
1569 
1570 #ifdef TIXML_USE_STL
1571 std::istream& operator>> (std::istream & in, TiXmlNode & base)
1572 {
1573  TIXML_STRING tag;
1574  tag.reserve( 8 * 1000 );
1575  base.StreamIn( &in, &tag );
1576 
1577  base.Parse( tag.c_str(), nullptr, TIXML_DEFAULT_ENCODING );
1578  return in;
1579 }
1580 #endif
1581 
1582 
1583 #ifdef TIXML_USE_STL
1584 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1585 {
1586  TiXmlPrinter printer;
1587  printer.SetStreamPrinting();
1588  base.Accept( &printer );
1589  out << printer.Str();
1590 
1591  return out;
1592 }
1593 
1594 
1595 std::string& operator<< (std::string& out, const TiXmlNode& base )
1596 {
1597  TiXmlPrinter printer;
1598  printer.SetStreamPrinting();
1599  base.Accept( &printer );
1600  out.append( printer.Str() );
1601 
1602  return out;
1603 }
1604 #endif
1605 
1606 
1608 {
1609  if ( node )
1610  {
1611  TiXmlNode* child = node->FirstChild();
1612  if ( child )
1613  return TiXmlHandle( child );
1614  }
1615  return TiXmlHandle( nullptr );
1616 }
1617 
1618 
1619 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1620 {
1621  if ( node )
1622  {
1623  TiXmlNode* child = node->FirstChild( value );
1624  if ( child )
1625  return TiXmlHandle( child );
1626  }
1627  return TiXmlHandle( nullptr );
1628 }
1629 
1630 
1632 {
1633  if ( node )
1634  {
1635  TiXmlElement* child = node->FirstChildElement();
1636  if ( child )
1637  return TiXmlHandle( child );
1638  }
1639  return TiXmlHandle( nullptr );
1640 }
1641 
1642 
1643 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1644 {
1645  if ( node )
1646  {
1647  TiXmlElement* child = node->FirstChildElement( value );
1648  if ( child )
1649  return TiXmlHandle( child );
1650  }
1651  return TiXmlHandle( nullptr );
1652 }
1653 
1654 
1656 {
1657  if ( node )
1658  {
1659  int i;
1660  TiXmlNode* child = node->FirstChild();
1661  for ( i=0;
1662  child && i<count;
1663  child = child->NextSibling(), ++i )
1664  {
1665  // nothing
1666  }
1667  if ( child )
1668  return TiXmlHandle( child );
1669  }
1670  return TiXmlHandle( nullptr );
1671 }
1672 
1673 
1674 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1675 {
1676  if ( node )
1677  {
1678  int i;
1679  TiXmlNode* child = node->FirstChild( value );
1680  for ( i=0;
1681  child && i<count;
1682  child = child->NextSibling( value ), ++i )
1683  {
1684  // nothing
1685  }
1686  if ( child )
1687  return TiXmlHandle( child );
1688  }
1689  return TiXmlHandle( nullptr );
1690 }
1691 
1692 
1694 {
1695  if ( node )
1696  {
1697  int i;
1698  TiXmlElement* child = node->FirstChildElement();
1699  for ( i=0;
1700  child && i<count;
1701  child = child->NextSiblingElement(), ++i )
1702  {
1703  // nothing
1704  }
1705  if ( child )
1706  return TiXmlHandle( child );
1707  }
1708  return TiXmlHandle( nullptr );
1709 }
1710 
1711 
1712 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1713 {
1714  if ( node )
1715  {
1716  int i;
1717  TiXmlElement* child = node->FirstChildElement( value );
1718  for ( i=0;
1719  child && i<count;
1720  child = child->NextSiblingElement( value ), ++i )
1721  {
1722  // nothing
1723  }
1724  if ( child )
1725  return TiXmlHandle( child );
1726  }
1727  return TiXmlHandle( nullptr );
1728 }
1729 
1730 
1732 {
1733  return true;
1734 }
1735 
1737 {
1738  return true;
1739 }
1740 
1741 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1742 {
1743  DoIndent();
1744  buffer += "<";
1745  buffer += element.Value();
1746 
1747  for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1748  {
1749  buffer += " ";
1750  attrib->Print( nullptr, 0, &buffer );
1751  }
1752 
1753  if ( !element.FirstChild() )
1754  {
1755  buffer += " />";
1756  DoLineBreak();
1757  }
1758  else
1759  {
1760  buffer += ">";
1761  if ( element.FirstChild()->ToText()
1762  && element.LastChild() == element.FirstChild()
1763  && element.FirstChild()->ToText()->CDATA() == false )
1764  {
1765  simpleTextPrint = true;
1766  // no DoLineBreak()!
1767  }
1768  else
1769  {
1770  DoLineBreak();
1771  }
1772  }
1773  ++depth;
1774  return true;
1775 }
1776 
1777 
1779 {
1780  --depth;
1781  if ( !element.FirstChild() )
1782  {
1783  // nothing.
1784  }
1785  else
1786  {
1787  if ( simpleTextPrint )
1788  {
1789  simpleTextPrint = false;
1790  }
1791  else
1792  {
1793  DoIndent();
1794  }
1795  buffer += "</";
1796  buffer += element.Value();
1797  buffer += ">";
1798  DoLineBreak();
1799  }
1800  return true;
1801 }
1802 
1803 
1804 bool TiXmlPrinter::Visit( const TiXmlText& text )
1805 {
1806  if ( text.CDATA() )
1807  {
1808  DoIndent();
1809  buffer += "<![CDATA[";
1810  buffer += text.Value();
1811  buffer += "]]>";
1812  DoLineBreak();
1813  }
1814  else if ( simpleTextPrint )
1815  {
1816  TIXML_STRING str;
1817  TiXmlBase::EncodeString( text.ValueTStr(), &str );
1818  buffer += str;
1819  }
1820  else
1821  {
1822  DoIndent();
1823  TIXML_STRING str;
1824  TiXmlBase::EncodeString( text.ValueTStr(), &str );
1825  buffer += str;
1826  DoLineBreak();
1827  }
1828  return true;
1829 }
1830 
1831 
1832 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1833 {
1834  DoIndent();
1835  declaration.Print( nullptr, 0, &buffer );
1836  DoLineBreak();
1837  return true;
1838 }
1839 
1840 
1841 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1842 {
1843  DoIndent();
1844  buffer += "<!--";
1845  buffer += comment.Value();
1846  buffer += "-->";
1847  DoLineBreak();
1848  return true;
1849 }
1850 
1851 
1852 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1853 {
1854  DoIndent();
1855  buffer += "<";
1856  buffer += unknown.Value();
1857  buffer += ">";
1858  DoLineBreak();
1859  return true;
1860 }
1861 
int QueryIntValue(int *_value) const
QueryIntValue examines the value string.
Definition: tinyxml.cpp:1213
An attribute is a name-value pair.
Definition: tinyxml.h:779
TiXmlHandle(TiXmlNode *_node)
Create a handle from any node (at any depth of the tree.) This can be a null pointer.
Definition: tinyxml.h:1635
Implements the interface to the "Visitor pattern" (see the Accept() method.) If you call the Accept()...
Definition: tinyxml.h:128
TiXmlComment()
Constructs an empty comment.
Definition: tinyxml.h:1159
virtual void Print(FILE *cfile, int depth) const
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
Definition: tinyxml.cpp:1308
const char * Name() const
Return the name of this attribute.
Definition: tinyxml.h:811
void Print() const
Write the document to standard out using formatted printing ("pretty print").
Definition: tinyxml.h:1512
int QueryDoubleAttribute(const char *name, double *_value) const
QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
Definition: tinyxml.cpp:698
int QueryDoubleValue(double *_value) const
QueryDoubleValue examines the value string. See QueryIntValue().
Definition: tinyxml.cpp:1220
void SetDoubleAttribute(const char *name, double value)
Sets an attribute of name to a given value.
Definition: tinyxml.cpp:738
virtual const TiXmlElement * ToElement() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:698
TiXmlHandle ChildElement(const char *value, int index) const
Return a handle to the "index" child element with the given name.
Definition: tinyxml.cpp:1712
const char * GetText() const
Convenience function for easy access to the text inside an element.
Definition: tinyxml.cpp:878
virtual bool Accept(TiXmlVisitor *content) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:1133
virtual const TiXmlText * ToText() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:701
bool Error() const
If an error occurs, Error will be set to true.
Definition: tinyxml.h:1453
virtual TiXmlNode * Clone() const
Creates a copy of this Unknown and returns it.
Definition: tinyxml.cpp:1463
TiXmlNode * ReplaceChild(TiXmlNode *replaceThis, const TiXmlNode &withThis)
Replace a child of this node.
Definition: tinyxml.cpp:314
bool CDATA() const
Queries whether this represents text using a CDATA section.
Definition: tinyxml.h:1236
void SetName(const char *_name)
Set the name of this attribute.
Definition: tinyxml.h:835
TiXmlDocument()
Create an empty document, that has no name.
Definition: tinyxml.cpp:891
virtual bool Accept(TiXmlVisitor *visitor) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:1425
void ClearError()
If you have handled the error, it can be reset with this call.
Definition: tinyxml.h:1504
virtual void Print(FILE *cfile, int depth) const
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
Definition: tinyxml.cpp:1273
virtual void Print(FILE *cfile, int depth) const
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
Definition: tinyxml.h:870
bool LoadFile(TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Load a file using the current document value.
Definition: tinyxml.cpp:931
void SetValue(const char *_value)
Changes the value of the node.
Definition: tinyxml.h:508
TiXmlNode * InsertEndChild(const TiXmlNode &addThis)
Add a new node related to this.
Definition: tinyxml.cpp:235
virtual bool VisitExit(const TiXmlDocument &doc)
Visit a document.
Definition: tinyxml.cpp:1736
TiXmlNode * InsertBeforeChild(TiXmlNode *beforeThis, const TiXmlNode &addThis)
Add a new node related to this.
Definition: tinyxml.cpp:250
NodeType
The types of XML nodes supported by TinyXml.
Definition: tinyxml.h:462
virtual bool VisitEnter(const TiXmlDocument &)
Visit a document.
Definition: tinyxml.h:134
static void EncodeString(const TiXmlString &str, TiXmlString *out)
Expands entities in a string.
Definition: tinyxml.cpp:74
TiXmlNode * LinkEndChild(TiXmlNode *addThis)
Add a new node related to this.
Definition: tinyxml.cpp:208
bool SaveFile() const
Save a file using the current document value. Returns true if successful.
Definition: tinyxml.cpp:937
TiXmlHandle Child(const char *value, int index) const
Return a handle to the "index" child with the given name.
Definition: tinyxml.cpp:1674
const TiXmlElement * FirstChildElement() const
Convenience function to get through elements.
Definition: tinyxml.cpp:470
void SetDoubleValue(double _value)
Set the value from a double.
Definition: tinyxml.cpp:1238
virtual bool Accept(TiXmlVisitor *visitor) const =0
Accept a hierchical visit the nodes in the TinyXML DOM.
virtual TiXmlNode * Clone() const
Returns a copy of this Comment.
Definition: tinyxml.cpp:1296
In correct XML the declaration is the first entry in the file.
Definition: tinyxml.h:1278
const TiXmlNode * PreviousSibling() const
Navigate to a sibling node.
Definition: tinyxml.h:614
virtual const TiXmlDocument * ToDocument() const
Cast to a more defined type. Will return null if not of the requested type.
Definition: tinyxml.h:697
const char * Value() const
Return the value of this attribute.
Definition: tinyxml.h:812
Any tag that tinyXml doesn't recognize is saved as an unknown.
Definition: tinyxml.h:1347
int QueryIntAttribute(const char *name, int *_value) const
QueryIntAttribute examines the attribute - it is an alternative to the Attribute() method with richer...
Definition: tinyxml.cpp:678
int IntValue() const
Return the value of this attribute, converted to an integer.
Definition: tinyxml.cpp:1249
virtual TiXmlNode * Clone() const
Creates a copy of this Declaration and returns it.
Definition: tinyxml.cpp:1431
const char * Value() const
The meaning of 'value' changes for the specific type of TiXmlNode.
Definition: tinyxml.h:487
void RemoveAttribute(const char *name)
Deletes an attribute with the given name.
Definition: tinyxml.cpp:455
void SetAttribute(const char *name, const char *_value)
Sets an attribute of name to a given value.
Definition: tinyxml.cpp:758
virtual void Print(FILE *cfile, int depth) const
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
Definition: tinyxml.cpp:778
double DoubleValue() const
Return the value of this attribute, converted to a double.
Definition: tinyxml.cpp:1254
const TiXmlElement * NextSiblingElement() const
Convenience function to get through elements.
Definition: tinyxml.cpp:500
Always the top level node.
Definition: tinyxml.h:1386
TiXmlHandle FirstChild() const
Return a handle to the first child node.
Definition: tinyxml.cpp:1607
TiXmlElement(const char *in_value)
Construct an element.
Definition: tinyxml.cpp:543
TiXmlNode * InsertAfterChild(TiXmlNode *afterThis, const TiXmlNode &addThis)
Add a new node related to this.
Definition: tinyxml.cpp:282
A TiXmlHandle is a class that wraps a node pointer with null checks; this is an incredibly useful thi...
Definition: tinyxml.h:1631
const TiXmlAttribute * Next() const
Get the next sibling attribute in the DOM. Returns null at end.
Definition: tinyxml.cpp:1147
const TiXmlDocument * GetDocument() const
Return a pointer to the Document this node lives in.
Definition: tinyxml.cpp:530
TiXmlBase is a base class for every class in TinyXml.
Definition: tinyxml.h:194
int Type() const
Query the type (as an enumerated value, above) of this node.
Definition: tinyxml.h:684
const TiXmlNode * FirstChild() const
The first child of this node. Will be null if there are no children.
Definition: tinyxml.h:522
virtual bool VisitEnter(const TiXmlDocument &doc)
Visit a document.
Definition: tinyxml.cpp:1731
virtual const char * Parse(const char *p, TiXmlParsingData *data=0, TiXmlEncoding encoding=TIXML_DEFAULT_ENCODING)
Parse the given null terminated block of xml data.
virtual TiXmlNode * Clone() const
Creates a new Element and returns it - the returned element is a copy.
Definition: tinyxml.cpp:867
virtual bool Accept(TiXmlVisitor *visitor) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:1290
The parent class for everything in the Document Object Model.
Definition: tinyxml.h:423
void SetIntValue(int _value)
Set the value from an integer.
Definition: tinyxml.cpp:1227
Print to memory functionality.
Definition: tinyxml.h:1730
XML text.
Definition: tinyxml.h:1205
virtual bool VisitExit(const TiXmlDocument &)
Visit a document.
Definition: tinyxml.h:136
const char * Attribute(const char *name) const
Given an attribute name, Attribute() returns the value for the attribute of that name,...
Definition: tinyxml.cpp:594
TiXmlText(const char *initValue)
Constructor for text element.
Definition: tinyxml.h:1213
bool RemoveChild(TiXmlNode *removeThis)
Delete a child of this node.
Definition: tinyxml.cpp:353
An XML comment.
Definition: tinyxml.h:1155
void Clear()
Delete all the children of this node. Does not affect 'this'.
Definition: tinyxml.cpp:191
void SetValue(const char *_value)
Set the value.
Definition: tinyxml.h:836
const TiXmlAttribute * Previous() const
Get the previous sibling attribute in the DOM. Returns null at beginning.
Definition: tinyxml.cpp:1167
const TiXmlNode * IterateChildren(const TiXmlNode *previous) const
An alternate way to walk the children of a node.
Definition: tinyxml.cpp:403
virtual bool Accept(TiXmlVisitor *content) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:1336
virtual bool Accept(TiXmlVisitor *visitor) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:853
TiXmlHandle FirstChildElement() const
Return a handle to the first child element.
Definition: tinyxml.cpp:1631
TiXmlDeclaration()
Construct an empty declaration.
Definition: tinyxml.h:1282
void SetStreamPrinting()
Switch over to "stream printing" which is the most dense formatting without linebreaks.
Definition: tinyxml.h:1764
virtual void Print(FILE *cfile, int depth) const =0
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
virtual TiXmlNode * Clone() const =0
Create an exact duplicate of this node and return it.
const TiXmlNode * NextSibling() const
Navigate to a sibling node.
Definition: tinyxml.h:631
virtual bool Visit(const TiXmlDeclaration &declaration)
Visit a declaration.
Definition: tinyxml.cpp:1832
The element is a container class.
Definition: tinyxml.h:940
virtual bool Accept(TiXmlVisitor *content) const
Walk the XML tree visiting this node and all of its children.
Definition: tinyxml.cpp:1457
virtual void Print(FILE *cfile, int depth) const
All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL ...
Definition: tinyxml.cpp:1443
virtual bool Visit(const TiXmlDeclaration &)
Visit a declaration.
Definition: tinyxml.h:144