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