source: branch_0_3_1/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
1111
1112bool document::save_file( const char * filename ) const
1113{
1114        // The old c stuff lives on...
1115        FILE* fp = fopen( filename, "wc" );
1116        if ( fp )
1117        {
1118                bool result = save_file( fp );
1119                fflush( fp );
1120                fclose( fp );
1121                return result;
1122        }
1123        return false;
1124}
1125
1126bool document::save_file( const wchar_t * filename ) const
1127{
1128        // The old c stuff lives on...
1129        FILE* fp = _wfopen( filename, L"wc" );
1130        if ( fp )
1131        {
1132                bool result = save_file( fp );
1133                fflush( fp );
1134                fclose( fp );
1135                return result;
1136        }
1137        return false;
1138}
1139
1140bool document::save_file( FILE* fp ) const
1141{
1142        if ( useMicrosoftBOM ) 
1143        {
1144                const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1145                const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1146                const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1147
1148                fputc( TIXML_UTF_LEAD_0, fp );
1149                fputc( TIXML_UTF_LEAD_1, fp );
1150                fputc( TIXML_UTF_LEAD_2, fp );
1151        }
1152        print( fp, 0 );
1153        return (ferror(fp) == 0);
1154}
1155
1156
1157void document::copy_to( document* target ) const
1158{
1159        node::copy_to( target );
1160
1161        target->error_ = error_;
1162        target->errorId = errorId;
1163        target->errorDesc = errorDesc;
1164        target->tabsize = tabsize;
1165        target->errorLocation = errorLocation;
1166        target->useMicrosoftBOM = useMicrosoftBOM;
1167
1168        node* node_ = 0;
1169        for ( node_ = firstChild; node_; node_ = node_->next_sibling() )
1170        {
1171                target->link_end_child( node_->clone() );
1172        }       
1173}
1174
1175
1176node* document::clone() const
1177{
1178        document* clone_ = new document();
1179        if ( !clone_ )
1180                return 0;
1181
1182        copy_to( clone_ );
1183        return clone_;
1184}
1185
1186
1187void document::print( FILE* cfile, int depth ) const
1188{
1189        assert( cfile );
1190        for ( const node* node_=first_child(); node_; node_=node_->next_sibling() )
1191        {
1192                node_->print( cfile, depth );
1193                fprintf( cfile, "\n" );
1194        }
1195}
1196
1197
1198bool document::accept( visitor* visitor_ ) const
1199{
1200        if ( visitor_->visit_enter( *this ) )
1201        {
1202                for ( const node* node_=first_child(); node_; node_=node_->next_sibling() )
1203                {
1204                        if ( !node_->accept( visitor_ ) )
1205                                break;
1206                }
1207        }
1208        return visitor_->visit_exit( *this );
1209}
1210
1211
1212const attribute* attribute::next() const
1213{
1214        // We are_ using knowledge of the sentinel. The sentinel
1215        // have a value_ or name_.
1216        if ( next_->value_.empty() && next_->name_.empty() )
1217                return 0;
1218        return next_;
1219}
1220
1221/*
1222attribute* attribute::next()
1223{
1224        // We are_ using knowledge of the sentinel. The sentinel
1225        // have a value_ or name_.
1226        if ( next_->value_.empty() && next_->name_.empty() )
1227                return 0;
1228        return next_;
1229}
1230*/
1231
1232const attribute* attribute::previous() const
1233{
1234        // We are_ using knowledge of the sentinel. The sentinel
1235        // have a value_ or name_.
1236        if ( prev->value_.empty() && prev->name_.empty() )
1237                return 0;
1238        return prev;
1239}
1240
1241/*
1242attribute* attribute::previous()
1243{
1244        // We are_ using knowledge of the sentinel. The sentinel
1245        // have a value_ or name_.
1246        if ( prev->value_.empty() && prev->name_.empty() )
1247                return 0;
1248        return prev;
1249}
1250*/
1251
1252void attribute::print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1253{
1254        TIXML_STRING n, v;
1255
1256        encode_string( name_, &n );
1257        encode_string( value_, &v );
1258
1259        if (value_.find ('\"') == TIXML_STRING::npos) {
1260                if ( cfile ) {
1261                fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1262                }
1263                if ( str ) {
1264                        (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1265                }
1266        }
1267        else {
1268                if ( cfile ) {
1269                fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1270                }
1271                if ( str ) {
1272                        (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1273                }
1274        }
1275}
1276
1277int attribute::query_int_value( int* ival ) const
1278{
1279        if ( TIXML_SSCANF( value_.c_str(), "%d", ival ) == 1 )
1280                return TIXML_SUCCESS;
1281        return TIXML_WRONG_TYPE;
1282}
1283
1284int attribute::query_double_value( double* dval ) const
1285{
1286        if ( TIXML_SSCANF( value_.c_str(), "%lf", dval ) == 1 )
1287                return TIXML_SUCCESS;
1288        return TIXML_WRONG_TYPE;
1289}
1290
1291void attribute::set_int_value( int _value )
1292{
1293        char buf [64];
1294        #if defined(TIXML_SNPRINTF)             
1295                TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1296        #else
1297                sprintf (buf, "%d", _value);
1298        #endif
1299        set_value (buf);
1300}
1301
1302void attribute::set_double_value( double _value )
1303{
1304        char buf [256];
1305        #if defined(TIXML_SNPRINTF)             
1306                TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1307        #else
1308                sprintf (buf, "%lf", _value);
1309        #endif
1310        set_value (buf);
1311}
1312
1313int attribute::int_value() const
1314{
1315        return atoi (value_.c_str ());
1316}
1317
1318double  attribute::double_value() const
1319{
1320        return atof (value_.c_str ());
1321}
1322
1323
1324comment::comment( const comment& copy_ ) : node( node::COMMENT )
1325{
1326        copy_.copy_to( this );
1327}
1328
1329
1330void comment::operator=( const comment& base_ )
1331{
1332        clear();
1333        base_.copy_to( this );
1334}
1335
1336
1337void comment::print( FILE* cfile, int depth ) const
1338{
1339        assert( cfile );
1340        for ( int i=0; i<depth; i++ )
1341        {
1342                fprintf( cfile,  "    " );
1343        }
1344        fprintf( cfile, "<!--%s-->", value_.c_str() );
1345}
1346
1347
1348void comment::copy_to( comment* target ) const
1349{
1350        node::copy_to( target );
1351}
1352
1353
1354bool comment::accept( visitor* visitor_ ) const
1355{
1356        return visitor_->visit( *this );
1357}
1358
1359
1360node* comment::clone() const
1361{
1362        comment* clone_ = new comment();
1363
1364        if ( !clone_ )
1365                return 0;
1366
1367        copy_to( clone_ );
1368        return clone_;
1369}
1370
1371
1372void text::print( FILE* cfile, int depth ) const
1373{
1374        assert( cfile );
1375        if ( cdata )
1376        {
1377                int i;
1378                fprintf( cfile, "\n" );
1379                for ( i=0; i<depth; i++ ) {
1380                        fprintf( cfile, "    " );
1381                }
1382                fprintf( cfile, "<![CDATA[%s]]>\n", value_.c_str() );   // unformatted output_
1383        }
1384        else
1385        {
1386                TIXML_STRING buffer;
1387                encode_string( value_, &buffer );
1388                fprintf( cfile, "%s", buffer.c_str() );
1389        }
1390}
1391
1392
1393void text::copy_to( text* target ) const
1394{
1395        node::copy_to( target );
1396        target->cdata = cdata;
1397}
1398
1399
1400bool text::accept( visitor* visitor_ ) const
1401{
1402        return visitor_->visit( *this );
1403}
1404
1405
1406node* text::clone() const
1407{       
1408        text* clone_ = 0;
1409        clone_ = new text( "" );
1410
1411        if ( !clone_ )
1412                return 0;
1413
1414        copy_to( clone_ );
1415        return clone_;
1416}
1417
1418
1419declaration::declaration( const char * _version,
1420                                                                        const char * _encoding,
1421                                                                        const char * _standalone )
1422        : node( node::DECLARATION )
1423{
1424        version_ = _version;
1425        encoding_ = _encoding;
1426        standalone_ = _standalone;
1427}
1428
1429
1430#ifdef TIXML_USE_STL
1431declaration::declaration(       const std::string& _version,
1432                                                                        const std::string& _encoding,
1433                                                                        const std::string& _standalone )
1434        : node( node::DECLARATION )
1435{
1436        version_ = _version;
1437        encoding_ = _encoding;
1438        standalone_ = _standalone;
1439}
1440#endif
1441
1442
1443declaration::declaration( const declaration& copy_ )
1444        : node( node::DECLARATION )
1445{
1446        copy_.copy_to( this ); 
1447}
1448
1449
1450void declaration::operator=( const declaration& copy_ )
1451{
1452        clear();
1453        copy_.copy_to( this );
1454}
1455
1456
1457void declaration::print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1458{
1459        if ( cfile ) fprintf( cfile, "<?xml " );
1460        if ( str )       (*str) += "<?xml ";
1461
1462        if ( !version_.empty() ) {
1463                if ( cfile ) fprintf (cfile, "version=\"%s\" ", version_.c_str ());
1464                if ( str ) { (*str) += "version=\""; (*str) += version_; (*str) += "\" "; }
1465        }
1466        if ( !encoding_.empty() ) {
1467                if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding_.c_str ());
1468                if ( str ) { (*str) += "encoding=\""; (*str) += encoding_; (*str) += "\" "; }
1469        }
1470        if ( !standalone_.empty() ) {
1471                if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone_.c_str ());
1472                if ( str ) { (*str) += "standalone=\""; (*str) += standalone_; (*str) += "\" "; }
1473        }
1474        if ( cfile ) fprintf( cfile, "?>" );
1475        if ( str )       (*str) += "?>";
1476}
1477
1478
1479void declaration::copy_to( declaration* target ) const
1480{
1481        node::copy_to( target );
1482
1483        target->version_ = version_;
1484        target->encoding_ = encoding_;
1485        target->standalone_ = standalone_;
1486}
1487
1488
1489bool declaration::accept( visitor* visitor_ ) const
1490{
1491        return visitor_->visit( *this );
1492}
1493
1494
1495node* declaration::clone() const
1496{       
1497        declaration* clone_ = new declaration();
1498
1499        if ( !clone_ )
1500                return 0;
1501
1502        copy_to( clone_ );
1503        return clone_;
1504}
1505
1506
1507void unknown::print( FILE* cfile, int depth ) const
1508{
1509        for ( int i=0; i<depth; i++ )
1510                fprintf( cfile, "    " );
1511        fprintf( cfile, "<%s>", value_.c_str() );
1512}
1513
1514
1515void unknown::copy_to( unknown* target ) const
1516{
1517        node::copy_to( target );
1518}
1519
1520
1521bool unknown::accept( visitor* visitor_ ) const
1522{
1523        return visitor_->visit( *this );
1524}
1525
1526
1527node* unknown::clone() const
1528{
1529        unknown* clone_ = new unknown();
1530
1531        if ( !clone_ )
1532                return 0;
1533
1534        copy_to( clone_ );
1535        return clone_;
1536}
1537
1538
1539attribute_set::attribute_set()
1540{
1541        sentinel.next_ = &sentinel;
1542        sentinel.prev = &sentinel;
1543}
1544
1545
1546attribute_set::~attribute_set()
1547{
1548        assert( sentinel.next_ == &sentinel );
1549        assert( sentinel.prev == &sentinel );
1550}
1551
1552
1553void attribute_set::add( attribute* addMe )
1554{
1555    #ifdef TIXML_USE_STL
1556        assert( !find( TIXML_STRING( addMe->name() ) ) );       // Shouldn't be multiply adding to the set.
1557        #else
1558        assert( !find( addMe->name() ) );       // Shouldn't be multiply adding to the set.
1559        #endif
1560
1561        addMe->next_ = &sentinel;
1562        addMe->prev = sentinel.prev;
1563
1564        sentinel.prev->next_ = addMe;
1565        sentinel.prev      = addMe;
1566}
1567
1568void attribute_set::remove( attribute* removeMe )
1569{
1570        attribute* node_;
1571
1572        for( node_ = sentinel.next_; node_ != &sentinel; node_ = node_->next_ )
1573        {
1574                if ( node_ == removeMe )
1575                {
1576                        node_->prev->next_ = node_->next_;
1577                        node_->next_->prev = node_->prev;
1578                        node_->next_ = 0;
1579                        node_->prev = 0;
1580                        return;
1581                }
1582        }
1583        assert( 0 );            // we tried to remove_ a non-linked attribute_.
1584}
1585
1586
1587#ifdef TIXML_USE_STL
1588const attribute* attribute_set::find( const std::string& name_ ) const
1589{
1590        for( const attribute* node_ = sentinel.next_; node_ != &sentinel; node_ = node_->next_ )
1591        {
1592                if ( node_->name_ == name_ )
1593                        return node_;
1594        }
1595        return 0;
1596}
1597
1598/*
1599attribute*      attribute_set::find( const std::string& name_ )
1600{
1601        for( attribute* node_ = sentinel.next_; node_ != &sentinel; node_ = node_->next_ )
1602        {
1603                if ( node_->name_ == name_ )
1604                        return node_;
1605        }
1606        return 0;
1607}
1608*/
1609#endif
1610
1611
1612const attribute* attribute_set::find( const char* name_ ) const
1613{
1614        for( const attribute* node_ = sentinel.next_; node_ != &sentinel; node_ = node_->next_ )
1615        {
1616                if ( strcmp( node_->name_.c_str(), name_ ) == 0 )
1617                        return node_;
1618        }
1619        return 0;
1620}
1621
1622/*
1623attribute*      attribute_set::find( const char* name_ )
1624{
1625        for( attribute* node_ = sentinel.next_; node_ != &sentinel; node_ = node_->next_ )
1626        {
1627                if ( strcmp( node_->name_.c_str(), name_ ) == 0 )
1628                        return node_;
1629        }
1630        return 0;
1631}
1632*/
1633
1634#ifdef TIXML_USE_STL   
1635std::istream& operator>> (std::istream & in, node & base_)
1636{
1637        TIXML_STRING tag;
1638        tag.reserve( 8 * 1000 );
1639        base_.stream_in( &in, &tag );
1640
1641        base_.parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1642        return in;
1643}
1644#endif
1645
1646
1647#ifdef TIXML_USE_STL   
1648std::ostream& operator<< (std::ostream & out, const node & base_)
1649{
1650        printer printer_;
1651        printer_.set_stream_printing();
1652        base_.accept( &printer_ );
1653        out << printer_.str();
1654
1655        return out;
1656}
1657
1658
1659std::string& operator<< (std::string& out, const node& base_ )
1660{
1661        printer printer_;
1662        printer_.set_stream_printing();
1663        base_.accept( &printer_ );
1664        out.append( printer_.str() );
1665
1666        return out;
1667}
1668#endif
1669
1670
1671handle handle::first_child() const
1672{
1673        if ( node_ )
1674        {
1675                node* child_ = node_->first_child();
1676                if ( child_ )
1677                        return handle( child_ );
1678        }
1679        return handle( 0 );
1680}
1681
1682
1683handle handle::first_child( const char * value_ ) const
1684{
1685        if ( node_ )
1686        {
1687                node* child_ = node_->first_child( value_ );
1688                if ( child_ )
1689                        return handle( child_ );
1690        }
1691        return handle( 0 );
1692}
1693
1694
1695handle handle::first_child_element() const
1696{
1697        if ( node_ )
1698        {
1699                element* child_ = node_->first_child_element();
1700                if ( child_ )
1701                        return handle( child_ );
1702        }
1703        return handle( 0 );
1704}
1705
1706
1707handle handle::first_child_element( const char * value_ ) const
1708{
1709        if ( node_ )
1710        {
1711                element* child_ = node_->first_child_element( value_ );
1712                if ( child_ )
1713                        return handle( child_ );
1714        }
1715        return handle( 0 );
1716}
1717
1718
1719handle handle::child( int count ) const
1720{
1721        if ( node_ )
1722        {
1723                int i;
1724                node* child_ = node_->first_child();
1725                for (   i=0;
1726                                child_ && i<count;
1727                                child_ = child_->next_sibling(), ++i )
1728                {
1729                        // nothing
1730                }
1731                if ( child_ )
1732                        return handle( child_ );
1733        }
1734        return handle( 0 );
1735}
1736
1737
1738handle handle::child( const char* value_, int count ) const
1739{
1740        if ( node_ )
1741        {
1742                int i;
1743                node* child_ = node_->first_child( value_ );
1744                for (   i=0;
1745                                child_ && i<count;
1746                                child_ = child_->next_sibling( value_ ), ++i )
1747                {
1748                        // nothing
1749                }
1750                if ( child_ )
1751                        return handle( child_ );
1752        }
1753        return handle( 0 );
1754}
1755
1756
1757handle handle::child_element( int count ) const
1758{
1759        if ( node_ )
1760        {
1761                int i;
1762                element* child_ = node_->first_child_element();
1763                for (   i=0;
1764                                child_ && i<count;
1765                                child_ = child_->next_sibling_element(), ++i )
1766                {
1767                        // nothing
1768                }
1769                if ( child_ )
1770                        return handle( child_ );
1771        }
1772        return handle( 0 );
1773}
1774
1775
1776handle handle::child_element( const char* value_, int count ) const
1777{
1778        if ( node_ )
1779        {
1780                int i;
1781                element* child_ = node_->first_child_element( value_ );
1782                for (   i=0;
1783                                child_ && i<count;
1784                                child_ = child_->next_sibling_element( value_ ), ++i )
1785                {
1786                        // nothing
1787                }
1788                if ( child_ )
1789                        return handle( child_ );
1790        }
1791        return handle( 0 );
1792}
1793
1794
1795bool printer::visit_enter( const document& )
1796{
1797        return true;
1798}
1799
1800bool printer::visit_exit( const document& )
1801{
1802        return true;
1803}
1804
1805bool printer::visit_enter( const element& element_, const attribute* firstAttribute )
1806{
1807        do_indent();
1808        buffer += "<";
1809        buffer += element_.value();
1810
1811        for( const attribute* attrib = firstAttribute; attrib; attrib = attrib->next() )
1812        {
1813                buffer += " ";
1814                attrib->print( 0, 0, &buffer );
1815        }
1816
1817        if ( !element_.first_child() ) 
1818        {               
1819                #if defined (HAL_BOOST_SERIALIZATION_COMPAT)
1820                buffer += ">"; 
1821                #else
1822                buffer += " />";
1823                do_line_break();
1824                #endif
1825        }
1826        else 
1827        {
1828                buffer += ">";
1829                if (    element_.first_child()->to_text()
1830                          && element_.last_child() == element_.first_child()
1831                          && element_.first_child()->to_text()->CDATA() == false )
1832                {
1833                        simpleTextPrint = true;
1834                        // no_ do_line_break()!
1835                }
1836                else
1837                {
1838                        do_line_break();
1839                }
1840        }
1841        ++depth;       
1842        return true;
1843}
1844
1845
1846bool printer::visit_exit( const element& element_ )
1847{
1848        --depth;
1849        if ( !element_.first_child() ) 
1850        {
1851                #if defined (HAL_BOOST_SERIALIZATION_COMPAT)
1852                buffer += "</";
1853                buffer += element_.value();
1854                buffer += ">";
1855                do_line_break();
1856                #else
1857                // nothing
1858                #endif
1859        }
1860        else 
1861        {
1862                if ( simpleTextPrint )
1863                {
1864                        simpleTextPrint = false;
1865                }
1866                else
1867                {
1868                        do_indent();
1869                }
1870                buffer += "</";
1871                buffer += element_.value();
1872                buffer += ">";
1873                do_line_break();
1874        }
1875        return true;
1876}
1877
1878
1879bool printer::visit( const text& text_ )
1880{
1881        if ( text_.CDATA() )
1882        {
1883                do_indent();
1884                buffer += "<![CDATA[";
1885                buffer += text_.value();
1886                buffer += "]]>";
1887                do_line_break();
1888        }
1889        else if ( simpleTextPrint )
1890        {
1891                TIXML_STRING str;
1892                base::encode_string( text_.value_t_str(), &str );
1893                buffer += str;
1894        }
1895        else
1896        {
1897                do_indent();
1898                TIXML_STRING str;
1899                base::encode_string( text_.value_t_str(), &str );
1900                buffer += str;
1901                do_line_break();
1902        }
1903        return true;
1904}
1905
1906
1907bool printer::visit( const declaration& declaration_ )
1908{
1909        do_indent();
1910        declaration_.print( 0, 0, &buffer );
1911        do_line_break();
1912        return true;
1913}
1914
1915
1916bool printer::visit( const comment& comment_ )
1917{
1918        do_indent();
1919        buffer += "<!--";
1920        buffer += comment_.value();
1921        buffer += "-->";
1922        do_line_break();
1923        return true;
1924}
1925
1926
1927bool printer::visit( const unknown& unknown_ )
1928{
1929        do_indent();
1930        buffer += "<";
1931        buffer += unknown_.value();
1932        buffer += ">";
1933        do_line_break();
1934        return true;
1935}
1936
1937} // namespace tinyxml
Note: See TracBrowser for help on using the repository browser.