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