/[pcsx2_0.9.7]/trunk/3rdparty/tinyxml/tinyxml.cpp
ViewVC logotype

Contents of /trunk/3rdparty/tinyxml/tinyxml.cpp

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.22