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