source: trunk/src/global/tinyxml.cpp @ 530

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