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


denso_robot_core
Author(s): DENSO WAVE INCORPORATED
autogenerated on Sat Feb 18 2023 04:06:02