1 /*
2 www.sourceforge.net/projects/tinyxml
3 Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com)
4 
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any
7 damages arising from the use of this software.
8 
9 Permission is granted to anyone to use this software for any
10 purpose, including commercial applications, and to alter it and
11 redistribute it freely, subject to the following restrictions:
12 
13 1. The origin of this software must not be misrepresented; you must
14 not claim that you wrote the original software. If you use this
15 software in a product, an acknowledgment in the product documentation
16 would be appreciated but is not required.
17 
18 2. Altered source versions must be plainly marked as such, and
19 must not be misrepresented as being the original software.
20 
21 3. This notice may not be removed or altered from any source
22 distribution.
23 */
24 
25 #include <ctype.h>
26 
27 #ifdef TIXML_USE_STL
28 #include <sstream>
29 #include <iostream>
30 #endif
31 
32 #include "tinyxml.h"
33 
34 
35 bool TiXmlBase::condenseWhiteSpace = true;
36 
37 // Microsoft compiler security
TiXmlFOpen(const char * filename,const char * mode)38 FILE* TiXmlFOpen( const char* filename, const char* mode )
39 {
40 	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
41 		FILE* fp = 0;
42 		errno_t err = fopen_s( &fp, filename, mode );
43 		if ( !err && fp )
44 			return fp;
45 		return 0;
46 	#else
47 		return fopen( filename, mode );
48 	#endif
49 }
50 
EncodeString(const TIXML_STRING & str,TIXML_STRING * outString)51 void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
52 {
53 	int i=0;
54 
55 	while( i<(int)str.length() )
56 	{
57 		unsigned char c = (unsigned char) str[i];
58 
59 		if (    c == '&'
60 		     && i < ( (int)str.length() - 2 )
61 			 && str[i+1] == '#'
62 			 && str[i+2] == 'x' )
63 		{
64 			// Hexadecimal character reference.
65 			// Pass through unchanged.
66 			// &#xA9;	-- copyright symbol, for example.
67 			//
68 			// The -1 is a bug fix from Rob Laveaux. It keeps
69 			// an overflow from happening if there is no ';'.
70 			// There are actually 2 ways to exit this loop -
71 			// while fails (error case) and break (semicolon found).
72 			// However, there is no mechanism (currently) for
73 			// this function to return an error.
74 			while ( i<(int)str.length()-1 )
75 			{
76 				outString->append( str.c_str() + i, 1 );
77 				++i;
78 				if ( str[i] == ';' )
79 					break;
80 			}
81 		}
82 		else if ( c == '&' )
83 		{
84 			outString->append( entity[0].str, entity[0].strLength );
85 			++i;
86 		}
87 		else if ( c == '<' )
88 		{
89 			outString->append( entity[1].str, entity[1].strLength );
90 			++i;
91 		}
92 		else if ( c == '>' )
93 		{
94 			outString->append( entity[2].str, entity[2].strLength );
95 			++i;
96 		}
97 		else if ( c == '\"' )
98 		{
99 			outString->append( entity[3].str, entity[3].strLength );
100 			++i;
101 		}
102 		else if ( c == '\'' )
103 		{
104 			outString->append( entity[4].str, entity[4].strLength );
105 			++i;
106 		}
107 		else if ( c < 32 )
108 		{
109 			// Easy pass at non-alpha/numeric/symbol
110 			// Below 32 is symbolic.
111 			char buf[ 32 ];
112 
113 			#if defined(TIXML_SNPRINTF)
114 				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
115 			#else
116 				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
117 			#endif
118 
119 			//*ME:	warning C4267: convert 'size_t' to 'int'
120 			//*ME:	Int-Cast to make compiler happy ...
121 			outString->append( buf, (int)strlen( buf ) );
122 			++i;
123 		}
124 		else
125 		{
126 			//char realc = (char) c;
127 			//outString->append( &realc, 1 );
128 			*outString += (char) c;	// somewhat more efficient function call.
129 			++i;
130 		}
131 	}
132 }
133 
134 
TiXmlNode(NodeType _type)135 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
136 {
137 	parent = 0;
138 	type = _type;
139 	firstChild = 0;
140 	lastChild = 0;
141 	prev = 0;
142 	next = 0;
143 }
144 
145 
~TiXmlNode()146 TiXmlNode::~TiXmlNode()
147 {
148 	TiXmlNode* node = firstChild;
149 	TiXmlNode* temp = 0;
150 
151 	while ( node )
152 	{
153 		temp = node;
154 		node = node->next;
155 		delete temp;
156 	}
157 }
158 
159 
CopyTo(TiXmlNode * target) const160 void TiXmlNode::CopyTo( TiXmlNode* target ) const
161 {
162 	target->SetValue (value.c_str() );
163 	target->userData = userData;
164 }
165 
166 
Clear()167 void TiXmlNode::Clear()
168 {
169 	TiXmlNode* node = firstChild;
170 	TiXmlNode* temp = 0;
171 
172 	while ( node )
173 	{
174 		temp = node;
175 		node = node->next;
176 		delete temp;
177 	}
178 
179 	firstChild = 0;
180 	lastChild = 0;
181 }
182 
183 
LinkEndChild(TiXmlNode * node)184 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
185 {
186 	assert( node->parent == 0 || node->parent == this );
187 	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
188 
189 	if ( node->Type() == TiXmlNode::DOCUMENT )
190 	{
191 		delete node;
192 		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
193 		return 0;
194 	}
195 
196 	node->parent = this;
197 
198 	node->prev = lastChild;
199 	node->next = 0;
200 
201 	if ( lastChild )
202 		lastChild->next = node;
203 	else
204 		firstChild = node;			// it was an empty list.
205 
206 	lastChild = node;
207 	return node;
208 }
209 
210 
InsertEndChild(const TiXmlNode & addThis)211 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
212 {
213 	if ( addThis.Type() == TiXmlNode::DOCUMENT )
214 	{
215 		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
216 		return 0;
217 	}
218 	TiXmlNode* node = addThis.Clone();
219 	if ( !node )
220 		return 0;
221 
222 	return LinkEndChild( node );
223 }
224 
225 
InsertBeforeChild(TiXmlNode * beforeThis,const TiXmlNode & addThis)226 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
227 {
228 	if ( !beforeThis || beforeThis->parent != this ) {
229 		return 0;
230 	}
231 	if ( addThis.Type() == TiXmlNode::DOCUMENT )
232 	{
233 		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
234 		return 0;
235 	}
236 
237 	TiXmlNode* node = addThis.Clone();
238 	if ( !node )
239 		return 0;
240 	node->parent = this;
241 
242 	node->next = beforeThis;
243 	node->prev = beforeThis->prev;
244 	if ( beforeThis->prev )
245 	{
246 		beforeThis->prev->next = node;
247 	}
248 	else
249 	{
250 		assert( firstChild == beforeThis );
251 		firstChild = node;
252 	}
253 	beforeThis->prev = node;
254 	return node;
255 }
256 
257 
InsertAfterChild(TiXmlNode * afterThis,const TiXmlNode & addThis)258 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
259 {
260 	if ( !afterThis || afterThis->parent != this ) {
261 		return 0;
262 	}
263 	if ( addThis.Type() == TiXmlNode::DOCUMENT )
264 	{
265 		if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
266 		return 0;
267 	}
268 
269 	TiXmlNode* node = addThis.Clone();
270 	if ( !node )
271 		return 0;
272 	node->parent = this;
273 
274 	node->prev = afterThis;
275 	node->next = afterThis->next;
276 	if ( afterThis->next )
277 	{
278 		afterThis->next->prev = node;
279 	}
280 	else
281 	{
282 		assert( lastChild == afterThis );
283 		lastChild = node;
284 	}
285 	afterThis->next = node;
286 	return node;
287 }
288 
289 
ReplaceChild(TiXmlNode * replaceThis,const TiXmlNode & withThis)290 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
291 {
292 	if ( replaceThis->parent != this )
293 		return 0;
294 
295 	TiXmlNode* node = withThis.Clone();
296 	if ( !node )
297 		return 0;
298 
299 	node->next = replaceThis->next;
300 	node->prev = replaceThis->prev;
301 
302 	if ( replaceThis->next )
303 		replaceThis->next->prev = node;
304 	else
305 		lastChild = node;
306 
307 	if ( replaceThis->prev )
308 		replaceThis->prev->next = node;
309 	else
310 		firstChild = node;
311 
312 	delete replaceThis;
313 	node->parent = this;
314 	return node;
315 }
316 
317 
RemoveChild(TiXmlNode * removeThis)318 bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
319 {
320 	if ( removeThis->parent != this )
321 	{
322 		assert( 0 );
323 		return false;
324 	}
325 
326 	if ( removeThis->next )
327 		removeThis->next->prev = removeThis->prev;
328 	else
329 		lastChild = removeThis->prev;
330 
331 	if ( removeThis->prev )
332 		removeThis->prev->next = removeThis->next;
333 	else
334 		firstChild = removeThis->next;
335 
336 	delete removeThis;
337 	return true;
338 }
339 
FirstChild(const char * _value) const340 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
341 {
342 	const TiXmlNode* node;
343 	for ( node = firstChild; node; node = node->next )
344 	{
345 		if ( strcmp( node->Value(), _value ) == 0 )
346 			return node;
347 	}
348 	return 0;
349 }
350 
351 
LastChild(const char * _value) const352 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
353 {
354 	const TiXmlNode* node;
355 	for ( node = lastChild; node; node = node->prev )
356 	{
357 		if ( strcmp( node->Value(), _value ) == 0 )
358 			return node;
359 	}
360 	return 0;
361 }
362 
363 
IterateChildren(const TiXmlNode * previous) const364 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
365 {
366 	if ( !previous )
367 	{
368 		return FirstChild();
369 	}
370 	else
371 	{
372 		assert( previous->parent == this );
373 		return previous->NextSibling();
374 	}
375 }
376 
377 
IterateChildren(const char * val,const TiXmlNode * previous) const378 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
379 {
380 	if ( !previous )
381 	{
382 		return FirstChild( val );
383 	}
384 	else
385 	{
386 		assert( previous->parent == this );
387 		return previous->NextSibling( val );
388 	}
389 }
390 
391 
NextSibling(const char * _value) const392 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
393 {
394 	const TiXmlNode* node;
395 	for ( node = next; node; node = node->next )
396 	{
397 		if ( strcmp( node->Value(), _value ) == 0 )
398 			return node;
399 	}
400 	return 0;
401 }
402 
403 
PreviousSibling(const char * _value) const404 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
405 {
406 	const TiXmlNode* node;
407 	for ( node = prev; node; node = node->prev )
408 	{
409 		if ( strcmp( node->Value(), _value ) == 0 )
410 			return node;
411 	}
412 	return 0;
413 }
414 
415 
RemoveAttribute(const char * name)416 void TiXmlElement::RemoveAttribute( const char * name )
417 {
418     #ifdef TIXML_USE_STL
419 	TIXML_STRING str( name );
420 	TiXmlAttribute* node = attributeSet.Find( str );
421 	#else
422 	TiXmlAttribute* node = attributeSet.Find( name );
423 	#endif
424 	if ( node )
425 	{
426 		attributeSet.Remove( node );
427 		delete node;
428 	}
429 }
430 
FirstChildElement() const431 const TiXmlElement* TiXmlNode::FirstChildElement() const
432 {
433 	const TiXmlNode* node;
434 
435 	for (	node = FirstChild();
436 			node;
437 			node = node->NextSibling() )
438 	{
439 		if ( node->ToElement() )
440 			return node->ToElement();
441 	}
442 	return 0;
443 }
444 
445 
FirstChildElement(const char * _value) const446 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
447 {
448 	const TiXmlNode* node;
449 
450 	for (	node = FirstChild( _value );
451 			node;
452 			node = node->NextSibling( _value ) )
453 	{
454 		if ( node->ToElement() )
455 			return node->ToElement();
456 	}
457 	return 0;
458 }
459 
460 
NextSiblingElement() const461 const TiXmlElement* TiXmlNode::NextSiblingElement() const
462 {
463 	const TiXmlNode* node;
464 
465 	for (	node = NextSibling();
466 			node;
467 			node = node->NextSibling() )
468 	{
469 		if ( node->ToElement() )
470 			return node->ToElement();
471 	}
472 	return 0;
473 }
474 
475 
NextSiblingElement(const char * _value) const476 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
477 {
478 	const TiXmlNode* node;
479 
480 	for (	node = NextSibling( _value );
481 			node;
482 			node = node->NextSibling( _value ) )
483 	{
484 		if ( node->ToElement() )
485 			return node->ToElement();
486 	}
487 	return 0;
488 }
489 
490 
GetDocument() const491 const TiXmlDocument* TiXmlNode::GetDocument() const
492 {
493 	const TiXmlNode* node;
494 
495 	for( node = this; node; node = node->parent )
496 	{
497 		if ( node->ToDocument() )
498 			return node->ToDocument();
499 	}
500 	return 0;
501 }
502 
503 
TiXmlElement(const char * _value)504 TiXmlElement::TiXmlElement (const char * _value)
505 	: TiXmlNode( TiXmlNode::ELEMENT )
506 {
507 	firstChild = lastChild = 0;
508 	value = _value;
509 }
510 
511 
512 #ifdef TIXML_USE_STL
TiXmlElement(const std::string & _value)513 TiXmlElement::TiXmlElement( const std::string& _value )
514 	: TiXmlNode( TiXmlNode::ELEMENT )
515 {
516 	firstChild = lastChild = 0;
517 	value = _value;
518 }
519 #endif
520 
521 
TiXmlElement(const TiXmlElement & copy)522 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
523 	: TiXmlNode( TiXmlNode::ELEMENT )
524 {
525 	firstChild = lastChild = 0;
526 	copy.CopyTo( this );
527 }
528 
529 
operator =(const TiXmlElement & base)530 void TiXmlElement::operator=( const TiXmlElement& base )
531 {
532 	ClearThis();
533 	base.CopyTo( this );
534 }
535 
536 
~TiXmlElement()537 TiXmlElement::~TiXmlElement()
538 {
539 	ClearThis();
540 }
541 
542 
ClearThis()543 void TiXmlElement::ClearThis()
544 {
545 	Clear();
546 	while( attributeSet.First() )
547 	{
548 		TiXmlAttribute* node = attributeSet.First();
549 		attributeSet.Remove( node );
550 		delete node;
551 	}
552 }
553 
554 
Attribute(const char * name) const555 const char* TiXmlElement::Attribute( const char* name ) const
556 {
557 	const TiXmlAttribute* node = attributeSet.Find( name );
558 	if ( node )
559 		return node->Value();
560 	return 0;
561 }
562 
563 
564 #ifdef TIXML_USE_STL
Attribute(const std::string & name) const565 const std::string* TiXmlElement::Attribute( const std::string& name ) const
566 {
567 	const TiXmlAttribute* node = attributeSet.Find( name );
568 	if ( node )
569 		return &node->ValueStr();
570 	return 0;
571 }
572 #endif
573 
574 
Attribute(const char * name,int * i) const575 const char* TiXmlElement::Attribute( const char* name, int* i ) const
576 {
577 	const char* s = Attribute( name );
578 	if ( i )
579 	{
580 		if ( s ) {
581 			*i = atoi( s );
582 		}
583 		else {
584 			*i = 0;
585 		}
586 	}
587 	return s;
588 }
589 
590 
591 #ifdef TIXML_USE_STL
Attribute(const std::string & name,int * i) const592 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
593 {
594 	const std::string* s = Attribute( name );
595 	if ( i )
596 	{
597 		if ( s ) {
598 			*i = atoi( s->c_str() );
599 		}
600 		else {
601 			*i = 0;
602 		}
603 	}
604 	return s;
605 }
606 #endif
607 
608 
Attribute(const char * name,double * d) const609 const char* TiXmlElement::Attribute( const char* name, double* d ) const
610 {
611 	const char* s = Attribute( name );
612 	if ( d )
613 	{
614 		if ( s ) {
615 			*d = atof( s );
616 		}
617 		else {
618 			*d = 0;
619 		}
620 	}
621 	return s;
622 }
623 
624 
625 #ifdef TIXML_USE_STL
Attribute(const std::string & name,double * d) const626 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
627 {
628 	const std::string* s = Attribute( name );
629 	if ( d )
630 	{
631 		if ( s ) {
632 			*d = atof( s->c_str() );
633 		}
634 		else {
635 			*d = 0;
636 		}
637 	}
638 	return s;
639 }
640 #endif
641 
642 
QueryIntAttribute(const char * name,int * ival) const643 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
644 {
645 	const TiXmlAttribute* node = attributeSet.Find( name );
646 	if ( !node )
647 		return TIXML_NO_ATTRIBUTE;
648 	return node->QueryIntValue( ival );
649 }
650 
651 
652 #ifdef TIXML_USE_STL
QueryIntAttribute(const std::string & name,int * ival) const653 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
654 {
655 	const TiXmlAttribute* node = attributeSet.Find( name );
656 	if ( !node )
657 		return TIXML_NO_ATTRIBUTE;
658 	return node->QueryIntValue( ival );
659 }
660 #endif
661 
662 
QueryDoubleAttribute(const char * name,double * dval) const663 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
664 {
665 	const TiXmlAttribute* node = attributeSet.Find( name );
666 	if ( !node )
667 		return TIXML_NO_ATTRIBUTE;
668 	return node->QueryDoubleValue( dval );
669 }
670 
671 
672 #ifdef TIXML_USE_STL
QueryDoubleAttribute(const std::string & name,double * dval) const673 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
674 {
675 	const TiXmlAttribute* node = attributeSet.Find( name );
676 	if ( !node )
677 		return TIXML_NO_ATTRIBUTE;
678 	return node->QueryDoubleValue( dval );
679 }
680 #endif
681 
682 
SetAttribute(const char * name,int val)683 void TiXmlElement::SetAttribute( const char * name, int val )
684 {
685 	char buf[64];
686 	#if defined(TIXML_SNPRINTF)
687 		TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
688 	#else
689 		sprintf( buf, "%d", val );
690 	#endif
691 	SetAttribute( name, buf );
692 }
693 
694 
695 #ifdef TIXML_USE_STL
SetAttribute(const std::string & name,int val)696 void TiXmlElement::SetAttribute( const std::string& name, int val )
697 {
698    std::ostringstream oss;
699    oss << val;
700    SetAttribute( name, oss.str() );
701 }
702 #endif
703 
704 
SetDoubleAttribute(const char * name,double val)705 void TiXmlElement::SetDoubleAttribute( const char * name, double val )
706 {
707 	char buf[256];
708 	#if defined(TIXML_SNPRINTF)
709 		TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
710 	#else
711 		sprintf( buf, "%f", val );
712 	#endif
713 	SetAttribute( name, buf );
714 }
715 
716 
SetAttribute(const char * cname,const char * cvalue)717 void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
718 {
719     #ifdef TIXML_USE_STL
720 	TIXML_STRING _name( cname );
721 	TIXML_STRING _value( cvalue );
722 	#else
723 	const char* _name = cname;
724 	const char* _value = cvalue;
725 	#endif
726 
727 	TiXmlAttribute* node = attributeSet.Find( _name );
728 	if ( node )
729 	{
730 		node->SetValue( _value );
731 		return;
732 	}
733 
734 	TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
735 	if ( attrib )
736 	{
737 		attributeSet.Add( attrib );
738 	}
739 	else
740 	{
741 		TiXmlDocument* document = GetDocument();
742 		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
743 	}
744 }
745 
746 
747 #ifdef TIXML_USE_STL
SetAttribute(const std::string & name,const std::string & _value)748 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
749 {
750 	TiXmlAttribute* node = attributeSet.Find( name );
751 	if ( node )
752 	{
753 		node->SetValue( _value );
754 		return;
755 	}
756 
757 	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
758 	if ( attrib )
759 	{
760 		attributeSet.Add( attrib );
761 	}
762 	else
763 	{
764 		TiXmlDocument* document = GetDocument();
765 		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
766 	}
767 }
768 #endif
769 
770 
Print(FILE * cfile,int depth) const771 void TiXmlElement::Print( FILE* cfile, int depth ) const
772 {
773 	int i;
774 	assert( cfile );
775 	for ( i=0; i<depth; i++ ) {
776 		fprintf( cfile, "    " );
777 	}
778 
779 	fprintf( cfile, "<%s", value.c_str() );
780 
781 	const TiXmlAttribute* attrib;
782 	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
783 	{
784 		fprintf( cfile, " " );
785 		attrib->Print( cfile, depth );
786 	}
787 
788 	// There are 3 different formatting approaches:
789 	// 1) An element without children is printed as a <foo /> node
790 	// 2) An element with only a text child is printed as <foo> text </foo>
791 	// 3) An element with children is printed on multiple lines.
792 	TiXmlNode* node;
793 	if ( !firstChild )
794 	{
795 		fprintf( cfile, " />" );
796 	}
797 	else if ( firstChild == lastChild && firstChild->ToText() )
798 	{
799 		fprintf( cfile, ">" );
800 		firstChild->Print( cfile, depth + 1 );
801 		fprintf( cfile, "</%s>", value.c_str() );
802 	}
803 	else
804 	{
805 		fprintf( cfile, ">" );
806 
807 		for ( node = firstChild; node; node=node->NextSibling() )
808 		{
809 			if ( !node->ToText() )
810 			{
811 				fprintf( cfile, "\n" );
812 			}
813 			node->Print( cfile, depth+1 );
814 		}
815 		fprintf( cfile, "\n" );
816 		for( i=0; i<depth; ++i ) {
817 			fprintf( cfile, "    " );
818 		}
819 		fprintf( cfile, "</%s>", value.c_str() );
820 	}
821 }
822 
823 
CopyTo(TiXmlElement * target) const824 void TiXmlElement::CopyTo( TiXmlElement* target ) const
825 {
826 	// superclass:
827 	TiXmlNode::CopyTo( target );
828 
829 	// Element class:
830 	// Clone the attributes, then clone the children.
831 	const TiXmlAttribute* attribute = 0;
832 	for(	attribute = attributeSet.First();
833 	attribute;
834 	attribute = attribute->Next() )
835 	{
836 		target->SetAttribute( attribute->Name(), attribute->Value() );
837 	}
838 
839 	TiXmlNode* node = 0;
840 	for ( node = firstChild; node; node = node->NextSibling() )
841 	{
842 		target->LinkEndChild( node->Clone() );
843 	}
844 }
845 
Accept(TiXmlVisitor * visitor) const846 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
847 {
848 	if ( visitor->VisitEnter( *this, attributeSet.First() ) )
849 	{
850 		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
851 		{
852 			if ( !node->Accept( visitor ) )
853 				break;
854 		}
855 	}
856 	return visitor->VisitExit( *this );
857 }
858 
859 
Clone() const860 TiXmlNode* TiXmlElement::Clone() const
861 {
862 	TiXmlElement* clone = new TiXmlElement( Value() );
863 	if ( !clone )
864 		return 0;
865 
866 	CopyTo( clone );
867 	return clone;
868 }
869 
870 
GetText() const871 const char* TiXmlElement::GetText() const
872 {
873 	const TiXmlNode* child = this->FirstChild();
874 	if ( child ) {
875 		const TiXmlText* childText = child->ToText();
876 		if ( childText ) {
877 			return childText->Value();
878 		}
879 	}
880 	return 0;
881 }
882 
883 
TiXmlDocument()884 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
885 {
886 	tabsize = 4;
887 	useMicrosoftBOM = false;
888 	ClearError();
889 }
890 
TiXmlDocument(const char * documentName)891 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
892 {
893 	tabsize = 4;
894 	useMicrosoftBOM = false;
895 	value = documentName;
896 	ClearError();
897 }
898 
899 
900 #ifdef TIXML_USE_STL
TiXmlDocument(const std::string & documentName)901 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
902 {
903 	tabsize = 4;
904 	useMicrosoftBOM = false;
905     value = documentName;
906 	ClearError();
907 }
908 #endif
909 
910 
TiXmlDocument(const TiXmlDocument & copy)911 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
912 {
913 	copy.CopyTo( this );
914 }
915 
916 
operator =(const TiXmlDocument & copy)917 void TiXmlDocument::operator=( const TiXmlDocument& copy )
918 {
919 	Clear();
920 	copy.CopyTo( this );
921 }
922 
923 
LoadFile(TiXmlEncoding encoding)924 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
925 {
926 	// See STL_STRING_BUG below.
927 	//StringToBuffer buf( value );
928 
929 	return LoadFile( Value(), encoding );
930 }
931 
932 
SaveFile() const933 bool TiXmlDocument::SaveFile() const
934 {
935 	// See STL_STRING_BUG below.
936 //	StringToBuffer buf( value );
937 //
938 //	if ( buf.buffer && SaveFile( buf.buffer ) )
939 //		return true;
940 //
941 //	return false;
942 	return SaveFile( Value() );
943 }
944 
LoadFile(const char * _filename,TiXmlEncoding encoding)945 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
946 {
947 	// There was a really terrifying little bug here. The code:
948 	//		value = filename
949 	// in the STL case, cause the assignment method of the std::string to
950 	// be called. What is strange, is that the std::string had the same
951 	// address as it's c_str() method, and so bad things happen. Looks
952 	// like a bug in the Microsoft STL implementation.
953 	// Add an extra string to avoid the crash.
954 	TIXML_STRING filename( _filename );
955 	value = filename;
956 
957 	// reading in binary mode so that tinyxml can normalize the EOL
958 	FILE* file = TiXmlFOpen( value.c_str (), "rb" );
959 
960 	if ( file )
961 	{
962 		bool result = LoadFile( file, encoding );
963 		fclose( file );
964 		return result;
965 	}
966 	else
967 	{
968 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
969 		return false;
970 	}
971 }
972 
LoadFile(FILE * file,TiXmlEncoding encoding)973 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
974 {
975 	if ( !file )
976 	{
977 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
978 		return false;
979 	}
980 
981 	// Delete the existing data:
982 	Clear();
983 	location.Clear();
984 
985 	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
986 	long length = 0;
987 	fseek( file, 0, SEEK_END );
988 	length = ftell( file );
989 	fseek( file, 0, SEEK_SET );
990 
991 	// Strange case, but good to handle up front.
992 	if ( length <= 0 )
993 	{
994 		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
995 		return false;
996 	}
997 
998 	// If we have a file, assume it is all one big XML file, and read it in.
999 	// The document parser may decide the document ends sooner than the entire file, however.
1000 	TIXML_STRING data;
1001 	data.reserve( length );
1002 
1003 	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
1004 	// 2.11 End-of-Line Handling
1005 	// <snip>
1006 	// <quote>
1007 	// ...the XML processor MUST behave as if it normalized all line breaks in external
1008 	// parsed entities (including the document entity) on input, before parsing, by translating
1009 	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1010 	// a single #xA character.
1011 	// </quote>
1012 	//
1013 	// It is not clear fgets does that, and certainly isn't clear it works cross platform.
1014 	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
1015 	// convention, and not work generally.
1016 
1017 	/*
1018 	while( fgets( buf, sizeof(buf), file ) )
1019 	{
1020 		data += buf;
1021 	}
1022 	*/
1023 
1024 	char* buf = new char[ length+1 ];
1025 	buf[0] = 0;
1026 
1027 	if ( fread( buf, length, 1, file ) != 1 ) {
1028 		delete [] buf;
1029 		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1030 		return false;
1031 	}
1032 
1033 	const char* lastPos = buf;
1034 	const char* p = buf;
1035 
1036 	buf[length] = 0;
1037 	while( *p ) {
1038 		assert( p < (buf+length) );
1039 		if ( *p == 0xa ) {
1040 			// Newline character. No special rules for this. Append all the characters
1041 			// since the last string, and include the newline.
1042 			data.append( lastPos, (p-lastPos+1) );	// append, include the newline
1043 			++p;									// move past the newline
1044 			lastPos = p;							// and point to the new buffer (may be 0)
1045 			assert( p <= (buf+length) );
1046 		}
1047 		else if ( *p == 0xd ) {
1048 			// Carriage return. Append what we have so far, then
1049 			// handle moving forward in the buffer.
1050 			if ( (p-lastPos) > 0 ) {
1051 				data.append( lastPos, p-lastPos );	// do not add the CR
1052 			}
1053 			data += (char)0xa;						// a proper newline
1054 
1055 			if ( *(p+1) == 0xa ) {
1056 				// Carriage return - new line sequence
1057 				p += 2;
1058 				lastPos = p;
1059 				assert( p <= (buf+length) );
1060 			}
1061 			else {
1062 				// it was followed by something else...that is presumably characters again.
1063 				++p;
1064 				lastPos = p;
1065 				assert( p <= (buf+length) );
1066 			}
1067 		}
1068 		else {
1069 			++p;
1070 		}
1071 	}
1072 	// Handle any left over characters.
1073 	if ( p-lastPos ) {
1074 		data.append( lastPos, p-lastPos );
1075 	}
1076 	delete [] buf;
1077 	buf = 0;
1078 
1079 	Parse( data.c_str(), 0, encoding );
1080 
1081 	if (  Error() )
1082         return false;
1083     else
1084 		return true;
1085 }
1086 
1087 
SaveFile(const char * filename) const1088 bool TiXmlDocument::SaveFile( const char * filename ) const
1089 {
1090 	// The old c stuff lives on...
1091 	FILE* fp = TiXmlFOpen( filename, "w" );
1092 	if ( fp )
1093 	{
1094 		bool result = SaveFile( fp );
1095 		fclose( fp );
1096 		return result;
1097 	}
1098 	return false;
1099 }
1100 
1101 
SaveFile(FILE * fp) const1102 bool TiXmlDocument::SaveFile( FILE* fp ) const
1103 {
1104 	if ( useMicrosoftBOM )
1105 	{
1106 		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1107 		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1108 		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1109 
1110 		fputc( TIXML_UTF_LEAD_0, fp );
1111 		fputc( TIXML_UTF_LEAD_1, fp );
1112 		fputc( TIXML_UTF_LEAD_2, fp );
1113 	}
1114 	Print( fp, 0 );
1115 	return (ferror(fp) == 0);
1116 }
1117 
1118 
CopyTo(TiXmlDocument * target) const1119 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1120 {
1121 	TiXmlNode::CopyTo( target );
1122 
1123 	target->error = error;
1124 	target->errorId = errorId;
1125 	target->errorDesc = errorDesc;
1126 	target->tabsize = tabsize;
1127 	target->errorLocation = errorLocation;
1128 	target->useMicrosoftBOM = useMicrosoftBOM;
1129 
1130 	TiXmlNode* node = 0;
1131 	for ( node = firstChild; node; node = node->NextSibling() )
1132 	{
1133 		target->LinkEndChild( node->Clone() );
1134 	}
1135 }
1136 
1137 
Clone() const1138 TiXmlNode* TiXmlDocument::Clone() const
1139 {
1140 	TiXmlDocument* clone = new TiXmlDocument();
1141 	if ( !clone )
1142 		return 0;
1143 
1144 	CopyTo( clone );
1145 	return clone;
1146 }
1147 
1148 
Print(FILE * cfile,int depth) const1149 void TiXmlDocument::Print( FILE* cfile, int depth ) const
1150 {
1151 	assert( cfile );
1152 	for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1153 	{
1154 		node->Print( cfile, depth );
1155 		fprintf( cfile, "\n" );
1156 	}
1157 }
1158 
1159 
Accept(TiXmlVisitor * visitor) const1160 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1161 {
1162 	if ( visitor->VisitEnter( *this ) )
1163 	{
1164 		for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1165 		{
1166 			if ( !node->Accept( visitor ) )
1167 				break;
1168 		}
1169 	}
1170 	return visitor->VisitExit( *this );
1171 }
1172 
1173 
Next() const1174 const TiXmlAttribute* TiXmlAttribute::Next() const
1175 {
1176 	// We are using knowledge of the sentinel. The sentinel
1177 	// have a value or name.
1178 	if ( next->value.empty() && next->name.empty() )
1179 		return 0;
1180 	return next;
1181 }
1182 
1183 /*
1184 TiXmlAttribute* TiXmlAttribute::Next()
1185 {
1186 	// We are using knowledge of the sentinel. The sentinel
1187 	// have a value or name.
1188 	if ( next->value.empty() && next->name.empty() )
1189 		return 0;
1190 	return next;
1191 }
1192 */
1193 
Previous() const1194 const TiXmlAttribute* TiXmlAttribute::Previous() const
1195 {
1196 	// We are using knowledge of the sentinel. The sentinel
1197 	// have a value or name.
1198 	if ( prev->value.empty() && prev->name.empty() )
1199 		return 0;
1200 	return prev;
1201 }
1202 
1203 /*
1204 TiXmlAttribute* TiXmlAttribute::Previous()
1205 {
1206 	// We are using knowledge of the sentinel. The sentinel
1207 	// have a value or name.
1208 	if ( prev->value.empty() && prev->name.empty() )
1209 		return 0;
1210 	return prev;
1211 }
1212 */
1213 
Print(FILE * cfile,int,TIXML_STRING * str) const1214 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1215 {
1216 	TIXML_STRING n, v;
1217 
1218 	EncodeString( name, &n );
1219 	EncodeString( value, &v );
1220 
1221 	if (value.find ('\"') == TIXML_STRING::npos) {
1222 		if ( cfile ) {
1223 		fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1224 		}
1225 		if ( str ) {
1226 			(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1227 		}
1228 	}
1229 	else {
1230 		if ( cfile ) {
1231 		fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1232 		}
1233 		if ( str ) {
1234 			(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1235 		}
1236 	}
1237 }
1238 
1239 
QueryIntValue(int * ival) const1240 int TiXmlAttribute::QueryIntValue( int* ival ) const
1241 {
1242 	if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1243 		return TIXML_SUCCESS;
1244 	return TIXML_WRONG_TYPE;
1245 }
1246 
QueryDoubleValue(double * dval) const1247 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1248 {
1249 	if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1250 		return TIXML_SUCCESS;
1251 	return TIXML_WRONG_TYPE;
1252 }
1253 
SetIntValue(int _value)1254 void TiXmlAttribute::SetIntValue( int _value )
1255 {
1256 	char buf [64];
1257 	#if defined(TIXML_SNPRINTF)
1258 		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1259 	#else
1260 		sprintf (buf, "%d", _value);
1261 	#endif
1262 	SetValue (buf);
1263 }
1264 
SetDoubleValue(double _value)1265 void TiXmlAttribute::SetDoubleValue( double _value )
1266 {
1267 	char buf [256];
1268 	#if defined(TIXML_SNPRINTF)
1269 		TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1270 	#else
1271 		sprintf (buf, "%lf", _value);
1272 	#endif
1273 	SetValue (buf);
1274 }
1275 
IntValue() const1276 int TiXmlAttribute::IntValue() const
1277 {
1278 	return atoi (value.c_str ());
1279 }
1280 
DoubleValue() const1281 double  TiXmlAttribute::DoubleValue() const
1282 {
1283 	return atof (value.c_str ());
1284 }
1285 
1286 
TiXmlComment(const TiXmlComment & copy)1287 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1288 {
1289 	copy.CopyTo( this );
1290 }
1291 
1292 
operator =(const TiXmlComment & base)1293 void TiXmlComment::operator=( const TiXmlComment& base )
1294 {
1295 	Clear();
1296 	base.CopyTo( this );
1297 }
1298 
1299 
Print(FILE * cfile,int depth) const1300 void TiXmlComment::Print( FILE* cfile, int depth ) const
1301 {
1302 	assert( cfile );
1303 	for ( int i=0; i<depth; i++ )
1304 	{
1305 		fprintf( cfile,  "    " );
1306 	}
1307 	fprintf( cfile, "<!--%s-->", value.c_str() );
1308 }
1309 
1310 
CopyTo(TiXmlComment * target) const1311 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1312 {
1313 	TiXmlNode::CopyTo( target );
1314 }
1315 
1316 
Accept(TiXmlVisitor * visitor) const1317 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1318 {
1319 	return visitor->Visit( *this );
1320 }
1321 
1322 
Clone() const1323 TiXmlNode* TiXmlComment::Clone() const
1324 {
1325 	TiXmlComment* clone = new TiXmlComment();
1326 
1327 	if ( !clone )
1328 		return 0;
1329 
1330 	CopyTo( clone );
1331 	return clone;
1332 }
1333 
1334 
Print(FILE * cfile,int depth) const1335 void TiXmlText::Print( FILE* cfile, int depth ) const
1336 {
1337 	assert( cfile );
1338 	if ( cdata )
1339 	{
1340 		int i;
1341 		fprintf( cfile, "\n" );
1342 		for ( i=0; i<depth; i++ ) {
1343 			fprintf( cfile, "    " );
1344 		}
1345 		fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() );	// unformatted output
1346 	}
1347 	else
1348 	{
1349 		TIXML_STRING buffer;
1350 		EncodeString( value, &buffer );
1351 		fprintf( cfile, "%s", buffer.c_str() );
1352 	}
1353 }
1354 
1355 
CopyTo(TiXmlText * target) const1356 void TiXmlText::CopyTo( TiXmlText* target ) const
1357 {
1358 	TiXmlNode::CopyTo( target );
1359 	target->cdata = cdata;
1360 }
1361 
1362 
Accept(TiXmlVisitor * visitor) const1363 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1364 {
1365 	return visitor->Visit( *this );
1366 }
1367 
1368 
Clone() const1369 TiXmlNode* TiXmlText::Clone() const
1370 {
1371 	TiXmlText* clone = 0;
1372 	clone = new TiXmlText( "" );
1373 
1374 	if ( !clone )
1375 		return 0;
1376 
1377 	CopyTo( clone );
1378 	return clone;
1379 }
1380 
1381 
TiXmlDeclaration(const char * _version,const char * _encoding,const char * _standalone)1382 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1383 									const char * _encoding,
1384 									const char * _standalone )
1385 	: TiXmlNode( TiXmlNode::DECLARATION )
1386 {
1387 	version = _version;
1388 	encoding = _encoding;
1389 	standalone = _standalone;
1390 }
1391 
1392 
1393 #ifdef TIXML_USE_STL
TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)1394 TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
1395 									const std::string& _encoding,
1396 									const std::string& _standalone )
1397 	: TiXmlNode( TiXmlNode::DECLARATION )
1398 {
1399 	version = _version;
1400 	encoding = _encoding;
1401 	standalone = _standalone;
1402 }
1403 #endif
1404 
1405 
TiXmlDeclaration(const TiXmlDeclaration & copy)1406 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1407 	: TiXmlNode( TiXmlNode::DECLARATION )
1408 {
1409 	copy.CopyTo( this );
1410 }
1411 
1412 
operator =(const TiXmlDeclaration & copy)1413 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1414 {
1415 	Clear();
1416 	copy.CopyTo( this );
1417 }
1418 
1419 
Print(FILE * cfile,int,TIXML_STRING * str) const1420 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1421 {
1422 	if ( cfile ) fprintf( cfile, "<?xml " );
1423 	if ( str )	 (*str) += "<?xml ";
1424 
1425 	if ( !version.empty() ) {
1426 		if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1427 		if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1428 	}
1429 	if ( !encoding.empty() ) {
1430 		if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1431 		if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1432 	}
1433 	if ( !standalone.empty() ) {
1434 		if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1435 		if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1436 	}
1437 	if ( cfile ) fprintf( cfile, "?>" );
1438 	if ( str )	 (*str) += "?>";
1439 }
1440 
1441 
CopyTo(TiXmlDeclaration * target) const1442 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1443 {
1444 	TiXmlNode::CopyTo( target );
1445 
1446 	target->version = version;
1447 	target->encoding = encoding;
1448 	target->standalone = standalone;
1449 }
1450 
1451 
Accept(TiXmlVisitor * visitor) const1452 bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1453 {
1454 	return visitor->Visit( *this );
1455 }
1456 
1457 
Clone() const1458 TiXmlNode* TiXmlDeclaration::Clone() const
1459 {
1460 	TiXmlDeclaration* clone = new TiXmlDeclaration();
1461 
1462 	if ( !clone )
1463 		return 0;
1464 
1465 	CopyTo( clone );
1466 	return clone;
1467 }
1468 
1469 
Print(FILE * cfile,int depth) const1470 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1471 {
1472 	for ( int i=0; i<depth; i++ )
1473 		fprintf( cfile, "    " );
1474 	fprintf( cfile, "<%s>", value.c_str() );
1475 }
1476 
1477 
CopyTo(TiXmlUnknown * target) const1478 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1479 {
1480 	TiXmlNode::CopyTo( target );
1481 }
1482 
1483 
Accept(TiXmlVisitor * visitor) const1484 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1485 {
1486 	return visitor->Visit( *this );
1487 }
1488 
1489 
Clone() const1490 TiXmlNode* TiXmlUnknown::Clone() const
1491 {
1492 	TiXmlUnknown* clone = new TiXmlUnknown();
1493 
1494 	if ( !clone )
1495 		return 0;
1496 
1497 	CopyTo( clone );
1498 	return clone;
1499 }
1500 
1501 
TiXmlAttributeSet()1502 TiXmlAttributeSet::TiXmlAttributeSet()
1503 {
1504 	sentinel.next = &sentinel;
1505 	sentinel.prev = &sentinel;
1506 }
1507 
1508 
~TiXmlAttributeSet()1509 TiXmlAttributeSet::~TiXmlAttributeSet()
1510 {
1511 	assert( sentinel.next == &sentinel );
1512 	assert( sentinel.prev == &sentinel );
1513 }
1514 
1515 
Add(TiXmlAttribute * addMe)1516 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1517 {
1518     #ifdef TIXML_USE_STL
1519 	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.
1520 	#else
1521 	assert( !Find( addMe->Name() ) );	// Shouldn't be multiply adding to the set.
1522 	#endif
1523 
1524 	addMe->next = &sentinel;
1525 	addMe->prev = sentinel.prev;
1526 
1527 	sentinel.prev->next = addMe;
1528 	sentinel.prev      = addMe;
1529 }
1530 
Remove(TiXmlAttribute * removeMe)1531 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1532 {
1533 	TiXmlAttribute* node;
1534 
1535 	for( node = sentinel.next; node != &sentinel; node = node->next )
1536 	{
1537 		if ( node == removeMe )
1538 		{
1539 			node->prev->next = node->next;
1540 			node->next->prev = node->prev;
1541 			node->next = 0;
1542 			node->prev = 0;
1543 			return;
1544 		}
1545 	}
1546 	assert( 0 );		// we tried to remove a non-linked attribute.
1547 }
1548 
1549 
1550 #ifdef TIXML_USE_STL
Find(const std::string & name) const1551 const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1552 {
1553 	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1554 	{
1555 		if ( node->name == name )
1556 			return node;
1557 	}
1558 	return 0;
1559 }
1560 
1561 /*
1562 TiXmlAttribute*	TiXmlAttributeSet::Find( const std::string& name )
1563 {
1564 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1565 	{
1566 		if ( node->name == name )
1567 			return node;
1568 	}
1569 	return 0;
1570 }
1571 */
1572 #endif
1573 
1574 
Find(const char * name) const1575 const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1576 {
1577 	for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1578 	{
1579 		if ( strcmp( node->name.c_str(), name ) == 0 )
1580 			return node;
1581 	}
1582 	return 0;
1583 }
1584 
1585 /*
1586 TiXmlAttribute*	TiXmlAttributeSet::Find( const char* name )
1587 {
1588 	for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1589 	{
1590 		if ( strcmp( node->name.c_str(), name ) == 0 )
1591 			return node;
1592 	}
1593 	return 0;
1594 }
1595 */
1596 
1597 #ifdef TIXML_USE_STL
operator >>(std::istream & in,TiXmlNode & base)1598 std::istream& operator>> (std::istream & in, TiXmlNode & base)
1599 {
1600 	TIXML_STRING tag;
1601 	tag.reserve( 8 * 1000 );
1602 	base.StreamIn( &in, &tag );
1603 
1604 	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1605 	return in;
1606 }
1607 #endif
1608 
1609 
1610 #ifdef TIXML_USE_STL
operator <<(std::ostream & out,const TiXmlNode & base)1611 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1612 {
1613 	TiXmlPrinter printer;
1614 	printer.SetStreamPrinting();
1615 	base.Accept( &printer );
1616 	out << printer.Str();
1617 
1618 	return out;
1619 }
1620 
1621 
operator <<(std::string & out,const TiXmlNode & base)1622 std::string& operator<< (std::string& out, const TiXmlNode& base )
1623 {
1624 	TiXmlPrinter printer;
1625 	printer.SetStreamPrinting();
1626 	base.Accept( &printer );
1627 	out.append( printer.Str() );
1628 
1629 	return out;
1630 }
1631 #endif
1632 
1633 
FirstChild() const1634 TiXmlHandle TiXmlHandle::FirstChild() const
1635 {
1636 	if ( node )
1637 	{
1638 		TiXmlNode* child = node->FirstChild();
1639 		if ( child )
1640 			return TiXmlHandle( child );
1641 	}
1642 	return TiXmlHandle( 0 );
1643 }
1644 
1645 
FirstChild(const char * value) const1646 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1647 {
1648 	if ( node )
1649 	{
1650 		TiXmlNode* child = node->FirstChild( value );
1651 		if ( child )
1652 			return TiXmlHandle( child );
1653 	}
1654 	return TiXmlHandle( 0 );
1655 }
1656 
1657 
FirstChildElement() const1658 TiXmlHandle TiXmlHandle::FirstChildElement() const
1659 {
1660 	if ( node )
1661 	{
1662 		TiXmlElement* child = node->FirstChildElement();
1663 		if ( child )
1664 			return TiXmlHandle( child );
1665 	}
1666 	return TiXmlHandle( 0 );
1667 }
1668 
1669 
FirstChildElement(const char * value) const1670 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1671 {
1672 	if ( node )
1673 	{
1674 		TiXmlElement* child = node->FirstChildElement( value );
1675 		if ( child )
1676 			return TiXmlHandle( child );
1677 	}
1678 	return TiXmlHandle( 0 );
1679 }
1680 
1681 
Child(int count) const1682 TiXmlHandle TiXmlHandle::Child( int count ) const
1683 {
1684 	if ( node )
1685 	{
1686 		int i;
1687 		TiXmlNode* child = node->FirstChild();
1688 		for (	i=0;
1689 				child && i<count;
1690 				child = child->NextSibling(), ++i )
1691 		{
1692 			// nothing
1693 		}
1694 		if ( child )
1695 			return TiXmlHandle( child );
1696 	}
1697 	return TiXmlHandle( 0 );
1698 }
1699 
1700 
Child(const char * value,int count) const1701 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1702 {
1703 	if ( node )
1704 	{
1705 		int i;
1706 		TiXmlNode* child = node->FirstChild( value );
1707 		for (	i=0;
1708 				child && i<count;
1709 				child = child->NextSibling( value ), ++i )
1710 		{
1711 			// nothing
1712 		}
1713 		if ( child )
1714 			return TiXmlHandle( child );
1715 	}
1716 	return TiXmlHandle( 0 );
1717 }
1718 
1719 
ChildElement(int count) const1720 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1721 {
1722 	if ( node )
1723 	{
1724 		int i;
1725 		TiXmlElement* child = node->FirstChildElement();
1726 		for (	i=0;
1727 				child && i<count;
1728 				child = child->NextSiblingElement(), ++i )
1729 		{
1730 			// nothing
1731 		}
1732 		if ( child )
1733 			return TiXmlHandle( child );
1734 	}
1735 	return TiXmlHandle( 0 );
1736 }
1737 
1738 
ChildElement(const char * value,int count) const1739 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1740 {
1741 	if ( node )
1742 	{
1743 		int i;
1744 		TiXmlElement* child = node->FirstChildElement( value );
1745 		for (	i=0;
1746 				child && i<count;
1747 				child = child->NextSiblingElement( value ), ++i )
1748 		{
1749 			// nothing
1750 		}
1751 		if ( child )
1752 			return TiXmlHandle( child );
1753 	}
1754 	return TiXmlHandle( 0 );
1755 }
1756 
1757 
VisitEnter(const TiXmlDocument &)1758 bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1759 {
1760 	return true;
1761 }
1762 
VisitExit(const TiXmlDocument &)1763 bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1764 {
1765 	return true;
1766 }
1767 
VisitEnter(const TiXmlElement & element,const TiXmlAttribute * firstAttribute)1768 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1769 {
1770 	DoIndent();
1771 	buffer += "<";
1772 	buffer += element.Value();
1773 
1774 	for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1775 	{
1776 		buffer += " ";
1777 		attrib->Print( 0, 0, &buffer );
1778 	}
1779 
1780 	if ( !element.FirstChild() )
1781 	{
1782 		buffer += " />";
1783 		DoLineBreak();
1784 	}
1785 	else
1786 	{
1787 		buffer += ">";
1788 		if (    element.FirstChild()->ToText()
1789 			  && element.LastChild() == element.FirstChild()
1790 			  && element.FirstChild()->ToText()->CDATA() == false )
1791 		{
1792 			simpleTextPrint = true;
1793 			// no DoLineBreak()!
1794 		}
1795 		else
1796 		{
1797 			DoLineBreak();
1798 		}
1799 	}
1800 	++depth;
1801 	return true;
1802 }
1803 
1804 
VisitExit(const TiXmlElement & element)1805 bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1806 {
1807 	--depth;
1808 	if ( !element.FirstChild() )
1809 	{
1810 		// nothing.
1811 	}
1812 	else
1813 	{
1814 		if ( simpleTextPrint )
1815 		{
1816 			simpleTextPrint = false;
1817 		}
1818 		else
1819 		{
1820 			DoIndent();
1821 		}
1822 		buffer += "</";
1823 		buffer += element.Value();
1824 		buffer += ">";
1825 		DoLineBreak();
1826 	}
1827 	return true;
1828 }
1829 
1830 
Visit(const TiXmlText & text)1831 bool TiXmlPrinter::Visit( const TiXmlText& text )
1832 {
1833 	if ( text.CDATA() )
1834 	{
1835 		DoIndent();
1836 		buffer += "<![CDATA[";
1837 		buffer += text.Value();
1838 		buffer += "]]>";
1839 		DoLineBreak();
1840 	}
1841 	else if ( simpleTextPrint )
1842 	{
1843 		TIXML_STRING str;
1844 		TiXmlBase::EncodeString( text.ValueTStr(), &str );
1845 		buffer += str;
1846 	}
1847 	else
1848 	{
1849 		DoIndent();
1850 		TIXML_STRING str;
1851 		TiXmlBase::EncodeString( text.ValueTStr(), &str );
1852 		buffer += str;
1853 		DoLineBreak();
1854 	}
1855 	return true;
1856 }
1857 
1858 
Visit(const TiXmlDeclaration & declaration)1859 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1860 {
1861 	DoIndent();
1862 	declaration.Print( 0, 0, &buffer );
1863 	DoLineBreak();
1864 	return true;
1865 }
1866 
1867 
Visit(const TiXmlComment & comment)1868 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1869 {
1870 	DoIndent();
1871 	buffer += "<!--";
1872 	buffer += comment.Value();
1873 	buffer += "-->";
1874 	DoLineBreak();
1875 	return true;
1876 }
1877 
1878 
Visit(const TiXmlUnknown & unknown)1879 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1880 {
1881 	DoIndent();
1882 	buffer += "<";
1883 	buffer += unknown.Value();
1884 	buffer += ">";
1885 	DoLineBreak();
1886 	return true;
1887 }
1888 
1889