Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/FICN/src/tinyxml/tinyxml.cc @ 738

Last change on this file since 738 was 738, checked in by landauf, 16 years ago

updated to the newest tinyXML library and changed one line in the LevelLoader

File size: 36.0 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
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
35bool TiXmlBase::condenseWhiteSpace = true;
36
37// Microsoft compiler security
38FILE* 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
51void 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
135TiXmlNode::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
146TiXmlNode::~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
160void TiXmlNode::CopyTo( TiXmlNode* target ) const
161{
162        target->SetValue (value.c_str() );
163        target->userData = userData;
164}
165
166
167void 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
184TiXmlNode* 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
211TiXmlNode* 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
226TiXmlNode* 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
258TiXmlNode* 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
290TiXmlNode* 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
318bool 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
340const 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
352const 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
364const 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
378const 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
392const 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
404const 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
416void 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
431const 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
446const 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
461const 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
476const 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
491const 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
504TiXmlElement::TiXmlElement (const char * _value)
505        : TiXmlNode( TiXmlNode::ELEMENT )
506{
507        firstChild = lastChild = 0;
508        value = _value;
509}
510
511
512#ifdef TIXML_USE_STL
513TiXmlElement::TiXmlElement( const std::string& _value )
514        : TiXmlNode( TiXmlNode::ELEMENT )
515{
516        firstChild = lastChild = 0;
517        value = _value;
518}
519#endif
520
521
522TiXmlElement::TiXmlElement( const TiXmlElement& copy)
523        : TiXmlNode( TiXmlNode::ELEMENT )
524{
525        firstChild = lastChild = 0;
526        copy.CopyTo( this );
527}
528
529
530void TiXmlElement::operator=( const TiXmlElement& base )
531{
532        ClearThis();
533        base.CopyTo( this );
534}
535
536
537TiXmlElement::~TiXmlElement()
538{
539        ClearThis();
540}
541
542
543void 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
555const 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
565const 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
575const 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
592const 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
609const 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
626const 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
643int 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
653int 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
663int 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
673int 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
683void 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
696void 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
705void 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
717void 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
748void 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
771void 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
824void 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
846bool 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
860TiXmlNode* 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
871const 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
884TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
885{
886        tabsize = 4;
887        useMicrosoftBOM = false;
888        ClearError();
889}
890
891TiXmlDocument::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
901TiXmlDocument::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
911TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
912{
913        copy.CopyTo( this );
914}
915
916
917void TiXmlDocument::operator=( const TiXmlDocument& copy )
918{
919        Clear();
920        copy.CopyTo( this );
921}
922
923
924bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
925{
926        // See STL_STRING_BUG below.
927        //StringToBuffer buf( value );
928
929        return LoadFile( Value(), encoding );
930}
931
932
933bool 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
945bool 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
973bool 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
1088bool 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
1102bool 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
1119void 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
1138TiXmlNode* 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
1149void 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
1160bool 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
1174const 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/*
1184TiXmlAttribute* 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
1194const 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/*
1204TiXmlAttribute* 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
1214void 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
1240int 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
1247int 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
1254void 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
1265void 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
1276int TiXmlAttribute::IntValue() const
1277{
1278        return atoi (value.c_str ());
1279}
1280
1281double  TiXmlAttribute::DoubleValue() const
1282{
1283        return atof (value.c_str ());
1284}
1285
1286
1287TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1288{
1289        copy.CopyTo( this );
1290}
1291
1292
1293void TiXmlComment::operator=( const TiXmlComment& base )
1294{
1295        Clear();
1296        base.CopyTo( this );
1297}
1298
1299
1300void 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
1311void TiXmlComment::CopyTo( TiXmlComment* target ) const
1312{
1313        TiXmlNode::CopyTo( target );
1314}
1315
1316
1317bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1318{
1319        return visitor->Visit( *this );
1320}
1321
1322
1323TiXmlNode* 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
1335void 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
1356void TiXmlText::CopyTo( TiXmlText* target ) const
1357{
1358        TiXmlNode::CopyTo( target );
1359        target->cdata = cdata;
1360}
1361
1362
1363bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1364{
1365        return visitor->Visit( *this );
1366}
1367
1368
1369TiXmlNode* 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
1382TiXmlDeclaration::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
1394TiXmlDeclaration::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
1406TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1407        : TiXmlNode( TiXmlNode::DECLARATION )
1408{
1409        copy.CopyTo( this );
1410}
1411
1412
1413void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1414{
1415        Clear();
1416        copy.CopyTo( this );
1417}
1418
1419
1420void 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
1442void 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
1452bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1453{
1454        return visitor->Visit( *this );
1455}
1456
1457
1458TiXmlNode* 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
1470void 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
1478void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1479{
1480        TiXmlNode::CopyTo( target );
1481}
1482
1483
1484bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1485{
1486        return visitor->Visit( *this );
1487}
1488
1489
1490TiXmlNode* 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
1502TiXmlAttributeSet::TiXmlAttributeSet()
1503{
1504        sentinel.next = &sentinel;
1505        sentinel.prev = &sentinel;
1506}
1507
1508
1509TiXmlAttributeSet::~TiXmlAttributeSet()
1510{
1511        assert( sentinel.next == &sentinel );
1512        assert( sentinel.prev == &sentinel );
1513}
1514
1515
1516void 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
1531void 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
1551const 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/*
1562TiXmlAttribute* 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
1575const 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/*
1586TiXmlAttribute* 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
1598std::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
1611std::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
1622std::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
1634TiXmlHandle 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
1646TiXmlHandle 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
1658TiXmlHandle 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
1670TiXmlHandle 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
1682TiXmlHandle 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
1701TiXmlHandle 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
1720TiXmlHandle 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
1739TiXmlHandle 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
1758bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1759{
1760        return true;
1761}
1762
1763bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1764{
1765        return true;
1766}
1767
1768bool 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
1805bool 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
1831bool 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
1859bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1860{
1861        DoIndent();
1862        declaration.Print( 0, 0, &buffer );
1863        DoLineBreak();
1864        return true;
1865}
1866
1867
1868bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1869{
1870        DoIndent();
1871        buffer += "<!--";
1872        buffer += comment.Value();
1873        buffer += "-->";
1874        DoLineBreak();
1875        return true;
1876}
1877
1878
1879bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1880{
1881        DoIndent();
1882        buffer += "<";
1883        buffer += unknown.Value();
1884        buffer += ">";
1885        DoLineBreak();
1886        return true;
1887}
1888
Note: See TracBrowser for help on using the repository browser.