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