Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/tinyxml/tinyxml.cc @ 1505

Last change on this file since 1505 was 1505, checked in by rgrieder, 16 years ago

f* svn: It doesn't even inform you if you attempt to set a non existing property. It is svn:eol-style and not eol-style when using the command by the way…

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