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