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