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