source: NonGTP/OSceneLoader/TinyXML/tinyxml.cpp @ 965

Revision 965, 21.6 KB checked in by igarcia, 18 years ago (diff)
Line 
1/*
2www.sourceforge.net/projects/tinyxml
3Original code (2.0 and earlier )copyright (c) 2000-2002 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#include "tinyxml.h"
27
28bool TiXmlBase::condenseWhiteSpace = true;
29
30void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
31{
32        TIXML_STRING buffer;
33        PutString( str, &buffer );
34        (*stream) << buffer;
35}
36
37void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
38{
39        int i=0;
40
41        while( i<(int)str.length() )
42        {
43                int c = str[i];
44
45                if (    c == '&'
46                     && i < ( (int)str.length() - 2 )
47                         && str[i+1] == '#'
48                         && str[i+2] == 'x' )
49                {
50                        // Hexadecimal character reference.
51                        // Pass through unchanged.
52                        // &#xA9;       -- copyright symbol, for example.
53                        while ( i<(int)str.length() )
54                        {
55                                outString->append( str.c_str() + i, 1 );
56                                ++i;
57                                if ( str[i] == ';' )
58                                        break;
59                        }
60                }
61                else if ( c == '&' )
62                {
63                        outString->append( entity[0].str, entity[0].strLength );
64                        ++i;
65                }
66                else if ( c == '<' )
67                {
68                        outString->append( entity[1].str, entity[1].strLength );
69                        ++i;
70                }
71                else if ( c == '>' )
72                {
73                        outString->append( entity[2].str, entity[2].strLength );
74                        ++i;
75                }
76                else if ( c == '\"' )
77                {
78                        outString->append( entity[3].str, entity[3].strLength );
79                        ++i;
80                }
81                else if ( c == '\'' )
82                {
83                        outString->append( entity[4].str, entity[4].strLength );
84                        ++i;
85                }
86                else if ( c < 32 || c > 126 )
87                {
88                        // Easy pass at non-alpha/numeric/symbol
89                        // 127 is the delete key. Below 32 is symbolic.
90                        char buf[ 32 ];
91                        sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
92                        outString->append( buf, strlen( buf ) );
93                        ++i;
94                }
95                else
96                {
97                        char realc = (char) c;
98                        outString->append( &realc, 1 );
99                        ++i;
100                }
101        }
102}
103
104
105TiXmlNode::TiXmlNode( NodeType _type )
106{
107        parent = 0;
108        type = _type;
109        firstChild = 0;
110        lastChild = 0;
111        prev = 0;
112        next = 0;
113        userData = 0;
114}
115
116
117TiXmlNode::~TiXmlNode()
118{
119        TiXmlNode* node = firstChild;
120        TiXmlNode* temp = 0;
121
122        while ( node )
123        {
124                temp = node;
125                node = node->next;
126                delete temp;
127        }       
128}
129
130
131void TiXmlNode::Clear()
132{
133        TiXmlNode* node = firstChild;
134        TiXmlNode* temp = 0;
135
136        while ( node )
137        {
138                temp = node;
139                node = node->next;
140                delete temp;
141        }       
142
143        firstChild = 0;
144        lastChild = 0;
145}
146
147
148TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
149{
150        node->parent = this;
151
152        node->prev = lastChild;
153        node->next = 0;
154
155        if ( lastChild )
156                lastChild->next = node;
157        else
158                firstChild = node;                      // it was an empty list.
159
160        lastChild = node;
161        return node;
162}
163
164
165TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
166{
167        TiXmlNode* node = addThis.Clone();
168        if ( !node )
169                return 0;
170
171        return LinkEndChild( node );
172}
173
174
175TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
176{       
177        if ( !beforeThis || beforeThis->parent != this )
178                return 0;
179
180        TiXmlNode* node = addThis.Clone();
181        if ( !node )
182                return 0;
183        node->parent = this;
184
185        node->next = beforeThis;
186        node->prev = beforeThis->prev;
187        if ( beforeThis->prev )
188        {
189                beforeThis->prev->next = node;
190        }
191        else
192        {
193                assert( firstChild == beforeThis );
194                firstChild = node;
195        }
196        beforeThis->prev = node;
197        return node;
198}
199
200
201TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
202{
203        if ( !afterThis || afterThis->parent != this )
204                return 0;
205
206        TiXmlNode* node = addThis.Clone();
207        if ( !node )
208                return 0;
209        node->parent = this;
210
211        node->prev = afterThis;
212        node->next = afterThis->next;
213        if ( afterThis->next )
214        {
215                afterThis->next->prev = node;
216        }
217        else
218        {
219                assert( lastChild == afterThis );
220                lastChild = node;
221        }
222        afterThis->next = node;
223        return node;
224}
225
226
227TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
228{
229        if ( replaceThis->parent != this )
230                return 0;
231
232        TiXmlNode* node = withThis.Clone();
233        if ( !node )
234                return 0;
235
236        node->next = replaceThis->next;
237        node->prev = replaceThis->prev;
238
239        if ( replaceThis->next )
240                replaceThis->next->prev = node;
241        else
242                lastChild = node;
243
244        if ( replaceThis->prev )
245                replaceThis->prev->next = node;
246        else
247                firstChild = node;
248
249        delete replaceThis;
250        node->parent = this;
251        return node;
252}
253
254
255bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
256{
257        if ( removeThis->parent != this )
258        {       
259                assert( 0 );
260                return false;
261        }
262
263        if ( removeThis->next )
264                removeThis->next->prev = removeThis->prev;
265        else
266                lastChild = removeThis->prev;
267
268        if ( removeThis->prev )
269                removeThis->prev->next = removeThis->next;
270        else
271                firstChild = removeThis->next;
272
273        delete removeThis;
274        return true;
275}
276
277TiXmlNode* TiXmlNode::FirstChild( const char * value ) const
278{
279        TiXmlNode* node;
280        for ( node = firstChild; node; node = node->next )
281        {
282                if ( node->SValue() == TIXML_STRING( value ))
283                        return node;
284        }
285        return 0;
286}
287
288TiXmlNode* TiXmlNode::LastChild( const char * value ) const
289{
290        TiXmlNode* node;
291        for ( node = lastChild; node; node = node->prev )
292        {
293                if ( node->SValue() == TIXML_STRING (value))
294                        return node;
295        }
296        return 0;
297}
298
299TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous ) const
300{
301        if ( !previous )
302        {
303                return FirstChild();
304        }
305        else
306        {
307                assert( previous->parent == this );
308                return previous->NextSibling();
309        }
310}
311
312TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous ) const
313{
314        if ( !previous )
315        {
316                return FirstChild( val );
317        }
318        else
319        {
320                assert( previous->parent == this );
321                return previous->NextSibling( val );
322        }
323}
324
325TiXmlNode* TiXmlNode::NextSibling( const char * value ) const
326{
327        TiXmlNode* node;
328        for ( node = next; node; node = node->next )
329        {
330                if ( node->SValue() == TIXML_STRING (value))
331                        return node;
332        }
333        return 0;
334}
335
336
337TiXmlNode* TiXmlNode::PreviousSibling( const char * value ) const
338{
339        TiXmlNode* node;
340        for ( node = prev; node; node = node->prev )
341        {
342                if ( node->SValue() == TIXML_STRING (value))
343                        return node;
344        }
345        return 0;
346}
347
348void TiXmlElement::RemoveAttribute( const char * name )
349{
350        TiXmlAttribute* node = attributeSet.Find( name );
351        if ( node )
352        {
353                attributeSet.Remove( node );
354                delete node;
355        }
356}
357
358TiXmlElement* TiXmlNode::FirstChildElement() const
359{
360        TiXmlNode* node;
361
362        for (   node = FirstChild();
363        node;
364        node = node->NextSibling() )
365        {
366                if ( node->ToElement() )
367                        return node->ToElement();
368        }
369        return 0;
370}
371
372TiXmlElement* TiXmlNode::FirstChildElement( const char * value ) const
373{
374        TiXmlNode* node;
375
376        for (   node = FirstChild( value );
377        node;
378        node = node->NextSibling( value ) )
379        {
380                if ( node->ToElement() )
381                        return node->ToElement();
382        }
383        return 0;
384}
385
386
387TiXmlElement* TiXmlNode::NextSiblingElement() const
388{
389        TiXmlNode* node;
390
391        for (   node = NextSibling();
392        node;
393        node = node->NextSibling() )
394        {
395                if ( node->ToElement() )
396                        return node->ToElement();
397        }
398        return 0;
399}
400
401TiXmlElement* TiXmlNode::NextSiblingElement( const char * value ) const
402{
403        TiXmlNode* node;
404
405        for (   node = NextSibling( value );
406        node;
407        node = node->NextSibling( value ) )
408        {
409                if ( node->ToElement() )
410                        return node->ToElement();
411        }
412        return 0;
413}
414
415
416
417TiXmlDocument* TiXmlNode::GetDocument() const
418{
419        const TiXmlNode* node;
420
421        for( node = this; node; node = node->parent )
422        {
423                if ( node->ToDocument() )
424                        return node->ToDocument();
425        }
426        return 0;
427}
428
429
430TiXmlElement::TiXmlElement (const char * _value)
431: TiXmlNode( TiXmlNode::ELEMENT )
432{
433        firstChild = lastChild = 0;
434        value = _value;
435}
436
437TiXmlElement::~TiXmlElement()
438{
439        while( attributeSet.First() )
440        {
441                TiXmlAttribute* node = attributeSet.First();
442                attributeSet.Remove( node );
443                delete node;
444        }
445}
446
447// BEGIN OGRE CHANGES
448// USE STL ALONE
449#ifndef TIXML_USE_STL
450const char * TiXmlElement::Attribute( const char * name ) const
451{
452        TiXmlAttribute* node = attributeSet.Find( name );
453
454        if ( node )
455                return node->Value();
456
457        return 0;
458}
459
460
461const char * TiXmlElement::Attribute( const char * name, int* i ) const
462{
463        const char * s = Attribute( name );
464        if ( i )
465        {
466                if ( s )
467                        *i = atoi( s );
468                else
469                        *i = 0;
470        }
471        return s;
472}
473
474
475void TiXmlElement::SetAttribute( const char * name, int val )
476{       
477        char buf[64];
478        sprintf( buf, "%d", val );
479        SetAttribute( name, buf );
480}
481
482
483void TiXmlElement::SetAttribute( const char * name, const char * value )
484{
485        TiXmlAttribute* node = attributeSet.Find( name );
486        if ( node )
487        {
488                node->SetValue( value );
489                return;
490        }
491
492        TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
493        if ( attrib )
494        {
495                attributeSet.Add( attrib );
496        }
497        else
498        {
499                TiXmlDocument* document = GetDocument();
500                if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
501        }
502}
503
504#endif
505
506#ifdef TIXML_USE_STL
507
508const char * TiXmlElement::Attribute( const std::string& name ) const
509{
510        TiXmlAttribute* node = attributeSet.Find( name.c_str() );
511
512        if ( node )
513                return node->Value();
514
515        return 0;
516}
517
518
519const char * TiXmlElement::Attribute( const std::string& name, int* i ) const
520{
521        const char * s = Attribute( name );
522        if ( i )
523        {
524                if ( s )
525                        *i = atoi( s );
526                else
527                        *i = 0;
528        }
529        return s;
530}
531
532
533void TiXmlElement::SetAttribute( const std::string& name, int val )
534{       
535        char buf[64];
536        sprintf( buf, "%d", val );
537        SetAttribute( name, buf );
538}
539
540
541void TiXmlElement::SetAttribute( const std::string& name, const std::string& value )
542{
543        TiXmlAttribute* node = attributeSet.Find( name.c_str() );
544        if ( node )
545        {
546                node->SetValue( value );
547                return;
548        }
549
550        TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
551        if ( attrib )
552        {
553                attributeSet.Add( attrib );
554        }
555        else
556        {
557                TiXmlDocument* document = GetDocument();
558                if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
559        }
560}
561
562#endif
563// END OGRE CHANGES
564void TiXmlElement::Print( FILE* cfile, int depth ) const
565{
566        int i;
567        for ( i=0; i<depth; i++ )
568        {
569                fprintf( cfile, "    " );
570        }
571
572        fprintf( cfile, "<%s", value.c_str() );
573
574        TiXmlAttribute* attrib;
575        for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
576        {
577                fprintf( cfile, " " );
578                attrib->Print( cfile, depth );
579        }
580
581        // There are 3 different formatting approaches:
582        // 1) An element without children is printed as a <foo /> node
583        // 2) An element with only a text child is printed as <foo> text </foo>
584        // 3) An element with children is printed on multiple lines.
585        TiXmlNode* node;
586        if ( !firstChild )
587        {
588                fprintf( cfile, " />" );
589        }
590        else if ( firstChild == lastChild && firstChild->ToText() )
591        {
592                fprintf( cfile, ">" );
593                firstChild->Print( cfile, depth + 1 );
594                fprintf( cfile, "</%s>", value.c_str() );
595        }
596        else
597        {
598                fprintf( cfile, ">" );
599
600                for ( node = firstChild; node; node=node->NextSibling() )
601                {
602                        if ( !node->ToText() )
603                        {
604                                fprintf( cfile, "\n" );
605                        }
606                        node->Print( cfile, depth+1 );
607                }
608                fprintf( cfile, "\n" );
609                for( i=0; i<depth; ++i )
610                fprintf( cfile, "    " );
611                fprintf( cfile, "</%s>", value.c_str() );
612        }
613}
614
615void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
616{
617        (*stream) << "<" << value;
618
619        TiXmlAttribute* attrib;
620        for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
621        {       
622                (*stream) << " ";
623                attrib->StreamOut( stream );
624        }
625
626        // If this node has children, give it a closing tag. Else
627        // make it an empty tag.
628        TiXmlNode* node;
629        if ( firstChild )
630        {               
631                (*stream) << ">";
632
633                for ( node = firstChild; node; node=node->NextSibling() )
634                {
635                        node->StreamOut( stream );
636                }
637                (*stream) << "</" << value << ">";
638        }
639        else
640        {
641                (*stream) << " />";
642        }
643}
644
645TiXmlNode* TiXmlElement::Clone() const
646{
647        TiXmlElement* clone = new TiXmlElement( Value() );
648        if ( !clone )
649                return 0;
650
651        CopyToClone( clone );
652
653        // Clone the attributes, then clone the children.
654        TiXmlAttribute* attribute = 0;
655        for(    attribute = attributeSet.First();
656        attribute;
657        attribute = attribute->Next() )
658        {
659                clone->SetAttribute( attribute->Name(), attribute->Value() );
660        }
661
662        TiXmlNode* node = 0;
663        for ( node = firstChild; node; node = node->NextSibling() )
664        {
665                clone->LinkEndChild( node->Clone() );
666        }
667        return clone;
668}
669
670
671TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
672{
673        error = false;
674        //      ignoreWhiteSpace = true;
675}
676
677TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
678{
679        //      ignoreWhiteSpace = true;
680        value = documentName;
681        error = false;
682}
683
684bool TiXmlDocument::LoadFile()
685{
686        if ( LoadFile( value.c_str() ) )
687                return true;
688
689        return false;
690}
691
692
693bool TiXmlDocument::SaveFile() const
694{
695        if ( SaveFile( value.c_str() ) )
696                return true;
697
698        return false;
699}
700
701bool TiXmlDocument::LoadFile( const char* filename )
702{
703        // Delete the existing data:
704        Clear();
705
706        // There was a really terrifying little bug here. The code:
707        //              value = filename
708        // in the STL case, cause the assignment method of the std::string to
709        // be called. What is strange, is that the std::string had the same
710        // address as it's c_str() method, and so bad things happen. Looks
711        // like a bug in the Microsoft STL implementation.
712        // See STL_STRING_BUG above.
713        // Fixed with the StringToBuffer class.
714        value = filename;
715
716        FILE* file = fopen( value.c_str (), "r" );
717
718        if ( file )
719        {
720                // Get the file size, so we can pre-allocate the string. HUGE speed impact.
721                long length = 0;
722                fseek( file, 0, SEEK_END );
723                length = ftell( file );
724                fseek( file, 0, SEEK_SET );
725
726                // Strange case, but good to handle up front.
727                if ( length == 0 )
728                {
729                        fclose( file );
730                        return false;
731                }
732
733                // If we have a file, assume it is all one big XML file, and read it in.
734                // The document parser may decide the document ends sooner than the entire file, however.
735                TIXML_STRING data;
736                data.reserve( length );
737
738                const int BUF_SIZE = 2048;
739                char buf[BUF_SIZE];
740
741                while( fgets( buf, BUF_SIZE, file ) )
742                {
743                        data += buf;
744                }
745                fclose( file );
746
747                Parse( data.c_str() );
748                if (  !Error() )
749                {
750                        return true;
751                }
752        }
753        SetError( TIXML_ERROR_OPENING_FILE );
754        return false;
755}
756
757bool TiXmlDocument::SaveFile( const char * filename ) const
758{
759        // The old c stuff lives on...
760        FILE* fp = fopen( filename, "w" );
761        if ( fp )
762        {
763                Print( fp, 0 );
764                fclose( fp );
765                return true;
766        }
767        return false;
768}
769
770
771TiXmlNode* TiXmlDocument::Clone() const
772{
773        TiXmlDocument* clone = new TiXmlDocument();
774        if ( !clone )
775                return 0;
776
777        CopyToClone( clone );
778        clone->error = error;
779        clone->errorDesc = errorDesc.c_str ();
780
781        TiXmlNode* node = 0;
782        for ( node = firstChild; node; node = node->NextSibling() )
783        {
784                clone->LinkEndChild( node->Clone() );
785        }
786        return clone;
787}
788
789
790void TiXmlDocument::Print( FILE* cfile, int depth ) const
791{
792        TiXmlNode* node;
793        for ( node=FirstChild(); node; node=node->NextSibling() )
794        {
795                node->Print( cfile, depth );
796                fprintf( cfile, "\n" );
797        }
798}
799
800void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
801{
802        TiXmlNode* node;
803        for ( node=FirstChild(); node; node=node->NextSibling() )
804        {
805                node->StreamOut( out );
806
807                // Special rule for streams: stop after the root element.
808                // The stream in code will only read one element, so don't
809                // write more than one.
810                if ( node->ToElement() )
811                        break;
812        }
813}
814
815TiXmlAttribute* TiXmlAttribute::Next() const
816{
817        // We are using knowledge of the sentinel. The sentinel
818        // have a value or name.
819        if ( next->value.empty() && next->name.empty() )
820                return 0;
821        return next;
822}
823
824
825TiXmlAttribute* TiXmlAttribute::Previous() const
826{
827        // We are using knowledge of the sentinel. The sentinel
828        // have a value or name.
829        if ( prev->value.empty() && prev->name.empty() )
830                return 0;
831        return prev;
832}
833
834
835void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
836{
837        TIXML_STRING n, v;
838
839        PutString( Name(), &n );
840        PutString( Value(), &v );
841
842        if (value.find ('\"') == TIXML_STRING::npos)
843                fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
844        else
845                fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
846}
847
848
849void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
850{
851        if (value.find( '\"' ) != TIXML_STRING::npos)
852        {
853                PutString( name, stream );
854                (*stream) << "=" << "'";
855                PutString( value, stream );
856                (*stream) << "'";
857        }
858        else
859        {
860                PutString( name, stream );
861                (*stream) << "=" << "\"";
862                PutString( value, stream );
863                (*stream) << "\"";
864        }
865}
866
867void TiXmlAttribute::SetIntValue( int value )
868{
869        char buf [64];
870        sprintf (buf, "%d", value);
871        SetValue (buf);
872}
873
874void TiXmlAttribute::SetDoubleValue( double value )
875{
876        char buf [64];
877        sprintf (buf, "%lf", value);
878        SetValue (buf);
879}
880
881const int TiXmlAttribute::IntValue() const
882{
883        return atoi (value.c_str ());
884}
885
886const double  TiXmlAttribute::DoubleValue() const
887{
888        return atof (value.c_str ());
889}
890
891void TiXmlComment::Print( FILE* cfile, int depth ) const
892{
893        for ( int i=0; i<depth; i++ )
894        {
895                fputs( "    ", cfile );
896        }
897        fprintf( cfile, "<!--%s-->", value.c_str() );
898}
899
900void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
901{
902        (*stream) << "<!--";
903        PutString( value, stream );
904        (*stream) << "-->";
905}
906
907TiXmlNode* TiXmlComment::Clone() const
908{
909        TiXmlComment* clone = new TiXmlComment();
910
911        if ( !clone )
912                return 0;
913
914        CopyToClone( clone );
915        return clone;
916}
917
918
919void TiXmlText::Print( FILE* cfile, int /*depth*/ ) const
920{
921        TIXML_STRING buffer;
922        PutString( value, &buffer );
923        fprintf( cfile, "%s", buffer.c_str() );
924}
925
926
927void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
928{
929        PutString( value, stream );
930}
931
932
933TiXmlNode* TiXmlText::Clone() const
934{       
935        TiXmlText* clone = 0;
936        clone = new TiXmlText( "" );
937
938        if ( !clone )
939                return 0;
940
941        CopyToClone( clone );
942        return clone;
943}
944
945
946TiXmlDeclaration::TiXmlDeclaration( const char * _version,
947        const char * _encoding,
948        const char * _standalone )
949: TiXmlNode( TiXmlNode::DECLARATION )
950{
951        version = _version;
952        encoding = _encoding;
953        standalone = _standalone;
954}
955
956
957void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
958{
959        fprintf (cfile, "<?xml ");
960
961        if ( !version.empty() )
962                fprintf (cfile, "version=\"%s\" ", version.c_str ());
963        if ( !encoding.empty() )
964                fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
965        if ( !standalone.empty() )
966                fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
967        fprintf (cfile, "?>");
968}
969
970void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
971{
972        (*stream) << "<?xml ";
973
974        if ( !version.empty() )
975        {
976                (*stream) << "version=\"";
977                PutString( version, stream );
978                (*stream) << "\" ";
979        }
980        if ( !encoding.empty() )
981        {
982                (*stream) << "encoding=\"";
983                PutString( encoding, stream );
984                (*stream ) << "\" ";
985        }
986        if ( !standalone.empty() )
987        {
988                (*stream) << "standalone=\"";
989                PutString( standalone, stream );
990                (*stream) << "\" ";
991        }
992        (*stream) << "?>";
993}
994
995TiXmlNode* TiXmlDeclaration::Clone() const
996{       
997        TiXmlDeclaration* clone = new TiXmlDeclaration();
998
999        if ( !clone )
1000                return 0;
1001
1002        CopyToClone( clone );
1003        clone->version = version;
1004        clone->encoding = encoding;
1005        clone->standalone = standalone;
1006        return clone;
1007}
1008
1009
1010void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1011{
1012        for ( int i=0; i<depth; i++ )
1013                fprintf( cfile, "    " );
1014        fprintf( cfile, "%s", value.c_str() );
1015}
1016
1017void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
1018{
1019        (*stream) << "<" << value << ">";               // Don't use entities hear! It is unknown.
1020}
1021
1022TiXmlNode* TiXmlUnknown::Clone() const
1023{
1024        TiXmlUnknown* clone = new TiXmlUnknown();
1025
1026        if ( !clone )
1027                return 0;
1028
1029        CopyToClone( clone );
1030        return clone;
1031}
1032
1033
1034TiXmlAttributeSet::TiXmlAttributeSet()
1035{
1036        sentinel.next = &sentinel;
1037        sentinel.prev = &sentinel;
1038}
1039
1040
1041TiXmlAttributeSet::~TiXmlAttributeSet()
1042{
1043        assert( sentinel.next == &sentinel );
1044        assert( sentinel.prev == &sentinel );
1045}
1046
1047
1048void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1049{
1050        assert( !Find( addMe->Name() ) );       // Shouldn't be multiply adding to the set.
1051
1052        addMe->next = &sentinel;
1053        addMe->prev = sentinel.prev;
1054
1055        sentinel.prev->next = addMe;
1056        sentinel.prev      = addMe;
1057}
1058
1059void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1060{
1061        TiXmlAttribute* node;
1062
1063        for( node = sentinel.next; node != &sentinel; node = node->next )
1064        {
1065                if ( node == removeMe )
1066                {
1067                        node->prev->next = node->next;
1068                        node->next->prev = node->prev;
1069                        node->next = 0;
1070                        node->prev = 0;
1071                        return;
1072                }
1073        }
1074        assert( 0 );            // we tried to remove a non-linked attribute.
1075}
1076
1077TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
1078{
1079        TiXmlAttribute* node;
1080
1081        for( node = sentinel.next; node != &sentinel; node = node->next )
1082        {
1083                if ( node->name == name )
1084                        return node;
1085        }
1086        return 0;
1087}
1088
1089
1090#ifdef TIXML_USE_STL   
1091TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
1092{
1093        TIXML_STRING tag;
1094        tag.reserve( 8 * 1000 );
1095        base.StreamIn( &in, &tag );
1096
1097        base.Parse( tag.c_str() );
1098        return in;
1099}
1100#endif
1101
1102
1103TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
1104{
1105        base.StreamOut (& out);
1106        return out;
1107}
1108
Note: See TracBrowser for help on using the repository browser.