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