Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/trunk/src/lib/xmlparser/tinyxml.cc @ 4180

Last change on this file since 4180 was 4010, checked in by bensch, 20 years ago

orxonox/trunk: merged the levelloader from lltrunktemp to the trunk. Big thanks to fuzzy to make this so easy for us, and for implementing it in the first place.

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