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