NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
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 const 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 const 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#if defined(_WIN64)
104 #define TIXML_FSEEK _fseeki64
105 #define TIXML_FTELL _ftelli64
106#elif defined(__APPLE__) || defined(__FreeBSD__)
107 #define TIXML_FSEEK fseeko
108 #define TIXML_FTELL ftello
109#elif defined(__unix__) && defined(__x86_64__)
110 #define TIXML_FSEEK fseeko64
111 #define TIXML_FTELL ftello64
112#else
113 #define TIXML_FSEEK fseek
114 #define TIXML_FTELL ftell
115#endif
116
117
118static const char LINE_FEED = static_cast<char>(0x0a); // all line endings are normalized to LF
119static const char LF = LINE_FEED;
120static const char CARRIAGE_RETURN = static_cast<char>(0x0d); // CR gets filtered out
121static const char CR = CARRIAGE_RETURN;
122static const char SINGLE_QUOTE = '\'';
123static const char DOUBLE_QUOTE = '\"';
124
125// Bunch of unicode info at:
126// http://www.unicode.org/faq/utf_bom.html
127// ef bb bf (Microsoft "lead bytes") - designates UTF-8
128
129static const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
130static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
131static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
132
133namespace tinyxml2
134{
135
136struct Entity {
137 const char* pattern;
139 char value;
140};
141
142static const int NUM_ENTITIES = 5;
143static const Entity entities[NUM_ENTITIES] = {
144 { "quot", 4, DOUBLE_QUOTE },
145 { "amp", 3, '&' },
146 { "apos", 4, SINGLE_QUOTE },
147 { "lt", 2, '<' },
148 { "gt", 2, '>' }
149};
150
151
153{
154 Reset();
155}
156
157
159{
160 if ( this == other ) {
161 return;
162 }
163 // This in effect implements the assignment operator by "moving"
164 // ownership (as in auto_ptr).
165
166 TIXMLASSERT( other != 0 );
167 TIXMLASSERT( other->_flags == 0 );
168 TIXMLASSERT( other->_start == 0 );
169 TIXMLASSERT( other->_end == 0 );
170
171 other->Reset();
172
173 other->_flags = _flags;
174 other->_start = _start;
175 other->_end = _end;
176
177 _flags = 0;
178 _start = 0;
179 _end = 0;
180}
181
182
184{
185 if ( _flags & NEEDS_DELETE ) {
186 delete [] _start;
187 }
188 _flags = 0;
189 _start = 0;
190 _end = 0;
191}
192
193
194void StrPair::SetStr( const char* str, int flags )
195{
196 TIXMLASSERT( str );
197 Reset();
198 size_t len = strlen( str );
199 TIXMLASSERT( _start == 0 );
200 _start = new char[ len+1 ];
201 memcpy( _start, str, len+1 );
202 _end = _start + len;
203 _flags = flags | NEEDS_DELETE;
204}
205
206
207char* StrPair::ParseText( char* p, const char* endTag, int strFlags, int* curLineNumPtr )
208{
209 TIXMLASSERT( p );
210 TIXMLASSERT( endTag && *endTag );
211 TIXMLASSERT(curLineNumPtr);
212
213 char* start = p;
214 const char endChar = *endTag;
215 size_t length = strlen( endTag );
216
217 // Inner loop of text parsing.
218 while ( *p ) {
219 if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) {
220 Set( start, p, strFlags );
221 return p + length;
222 } else if (*p == '\n') {
223 ++(*curLineNumPtr);
224 }
225 ++p;
226 TIXMLASSERT( p );
227 }
228 return 0;
229}
230
231
232char* StrPair::ParseName( char* p )
233{
234 if ( !p || !(*p) ) {
235 return 0;
236 }
237 if ( !XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {
238 return 0;
239 }
240
241 char* const start = p;
242 ++p;
243 while ( *p && XMLUtil::IsNameChar( (unsigned char) *p ) ) {
244 ++p;
245 }
246
247 Set( start, p, 0 );
248 return p;
249}
250
251
253{
254 // Adjusting _start would cause undefined behavior on delete[]
255 TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 );
256 // Trim leading space.
258
259 if ( *_start ) {
260 const char* p = _start; // the read pointer
261 char* q = _start; // the write pointer
262
263 while( *p ) {
264 if ( XMLUtil::IsWhiteSpace( *p )) {
265 p = XMLUtil::SkipWhiteSpace( p, 0 );
266 if ( *p == 0 ) {
267 break; // don't write to q; this trims the trailing space.
268 }
269 *q = ' ';
270 ++q;
271 }
272 *q = *p;
273 ++q;
274 ++p;
275 }
276 *q = 0;
277 }
278}
279
280
281const char* StrPair::GetStr()
282{
284 TIXMLASSERT( _end );
285 if ( _flags & NEEDS_FLUSH ) {
286 *_end = 0;
288
289 if ( _flags ) {
290 const char* p = _start; // the read pointer
291 char* q = _start; // the write pointer
292
293 while( p < _end ) {
294 if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) {
295 // CR-LF pair becomes LF
296 // CR alone becomes LF
297 // LF-CR becomes LF
298 if ( *(p+1) == LF ) {
299 p += 2;
300 }
301 else {
302 ++p;
303 }
304 *q = LF;
305 ++q;
306 }
307 else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) {
308 if ( *(p+1) == CR ) {
309 p += 2;
310 }
311 else {
312 ++p;
313 }
314 *q = LF;
315 ++q;
316 }
317 else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) {
318 // Entities handled by tinyXML2:
319 // - special entities in the entity table [in/out]
320 // - numeric character reference [in]
321 // &#20013; or &#x4e2d;
322
323 if ( *(p+1) == '#' ) {
324 const int buflen = 10;
325 char buf[buflen] = { 0 };
326 int len = 0;
327 const char* adjusted = const_cast<char*>( XMLUtil::GetCharacterRef( p, buf, &len ) );
328 if ( adjusted == 0 ) {
329 *q = *p;
330 ++p;
331 ++q;
332 }
333 else {
334 TIXMLASSERT( 0 <= len && len <= buflen );
335 TIXMLASSERT( q + len <= adjusted );
336 p = adjusted;
337 memcpy( q, buf, len );
338 q += len;
339 }
340 }
341 else {
342 bool entityFound = false;
343 for( int i = 0; i < NUM_ENTITIES; ++i ) {
344 const Entity& entity = entities[i];
345 if ( strncmp( p + 1, entity.pattern, entity.length ) == 0
346 && *( p + entity.length + 1 ) == ';' ) {
347 // Found an entity - convert.
348 *q = entity.value;
349 ++q;
350 p += entity.length + 2;
351 entityFound = true;
352 break;
353 }
354 }
355 if ( !entityFound ) {
356 // fixme: treat as error?
357 ++p;
358 ++q;
359 }
360 }
361 }
362 else {
363 *q = *p;
364 ++p;
365 ++q;
366 }
367 }
368 *q = 0;
369 }
370 // The loop below has plenty going on, and this
371 // is a less useful mode. Break it out.
374 }
376 }
378 return _start;
379}
380
381
382
383
384// --------- XMLUtil ----------- //
385
386const char* XMLUtil::writeBoolTrue = "true";
387const char* XMLUtil::writeBoolFalse = "false";
388
389void XMLUtil::SetBoolSerialization(const char* writeTrue, const char* writeFalse)
390{
391 static const char* defTrue = "true";
392 static const char* defFalse = "false";
393
394 writeBoolTrue = (writeTrue) ? writeTrue : defTrue;
395 writeBoolFalse = (writeFalse) ? writeFalse : defFalse;
396}
397
398
399const char* XMLUtil::ReadBOM( const char* p, bool* bom )
400{
401 TIXMLASSERT( p );
402 TIXMLASSERT( bom );
403 *bom = false;
404 const unsigned char* pu = reinterpret_cast<const unsigned char*>(p);
405 // Check for BOM:
406 if ( *(pu+0) == TIXML_UTF_LEAD_0
407 && *(pu+1) == TIXML_UTF_LEAD_1
408 && *(pu+2) == TIXML_UTF_LEAD_2 ) {
409 *bom = true;
410 p += 3;
411 }
412 TIXMLASSERT( p );
413 return p;
414}
415
416
417void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length )
418{
419 const unsigned long BYTE_MASK = 0xBF;
420 const unsigned long BYTE_MARK = 0x80;
421 const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
422
423 if (input < 0x80) {
424 *length = 1;
425 }
426 else if ( input < 0x800 ) {
427 *length = 2;
428 }
429 else if ( input < 0x10000 ) {
430 *length = 3;
431 }
432 else if ( input < 0x200000 ) {
433 *length = 4;
434 }
435 else {
436 *length = 0; // This code won't convert this correctly anyway.
437 return;
438 }
439
440 output += *length;
441
442 // Scary scary fall throughs are annotated with carefully designed comments
443 // to suppress compiler warnings such as -Wimplicit-fallthrough in gcc
444 switch (*length) {
445 case 4:
446 --output;
447 *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);
448 input >>= 6;
449 //fall through
450 case 3:
451 --output;
452 *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);
453 input >>= 6;
454 //fall through
455 case 2:
456 --output;
457 *output = static_cast<char>((input | BYTE_MARK) & BYTE_MASK);
458 input >>= 6;
459 //fall through
460 case 1:
461 --output;
462 *output = static_cast<char>(input | FIRST_BYTE_MARK[*length]);
463 break;
464 default:
465 TIXMLASSERT( false );
466 }
467}
468
469
470const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length )
471{
472 // Presume an entity, and pull it out.
473 *length = 0;
474
475 if ( *(p+1) == '#' && *(p+2) ) {
476 unsigned long ucs = 0;
477 TIXMLASSERT( sizeof( ucs ) >= 4 );
478 ptrdiff_t delta = 0;
479 unsigned mult = 1;
480 static const char SEMICOLON = ';';
481
482 if ( *(p+2) == 'x' ) {
483 // Hexadecimal.
484 const char* q = p+3;
485 if ( !(*q) ) {
486 return 0;
487 }
488
489 q = strchr( q, SEMICOLON );
490
491 if ( !q ) {
492 return 0;
493 }
494 TIXMLASSERT( *q == SEMICOLON );
495
496 delta = q-p;
497 --q;
498
499 while ( *q != 'x' ) {
500 unsigned int digit = 0;
501
502 if ( *q >= '0' && *q <= '9' ) {
503 digit = *q - '0';
504 }
505 else if ( *q >= 'a' && *q <= 'f' ) {
506 digit = *q - 'a' + 10;
507 }
508 else if ( *q >= 'A' && *q <= 'F' ) {
509 digit = *q - 'A' + 10;
510 }
511 else {
512 return 0;
513 }
514 TIXMLASSERT( digit < 16 );
515 TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
516 const unsigned int digitScaled = mult * digit;
517 TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
518 ucs += digitScaled;
519 TIXMLASSERT( mult <= UINT_MAX / 16 );
520 mult *= 16;
521 --q;
522 }
523 }
524 else {
525 // Decimal.
526 const char* q = p+2;
527 if ( !(*q) ) {
528 return 0;
529 }
530
531 q = strchr( q, SEMICOLON );
532
533 if ( !q ) {
534 return 0;
535 }
536 TIXMLASSERT( *q == SEMICOLON );
537
538 delta = q-p;
539 --q;
540
541 while ( *q != '#' ) {
542 if ( *q >= '0' && *q <= '9' ) {
543 const unsigned int digit = *q - '0';
544 TIXMLASSERT( digit < 10 );
545 TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit );
546 const unsigned int digitScaled = mult * digit;
547 TIXMLASSERT( ucs <= ULONG_MAX - digitScaled );
548 ucs += digitScaled;
549 }
550 else {
551 return 0;
552 }
553 TIXMLASSERT( mult <= UINT_MAX / 10 );
554 mult *= 10;
555 --q;
556 }
557 }
558 // convert the UCS to UTF-8
559 ConvertUTF32ToUTF8( ucs, value, length );
560 return p + delta + 1;
561 }
562 return p+1;
563}
564
565
566void XMLUtil::ToStr( int v, char* buffer, int bufferSize )
567{
568 TIXML_SNPRINTF( buffer, bufferSize, "%d", v );
569}
570
571
572void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize )
573{
574 TIXML_SNPRINTF( buffer, bufferSize, "%u", v );
575}
576
577
578void XMLUtil::ToStr( bool v, char* buffer, int bufferSize )
579{
580 TIXML_SNPRINTF( buffer, bufferSize, "%s", v ? writeBoolTrue : writeBoolFalse);
581}
582
583/*
584 ToStr() of a number is a very tricky topic.
585 https://github.com/leethomason/tinyxml2/issues/106
586*/
587void XMLUtil::ToStr( float v, char* buffer, int bufferSize )
588{
589 TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v );
590}
591
592
593void XMLUtil::ToStr( double v, char* buffer, int bufferSize )
594{
595 TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v );
596}
597
598
599void XMLUtil::ToStr( int64_t v, char* buffer, int bufferSize )
600{
601 // horrible syntax trick to make the compiler happy about %lld
602 TIXML_SNPRINTF(buffer, bufferSize, "%lld", static_cast<long long>(v));
603}
604
605void XMLUtil::ToStr( uint64_t v, char* buffer, int bufferSize )
606{
607 // horrible syntax trick to make the compiler happy about %llu
608 TIXML_SNPRINTF(buffer, bufferSize, "%llu", (long long)v);
609}
610
611bool XMLUtil::ToInt(const char* str, int* value)
612{
613 if (IsPrefixHex(str)) {
614 unsigned v;
615 if (TIXML_SSCANF(str, "%x", &v) == 1) {
616 *value = static_cast<int>(v);
617 return true;
618 }
619 }
620 else {
621 if (TIXML_SSCANF(str, "%d", value) == 1) {
622 return true;
623 }
624 }
625 return false;
626}
627
628bool XMLUtil::ToUnsigned(const char* str, unsigned* value)
629{
630 if (TIXML_SSCANF(str, IsPrefixHex(str) ? "%x" : "%u", value) == 1) {
631 return true;
632 }
633 return false;
634}
635
636bool XMLUtil::ToBool( const char* str, bool* value )
637{
638 int ival = 0;
639 if ( ToInt( str, &ival )) {
640 *value = (ival==0) ? false : true;
641 return true;
642 }
643 static const char* TRUE_VALS[] = { "true", "True", "TRUE", 0 };
644 static const char* FALSE_VALS[] = { "false", "False", "FALSE", 0 };
645
646 for (int i = 0; TRUE_VALS[i]; ++i) {
647 if (StringEqual(str, TRUE_VALS[i])) {
648 *value = true;
649 return true;
650 }
651 }
652 for (int i = 0; FALSE_VALS[i]; ++i) {
653 if (StringEqual(str, FALSE_VALS[i])) {
654 *value = false;
655 return true;
656 }
657 }
658 return false;
659}
660
661
662bool XMLUtil::ToFloat( const char* str, float* value )
663{
664 if ( TIXML_SSCANF( str, "%f", value ) == 1 ) {
665 return true;
666 }
667 return false;
668}
669
670
671bool XMLUtil::ToDouble( const char* str, double* value )
672{
673 if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) {
674 return true;
675 }
676 return false;
677}
678
679
680bool XMLUtil::ToInt64(const char* str, int64_t* value)
681{
682 if (IsPrefixHex(str)) {
683 unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llx
684 if (TIXML_SSCANF(str, "%llx", &v) == 1) {
685 *value = static_cast<int64_t>(v);
686 return true;
687 }
688 }
689 else {
690 long long v = 0; // horrible syntax trick to make the compiler happy about %lld
691 if (TIXML_SSCANF(str, "%lld", &v) == 1) {
692 *value = static_cast<int64_t>(v);
693 return true;
694 }
695 }
696 return false;
697}
698
699
700bool XMLUtil::ToUnsigned64(const char* str, uint64_t* value) {
701 unsigned long long v = 0; // horrible syntax trick to make the compiler happy about %llu
702 if(TIXML_SSCANF(str, IsPrefixHex(str) ? "%llx" : "%llu", &v) == 1) {
703 *value = (uint64_t)v;
704 return true;
705 }
706 return false;
707}
708
709
710char* XMLDocument::Identify( char* p, XMLNode** node )
711{
712 TIXMLASSERT( node );
713 TIXMLASSERT( p );
714 char* const start = p;
715 int const startLine = _parseCurLineNum;
717 if( !*p ) {
718 *node = 0;
719 TIXMLASSERT( p );
720 return p;
721 }
722
723 // These strings define the matching patterns:
724 static const char* xmlHeader = { "<?" };
725 static const char* commentHeader = { "<!--" };
726 static const char* cdataHeader = { "<![CDATA[" };
727 static const char* dtdHeader = { "<!" };
728 static const char* elementHeader = { "<" }; // and a header for everything else; check last.
729
730 static const int xmlHeaderLen = 2;
731 static const int commentHeaderLen = 4;
732 static const int cdataHeaderLen = 9;
733 static const int dtdHeaderLen = 2;
734 static const int elementHeaderLen = 1;
735
736 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLUnknown ) ); // use same memory pool
737 TIXMLASSERT( sizeof( XMLComment ) == sizeof( XMLDeclaration ) ); // use same memory pool
738 XMLNode* returnNode = 0;
739 if ( XMLUtil::StringEqual( p, xmlHeader, xmlHeaderLen ) ) {
740 returnNode = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
741 returnNode->_parseLineNum = _parseCurLineNum;
742 p += xmlHeaderLen;
743 }
744 else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) {
745 returnNode = CreateUnlinkedNode<XMLComment>( _commentPool );
746 returnNode->_parseLineNum = _parseCurLineNum;
747 p += commentHeaderLen;
748 }
749 else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) {
750 XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
751 returnNode = text;
752 returnNode->_parseLineNum = _parseCurLineNum;
753 p += cdataHeaderLen;
754 text->SetCData( true );
755 }
756 else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) {
757 returnNode = CreateUnlinkedNode<XMLUnknown>( _commentPool );
758 returnNode->_parseLineNum = _parseCurLineNum;
759 p += dtdHeaderLen;
760 }
761 else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) {
762 returnNode = CreateUnlinkedNode<XMLElement>( _elementPool );
763 returnNode->_parseLineNum = _parseCurLineNum;
764 p += elementHeaderLen;
765 }
766 else {
767 returnNode = CreateUnlinkedNode<XMLText>( _textPool );
768 returnNode->_parseLineNum = _parseCurLineNum; // Report line of first non-whitespace character
769 p = start; // Back it up, all the text counts.
770 _parseCurLineNum = startLine;
771 }
772
773 TIXMLASSERT( returnNode );
774 TIXMLASSERT( p );
775 *node = returnNode;
776 return p;
777}
778
779
780bool XMLDocument::Accept( XMLVisitor* visitor ) const
781{
782 TIXMLASSERT( visitor );
783 if ( visitor->VisitEnter( *this ) ) {
784 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
785 if ( !node->Accept( visitor ) ) {
786 break;
787 }
788 }
789 }
790 return visitor->VisitExit( *this );
791}
792
793
794// --------- XMLNode ----------- //
795
797 _document( doc ),
798 _parent( 0 ),
799 _value(),
800 _parseLineNum( 0 ),
801 _firstChild( 0 ), _lastChild( 0 ),
802 _prev( 0 ), _next( 0 ),
803 _userData( 0 ),
804 _memPool( 0 )
805{
806}
807
808
810{
812 if ( _parent ) {
813 _parent->Unlink( this );
814 }
815}
816
817const char* XMLNode::Value() const
818{
819 // Edge case: XMLDocuments don't have a Value. Return null.
820 if ( this->ToDocument() )
821 return 0;
822 return _value.GetStr();
823}
824
825void XMLNode::SetValue( const char* str, bool staticMem )
826{
827 if ( staticMem ) {
828 _value.SetInternedStr( str );
829 }
830 else {
831 _value.SetStr( str );
832 }
833}
834
836{
837 XMLNode* clone = this->ShallowClone(target);
838 if (!clone) return 0;
839
840 for (const XMLNode* child = this->FirstChild(); child; child = child->NextSibling()) {
841 XMLNode* childClone = child->DeepClone(target);
842 TIXMLASSERT(childClone);
843 clone->InsertEndChild(childClone);
844 }
845 return clone;
846}
847
849{
850 while( _firstChild ) {
853 }
855}
856
857
859{
860 TIXMLASSERT( child );
861 TIXMLASSERT( child->_document == _document );
862 TIXMLASSERT( child->_parent == this );
863 if ( child == _firstChild ) {
865 }
866 if ( child == _lastChild ) {
868 }
869
870 if ( child->_prev ) {
871 child->_prev->_next = child->_next;
872 }
873 if ( child->_next ) {
874 child->_next->_prev = child->_prev;
875 }
876 child->_next = 0;
877 child->_prev = 0;
878 child->_parent = 0;
879}
880
881
883{
884 TIXMLASSERT( node );
885 TIXMLASSERT( node->_document == _document );
886 TIXMLASSERT( node->_parent == this );
887 Unlink( node );
888 TIXMLASSERT(node->_prev == 0);
889 TIXMLASSERT(node->_next == 0);
890 TIXMLASSERT(node->_parent == 0);
891 DeleteNode( node );
892}
893
894
896{
897 TIXMLASSERT( addThis );
898 if ( addThis->_document != _document ) {
899 TIXMLASSERT( false );
900 return 0;
901 }
902 InsertChildPreamble( addThis );
903
904 if ( _lastChild ) {
907 _lastChild->_next = addThis;
908 addThis->_prev = _lastChild;
909 _lastChild = addThis;
910
911 addThis->_next = 0;
912 }
913 else {
914 TIXMLASSERT( _firstChild == 0 );
915 _firstChild = _lastChild = addThis;
916
917 addThis->_prev = 0;
918 addThis->_next = 0;
919 }
920 addThis->_parent = this;
921 return addThis;
922}
923
924
926{
927 TIXMLASSERT( addThis );
928 if ( addThis->_document != _document ) {
929 TIXMLASSERT( false );
930 return 0;
931 }
932 InsertChildPreamble( addThis );
933
934 if ( _firstChild ) {
937
938 _firstChild->_prev = addThis;
939 addThis->_next = _firstChild;
940 _firstChild = addThis;
941
942 addThis->_prev = 0;
943 }
944 else {
945 TIXMLASSERT( _lastChild == 0 );
946 _firstChild = _lastChild = addThis;
947
948 addThis->_prev = 0;
949 addThis->_next = 0;
950 }
951 addThis->_parent = this;
952 return addThis;
953}
954
955
957{
958 TIXMLASSERT( addThis );
959 if ( addThis->_document != _document ) {
960 TIXMLASSERT( false );
961 return 0;
962 }
963
964 TIXMLASSERT( afterThis );
965
966 if ( afterThis->_parent != this ) {
967 TIXMLASSERT( false );
968 return 0;
969 }
970 if ( afterThis == addThis ) {
971 // Current state: BeforeThis -> AddThis -> OneAfterAddThis
972 // Now AddThis must disappear from it's location and then
973 // reappear between BeforeThis and OneAfterAddThis.
974 // So just leave it where it is.
975 return addThis;
976 }
977
978 if ( afterThis->_next == 0 ) {
979 // The last node or the only node.
980 return InsertEndChild( addThis );
981 }
982 InsertChildPreamble( addThis );
983 addThis->_prev = afterThis;
984 addThis->_next = afterThis->_next;
985 afterThis->_next->_prev = addThis;
986 afterThis->_next = addThis;
987 addThis->_parent = this;
988 return addThis;
989}
990
991
992
993
994const XMLElement* XMLNode::FirstChildElement( const char* name ) const
995{
996 for( const XMLNode* node = _firstChild; node; node = node->_next ) {
997 const XMLElement* element = node->ToElementWithName( name );
998 if ( element ) {
999 return element;
1000 }
1001 }
1002 return 0;
1003}
1004
1005
1006const XMLElement* XMLNode::LastChildElement( const char* name ) const
1007{
1008 for( const XMLNode* node = _lastChild; node; node = node->_prev ) {
1009 const XMLElement* element = node->ToElementWithName( name );
1010 if ( element ) {
1011 return element;
1012 }
1013 }
1014 return 0;
1015}
1016
1017
1019{
1020 for( const XMLNode* node = _next; node; node = node->_next ) {
1021 const XMLElement* element = node->ToElementWithName( name );
1022 if ( element ) {
1023 return element;
1024 }
1025 }
1026 return 0;
1027}
1028
1029
1031{
1032 for( const XMLNode* node = _prev; node; node = node->_prev ) {
1033 const XMLElement* element = node->ToElementWithName( name );
1034 if ( element ) {
1035 return element;
1036 }
1037 }
1038 return 0;
1039}
1040
1041
1042char* XMLNode::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
1043{
1044 // This is a recursive method, but thinking about it "at the current level"
1045 // it is a pretty simple flat list:
1046 // <foo/>
1047 // <!-- comment -->
1048 //
1049 // With a special case:
1050 // <foo>
1051 // </foo>
1052 // <!-- comment -->
1053 //
1054 // Where the closing element (/foo) *must* be the next thing after the opening
1055 // element, and the names must match. BUT the tricky bit is that the closing
1056 // element will be read by the child.
1057 //
1058 // 'endTag' is the end tag for this node, it is returned by a call to a child.
1059 // 'parentEnd' is the end tag for the parent, which is filled in and returned.
1060
1062 if (_document->Error())
1063 return 0;
1064
1065 while( p && *p ) {
1066 XMLNode* node = 0;
1067
1068 p = _document->Identify( p, &node );
1069 TIXMLASSERT( p );
1070 if ( node == 0 ) {
1071 break;
1072 }
1073
1074 const int initialLineNum = node->_parseLineNum;
1075
1076 StrPair endTag;
1077 p = node->ParseDeep( p, &endTag, curLineNumPtr );
1078 if ( !p ) {
1079 DeleteNode( node );
1080 if ( !_document->Error() ) {
1081 _document->SetError( XML_ERROR_PARSING, initialLineNum, 0);
1082 }
1083 break;
1084 }
1085
1086 const XMLDeclaration* const decl = node->ToDeclaration();
1087 if ( decl ) {
1088 // Declarations are only allowed at document level
1089 //
1090 // Multiple declarations are allowed but all declarations
1091 // must occur before anything else.
1092 //
1093 // Optimized due to a security test case. If the first node is
1094 // a declaration, and the last node is a declaration, then only
1095 // declarations have so far been added.
1096 bool wellLocated = false;
1097
1098 if (ToDocument()) {
1099 if (FirstChild()) {
1100 wellLocated =
1101 FirstChild() &&
1103 LastChild() &&
1105 }
1106 else {
1107 wellLocated = true;
1108 }
1109 }
1110 if ( !wellLocated ) {
1111 _document->SetError( XML_ERROR_PARSING_DECLARATION, initialLineNum, "XMLDeclaration value=%s", decl->Value());
1112 DeleteNode( node );
1113 break;
1114 }
1115 }
1116
1117 XMLElement* ele = node->ToElement();
1118 if ( ele ) {
1119 // We read the end tag. Return it to the parent.
1120 if ( ele->ClosingType() == XMLElement::CLOSING ) {
1121 if ( parentEndTag ) {
1122 ele->_value.TransferTo( parentEndTag );
1123 }
1124 node->_memPool->SetTracked(); // created and then immediately deleted.
1125 DeleteNode( node );
1126 return p;
1127 }
1128
1129 // Handle an end tag returned to this level.
1130 // And handle a bunch of annoying errors.
1131 bool mismatch = false;
1132 if ( endTag.Empty() ) {
1133 if ( ele->ClosingType() == XMLElement::OPEN ) {
1134 mismatch = true;
1135 }
1136 }
1137 else {
1138 if ( ele->ClosingType() != XMLElement::OPEN ) {
1139 mismatch = true;
1140 }
1141 else if ( !XMLUtil::StringEqual( endTag.GetStr(), ele->Name() ) ) {
1142 mismatch = true;
1143 }
1144 }
1145 if ( mismatch ) {
1146 _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, initialLineNum, "XMLElement name=%s", ele->Name());
1147 DeleteNode( node );
1148 break;
1149 }
1150 }
1151 InsertEndChild( node );
1152 }
1153 return 0;
1154}
1155
1156/*static*/ void XMLNode::DeleteNode( XMLNode* node )
1157{
1158 if ( node == 0 ) {
1159 return;
1160 }
1161 TIXMLASSERT(node->_document);
1162 if (!node->ToDocument()) {
1163 node->_document->MarkInUse(node);
1164 }
1165
1166 MemPool* pool = node->_memPool;
1167 node->~XMLNode();
1168 pool->Free( node );
1169}
1170
1171void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const
1172{
1173 TIXMLASSERT( insertThis );
1174 TIXMLASSERT( insertThis->_document == _document );
1175
1176 if (insertThis->_parent) {
1177 insertThis->_parent->Unlink( insertThis );
1178 }
1179 else {
1180 insertThis->_document->MarkInUse(insertThis);
1181 insertThis->_memPool->SetTracked();
1182 }
1183}
1184
1185const XMLElement* XMLNode::ToElementWithName( const char* name ) const
1186{
1187 const XMLElement* element = this->ToElement();
1188 if ( element == 0 ) {
1189 return 0;
1190 }
1191 if ( name == 0 ) {
1192 return element;
1193 }
1194 if ( XMLUtil::StringEqual( element->Name(), name ) ) {
1195 return element;
1196 }
1197 return 0;
1198}
1199
1200// --------- XMLText ---------- //
1201char* XMLText::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1202{
1203 if ( this->CData() ) {
1204 p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1205 if ( !p ) {
1207 }
1208 return p;
1209 }
1210 else {
1214 }
1215
1216 p = _value.ParseText( p, "<", flags, curLineNumPtr );
1217 if ( p && *p ) {
1218 return p-1;
1219 }
1220 if ( !p ) {
1222 }
1223 }
1224 return 0;
1225}
1226
1227
1229{
1230 if ( !doc ) {
1231 doc = _document;
1232 }
1233 XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern?
1234 text->SetCData( this->CData() );
1235 return text;
1236}
1237
1238
1240{
1242 const XMLText* text = compare->ToText();
1243 return ( text && XMLUtil::StringEqual( text->Value(), Value() ) );
1244}
1245
1246
1247bool XMLText::Accept( XMLVisitor* visitor ) const
1248{
1249 TIXMLASSERT( visitor );
1250 return visitor->Visit( *this );
1251}
1252
1253
1254// --------- XMLComment ---------- //
1255
1257{
1258}
1259
1260
1262{
1263}
1264
1265
1266char* XMLComment::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1267{
1268 // Comment parses as text.
1269 p = _value.ParseText( p, "-->", StrPair::COMMENT, curLineNumPtr );
1270 if ( p == 0 ) {
1272 }
1273 return p;
1274}
1275
1276
1278{
1279 if ( !doc ) {
1280 doc = _document;
1281 }
1282 XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern?
1283 return comment;
1284}
1285
1286
1288{
1290 const XMLComment* comment = compare->ToComment();
1291 return ( comment && XMLUtil::StringEqual( comment->Value(), Value() ));
1292}
1293
1294
1295bool XMLComment::Accept( XMLVisitor* visitor ) const
1296{
1297 TIXMLASSERT( visitor );
1298 return visitor->Visit( *this );
1299}
1300
1301
1302// --------- XMLDeclaration ---------- //
1303
1305{
1306}
1307
1308
1310{
1311 //printf( "~XMLDeclaration\n" );
1312}
1313
1314
1315char* XMLDeclaration::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1316{
1317 // Declaration parses as text.
1318 p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1319 if ( p == 0 ) {
1321 }
1322 return p;
1323}
1324
1325
1327{
1328 if ( !doc ) {
1329 doc = _document;
1330 }
1331 XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern?
1332 return dec;
1333}
1334
1335
1337{
1339 const XMLDeclaration* declaration = compare->ToDeclaration();
1340 return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() ));
1341}
1342
1343
1344
1346{
1347 TIXMLASSERT( visitor );
1348 return visitor->Visit( *this );
1349}
1350
1351// --------- XMLUnknown ---------- //
1352
1354{
1355}
1356
1357
1359{
1360}
1361
1362
1363char* XMLUnknown::ParseDeep( char* p, StrPair*, int* curLineNumPtr )
1364{
1365 // Unknown parses as text.
1366 p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION, curLineNumPtr );
1367 if ( !p ) {
1369 }
1370 return p;
1371}
1372
1373
1375{
1376 if ( !doc ) {
1377 doc = _document;
1378 }
1379 XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern?
1380 return text;
1381}
1382
1383
1385{
1387 const XMLUnknown* unknown = compare->ToUnknown();
1388 return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() ));
1389}
1390
1391
1392bool XMLUnknown::Accept( XMLVisitor* visitor ) const
1393{
1394 TIXMLASSERT( visitor );
1395 return visitor->Visit( *this );
1396}
1397
1398// --------- XMLAttribute ---------- //
1399
1400const char* XMLAttribute::Name() const
1401{
1402 return _name.GetStr();
1403}
1404
1405const char* XMLAttribute::Value() const
1406{
1407 return _value.GetStr();
1408}
1409
1410char* XMLAttribute::ParseDeep( char* p, bool processEntities, int* curLineNumPtr )
1411{
1412 // Parse using the name rules: bug fix, was using ParseText before
1413 p = _name.ParseName( p );
1414 if ( !p || !*p ) {
1415 return 0;
1416 }
1417
1418 // Skip white space before =
1419 p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1420 if ( *p != '=' ) {
1421 return 0;
1422 }
1423
1424 ++p; // move up to opening quote
1425 p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1426 if ( *p != '\"' && *p != '\'' ) {
1427 return 0;
1428 }
1429
1430 const char endTag[2] = { *p, 0 };
1431 ++p; // move past opening quote
1432
1433 p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES, curLineNumPtr );
1434 return p;
1435}
1436
1437
1438void XMLAttribute::SetName( const char* n )
1439{
1440 _name.SetStr( n );
1441}
1442
1443
1445{
1446 if ( XMLUtil::ToInt( Value(), value )) {
1447 return XML_SUCCESS;
1448 }
1450}
1451
1452
1453XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const
1454{
1455 if ( XMLUtil::ToUnsigned( Value(), value )) {
1456 return XML_SUCCESS;
1457 }
1459}
1460
1461
1463{
1464 if (XMLUtil::ToInt64(Value(), value)) {
1465 return XML_SUCCESS;
1466 }
1468}
1469
1470
1472{
1473 if(XMLUtil::ToUnsigned64(Value(), value)) {
1474 return XML_SUCCESS;
1475 }
1477}
1478
1479
1481{
1482 if ( XMLUtil::ToBool( Value(), value )) {
1483 return XML_SUCCESS;
1484 }
1486}
1487
1488
1490{
1491 if ( XMLUtil::ToFloat( Value(), value )) {
1492 return XML_SUCCESS;
1493 }
1495}
1496
1497
1499{
1500 if ( XMLUtil::ToDouble( Value(), value )) {
1501 return XML_SUCCESS;
1502 }
1504}
1505
1506
1507void XMLAttribute::SetAttribute( const char* v )
1508{
1509 _value.SetStr( v );
1510}
1511
1512
1514{
1515 char buf[BUF_SIZE];
1516 XMLUtil::ToStr( v, buf, BUF_SIZE );
1517 _value.SetStr( buf );
1518}
1519
1520
1522{
1523 char buf[BUF_SIZE];
1524 XMLUtil::ToStr( v, buf, BUF_SIZE );
1525 _value.SetStr( buf );
1526}
1527
1528
1530{
1531 char buf[BUF_SIZE];
1532 XMLUtil::ToStr(v, buf, BUF_SIZE);
1533 _value.SetStr(buf);
1534}
1535
1537{
1538 char buf[BUF_SIZE];
1539 XMLUtil::ToStr(v, buf, BUF_SIZE);
1540 _value.SetStr(buf);
1541}
1542
1543
1545{
1546 char buf[BUF_SIZE];
1547 XMLUtil::ToStr( v, buf, BUF_SIZE );
1548 _value.SetStr( buf );
1549}
1550
1552{
1553 char buf[BUF_SIZE];
1554 XMLUtil::ToStr( v, buf, BUF_SIZE );
1555 _value.SetStr( buf );
1556}
1557
1559{
1560 char buf[BUF_SIZE];
1561 XMLUtil::ToStr( v, buf, BUF_SIZE );
1562 _value.SetStr( buf );
1563}
1564
1565
1566// --------- XMLElement ---------- //
1568 _closingType( OPEN ),
1569 _rootAttribute( 0 )
1570{
1571}
1572
1573
1575{
1576 while( _rootAttribute ) {
1579 _rootAttribute = next;
1580 }
1581}
1582
1583
1585{
1586 for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) {
1587 if ( XMLUtil::StringEqual( a->Name(), name ) ) {
1588 return a;
1589 }
1590 }
1591 return 0;
1592}
1593
1594
1595const char* XMLElement::Attribute( const char* name, const char* value ) const
1596{
1597 const XMLAttribute* a = FindAttribute( name );
1598 if ( !a ) {
1599 return 0;
1600 }
1601 if ( !value || XMLUtil::StringEqual( a->Value(), value )) {
1602 return a->Value();
1603 }
1604 return 0;
1605}
1606
1607int XMLElement::IntAttribute(const char* name, int defaultValue) const
1608{
1609 int i = defaultValue;
1611 return i;
1612}
1613
1614unsigned XMLElement::UnsignedAttribute(const char* name, unsigned defaultValue) const
1615{
1616 unsigned i = defaultValue;
1618 return i;
1619}
1620
1621int64_t XMLElement::Int64Attribute(const char* name, int64_t defaultValue) const
1622{
1623 int64_t i = defaultValue;
1625 return i;
1626}
1627
1628uint64_t XMLElement::Unsigned64Attribute(const char* name, uint64_t defaultValue) const
1629{
1630 uint64_t i = defaultValue;
1632 return i;
1633}
1634
1635bool XMLElement::BoolAttribute(const char* name, bool defaultValue) const
1636{
1637 bool b = defaultValue;
1639 return b;
1640}
1641
1642double XMLElement::DoubleAttribute(const char* name, double defaultValue) const
1643{
1644 double d = defaultValue;
1646 return d;
1647}
1648
1649float XMLElement::FloatAttribute(const char* name, float defaultValue) const
1650{
1651 float f = defaultValue;
1653 return f;
1654}
1655
1656const char* XMLElement::GetText() const
1657{
1658 /* skip comment node */
1659 const XMLNode* node = FirstChild();
1660 while (node) {
1661 if (node->ToComment()) {
1662 node = node->NextSibling();
1663 continue;
1664 }
1665 break;
1666 }
1667
1668 if ( node && node->ToText() ) {
1669 return node->Value();
1670 }
1671 return 0;
1672}
1673
1674
1675void XMLElement::SetText( const char* inText )
1676{
1677 if ( FirstChild() && FirstChild()->ToText() )
1678 FirstChild()->SetValue( inText );
1679 else {
1680 XMLText* theText = GetDocument()->NewText( inText );
1681 InsertFirstChild( theText );
1682 }
1683}
1684
1685
1687{
1688 char buf[BUF_SIZE];
1689 XMLUtil::ToStr( v, buf, BUF_SIZE );
1690 SetText( buf );
1691}
1692
1693
1694void XMLElement::SetText( unsigned v )
1695{
1696 char buf[BUF_SIZE];
1697 XMLUtil::ToStr( v, buf, BUF_SIZE );
1698 SetText( buf );
1699}
1700
1701
1702void XMLElement::SetText(int64_t v)
1703{
1704 char buf[BUF_SIZE];
1705 XMLUtil::ToStr(v, buf, BUF_SIZE);
1706 SetText(buf);
1707}
1708
1709void XMLElement::SetText(uint64_t v) {
1710 char buf[BUF_SIZE];
1711 XMLUtil::ToStr(v, buf, BUF_SIZE);
1712 SetText(buf);
1713}
1714
1715
1717{
1718 char buf[BUF_SIZE];
1719 XMLUtil::ToStr( v, buf, BUF_SIZE );
1720 SetText( buf );
1721}
1722
1723
1724void XMLElement::SetText( float v )
1725{
1726 char buf[BUF_SIZE];
1727 XMLUtil::ToStr( v, buf, BUF_SIZE );
1728 SetText( buf );
1729}
1730
1731
1732void XMLElement::SetText( double v )
1733{
1734 char buf[BUF_SIZE];
1735 XMLUtil::ToStr( v, buf, BUF_SIZE );
1736 SetText( buf );
1737}
1738
1739
1741{
1742 if ( FirstChild() && FirstChild()->ToText() ) {
1743 const char* t = FirstChild()->Value();
1744 if ( XMLUtil::ToInt( t, ival ) ) {
1745 return XML_SUCCESS;
1746 }
1748 }
1749 return XML_NO_TEXT_NODE;
1750}
1751
1752
1754{
1755 if ( FirstChild() && FirstChild()->ToText() ) {
1756 const char* t = FirstChild()->Value();
1757 if ( XMLUtil::ToUnsigned( t, uval ) ) {
1758 return XML_SUCCESS;
1759 }
1761 }
1762 return XML_NO_TEXT_NODE;
1763}
1764
1765
1767{
1768 if (FirstChild() && FirstChild()->ToText()) {
1769 const char* t = FirstChild()->Value();
1770 if (XMLUtil::ToInt64(t, ival)) {
1771 return XML_SUCCESS;
1772 }
1774 }
1775 return XML_NO_TEXT_NODE;
1776}
1777
1778
1780{
1781 if(FirstChild() && FirstChild()->ToText()) {
1782 const char* t = FirstChild()->Value();
1783 if(XMLUtil::ToUnsigned64(t, ival)) {
1784 return XML_SUCCESS;
1785 }
1787 }
1788 return XML_NO_TEXT_NODE;
1789}
1790
1791
1793{
1794 if ( FirstChild() && FirstChild()->ToText() ) {
1795 const char* t = FirstChild()->Value();
1796 if ( XMLUtil::ToBool( t, bval ) ) {
1797 return XML_SUCCESS;
1798 }
1800 }
1801 return XML_NO_TEXT_NODE;
1802}
1803
1804
1806{
1807 if ( FirstChild() && FirstChild()->ToText() ) {
1808 const char* t = FirstChild()->Value();
1809 if ( XMLUtil::ToDouble( t, dval ) ) {
1810 return XML_SUCCESS;
1811 }
1813 }
1814 return XML_NO_TEXT_NODE;
1815}
1816
1817
1819{
1820 if ( FirstChild() && FirstChild()->ToText() ) {
1821 const char* t = FirstChild()->Value();
1822 if ( XMLUtil::ToFloat( t, fval ) ) {
1823 return XML_SUCCESS;
1824 }
1826 }
1827 return XML_NO_TEXT_NODE;
1828}
1829
1830int XMLElement::IntText(int defaultValue) const
1831{
1832 int i = defaultValue;
1833 QueryIntText(&i);
1834 return i;
1835}
1836
1837unsigned XMLElement::UnsignedText(unsigned defaultValue) const
1838{
1839 unsigned i = defaultValue;
1841 return i;
1842}
1843
1844int64_t XMLElement::Int64Text(int64_t defaultValue) const
1845{
1846 int64_t i = defaultValue;
1847 QueryInt64Text(&i);
1848 return i;
1849}
1850
1851uint64_t XMLElement::Unsigned64Text(uint64_t defaultValue) const
1852{
1853 uint64_t i = defaultValue;
1855 return i;
1856}
1857
1858bool XMLElement::BoolText(bool defaultValue) const
1859{
1860 bool b = defaultValue;
1861 QueryBoolText(&b);
1862 return b;
1863}
1864
1865double XMLElement::DoubleText(double defaultValue) const
1866{
1867 double d = defaultValue;
1868 QueryDoubleText(&d);
1869 return d;
1870}
1871
1872float XMLElement::FloatText(float defaultValue) const
1873{
1874 float f = defaultValue;
1875 QueryFloatText(&f);
1876 return f;
1877}
1878
1879
1881{
1882 XMLAttribute* last = 0;
1883 XMLAttribute* attrib = 0;
1884 for( attrib = _rootAttribute;
1885 attrib;
1886 last = attrib, attrib = attrib->_next ) {
1887 if ( XMLUtil::StringEqual( attrib->Name(), name ) ) {
1888 break;
1889 }
1890 }
1891 if ( !attrib ) {
1892 attrib = CreateAttribute();
1893 TIXMLASSERT( attrib );
1894 if ( last ) {
1895 TIXMLASSERT( last->_next == 0 );
1896 last->_next = attrib;
1897 }
1898 else {
1900 _rootAttribute = attrib;
1901 }
1902 attrib->SetName( name );
1903 }
1904 return attrib;
1905}
1906
1907
1909{
1910 XMLAttribute* prev = 0;
1911 for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) {
1912 if ( XMLUtil::StringEqual( name, a->Name() ) ) {
1913 if ( prev ) {
1914 prev->_next = a->_next;
1915 }
1916 else {
1917 _rootAttribute = a->_next;
1918 }
1919 DeleteAttribute( a );
1920 break;
1921 }
1922 prev = a;
1923 }
1924}
1925
1926
1927char* XMLElement::ParseAttributes( char* p, int* curLineNumPtr )
1928{
1929 XMLAttribute* prevAttribute = 0;
1930
1931 // Read the attributes.
1932 while( p ) {
1933 p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
1934 if ( !(*p) ) {
1935 _document->SetError( XML_ERROR_PARSING_ELEMENT, _parseLineNum, "XMLElement name=%s", Name() );
1936 return 0;
1937 }
1938
1939 // attribute.
1940 if (XMLUtil::IsNameStartChar( (unsigned char) *p ) ) {
1941 XMLAttribute* attrib = CreateAttribute();
1942 TIXMLASSERT( attrib );
1944
1945 const int attrLineNum = attrib->_parseLineNum;
1946
1947 p = attrib->ParseDeep( p, _document->ProcessEntities(), curLineNumPtr );
1948 if ( !p || Attribute( attrib->Name() ) ) {
1949 DeleteAttribute( attrib );
1950 _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, attrLineNum, "XMLElement name=%s", Name() );
1951 return 0;
1952 }
1953 // There is a minor bug here: if the attribute in the source xml
1954 // document is duplicated, it will not be detected and the
1955 // attribute will be doubly added. However, tracking the 'prevAttribute'
1956 // avoids re-scanning the attribute list. Preferring performance for
1957 // now, may reconsider in the future.
1958 if ( prevAttribute ) {
1959 TIXMLASSERT( prevAttribute->_next == 0 );
1960 prevAttribute->_next = attrib;
1961 }
1962 else {
1964 _rootAttribute = attrib;
1965 }
1966 prevAttribute = attrib;
1967 }
1968 // end of the tag
1969 else if ( *p == '>' ) {
1970 ++p;
1971 break;
1972 }
1973 // end of the tag
1974 else if ( *p == '/' && *(p+1) == '>' ) {
1976 return p+2; // done; sealed element.
1977 }
1978 else {
1980 return 0;
1981 }
1982 }
1983 return p;
1984}
1985
1987{
1988 if ( attribute == 0 ) {
1989 return;
1990 }
1991 MemPool* pool = attribute->_memPool;
1992 attribute->~XMLAttribute();
1993 pool->Free( attribute );
1994}
1995
1997{
1998 TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() );
1999 XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute();
2000 TIXMLASSERT( attrib );
2001 attrib->_memPool = &_document->_attributePool;
2002 attrib->_memPool->SetTracked();
2003 return attrib;
2004}
2005
2006
2008{
2010 return InsertEndChild(node) ? node : 0;
2011}
2012
2014{
2015 XMLComment* node = _document->NewComment(comment);
2016 return InsertEndChild(node) ? node : 0;
2017}
2018
2020{
2021 XMLText* node = _document->NewText(text);
2022 return InsertEndChild(node) ? node : 0;
2023}
2024
2026{
2028 return InsertEndChild(node) ? node : 0;
2029}
2030
2032{
2033 XMLUnknown* node = _document->NewUnknown(text);
2034 return InsertEndChild(node) ? node : 0;
2035}
2036
2037
2038
2039//
2040// <ele></ele>
2041// <ele>foo<b>bar</b></ele>
2042//
2043char* XMLElement::ParseDeep( char* p, StrPair* parentEndTag, int* curLineNumPtr )
2044{
2045 // Read the element name.
2046 p = XMLUtil::SkipWhiteSpace( p, curLineNumPtr );
2047
2048 // The closing element is the </element> form. It is
2049 // parsed just like a regular element then deleted from
2050 // the DOM.
2051 if ( *p == '/' ) {
2053 ++p;
2054 }
2055
2056 p = _value.ParseName( p );
2057 if ( _value.Empty() ) {
2058 return 0;
2059 }
2060
2061 p = ParseAttributes( p, curLineNumPtr );
2062 if ( !p || !*p || _closingType != OPEN ) {
2063 return p;
2064 }
2065
2066 p = XMLNode::ParseDeep( p, parentEndTag, curLineNumPtr );
2067 return p;
2068}
2069
2070
2071
2073{
2074 if ( !doc ) {
2075 doc = _document;
2076 }
2077 XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern?
2078 for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) {
2079 element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern?
2080 }
2081 return element;
2082}
2083
2084
2086{
2088 const XMLElement* other = compare->ToElement();
2089 if ( other && XMLUtil::StringEqual( other->Name(), Name() )) {
2090
2091 const XMLAttribute* a=FirstAttribute();
2092 const XMLAttribute* b=other->FirstAttribute();
2093
2094 while ( a && b ) {
2095 if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) {
2096 return false;
2097 }
2098 a = a->Next();
2099 b = b->Next();
2100 }
2101 if ( a || b ) {
2102 // different count
2103 return false;
2104 }
2105 return true;
2106 }
2107 return false;
2108}
2109
2110
2111bool XMLElement::Accept( XMLVisitor* visitor ) const
2112{
2113 TIXMLASSERT( visitor );
2114 if ( visitor->VisitEnter( *this, _rootAttribute ) ) {
2115 for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) {
2116 if ( !node->Accept( visitor ) ) {
2117 break;
2118 }
2119 }
2120 }
2121 return visitor->VisitExit( *this );
2122}
2123
2124
2125// --------- XMLDocument ----------- //
2126
2127// Warning: List must match 'enum XMLError'
2129 "XML_SUCCESS",
2130 "XML_NO_ATTRIBUTE",
2131 "XML_WRONG_ATTRIBUTE_TYPE",
2132 "XML_ERROR_FILE_NOT_FOUND",
2133 "XML_ERROR_FILE_COULD_NOT_BE_OPENED",
2134 "XML_ERROR_FILE_READ_ERROR",
2135 "XML_ERROR_PARSING_ELEMENT",
2136 "XML_ERROR_PARSING_ATTRIBUTE",
2137 "XML_ERROR_PARSING_TEXT",
2138 "XML_ERROR_PARSING_CDATA",
2139 "XML_ERROR_PARSING_COMMENT",
2140 "XML_ERROR_PARSING_DECLARATION",
2141 "XML_ERROR_PARSING_UNKNOWN",
2142 "XML_ERROR_EMPTY_DOCUMENT",
2143 "XML_ERROR_MISMATCHED_ELEMENT",
2144 "XML_ERROR_PARSING",
2145 "XML_CAN_NOT_CONVERT_TEXT",
2146 "XML_NO_TEXT_NODE",
2147 "XML_ELEMENT_DEPTH_EXCEEDED"
2148};
2149
2150
2151XMLDocument::XMLDocument( bool processEntities, Whitespace whitespaceMode ) :
2152 XMLNode( 0 ),
2153 _writeBOM( false ),
2154 _processEntities( processEntities ),
2155 _errorID(XML_SUCCESS),
2156 _whitespaceMode( whitespaceMode ),
2157 _errorStr(),
2158 _errorLineNum( 0 ),
2159 _charBuffer( 0 ),
2160 _parseCurLineNum( 0 ),
2161 _parsingDepth(0),
2162 _unlinked(),
2163 _elementPool(),
2164 _attributePool(),
2165 _textPool(),
2166 _commentPool()
2167{
2168 // avoid VC++ C4355 warning about 'this' in initializer list (C4355 is off by default in VS2012+)
2169 _document = this;
2170}
2171
2172
2174{
2175 Clear();
2176}
2177
2178
2179void XMLDocument::MarkInUse(const XMLNode* const node)
2180{
2181 TIXMLASSERT(node);
2182 TIXMLASSERT(node->_parent == 0);
2183
2184 for (int i = 0; i < _unlinked.Size(); ++i) {
2185 if (node == _unlinked[i]) {
2186 _unlinked.SwapRemove(i);
2187 break;
2188 }
2189 }
2190}
2191
2193{
2195 while( _unlinked.Size()) {
2196 DeleteNode(_unlinked[0]); // Will remove from _unlinked as part of delete.
2197 }
2198
2199#ifdef TINYXML2_DEBUG
2200 const bool hadError = Error();
2201#endif
2202 ClearError();
2203
2204 delete [] _charBuffer;
2205 _charBuffer = 0;
2206 _parsingDepth = 0;
2207
2208#if 0
2209 _textPool.Trace( "text" );
2210 _elementPool.Trace( "element" );
2211 _commentPool.Trace( "comment" );
2212 _attributePool.Trace( "attribute" );
2213#endif
2214
2215#ifdef TINYXML2_DEBUG
2216 if ( !hadError ) {
2217 TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() );
2218 TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() );
2219 TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() );
2220 TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() );
2221 }
2222#endif
2223}
2224
2225
2227{
2228 TIXMLASSERT(target);
2229 if (target == this) {
2230 return; // technically success - a no-op.
2231 }
2232
2233 target->Clear();
2234 for (const XMLNode* node = this->FirstChild(); node; node = node->NextSibling()) {
2235 target->InsertEndChild(node->DeepClone(target));
2236 }
2237}
2238
2240{
2241 XMLElement* ele = CreateUnlinkedNode<XMLElement>( _elementPool );
2242 ele->SetName( name );
2243 return ele;
2244}
2245
2246
2248{
2249 XMLComment* comment = CreateUnlinkedNode<XMLComment>( _commentPool );
2250 comment->SetValue( str );
2251 return comment;
2252}
2253
2254
2256{
2257 XMLText* text = CreateUnlinkedNode<XMLText>( _textPool );
2258 text->SetValue( str );
2259 return text;
2260}
2261
2262
2264{
2265 XMLDeclaration* dec = CreateUnlinkedNode<XMLDeclaration>( _commentPool );
2266 dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" );
2267 return dec;
2268}
2269
2270
2272{
2273 XMLUnknown* unk = CreateUnlinkedNode<XMLUnknown>( _commentPool );
2274 unk->SetValue( str );
2275 return unk;
2276}
2277
2278static FILE* callfopen( const char* filepath, const char* mode )
2279{
2280 TIXMLASSERT( filepath );
2281 TIXMLASSERT( mode );
2282#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE)
2283 FILE* fp = 0;
2284 const errno_t err = fopen_s( &fp, filepath, mode );
2285 if ( err ) {
2286 return 0;
2287 }
2288#else
2289 FILE* fp = fopen( filepath, mode );
2290#endif
2291 return fp;
2292}
2293
2295 TIXMLASSERT( node );
2296 TIXMLASSERT(node->_document == this );
2297 if (node->_parent) {
2298 node->_parent->DeleteChild( node );
2299 }
2300 else {
2301 // Isn't in the tree.
2302 // Use the parent delete.
2303 // Also, we need to mark it tracked: we 'know'
2304 // it was never used.
2305 node->_memPool->SetTracked();
2306 // Call the static XMLNode version:
2307 XMLNode::DeleteNode(node);
2308 }
2309}
2310
2311
2312XMLError XMLDocument::LoadFile( const char* filename )
2313{
2314 if ( !filename ) {
2315 TIXMLASSERT( false );
2316 SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2317 return _errorID;
2318 }
2319
2320 Clear();
2321 FILE* fp = callfopen( filename, "rb" );
2322 if ( !fp ) {
2323 SetError( XML_ERROR_FILE_NOT_FOUND, 0, "filename=%s", filename );
2324 return _errorID;
2325 }
2326 LoadFile( fp );
2327 fclose( fp );
2328 return _errorID;
2329}
2330
2332{
2333 Clear();
2334
2335 TIXML_FSEEK( fp, 0, SEEK_SET );
2336 if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) {
2338 return _errorID;
2339 }
2340
2341 TIXML_FSEEK( fp, 0, SEEK_END );
2342
2343 unsigned long long filelength;
2344 {
2345 const long long fileLengthSigned = TIXML_FTELL( fp );
2346 TIXML_FSEEK( fp, 0, SEEK_SET );
2347 if ( fileLengthSigned == -1L ) {
2349 return _errorID;
2350 }
2351 TIXMLASSERT( fileLengthSigned >= 0 );
2352 filelength = static_cast<unsigned long long>(fileLengthSigned);
2353 }
2354
2355 const size_t maxSizeT = static_cast<size_t>(-1);
2356 // We'll do the comparison as an unsigned long long, because that's guaranteed to be at
2357 // least 8 bytes, even on a 32-bit platform.
2358 if ( filelength >= static_cast<unsigned long long>(maxSizeT) ) {
2359 // Cannot handle files which won't fit in buffer together with null terminator
2361 return _errorID;
2362 }
2363
2364 if ( filelength == 0 ) {
2366 return _errorID;
2367 }
2368
2369 const size_t size = static_cast<size_t>(filelength);
2370 TIXMLASSERT( _charBuffer == 0 );
2371 _charBuffer = new char[size+1];
2372 const size_t read = fread( _charBuffer, 1, size, fp );
2373 if ( read != size ) {
2375 return _errorID;
2376 }
2377
2378 _charBuffer[size] = 0;
2379
2380 Parse();
2381 return _errorID;
2382}
2383
2384
2385XMLError XMLDocument::SaveFile( const char* filename, bool compact )
2386{
2387 if ( !filename ) {
2388 TIXMLASSERT( false );
2389 SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=<null>" );
2390 return _errorID;
2391 }
2392
2393 FILE* fp = callfopen( filename, "w" );
2394 if ( !fp ) {
2395 SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, 0, "filename=%s", filename );
2396 return _errorID;
2397 }
2398 SaveFile(fp, compact);
2399 fclose( fp );
2400 return _errorID;
2401}
2402
2403
2404XMLError XMLDocument::SaveFile( FILE* fp, bool compact )
2405{
2406 // Clear any error from the last save, otherwise it will get reported
2407 // for *this* call.
2408 ClearError();
2409 XMLPrinter stream( fp, compact );
2410 Print( &stream );
2411 return _errorID;
2412}
2413
2414
2415XMLError XMLDocument::Parse( const char* p, size_t len )
2416{
2417 Clear();
2418
2419 if ( len == 0 || !p || !*p ) {
2421 return _errorID;
2422 }
2423 if ( len == static_cast<size_t>(-1) ) {
2424 len = strlen( p );
2425 }
2426 TIXMLASSERT( _charBuffer == 0 );
2427 _charBuffer = new char[ len+1 ];
2428 memcpy( _charBuffer, p, len );
2429 _charBuffer[len] = 0;
2430
2431 Parse();
2432 if ( Error() ) {
2433 // clean up now essentially dangling memory.
2434 // and the parse fail can put objects in the
2435 // pools that are dead and inaccessible.
2437 _elementPool.Clear();
2438 _attributePool.Clear();
2439 _textPool.Clear();
2440 _commentPool.Clear();
2441 }
2442 return _errorID;
2443}
2444
2445
2446void XMLDocument::Print( XMLPrinter* streamer ) const
2447{
2448 if ( streamer ) {
2449 Accept( streamer );
2450 }
2451 else {
2452 XMLPrinter stdoutStreamer( stdout );
2453 Accept( &stdoutStreamer );
2454 }
2455}
2456
2457
2460 _errorLineNum = 0;
2461 _errorStr.Reset();
2462}
2463
2464
2465void XMLDocument::SetError( XMLError error, int lineNum, const char* format, ... )
2466{
2467 TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT );
2468 _errorID = error;
2469 _errorLineNum = lineNum;
2470 _errorStr.Reset();
2471
2472 const size_t BUFFER_SIZE = 1000;
2473 char* buffer = new char[BUFFER_SIZE];
2474
2475 TIXMLASSERT(sizeof(error) <= sizeof(int));
2476 TIXML_SNPRINTF(buffer, BUFFER_SIZE, "Error=%s ErrorID=%d (0x%x) Line number=%d", ErrorIDToName(error), int(error), int(error), lineNum);
2477
2478 if (format) {
2479 size_t len = strlen(buffer);
2480 TIXML_SNPRINTF(buffer + len, BUFFER_SIZE - len, ": ");
2481 len = strlen(buffer);
2482
2483 va_list va;
2484 va_start(va, format);
2485 TIXML_VSNPRINTF(buffer + len, BUFFER_SIZE - len, format, va);
2486 va_end(va);
2487 }
2488 _errorStr.SetStr(buffer);
2489 delete[] buffer;
2490}
2491
2492
2493/*static*/ const char* XMLDocument::ErrorIDToName(XMLError errorID)
2494{
2495 TIXMLASSERT( errorID >= 0 && errorID < XML_ERROR_COUNT );
2496 const char* errorName = _errorNames[errorID];
2497 TIXMLASSERT( errorName && errorName[0] );
2498 return errorName;
2499}
2500
2501const char* XMLDocument::ErrorStr() const
2502{
2503 return _errorStr.Empty() ? "" : _errorStr.GetStr();
2504}
2505
2506
2508{
2509 printf("%s\n", ErrorStr());
2510}
2511
2512const char* XMLDocument::ErrorName() const
2513{
2514 return ErrorIDToName(_errorID);
2515}
2516
2518{
2519 TIXMLASSERT( NoChildren() ); // Clear() must have been called previously
2521 _parseCurLineNum = 1;
2522 _parseLineNum = 1;
2523 char* p = _charBuffer;
2525 p = const_cast<char*>( XMLUtil::ReadBOM( p, &_writeBOM ) );
2526 if ( !*p ) {
2528 return;
2529 }
2530 ParseDeep(p, 0, &_parseCurLineNum );
2531}
2532
2534{
2535 _parsingDepth++;
2537 SetError(XML_ELEMENT_DEPTH_EXCEEDED, _parseCurLineNum, "Element nesting is too deep." );
2538 }
2539}
2540
2542{
2544 --_parsingDepth;
2545}
2546
2547XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) :
2548 _elementJustOpened( false ),
2549 _stack(),
2550 _firstElement( true ),
2551 _fp( file ),
2552 _depth( depth ),
2553 _textDepth( -1 ),
2554 _processEntities( true ),
2555 _compactMode( compact ),
2556 _buffer()
2557{
2558 for( int i=0; i<ENTITY_RANGE; ++i ) {
2559 _entityFlag[i] = false;
2560 _restrictedEntityFlag[i] = false;
2561 }
2562 for( int i=0; i<NUM_ENTITIES; ++i ) {
2563 const char entityValue = entities[i].value;
2564 const unsigned char flagIndex = static_cast<unsigned char>(entityValue);
2565 TIXMLASSERT( flagIndex < ENTITY_RANGE );
2566 _entityFlag[flagIndex] = true;
2567 }
2568 _restrictedEntityFlag[static_cast<unsigned char>('&')] = true;
2569 _restrictedEntityFlag[static_cast<unsigned char>('<')] = true;
2570 _restrictedEntityFlag[static_cast<unsigned char>('>')] = true; // not required, but consistency is nice
2571 _buffer.Push( 0 );
2572}
2573
2574
2575void XMLPrinter::Print( const char* format, ... )
2576{
2577 va_list va;
2578 va_start( va, format );
2579
2580 if ( _fp ) {
2581 vfprintf( _fp, format, va );
2582 }
2583 else {
2584 const int len = TIXML_VSCPRINTF( format, va );
2585 // Close out and re-start the va-args
2586 va_end( va );
2587 TIXMLASSERT( len >= 0 );
2588 va_start( va, format );
2589 TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 );
2590 char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator.
2591 TIXML_VSNPRINTF( p, len+1, format, va );
2592 }
2593 va_end( va );
2594}
2595
2596
2597void XMLPrinter::Write( const char* data, size_t size )
2598{
2599 if ( _fp ) {
2600 fwrite ( data , sizeof(char), size, _fp);
2601 }
2602 else {
2603 char* p = _buffer.PushArr( static_cast<int>(size) ) - 1; // back up over the null terminator.
2604 memcpy( p, data, size );
2605 p[size] = 0;
2606 }
2607}
2608
2609
2610void XMLPrinter::Putc( char ch )
2611{
2612 if ( _fp ) {
2613 fputc ( ch, _fp);
2614 }
2615 else {
2616 char* p = _buffer.PushArr( sizeof(char) ) - 1; // back up over the null terminator.
2617 p[0] = ch;
2618 p[1] = 0;
2619 }
2620}
2621
2622
2623void XMLPrinter::PrintSpace( int depth )
2624{
2625 for( int i=0; i<depth; ++i ) {
2626 Write( " " );
2627 }
2628}
2629
2630
2631void XMLPrinter::PrintString( const char* p, bool restricted )
2632{
2633 // Look for runs of bytes between entities to print.
2634 const char* q = p;
2635
2636 if ( _processEntities ) {
2637 const bool* flag = restricted ? _restrictedEntityFlag : _entityFlag;
2638 while ( *q ) {
2639 TIXMLASSERT( p <= q );
2640 // Remember, char is sometimes signed. (How many times has that bitten me?)
2641 if ( *q > 0 && *q < ENTITY_RANGE ) {
2642 // Check for entities. If one is found, flush
2643 // the stream up until the entity, write the
2644 // entity, and keep looking.
2645 if ( flag[static_cast<unsigned char>(*q)] ) {
2646 while ( p < q ) {
2647 const size_t delta = q - p;
2648 const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast<int>(delta);
2649 Write( p, toPrint );
2650 p += toPrint;
2651 }
2652 bool entityPatternPrinted = false;
2653 for( int i=0; i<NUM_ENTITIES; ++i ) {
2654 if ( entities[i].value == *q ) {
2655 Putc( '&' );
2656 Write( entities[i].pattern, entities[i].length );
2657 Putc( ';' );
2658 entityPatternPrinted = true;
2659 break;
2660 }
2661 }
2662 if ( !entityPatternPrinted ) {
2663 // TIXMLASSERT( entityPatternPrinted ) causes gcc -Wunused-but-set-variable in release
2664 TIXMLASSERT( false );
2665 }
2666 ++p;
2667 }
2668 }
2669 ++q;
2670 TIXMLASSERT( p <= q );
2671 }
2672 // Flush the remaining string. This will be the entire
2673 // string if an entity wasn't found.
2674 if ( p < q ) {
2675 const size_t delta = q - p;
2676 const int toPrint = ( INT_MAX < delta ) ? INT_MAX : static_cast<int>(delta);
2677 Write( p, toPrint );
2678 }
2679 }
2680 else {
2681 Write( p );
2682 }
2683}
2684
2685
2686void XMLPrinter::PushHeader( bool writeBOM, bool writeDec )
2687{
2688 if ( writeBOM ) {
2689 static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 };
2690 Write( reinterpret_cast< const char* >( bom ) );
2691 }
2692 if ( writeDec ) {
2693 PushDeclaration( "xml version=\"1.0\"" );
2694 }
2695}
2696
2697void XMLPrinter::PrepareForNewNode( bool compactMode )
2698{
2700
2701 if ( compactMode ) {
2702 return;
2703 }
2704
2705 if ( _firstElement ) {
2707 } else if ( _textDepth < 0) {
2708 Putc( '\n' );
2709 PrintSpace( _depth );
2710 }
2711
2712 _firstElement = false;
2713}
2714
2715void XMLPrinter::OpenElement( const char* name, bool compactMode )
2716{
2717 PrepareForNewNode( compactMode );
2718 _stack.Push( name );
2719
2720 Write ( "<" );
2721 Write ( name );
2722
2723 _elementJustOpened = true;
2724 ++_depth;
2725}
2726
2727
2728void XMLPrinter::PushAttribute( const char* name, const char* value )
2729{
2731 Putc ( ' ' );
2732 Write( name );
2733 Write( "=\"" );
2734 PrintString( value, false );
2735 Putc ( '\"' );
2736}
2737
2738
2739void XMLPrinter::PushAttribute( const char* name, int v )
2740{
2741 char buf[BUF_SIZE];
2742 XMLUtil::ToStr( v, buf, BUF_SIZE );
2743 PushAttribute( name, buf );
2744}
2745
2746
2747void XMLPrinter::PushAttribute( const char* name, unsigned v )
2748{
2749 char buf[BUF_SIZE];
2750 XMLUtil::ToStr( v, buf, BUF_SIZE );
2751 PushAttribute( name, buf );
2752}
2753
2754
2755void XMLPrinter::PushAttribute(const char* name, int64_t v)
2756{
2757 char buf[BUF_SIZE];
2758 XMLUtil::ToStr(v, buf, BUF_SIZE);
2759 PushAttribute(name, buf);
2760}
2761
2762
2763void XMLPrinter::PushAttribute(const char* name, uint64_t v)
2764{
2765 char buf[BUF_SIZE];
2766 XMLUtil::ToStr(v, buf, BUF_SIZE);
2767 PushAttribute(name, buf);
2768}
2769
2770
2771void XMLPrinter::PushAttribute( const char* name, bool v )
2772{
2773 char buf[BUF_SIZE];
2774 XMLUtil::ToStr( v, buf, BUF_SIZE );
2775 PushAttribute( name, buf );
2776}
2777
2778
2779void XMLPrinter::PushAttribute( const char* name, double v )
2780{
2781 char buf[BUF_SIZE];
2782 XMLUtil::ToStr( v, buf, BUF_SIZE );
2783 PushAttribute( name, buf );
2784}
2785
2786
2787void XMLPrinter::CloseElement( bool compactMode )
2788{
2789 --_depth;
2790 const char* name = _stack.Pop();
2791
2792 if ( _elementJustOpened ) {
2793 Write( "/>" );
2794 }
2795 else {
2796 if ( _textDepth < 0 && !compactMode) {
2797 Putc( '\n' );
2798 PrintSpace( _depth );
2799 }
2800 Write ( "</" );
2801 Write ( name );
2802 Write ( ">" );
2803 }
2804
2805 if ( _textDepth == _depth ) {
2806 _textDepth = -1;
2807 }
2808 if ( _depth == 0 && !compactMode) {
2809 Putc( '\n' );
2810 }
2811 _elementJustOpened = false;
2812}
2813
2814
2816{
2817 if ( !_elementJustOpened ) {
2818 return;
2819 }
2820 _elementJustOpened = false;
2821 Putc( '>' );
2822}
2823
2824
2825void XMLPrinter::PushText( const char* text, bool cdata )
2826{
2827 _textDepth = _depth-1;
2828
2830 if ( cdata ) {
2831 Write( "<![CDATA[" );
2832 Write( text );
2833 Write( "]]>" );
2834 }
2835 else {
2836 PrintString( text, true );
2837 }
2838}
2839
2840
2841void XMLPrinter::PushText( int64_t value )
2842{
2843 char buf[BUF_SIZE];
2844 XMLUtil::ToStr( value, buf, BUF_SIZE );
2845 PushText( buf, false );
2846}
2847
2848
2849void XMLPrinter::PushText( uint64_t value )
2850{
2851 char buf[BUF_SIZE];
2852 XMLUtil::ToStr(value, buf, BUF_SIZE);
2853 PushText(buf, false);
2854}
2855
2856
2857void XMLPrinter::PushText( int value )
2858{
2859 char buf[BUF_SIZE];
2860 XMLUtil::ToStr( value, buf, BUF_SIZE );
2861 PushText( buf, false );
2862}
2863
2864
2865void XMLPrinter::PushText( unsigned value )
2866{
2867 char buf[BUF_SIZE];
2868 XMLUtil::ToStr( value, buf, BUF_SIZE );
2869 PushText( buf, false );
2870}
2871
2872
2873void XMLPrinter::PushText( bool value )
2874{
2875 char buf[BUF_SIZE];
2876 XMLUtil::ToStr( value, buf, BUF_SIZE );
2877 PushText( buf, false );
2878}
2879
2880
2881void XMLPrinter::PushText( float value )
2882{
2883 char buf[BUF_SIZE];
2884 XMLUtil::ToStr( value, buf, BUF_SIZE );
2885 PushText( buf, false );
2886}
2887
2888
2889void XMLPrinter::PushText( double value )
2890{
2891 char buf[BUF_SIZE];
2892 XMLUtil::ToStr( value, buf, BUF_SIZE );
2893 PushText( buf, false );
2894}
2895
2896
2897void XMLPrinter::PushComment( const char* comment )
2898{
2900
2901 Write( "<!--" );
2902 Write( comment );
2903 Write( "-->" );
2904}
2905
2906
2907void XMLPrinter::PushDeclaration( const char* value )
2908{
2910
2911 Write( "<?" );
2912 Write( value );
2913 Write( "?>" );
2914}
2915
2916
2917void XMLPrinter::PushUnknown( const char* value )
2918{
2920
2921 Write( "<!" );
2922 Write( value );
2923 Putc( '>' );
2924}
2925
2926
2928{
2930 if ( doc.HasBOM() ) {
2931 PushHeader( true, false );
2932 }
2933 return true;
2934}
2935
2936
2937bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute )
2938{
2939 const XMLElement* parentElem = 0;
2940 if ( element.Parent() ) {
2941 parentElem = element.Parent()->ToElement();
2942 }
2943 const bool compactMode = parentElem ? CompactMode( *parentElem ) : _compactMode;
2944 OpenElement( element.Name(), compactMode );
2945 while ( attribute ) {
2946 PushAttribute( attribute->Name(), attribute->Value() );
2947 attribute = attribute->Next();
2948 }
2949 return true;
2950}
2951
2952
2953bool XMLPrinter::VisitExit( const XMLElement& element )
2954{
2955 CloseElement( CompactMode(element) );
2956 return true;
2957}
2958
2959
2960bool XMLPrinter::Visit( const XMLText& text )
2961{
2962 PushText( text.Value(), text.CData() );
2963 return true;
2964}
2965
2966
2967bool XMLPrinter::Visit( const XMLComment& comment )
2968{
2969 PushComment( comment.Value() );
2970 return true;
2971}
2972
2973bool XMLPrinter::Visit( const XMLDeclaration& declaration )
2974{
2975 PushDeclaration( declaration.Value() );
2976 return true;
2977}
2978
2979
2980bool XMLPrinter::Visit( const XMLUnknown& unknown )
2981{
2982 PushUnknown( unknown.Value() );
2983 return true;
2984}
2985
2986} // namespace tinyxml2
int Size() const
Definition: tinyxml2.h:272
T * PushArr(int count)
Definition: tinyxml2.h:233
void Push(T t)
Definition: tinyxml2.h:226
virtual void Free(void *)=0
virtual void SetTracked()=0
void SetStr(const char *str, int flags=0)
Definition: tinyxml2.cpp:194
void SetInternedStr(const char *str)
Definition: tinyxml2.h:170
void TransferTo(StrPair *other)
Definition: tinyxml2.cpp:158
void Set(char *start, char *end, int flags)
Definition: tinyxml2.h:155
char * ParseText(char *in, const char *endTag, int strFlags, int *curLineNumPtr)
Definition: tinyxml2.cpp:207
char * ParseName(char *in)
Definition: tinyxml2.cpp:232
@ NEEDS_WHITESPACE_COLLAPSING
Definition: tinyxml2.h:142
@ ATTRIBUTE_VALUE_LEAVE_ENTITIES
Definition: tinyxml2.h:148
@ NEEDS_NEWLINE_NORMALIZATION
Definition: tinyxml2.h:141
@ TEXT_ELEMENT_LEAVE_ENTITIES
Definition: tinyxml2.h:145
bool Empty() const
Definition: tinyxml2.h:166
const char * GetStr()
Definition: tinyxml2.cpp:281
void CollapseWhitespace()
Definition: tinyxml2.cpp:252
XMLError QueryFloatValue(float *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1489
virtual ~XMLAttribute()
Definition: tinyxml2.h:1244
XMLError QueryDoubleValue(double *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1498
XMLAttribute * _next
Definition: tinyxml2.h:1255
void SetAttribute(const char *value)
Set the attribute to a string value.
Definition: tinyxml2.cpp:1507
void SetName(const char *name)
Definition: tinyxml2.cpp:1438
XMLError QueryUnsignedValue(unsigned int *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1453
char * ParseDeep(char *p, bool processEntities, int *curLineNumPtr)
Definition: tinyxml2.cpp:1410
XMLError QueryInt64Value(int64_t *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1462
const char * Name() const
The name of the attribute.
Definition: tinyxml2.cpp:1400
XMLError QueryBoolValue(bool *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1480
XMLError QueryIntValue(int *value) const
Definition: tinyxml2.cpp:1444
const XMLAttribute * Next() const
The next attribute in the list.
Definition: tinyxml2.h:1154
const char * Value() const
The value of the attribute.
Definition: tinyxml2.cpp:1405
XMLError QueryUnsigned64Value(uint64_t *value) const
See QueryIntValue.
Definition: tinyxml2.cpp:1471
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1295
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1266
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1287
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1277
XMLComment(XMLDocument *doc)
Definition: tinyxml2.cpp:1256
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1315
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1345
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1326
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1336
XMLDeclaration(XMLDocument *doc)
Definition: tinyxml2.cpp:1304
MemPoolT< sizeof(XMLAttribute) > _attributePool
Definition: tinyxml2.h:1952
const char * ErrorName() const
Definition: tinyxml2.cpp:2512
void PrintError() const
A (trivial) utility function that prints the ErrorStr() to stdout.
Definition: tinyxml2.cpp:2507
DynArray< XMLNode *, 10 > _unlinked
Definition: tinyxml2.h:1949
MemPoolT< sizeof(XMLElement) > _elementPool
Definition: tinyxml2.h:1951
char * Identify(char *p, XMLNode **node)
Definition: tinyxml2.cpp:710
XMLError LoadFile(const char *filename)
Definition: tinyxml2.cpp:2312
bool HasBOM() const
Definition: tinyxml2.h:1798
bool Error() const
Return true if there was an error parsing the document.
Definition: tinyxml2.h:1881
XMLComment * NewComment(const char *comment)
Definition: tinyxml2.cpp:2247
XMLElement * NewElement(const char *name)
Definition: tinyxml2.cpp:2239
void ClearError()
Clears the error flags.
Definition: tinyxml2.cpp:2458
XMLUnknown * NewUnknown(const char *text)
Definition: tinyxml2.cpp:2271
bool ProcessEntities() const
Definition: tinyxml2.h:1788
static const char * ErrorIDToName(XMLError errorID)
Definition: tinyxml2.cpp:2493
void MarkInUse(const XMLNode *const)
Definition: tinyxml2.cpp:2179
void Clear()
Clear the document, resetting it to the initial state.
Definition: tinyxml2.cpp:2192
XMLError SaveFile(const char *filename, bool compact=false)
Definition: tinyxml2.cpp:2385
Whitespace WhitespaceMode() const
Definition: tinyxml2.h:1791
void Print(XMLPrinter *streamer=0) const
Definition: tinyxml2.cpp:2446
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:780
void SetError(XMLError error, int lineNum, const char *format,...)
Definition: tinyxml2.cpp:2465
void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:2294
MemPoolT< sizeof(XMLComment) > _commentPool
Definition: tinyxml2.h:1954
XMLText * NewText(const char *text)
Definition: tinyxml2.cpp:2255
XMLDeclaration * NewDeclaration(const char *text=0)
Definition: tinyxml2.cpp:2263
const char * ErrorStr() const
Definition: tinyxml2.cpp:2501
static const char * _errorNames[XML_ERROR_COUNT]
Definition: tinyxml2.h:1956
void DeepCopy(XMLDocument *target) const
Definition: tinyxml2.cpp:2226
MemPoolT< sizeof(XMLText) > _textPool
Definition: tinyxml2.h:1953
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:2043
const char * GetText() const
Definition: tinyxml2.cpp:1656
double DoubleAttribute(const char *name, double defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1642
XMLAttribute * CreateAttribute()
Definition: tinyxml2.cpp:1996
void SetAttribute(const char *name, const char *value)
Sets the named attribute to value.
Definition: tinyxml2.h:1465
XMLError QueryInt64Text(int64_t *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1766
XMLError QueryUnsigned64Attribute(const char *name, uint64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1370
XMLError QueryBoolAttribute(const char *name, bool *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1379
XMLError QueryUnsignedText(unsigned *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1753
const XMLAttribute * FindAttribute(const char *name) const
Query a specific attribute in the list.
Definition: tinyxml2.cpp:1584
char * ParseAttributes(char *p, int *curLineNumPtr)
Definition: tinyxml2.cpp:1927
void SetText(const char *inText)
Definition: tinyxml2.cpp:1675
uint64_t Unsigned64Attribute(const char *name, uint64_t defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1628
XMLError QueryUnsignedAttribute(const char *name, unsigned int *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1352
int IntText(int defaultValue=0) const
Definition: tinyxml2.cpp:1830
ElementClosingType _closingType
Definition: tinyxml2.h:1697
XMLError QueryBoolText(bool *bval) const
See QueryIntText()
Definition: tinyxml2.cpp:1792
float FloatText(float defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1872
const char * Attribute(const char *name, const char *value=0) const
Definition: tinyxml2.cpp:1595
unsigned UnsignedText(unsigned defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1837
const XMLAttribute * FirstAttribute() const
Return the first attribute in the list.
Definition: tinyxml2.h:1514
bool BoolAttribute(const char *name, bool defaultValue=false) const
See IntAttribute()
Definition: tinyxml2.cpp:1635
XMLError QueryDoubleAttribute(const char *name, double *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1387
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:2085
int64_t Int64Attribute(const char *name, int64_t defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1621
XMLError QueryDoubleText(double *dval) const
See QueryIntText()
Definition: tinyxml2.cpp:1805
bool BoolText(bool defaultValue=false) const
See QueryIntText()
Definition: tinyxml2.cpp:1858
ElementClosingType ClosingType() const
Definition: tinyxml2.h:1676
XMLError QueryInt64Attribute(const char *name, int64_t *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1361
XMLDeclaration * InsertNewDeclaration(const char *text)
See InsertNewChildElement()
Definition: tinyxml2.cpp:2025
double DoubleText(double defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1865
XMLError QueryIntAttribute(const char *name, int *value) const
Definition: tinyxml2.h:1343
XMLError QueryIntText(int *ival) const
Definition: tinyxml2.cpp:1740
int IntAttribute(const char *name, int defaultValue=0) const
Definition: tinyxml2.cpp:1607
void SetName(const char *str, bool staticMem=false)
Set the name of the element.
Definition: tinyxml2.h:1273
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:2111
int64_t Int64Text(int64_t defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1844
XMLComment * InsertNewComment(const char *comment)
See InsertNewChildElement()
Definition: tinyxml2.cpp:2013
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:2072
float FloatAttribute(const char *name, float defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1649
const char * Name() const
Get the name of an element (which is the Value() of the node.)
Definition: tinyxml2.h:1269
XMLElement * InsertNewChildElement(const char *name)
Definition: tinyxml2.cpp:2007
XMLError QueryUnsigned64Text(uint64_t *uval) const
See QueryIntText()
Definition: tinyxml2.cpp:1779
XMLText * InsertNewText(const char *text)
See InsertNewChildElement()
Definition: tinyxml2.cpp:2019
XMLAttribute * FindOrCreateAttribute(const char *name)
Definition: tinyxml2.cpp:1880
XMLError QueryFloatAttribute(const char *name, float *value) const
See QueryIntAttribute()
Definition: tinyxml2.h:1395
XMLAttribute * _rootAttribute
Definition: tinyxml2.h:1701
void DeleteAttribute(const char *name)
Definition: tinyxml2.cpp:1908
uint64_t Unsigned64Text(uint64_t defaultValue=0) const
See QueryIntText()
Definition: tinyxml2.cpp:1851
XMLError QueryFloatText(float *fval) const
See QueryIntText()
Definition: tinyxml2.cpp:1818
XMLUnknown * InsertNewUnknown(const char *text)
See InsertNewChildElement()
Definition: tinyxml2.cpp:2031
unsigned UnsignedAttribute(const char *name, unsigned defaultValue=0) const
See IntAttribute()
Definition: tinyxml2.cpp:1614
void DeleteChildren()
Definition: tinyxml2.cpp:848
const char * Value() const
Definition: tinyxml2.cpp:817
XMLNode * _lastChild
Definition: tinyxml2.h:960
void SetValue(const char *val, bool staticMem=false)
Definition: tinyxml2.cpp:825
virtual XMLText * ToText()
Safely cast to Text, or null.
Definition: tinyxml2.h:696
void InsertChildPreamble(XMLNode *insertThis) const
Definition: tinyxml2.cpp:1171
virtual XMLDeclaration * ToDeclaration()
Safely cast to a Declaration, or null.
Definition: tinyxml2.h:708
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:1018
XMLNode * _parent
Definition: tinyxml2.h:955
const XMLElement * FirstChildElement(const char *name=0) const
Definition: tinyxml2.cpp:994
XMLNode * _next
Definition: tinyxml2.h:963
XMLNode(XMLDocument *)
Definition: tinyxml2.cpp:796
void DeleteChild(XMLNode *node)
Definition: tinyxml2.cpp:882
XMLNode * DeepClone(XMLDocument *target) const
Definition: tinyxml2.cpp:835
StrPair _value
Definition: tinyxml2.h:956
const XMLNode * Parent() const
Get the parent of this node on the DOM.
Definition: tinyxml2.h:755
MemPool * _memPool
Definition: tinyxml2.h:968
friend class XMLDocument
Definition: tinyxml2.h:676
const XMLElement * ToElementWithName(const char *name) const
Definition: tinyxml2.cpp:1185
virtual XMLComment * ToComment()
Safely cast to a Comment, or null.
Definition: tinyxml2.h:700
const XMLElement * LastChildElement(const char *name=0) const
Definition: tinyxml2.cpp:1006
virtual XMLDocument * ToDocument()
Safely cast to a Document, or null.
Definition: tinyxml2.h:704
const XMLNode * LastChild() const
Get the last child node, or null if none exists.
Definition: tinyxml2.h:787
const XMLDocument * GetDocument() const
Get the XMLDocument that owns this XMLNode.
Definition: tinyxml2.h:681
XMLDocument * _document
Definition: tinyxml2.h:954
virtual ~XMLNode()
Definition: tinyxml2.cpp:809
virtual XMLNode * ShallowClone(XMLDocument *document) const =0
virtual char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1042
XMLNode * InsertAfterChild(XMLNode *afterThis, XMLNode *addThis)
Definition: tinyxml2.cpp:956
virtual XMLElement * ToElement()
Safely cast to an Element, or null.
Definition: tinyxml2.h:692
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:1030
void Unlink(XMLNode *child)
Definition: tinyxml2.cpp:858
XMLNode * _prev
Definition: tinyxml2.h:962
XMLNode * _firstChild
Definition: tinyxml2.h:959
static void DeleteNode(XMLNode *node)
Definition: tinyxml2.cpp:1156
const XMLNode * FirstChild() const
Get the first child node, or null if none exists.
Definition: tinyxml2.h:769
friend class XMLElement
Definition: tinyxml2.h:677
bool NoChildren() const
Returns true if this node has no children.
Definition: tinyxml2.h:764
XMLNode * InsertFirstChild(XMLNode *addThis)
Definition: tinyxml2.cpp:925
XMLNode * InsertEndChild(XMLNode *addThis)
Definition: tinyxml2.cpp:895
const XMLNode * NextSibling() const
Get the next (right) sibling node of this node.
Definition: tinyxml2.h:821
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:2290
void PushHeader(bool writeBOM, bool writeDeclaration)
Definition: tinyxml2.cpp:2686
DynArray< char, 20 > _buffer
Definition: tinyxml2.h:2366
virtual void PrintSpace(int depth)
Definition: tinyxml2.cpp:2623
void PushText(const char *text, bool cdata=false)
Add a text node.
Definition: tinyxml2.cpp:2825
void OpenElement(const char *name, bool compactMode=false)
Definition: tinyxml2.cpp:2715
void PushDeclaration(const char *value)
Definition: tinyxml2.cpp:2907
bool _entityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2363
virtual bool CompactMode(const XMLElement &)
Definition: tinyxml2.h:2328
void PrintString(const char *, bool restrictedEntitySet)
Definition: tinyxml2.cpp:2631
bool _restrictedEntityFlag[ENTITY_RANGE]
Definition: tinyxml2.h:2364
void PrepareForNewNode(bool compactMode)
Definition: tinyxml2.cpp:2697
virtual void Putc(char ch)
Definition: tinyxml2.cpp:2610
DynArray< const char *, 10 > _stack
Definition: tinyxml2.h:2342
void PushAttribute(const char *name, const char *value)
If streaming, add an attribute to an open element.
Definition: tinyxml2.cpp:2728
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.cpp:2927
XMLPrinter(FILE *file=0, bool compact=false, int depth=0)
Definition: tinyxml2.cpp:2547
void PushUnknown(const char *value)
Definition: tinyxml2.cpp:2917
virtual void Print(const char *format,...)
Definition: tinyxml2.cpp:2575
void SealElementIfJustOpened()
Definition: tinyxml2.cpp:2815
virtual bool Visit(const XMLText &text)
Visit a text node.
Definition: tinyxml2.cpp:2960
virtual void CloseElement(bool compactMode=false)
If streaming, close the Element.
Definition: tinyxml2.cpp:2787
void PushComment(const char *comment)
Add a comment.
Definition: tinyxml2.cpp:2897
virtual void Write(const char *data, size_t size)
Definition: tinyxml2.cpp:2597
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1247
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1228
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1239
bool CData() const
Returns true if this is a CDATA text element.
Definition: tinyxml2.h:1009
void SetCData(bool isCData)
Declare whether this should be CDATA or standard text.
Definition: tinyxml2.h:1005
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1201
virtual bool Accept(XMLVisitor *visitor) const
Definition: tinyxml2.cpp:1392
XMLUnknown(XMLDocument *doc)
Definition: tinyxml2.cpp:1353
virtual XMLNode * ShallowClone(XMLDocument *document) const
Definition: tinyxml2.cpp:1374
virtual bool ShallowEqual(const XMLNode *compare) const
Definition: tinyxml2.cpp:1384
char * ParseDeep(char *p, StrPair *parentEndTag, int *curLineNumPtr)
Definition: tinyxml2.cpp:1363
static bool IsNameChar(unsigned char ch)
Definition: tinyxml2.h:587
static bool ToUnsigned(const char *str, unsigned *value)
Definition: tinyxml2.cpp:628
static bool IsPrefixHex(const char *p)
Definition: tinyxml2.h:594
static void ConvertUTF32ToUTF8(unsigned long input, char *output, int *length)
Definition: tinyxml2.cpp:417
static bool IsWhiteSpace(char p)
Definition: tinyxml2.h:572
static bool ToFloat(const char *str, float *value)
Definition: tinyxml2.cpp:662
static void ToStr(int v, char *buffer, int bufferSize)
Definition: tinyxml2.cpp:566
static const char * GetCharacterRef(const char *p, char *value, int *length)
Definition: tinyxml2.cpp:470
static const char * writeBoolTrue
Definition: tinyxml2.h:644
static bool IsNameStartChar(unsigned char ch)
Definition: tinyxml2.h:576
static const char * SkipWhiteSpace(const char *p, int *curLineNumPtr)
Definition: tinyxml2.h:554
static bool StringEqual(const char *p, const char *q, int nChar=INT_MAX)
Definition: tinyxml2.h:599
static bool ToInt(const char *str, int *value)
Definition: tinyxml2.cpp:611
static bool ToDouble(const char *str, double *value)
Definition: tinyxml2.cpp:671
static const char * writeBoolFalse
Definition: tinyxml2.h:645
static bool ToUnsigned64(const char *str, uint64_t *value)
Definition: tinyxml2.cpp:700
static bool ToBool(const char *str, bool *value)
Definition: tinyxml2.cpp:636
static const char * ReadBOM(const char *p, bool *hasBOM)
Definition: tinyxml2.cpp:399
static void SetBoolSerialization(const char *writeTrue, const char *writeFalse)
Definition: tinyxml2.cpp:389
static bool ToInt64(const char *str, int64_t *value)
Definition: tinyxml2.cpp:680
virtual bool VisitExit(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:491
virtual bool VisitEnter(const XMLDocument &)
Visit a document.
Definition: tinyxml2.h:487
virtual bool Visit(const XMLDeclaration &)
Visit a declaration.
Definition: tinyxml2.h:505
static bool compare(const Dependency &first, const Dependency &second)
Static helper function for DependencyList::unique.
Definition: dependency.cpp:37
void read(std::basic_istream< CharT, Traits > &)
Definition: date.h:6444
CONSTDATA date::last_spec last
Definition: date.h:1989
CONSTDATA date::month dec
Definition: date.h:2002
auto format(const std::locale &loc, const CharT *fmt, const Streamable &tp) -> decltype(to_stream(std::declval< std::basic_ostream< CharT > & >(), fmt, tp), std::basic_string< CharT >{})
Definition: date.h:6249
@ XML_ERROR_MISMATCHED_ELEMENT
Definition: tinyxml2.h:538
@ XML_ELEMENT_DEPTH_EXCEEDED
Definition: tinyxml2.h:542
@ XML_ERROR_EMPTY_DOCUMENT
Definition: tinyxml2.h:537
@ XML_SUCCESS
Definition: tinyxml2.h:524
@ XML_ERROR_PARSING_ATTRIBUTE
Definition: tinyxml2.h:531
@ XML_ERROR_FILE_NOT_FOUND
Definition: tinyxml2.h:527
@ XML_ERROR_PARSING_TEXT
Definition: tinyxml2.h:532
@ XML_ERROR_PARSING_COMMENT
Definition: tinyxml2.h:534
@ XML_NO_TEXT_NODE
Definition: tinyxml2.h:541
@ XML_ERROR_FILE_READ_ERROR
Definition: tinyxml2.h:529
@ XML_ERROR_PARSING_UNKNOWN
Definition: tinyxml2.h:536
@ XML_ERROR_PARSING_CDATA
Definition: tinyxml2.h:533
@ XML_ERROR_COUNT
Definition: tinyxml2.h:544
@ XML_ERROR_PARSING_DECLARATION
Definition: tinyxml2.h:535
@ XML_WRONG_ATTRIBUTE_TYPE
Definition: tinyxml2.h:526
@ XML_ERROR_PARSING
Definition: tinyxml2.h:539
@ XML_ERROR_PARSING_ELEMENT
Definition: tinyxml2.h:530
@ XML_ERROR_FILE_COULD_NOT_BE_OPENED
Definition: tinyxml2.h:528
@ XML_CAN_NOT_CONVERT_TEXT
Definition: tinyxml2.h:540
static FILE * callfopen(const char *filepath, const char *mode)
Definition: tinyxml2.cpp:2278
@ COLLAPSE_WHITESPACE
Definition: tinyxml2.h:1707
static const Entity entities[NUM_ENTITIES]
Definition: tinyxml2.cpp:143
static const int NUM_ENTITIES
Definition: tinyxml2.cpp:142
char name[32]
Definition: resampler.cpp:371
const char * pattern
Definition: tinyxml2.cpp:137
static const char LF
Definition: tinyxml2.cpp:119
#define TIXML_FSEEK
Definition: tinyxml2.cpp:113
static const char DOUBLE_QUOTE
Definition: tinyxml2.cpp:123
static const unsigned char TIXML_UTF_LEAD_0
Definition: tinyxml2.cpp:129
static const unsigned char TIXML_UTF_LEAD_1
Definition: tinyxml2.cpp:130
static const char SINGLE_QUOTE
Definition: tinyxml2.cpp:122
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:131
#define TIXML_VSNPRINTF
Definition: tinyxml2.cpp:93
#define TIXML_SSCANF
Definition: tinyxml2.cpp:100
static const char LINE_FEED
Definition: tinyxml2.cpp:118
static const char CR
Definition: tinyxml2.cpp:121
static const char CARRIAGE_RETURN
Definition: tinyxml2.cpp:120
#define TIXML_FTELL
Definition: tinyxml2.cpp:114
#define TIXML_SNPRINTF
Definition: tinyxml2.cpp:92
#define TIXMLASSERT(x)
Definition: tinyxml2.h:95
static const int TINYXML2_MAX_ELEMENT_DEPTH
Definition: tinyxml2.h:115
#define EOF
Definition: zip.cpp:76