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