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