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 <new>
33
34 #include "tinyxml.h"
35
36
37 bool TiXmlBase::condenseWhiteSpace = true;
38
39 // Microsoft compiler security
TiXmlFOpen(const char * filename,const char * mode)40 FILE* TiXmlFOpen( 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
EncodeString(const TIXML_STRING & str,TIXML_STRING * outString)53 void TiXmlBase::EncodeString( 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 // © -- 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
TiXmlNode(NodeType _type)137 TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
138 {
139 parent = 0;
140 type = _type;
141 firstChild = 0;
142 lastChild = 0;
143 prev = 0;
144 next = 0;
145 }
146
147
~TiXmlNode()148 TiXmlNode::~TiXmlNode()
149 {
150 TiXmlNode* node = firstChild;
151 TiXmlNode* temp = 0;
152
153 while ( node )
154 {
155 temp = node;
156 node = node->next;
157 delete temp;
158 }
159 }
160
161
CopyTo(TiXmlNode * target) const162 void TiXmlNode::CopyTo( TiXmlNode* target ) const
163 {
164 target->SetValue (value.c_str() );
165 target->userData = userData;
166 }
167
168
Clear()169 void TiXmlNode::Clear()
170 {
171 TiXmlNode* node = firstChild;
172 TiXmlNode* 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
LinkEndChild(TiXmlNode * node)186 TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
187 {
188 assert( node->parent == 0 || node->parent == this );
189 assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
190
191 if ( node->Type() == TiXmlNode::DOCUMENT )
192 {
193 delete node;
194 if ( GetDocument() ) GetDocument()->SetError( 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
InsertEndChild(const TiXmlNode & addThis)213 TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
214 {
215 if ( addThis.Type() == TiXmlNode::DOCUMENT )
216 {
217 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
218 return 0;
219 }
220 TiXmlNode* node = addThis.Clone();
221 if ( !node )
222 return 0;
223
224 return LinkEndChild( node );
225 }
226
227
InsertBeforeChild(TiXmlNode * beforeThis,const TiXmlNode & addThis)228 TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
229 {
230 if ( !beforeThis || beforeThis->parent != this ) {
231 return 0;
232 }
233 if ( addThis.Type() == TiXmlNode::DOCUMENT )
234 {
235 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
236 return 0;
237 }
238
239 TiXmlNode* 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
InsertAfterChild(TiXmlNode * afterThis,const TiXmlNode & addThis)260 TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
261 {
262 if ( !afterThis || afterThis->parent != this ) {
263 return 0;
264 }
265 if ( addThis.Type() == TiXmlNode::DOCUMENT )
266 {
267 if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
268 return 0;
269 }
270
271 TiXmlNode* 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
ReplaceChild(TiXmlNode * replaceThis,const TiXmlNode & withThis)292 TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
293 {
294 if ( replaceThis->parent != this )
295 return 0;
296
297 TiXmlNode* 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
RemoveChild(TiXmlNode * removeThis)320 bool TiXmlNode::RemoveChild( TiXmlNode* 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
FirstChild(const char * _value) const342 const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
343 {
344 const TiXmlNode* 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
LastChild(const char * _value) const354 const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
355 {
356 const TiXmlNode* 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
IterateChildren(const TiXmlNode * previous) const366 const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
367 {
368 if ( !previous )
369 {
370 return FirstChild();
371 }
372 else
373 {
374 assert( previous->parent == this );
375 return previous->NextSibling();
376 }
377 }
378
379
IterateChildren(const char * val,const TiXmlNode * previous) const380 const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
381 {
382 if ( !previous )
383 {
384 return FirstChild( val );
385 }
386 else
387 {
388 assert( previous->parent == this );
389 return previous->NextSibling( val );
390 }
391 }
392
393
NextSibling(const char * _value) const394 const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
395 {
396 const TiXmlNode* 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
PreviousSibling(const char * _value) const406 const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
407 {
408 const TiXmlNode* 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
RemoveAttribute(const char * name)418 void TiXmlElement::RemoveAttribute( const char * name )
419 {
420 #ifdef TIXML_USE_STL
421 TIXML_STRING str( name );
422 TiXmlAttribute* node = attributeSet.Find( str );
423 #else
424 TiXmlAttribute* node = attributeSet.Find( name );
425 #endif
426 if ( node )
427 {
428 attributeSet.Remove( node );
429 delete node;
430 }
431 }
432
FirstChildElement() const433 const TiXmlElement* TiXmlNode::FirstChildElement() const
434 {
435 const TiXmlNode* node;
436
437 for ( node = FirstChild();
438 node;
439 node = node->NextSibling() )
440 {
441 if ( node->ToElement() )
442 return node->ToElement();
443 }
444 return 0;
445 }
446
447
FirstChildElement(const char * _value) const448 const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
449 {
450 const TiXmlNode* node;
451
452 for ( node = FirstChild( _value );
453 node;
454 node = node->NextSibling( _value ) )
455 {
456 if ( node->ToElement() )
457 return node->ToElement();
458 }
459 return 0;
460 }
461
462
NextSiblingElement() const463 const TiXmlElement* TiXmlNode::NextSiblingElement() const
464 {
465 const TiXmlNode* node;
466
467 for ( node = NextSibling();
468 node;
469 node = node->NextSibling() )
470 {
471 if ( node->ToElement() )
472 return node->ToElement();
473 }
474 return 0;
475 }
476
477
NextSiblingElement(const char * _value) const478 const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
479 {
480 const TiXmlNode* node;
481
482 for ( node = NextSibling( _value );
483 node;
484 node = node->NextSibling( _value ) )
485 {
486 if ( node->ToElement() )
487 return node->ToElement();
488 }
489 return 0;
490 }
491
492
GetDocument() const493 const TiXmlDocument* TiXmlNode::GetDocument() const
494 {
495 const TiXmlNode* node;
496
497 for( node = this; node; node = node->parent )
498 {
499 if ( node->ToDocument() )
500 return node->ToDocument();
501 }
502 return 0;
503 }
504
505
TiXmlElement(const char * _value)506 TiXmlElement::TiXmlElement (const char * _value)
507 : TiXmlNode( TiXmlNode::ELEMENT )
508 {
509 firstChild = lastChild = 0;
510 value = _value;
511 }
512
513
514 #ifdef TIXML_USE_STL
TiXmlElement(const std::string & _value)515 TiXmlElement::TiXmlElement( const std::string& _value )
516 : TiXmlNode( TiXmlNode::ELEMENT )
517 {
518 firstChild = lastChild = 0;
519 value = _value;
520 }
521 #endif
522
523
TiXmlElement(const TiXmlElement & copy)524 TiXmlElement::TiXmlElement( const TiXmlElement& copy)
525 : TiXmlNode( TiXmlNode::ELEMENT )
526 {
527 firstChild = lastChild = 0;
528 copy.CopyTo( this );
529 }
530
531
operator =(const TiXmlElement & base)532 void TiXmlElement::operator=( const TiXmlElement& base )
533 {
534 ClearThis();
535 base.CopyTo( this );
536 }
537
538
~TiXmlElement()539 TiXmlElement::~TiXmlElement()
540 {
541 ClearThis();
542 }
543
544
ClearThis()545 void TiXmlElement::ClearThis()
546 {
547 Clear();
548 while( attributeSet.First() )
549 {
550 TiXmlAttribute* node = attributeSet.First();
551 attributeSet.Remove( node );
552 delete node;
553 }
554 }
555
556
Attribute(const char * name) const557 const char* TiXmlElement::Attribute( const char* name ) const
558 {
559 const TiXmlAttribute* node = attributeSet.Find( name );
560 if ( node )
561 return node->Value();
562 return 0;
563 }
564
565
566 #ifdef TIXML_USE_STL
Attribute(const std::string & name) const567 const std::string* TiXmlElement::Attribute( const std::string& name ) const
568 {
569 const TiXmlAttribute* node = attributeSet.Find( name );
570 if ( node )
571 return &node->ValueStr();
572 return 0;
573 }
574 #endif
575
576
Attribute(const char * name,int * i) const577 const char* TiXmlElement::Attribute( const char* name, int* i ) const
578 {
579 const char* s = 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
Attribute(const std::string & name,int * i) const594 const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
595 {
596 const std::string* s = 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
Attribute(const char * name,double * d) const611 const char* TiXmlElement::Attribute( const char* name, double* d ) const
612 {
613 const char* s = 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
Attribute(const std::string & name,double * d) const628 const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const
629 {
630 const std::string* s = 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
QueryIntAttribute(const char * name,int * ival) const645 int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
646 {
647 const TiXmlAttribute* node = attributeSet.Find( name );
648 if ( !node )
649 return TIXML_NO_ATTRIBUTE;
650 return node->QueryIntValue( ival );
651 }
652
653
654 #ifdef TIXML_USE_STL
QueryIntAttribute(const std::string & name,int * ival) const655 int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const
656 {
657 const TiXmlAttribute* node = attributeSet.Find( name );
658 if ( !node )
659 return TIXML_NO_ATTRIBUTE;
660 return node->QueryIntValue( ival );
661 }
662 #endif
663
664
QueryDoubleAttribute(const char * name,double * dval) const665 int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
666 {
667 const TiXmlAttribute* node = attributeSet.Find( name );
668 if ( !node )
669 return TIXML_NO_ATTRIBUTE;
670 return node->QueryDoubleValue( dval );
671 }
672
673
674 #ifdef TIXML_USE_STL
QueryDoubleAttribute(const std::string & name,double * dval) const675 int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const
676 {
677 const TiXmlAttribute* node = attributeSet.Find( name );
678 if ( !node )
679 return TIXML_NO_ATTRIBUTE;
680 return node->QueryDoubleValue( dval );
681 }
682 #endif
683
684
SetAttribute(const char * name,int val)685 void TiXmlElement::SetAttribute( 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 SetAttribute( name, buf );
694 }
695
696
697 #ifdef TIXML_USE_STL
SetAttribute(const std::string & name,int val)698 void TiXmlElement::SetAttribute( const std::string& name, int val )
699 {
700 std::ostringstream oss;
701 oss << val;
702 SetAttribute( name, oss.str() );
703 }
704 #endif
705
706
SetDoubleAttribute(const char * name,double val)707 void TiXmlElement::SetDoubleAttribute( 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 SetAttribute( name, buf );
716 }
717
718
SetAttribute(const char * cname,const char * cvalue)719 void TiXmlElement::SetAttribute( 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 TiXmlAttribute* node = attributeSet.Find( _name );
730 if ( node )
731 {
732 node->SetValue( _value );
733 return;
734 }
735
736 TiXmlAttribute* attrib = new (std::nothrow) TiXmlAttribute( cname, cvalue );
737 if ( attrib )
738 {
739 attributeSet.Add( attrib );
740 }
741 else
742 {
743 TiXmlDocument* document = GetDocument();
744 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
745 }
746 }
747
748
749 #ifdef TIXML_USE_STL
SetAttribute(const std::string & name,const std::string & _value)750 void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
751 {
752 TiXmlAttribute* node = attributeSet.Find( name );
753 if ( node )
754 {
755 node->SetValue( _value );
756 return;
757 }
758
759 TiXmlAttribute* attrib = new (std::nothrow) TiXmlAttribute( name, _value );
760 if ( attrib )
761 {
762 attributeSet.Add( attrib );
763 }
764 else
765 {
766 TiXmlDocument* document = GetDocument();
767 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
768 }
769 }
770 #endif
771
772
Print(FILE * cfile,int depth) const773 void TiXmlElement::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 TiXmlAttribute* 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 TiXmlNode* node;
795 if ( !firstChild )
796 {
797 fprintf( cfile, " />" );
798 }
799 else if ( firstChild == lastChild && firstChild->ToText() )
800 {
801 fprintf( cfile, ">" );
802 firstChild->Print( cfile, depth + 1 );
803 fprintf( cfile, "</%s>", value.c_str() );
804 }
805 else
806 {
807 fprintf( cfile, ">" );
808
809 for ( node = firstChild; node; node=node->NextSibling() )
810 {
811 if ( !node->ToText() )
812 {
813 fprintf( cfile, "\n" );
814 }
815 node->Print( cfile, depth+1 );
816 }
817 fprintf( cfile, "\n" );
818 for( i=0; i<depth; ++i ) {
819 fprintf( cfile, " " );
820 }
821 fprintf( cfile, "</%s>", value.c_str() );
822 }
823 }
824
825
CopyTo(TiXmlElement * target) const826 void TiXmlElement::CopyTo( TiXmlElement* target ) const
827 {
828 // superclass:
829 TiXmlNode::CopyTo( target );
830
831 // Element class:
832 // Clone the attributes, then clone the children.
833 const TiXmlAttribute* attribute = 0;
834 for( attribute = attributeSet.First();
835 attribute;
836 attribute = attribute->Next() )
837 {
838 target->SetAttribute( attribute->Name(), attribute->Value() );
839 }
840
841 TiXmlNode* node = 0;
842 for ( node = firstChild; node; node = node->NextSibling() )
843 {
844 target->LinkEndChild( node->Clone() );
845 }
846 }
847
Accept(TiXmlVisitor * visitor) const848 bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const
849 {
850 if ( visitor->VisitEnter( *this, attributeSet.First() ) )
851 {
852 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
853 {
854 if ( !node->Accept( visitor ) )
855 break;
856 }
857 }
858 return visitor->VisitExit( *this );
859 }
860
861
Clone() const862 TiXmlNode* TiXmlElement::Clone() const
863 {
864 TiXmlElement* clone = new (std::nothrow) TiXmlElement( Value() );
865 if ( !clone )
866 return 0;
867
868 CopyTo( clone );
869 return clone;
870 }
871
872
GetText() const873 const char* TiXmlElement::GetText() const
874 {
875 const TiXmlNode* child = this->FirstChild();
876 if ( child ) {
877 const TiXmlText* childText = child->ToText();
878 if ( childText ) {
879 return childText->Value();
880 }
881 }
882 return 0;
883 }
884
885
TiXmlDocument()886 TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
887 {
888 tabsize = 4;
889 useMicrosoftBOM = false;
890 ClearError();
891 }
892
TiXmlDocument(const char * documentName)893 TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
894 {
895 tabsize = 4;
896 useMicrosoftBOM = false;
897 value = documentName;
898 ClearError();
899 }
900
901
902 #ifdef TIXML_USE_STL
TiXmlDocument(const std::string & documentName)903 TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
904 {
905 tabsize = 4;
906 useMicrosoftBOM = false;
907 value = documentName;
908 ClearError();
909 }
910 #endif
911
912
TiXmlDocument(const TiXmlDocument & copy)913 TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
914 {
915 copy.CopyTo( this );
916 }
917
918
operator =(const TiXmlDocument & copy)919 void TiXmlDocument::operator=( const TiXmlDocument& copy )
920 {
921 Clear();
922 copy.CopyTo( this );
923 }
924
925
LoadFile(TiXmlEncoding encoding)926 bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
927 {
928 // See STL_STRING_BUG below.
929 //StringToBuffer buf( value );
930
931 return LoadFile( Value(), encoding );
932 }
933
934
SaveFile() const935 bool TiXmlDocument::SaveFile() const
936 {
937 // See STL_STRING_BUG below.
938 // StringToBuffer buf( value );
939 //
940 // if ( buf.buffer && SaveFile( buf.buffer ) )
941 // return true;
942 //
943 // return false;
944 return SaveFile( Value() );
945 }
946
LoadFile(const char * _filename,TiXmlEncoding encoding)947 bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
948 {
949 // There was a really terrifying little bug here. The code:
950 // value = filename
951 // in the STL case, cause the assignment method of the std::string to
952 // be called. What is strange, is that the std::string had the same
953 // address as its c_str() method, and so bad things happen. Looks
954 // like a bug in the Microsoft STL implementation.
955 // Add an extra string to avoid the crash.
956 TIXML_STRING filename( _filename );
957 value = filename;
958
959 // reading in binary mode so that tinyxml can normalize the EOL
960 FILE* file = TiXmlFOpen( value.c_str (), "rb" );
961
962 if ( file )
963 {
964 bool result = LoadFile( file, encoding );
965 fclose( file );
966 return result;
967 }
968 else
969 {
970 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
971 return false;
972 }
973 }
974
LoadFile(FILE * file,TiXmlEncoding encoding)975 bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
976 {
977 if ( !file )
978 {
979 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
980 return false;
981 }
982
983 // Delete the existing data:
984 Clear();
985 location.Clear();
986
987 // Get the file size, so we can pre-allocate the string. HUGE speed impact.
988 long length = 0;
989 fseek( file, 0, SEEK_END );
990 length = ftell( file );
991 fseek( file, 0, SEEK_SET );
992
993 // Strange case, but good to handle up front.
994 if ( length <= 0 )
995 {
996 SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
997 return false;
998 }
999
1000 // If we have a file, assume it is all one big XML file, and read it in.
1001 // The document parser may decide the document ends sooner than the entire file, however.
1002 TIXML_STRING data;
1003 data.reserve( length );
1004
1005 // Subtle bug here. TinyXml did use fgets. But from the XML spec:
1006 // 2.11 End-of-Line Handling
1007 // <snip>
1008 // <quote>
1009 // ...the XML processor MUST behave as if it normalized all line breaks in external
1010 // parsed entities (including the document entity) on input, before parsing, by translating
1011 // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1012 // a single #xA character.
1013 // </quote>
1014 //
1015 // It is not clear fgets does that, and certainly isn't clear it works cross platform.
1016 // Generally, you expect fgets to translate from the convention of the OS to the c/unix
1017 // convention, and not work generally.
1018
1019 /*
1020 while( fgets( buf, sizeof(buf), file ) )
1021 {
1022 data += buf;
1023 }
1024 */
1025
1026 char* buf = new char[ length+1 ];
1027 buf[0] = 0;
1028
1029 if ( fread( buf, length, 1, file ) != 1 ) {
1030 delete [] buf;
1031 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1032 return false;
1033 }
1034
1035 const char* lastPos = buf;
1036 const char* p = buf;
1037
1038 buf[length] = 0;
1039 while( *p ) {
1040 assert( p < (buf+length) );
1041 if ( *p == 0xa ) {
1042 // Newline character. No special rules for this. Append all the characters
1043 // since the last string, and include the newline.
1044 data.append( lastPos, (p-lastPos+1) ); // append, include the newline
1045 ++p; // move past the newline
1046 lastPos = p; // and point to the new buffer (may be 0)
1047 assert( p <= (buf+length) );
1048 }
1049 else if ( *p == 0xd ) {
1050 // Carriage return. Append what we have so far, then
1051 // handle moving forward in the buffer.
1052 if ( (p-lastPos) > 0 ) {
1053 data.append( lastPos, p-lastPos ); // do not add the CR
1054 }
1055 data += (char)0xa; // a proper newline
1056
1057 if ( *(p+1) == 0xa ) {
1058 // Carriage return - new line sequence
1059 p += 2;
1060 lastPos = p;
1061 assert( p <= (buf+length) );
1062 }
1063 else {
1064 // it was followed by something else...that is presumably characters again.
1065 ++p;
1066 lastPos = p;
1067 assert( p <= (buf+length) );
1068 }
1069 }
1070 else {
1071 ++p;
1072 }
1073 }
1074 // Handle any left over characters.
1075 if ( p-lastPos ) {
1076 data.append( lastPos, p-lastPos );
1077 }
1078 delete [] buf;
1079 buf = 0;
1080
1081 Parse( data.c_str(), 0, encoding );
1082
1083 if ( Error() )
1084 return false;
1085 else
1086 return true;
1087 }
1088
1089
SaveFile(const char * filename) const1090 bool TiXmlDocument::SaveFile( const char * filename ) const
1091 {
1092 // The old c stuff lives on...
1093 FILE* fp = TiXmlFOpen( filename, "w" );
1094 if ( fp )
1095 {
1096 bool result = SaveFile( fp );
1097 fclose( fp );
1098 return result;
1099 }
1100 return false;
1101 }
1102
1103
SaveFile(FILE * fp) const1104 bool TiXmlDocument::SaveFile( FILE* fp ) const
1105 {
1106 if ( useMicrosoftBOM )
1107 {
1108 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1109 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1110 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1111
1112 fputc( TIXML_UTF_LEAD_0, fp );
1113 fputc( TIXML_UTF_LEAD_1, fp );
1114 fputc( TIXML_UTF_LEAD_2, fp );
1115 }
1116 Print( fp, 0 );
1117 return (ferror(fp) == 0);
1118 }
1119
1120
CopyTo(TiXmlDocument * target) const1121 void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1122 {
1123 TiXmlNode::CopyTo( target );
1124
1125 target->error = error;
1126 target->errorId = errorId;
1127 target->errorDesc = errorDesc;
1128 target->tabsize = tabsize;
1129 target->errorLocation = errorLocation;
1130 target->useMicrosoftBOM = useMicrosoftBOM;
1131
1132 TiXmlNode* node = 0;
1133 for ( node = firstChild; node; node = node->NextSibling() )
1134 {
1135 TiXmlNode* clonedNode=node->Clone();
1136 if (clonedNode!=NULL) target->LinkEndChild( clonedNode );
1137 }
1138 }
1139
1140
Clone() const1141 TiXmlNode* TiXmlDocument::Clone() const
1142 {
1143 TiXmlDocument* clone = new (std::nothrow) TiXmlDocument();
1144 if ( !clone )
1145 return 0;
1146
1147 CopyTo( clone );
1148 return clone;
1149 }
1150
1151
Print(FILE * cfile,int depth) const1152 void TiXmlDocument::Print( FILE* cfile, int depth ) const
1153 {
1154 assert( cfile );
1155 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1156 {
1157 node->Print( cfile, depth );
1158 fprintf( cfile, "\n" );
1159 }
1160 }
1161
1162
Accept(TiXmlVisitor * visitor) const1163 bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const
1164 {
1165 if ( visitor->VisitEnter( *this ) )
1166 {
1167 for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() )
1168 {
1169 if ( !node->Accept( visitor ) )
1170 break;
1171 }
1172 }
1173 return visitor->VisitExit( *this );
1174 }
1175
1176
Next() const1177 const TiXmlAttribute* TiXmlAttribute::Next() const
1178 {
1179 // We are using knowledge of the sentinel. The sentinel
1180 // have a value or name.
1181 if ( next->value.empty() && next->name.empty() )
1182 return 0;
1183 return next;
1184 }
1185
1186 /*
1187 TiXmlAttribute* TiXmlAttribute::Next()
1188 {
1189 // We are using knowledge of the sentinel. The sentinel
1190 // have a value or name.
1191 if ( next->value.empty() && next->name.empty() )
1192 return 0;
1193 return next;
1194 }
1195 */
1196
Previous() const1197 const TiXmlAttribute* TiXmlAttribute::Previous() const
1198 {
1199 // We are using knowledge of the sentinel. The sentinel
1200 // have a value or name.
1201 if ( prev->value.empty() && prev->name.empty() )
1202 return 0;
1203 return prev;
1204 }
1205
1206 /*
1207 TiXmlAttribute* TiXmlAttribute::Previous()
1208 {
1209 // We are using knowledge of the sentinel. The sentinel
1210 // have a value or name.
1211 if ( prev->value.empty() && prev->name.empty() )
1212 return 0;
1213 return prev;
1214 }
1215 */
1216
Print(FILE * cfile,int,TIXML_STRING * str) const1217 void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1218 {
1219 TIXML_STRING n, v;
1220
1221 EncodeString( name, &n );
1222 EncodeString( value, &v );
1223
1224 if (value.find ('\"') == TIXML_STRING::npos) {
1225 if ( cfile ) {
1226 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1227 }
1228 if ( str ) {
1229 (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
1230 }
1231 }
1232 else {
1233 if ( cfile ) {
1234 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
1235 }
1236 if ( str ) {
1237 (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
1238 }
1239 }
1240 }
1241
1242
QueryIntValue(int * ival) const1243 int TiXmlAttribute::QueryIntValue( int* ival ) const
1244 {
1245 if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 )
1246 return TIXML_SUCCESS;
1247 return TIXML_WRONG_TYPE;
1248 }
1249
QueryDoubleValue(double * dval) const1250 int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1251 {
1252 if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 )
1253 return TIXML_SUCCESS;
1254 return TIXML_WRONG_TYPE;
1255 }
1256
SetIntValue(int _value)1257 void TiXmlAttribute::SetIntValue( int _value )
1258 {
1259 char buf [64];
1260 #if defined(TIXML_SNPRINTF)
1261 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1262 #else
1263 sprintf (buf, "%d", _value);
1264 #endif
1265 SetValue (buf);
1266 }
1267
SetDoubleValue(double _value)1268 void TiXmlAttribute::SetDoubleValue( double _value )
1269 {
1270 char buf [256];
1271 #if defined(TIXML_SNPRINTF)
1272 TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
1273 #else
1274 sprintf (buf, "%lf", _value);
1275 #endif
1276 SetValue (buf);
1277 }
1278
IntValue() const1279 int TiXmlAttribute::IntValue() const
1280 {
1281 return atoi (value.c_str ());
1282 }
1283
DoubleValue() const1284 double TiXmlAttribute::DoubleValue() const
1285 {
1286 return atof (value.c_str ());
1287 }
1288
1289
TiXmlComment(const TiXmlComment & copy)1290 TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
1291 {
1292 copy.CopyTo( this );
1293 }
1294
1295
operator =(const TiXmlComment & base)1296 void TiXmlComment::operator=( const TiXmlComment& base )
1297 {
1298 Clear();
1299 base.CopyTo( this );
1300 }
1301
1302
Print(FILE * cfile,int depth) const1303 void TiXmlComment::Print( FILE* cfile, int depth ) const
1304 {
1305 assert( cfile );
1306 for ( int i=0; i<depth; i++ )
1307 {
1308 fprintf( cfile, " " );
1309 }
1310 fprintf( cfile, "<!--%s-->", value.c_str() );
1311 }
1312
1313
CopyTo(TiXmlComment * target) const1314 void TiXmlComment::CopyTo( TiXmlComment* target ) const
1315 {
1316 TiXmlNode::CopyTo( target );
1317 }
1318
1319
Accept(TiXmlVisitor * visitor) const1320 bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const
1321 {
1322 return visitor->Visit( *this );
1323 }
1324
1325
Clone() const1326 TiXmlNode* TiXmlComment::Clone() const
1327 {
1328 TiXmlComment* clone = new (std::nothrow) TiXmlComment();
1329
1330 if ( !clone )
1331 return 0;
1332
1333 CopyTo( clone );
1334 return clone;
1335 }
1336
1337
Print(FILE * cfile,int depth) const1338 void TiXmlText::Print( FILE* cfile, int depth ) const
1339 {
1340 assert( cfile );
1341 if ( cdata )
1342 {
1343 int i;
1344 fprintf( cfile, "\n" );
1345 for ( i=0; i<depth; i++ ) {
1346 fprintf( cfile, " " );
1347 }
1348 fprintf( cfile, "<![CDATA[%s]]>\n", value.c_str() ); // unformatted output
1349 }
1350 else
1351 {
1352 TIXML_STRING buffer;
1353 EncodeString( value, &buffer );
1354 fprintf( cfile, "%s", buffer.c_str() );
1355 }
1356 }
1357
1358
CopyTo(TiXmlText * target) const1359 void TiXmlText::CopyTo( TiXmlText* target ) const
1360 {
1361 TiXmlNode::CopyTo( target );
1362 target->cdata = cdata;
1363 }
1364
1365
Accept(TiXmlVisitor * visitor) const1366 bool TiXmlText::Accept( TiXmlVisitor* visitor ) const
1367 {
1368 return visitor->Visit( *this );
1369 }
1370
1371
Clone() const1372 TiXmlNode* TiXmlText::Clone() const
1373 {
1374 TiXmlText* clone = 0;
1375 clone = new (std::nothrow) TiXmlText( "" );
1376
1377 if ( !clone )
1378 return 0;
1379
1380 CopyTo( clone );
1381 return clone;
1382 }
1383
1384
TiXmlDeclaration(const char * _version,const char * _encoding,const char * _standalone)1385 TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1386 const char * _encoding,
1387 const char * _standalone )
1388 : TiXmlNode( TiXmlNode::DECLARATION )
1389 {
1390 version = _version;
1391 encoding = _encoding;
1392 standalone = _standalone;
1393 }
1394
1395
1396 #ifdef TIXML_USE_STL
TiXmlDeclaration(const std::string & _version,const std::string & _encoding,const std::string & _standalone)1397 TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1398 const std::string& _encoding,
1399 const std::string& _standalone )
1400 : TiXmlNode( TiXmlNode::DECLARATION )
1401 {
1402 version = _version;
1403 encoding = _encoding;
1404 standalone = _standalone;
1405 }
1406 #endif
1407
1408
TiXmlDeclaration(const TiXmlDeclaration & copy)1409 TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
1410 : TiXmlNode( TiXmlNode::DECLARATION )
1411 {
1412 copy.CopyTo( this );
1413 }
1414
1415
operator =(const TiXmlDeclaration & copy)1416 void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
1417 {
1418 Clear();
1419 copy.CopyTo( this );
1420 }
1421
1422
Print(FILE * cfile,int,TIXML_STRING * str) const1423 void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
1424 {
1425 if ( cfile ) fprintf( cfile, "<?xml " );
1426 if ( str ) (*str) += "<?xml ";
1427
1428 if ( !version.empty() ) {
1429 if ( cfile ) fprintf (cfile, "version=\"%s\" ", version.c_str ());
1430 if ( str ) { (*str) += "version=\""; (*str) += version; (*str) += "\" "; }
1431 }
1432 if ( !encoding.empty() ) {
1433 if ( cfile ) fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1434 if ( str ) { (*str) += "encoding=\""; (*str) += encoding; (*str) += "\" "; }
1435 }
1436 if ( !standalone.empty() ) {
1437 if ( cfile ) fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1438 if ( str ) { (*str) += "standalone=\""; (*str) += standalone; (*str) += "\" "; }
1439 }
1440 if ( cfile ) fprintf( cfile, "?>" );
1441 if ( str ) (*str) += "?>";
1442 }
1443
1444
CopyTo(TiXmlDeclaration * target) const1445 void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1446 {
1447 TiXmlNode::CopyTo( target );
1448
1449 target->version = version;
1450 target->encoding = encoding;
1451 target->standalone = standalone;
1452 }
1453
1454
Accept(TiXmlVisitor * visitor) const1455 bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const
1456 {
1457 return visitor->Visit( *this );
1458 }
1459
1460
Clone() const1461 TiXmlNode* TiXmlDeclaration::Clone() const
1462 {
1463 TiXmlDeclaration* clone = new (std::nothrow) TiXmlDeclaration();
1464
1465 if ( !clone )
1466 return 0;
1467
1468 CopyTo( clone );
1469 return clone;
1470 }
1471
1472
Print(FILE * cfile,int depth) const1473 void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1474 {
1475 for ( int i=0; i<depth; i++ )
1476 fprintf( cfile, " " );
1477 fprintf( cfile, "<%s>", value.c_str() );
1478 }
1479
1480
CopyTo(TiXmlUnknown * target) const1481 void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
1482 {
1483 TiXmlNode::CopyTo( target );
1484 }
1485
1486
Accept(TiXmlVisitor * visitor) const1487 bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const
1488 {
1489 return visitor->Visit( *this );
1490 }
1491
1492
Clone() const1493 TiXmlNode* TiXmlUnknown::Clone() const
1494 {
1495 TiXmlUnknown* clone = new (std::nothrow) TiXmlUnknown();
1496
1497 if ( !clone )
1498 return 0;
1499
1500 CopyTo( clone );
1501 return clone;
1502 }
1503
1504
TiXmlAttributeSet()1505 TiXmlAttributeSet::TiXmlAttributeSet()
1506 {
1507 sentinel.next = &sentinel;
1508 sentinel.prev = &sentinel;
1509 }
1510
1511
~TiXmlAttributeSet()1512 TiXmlAttributeSet::~TiXmlAttributeSet()
1513 {
1514 assert( sentinel.next == &sentinel );
1515 assert( sentinel.prev == &sentinel );
1516 }
1517
1518
Add(TiXmlAttribute * addMe)1519 void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1520 {
1521 #ifdef TIXML_USE_STL
1522 assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set.
1523 #else
1524 assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1525 #endif
1526
1527 addMe->next = &sentinel;
1528 addMe->prev = sentinel.prev;
1529
1530 sentinel.prev->next = addMe;
1531 sentinel.prev = addMe;
1532 }
1533
Remove(TiXmlAttribute * removeMe)1534 void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1535 {
1536 TiXmlAttribute* node;
1537
1538 for( node = sentinel.next; node != &sentinel; node = node->next )
1539 {
1540 if ( node == removeMe )
1541 {
1542 node->prev->next = node->next;
1543 node->next->prev = node->prev;
1544 node->next = 0;
1545 node->prev = 0;
1546 return;
1547 }
1548 }
1549 assert( 0 ); // we tried to remove a non-linked attribute.
1550 }
1551
1552
1553 #ifdef TIXML_USE_STL
Find(const std::string & name) const1554 const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
1555 {
1556 for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1557 {
1558 if ( node->name == name )
1559 return node;
1560 }
1561 return 0;
1562 }
1563
1564 /*
1565 TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name )
1566 {
1567 for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1568 {
1569 if ( node->name == name )
1570 return node;
1571 }
1572 return 0;
1573 }
1574 */
1575 #endif
1576
1577
Find(const char * name) const1578 const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const
1579 {
1580 for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1581 {
1582 if ( strcmp( node->name.c_str(), name ) == 0 )
1583 return node;
1584 }
1585 return 0;
1586 }
1587
1588 /*
1589 TiXmlAttribute* TiXmlAttributeSet::Find( const char* name )
1590 {
1591 for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next )
1592 {
1593 if ( strcmp( node->name.c_str(), name ) == 0 )
1594 return node;
1595 }
1596 return 0;
1597 }
1598 */
1599
1600 #ifdef TIXML_USE_STL
operator >>(std::istream & in,TiXmlNode & base)1601 std::istream& operator>> (std::istream & in, TiXmlNode & base)
1602 {
1603 TIXML_STRING tag;
1604 tag.reserve( 8 * 1000 );
1605 base.StreamIn( &in, &tag );
1606
1607 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1608 return in;
1609 }
1610 #endif
1611
1612
1613 #ifdef TIXML_USE_STL
operator <<(std::ostream & out,const TiXmlNode & base)1614 std::ostream& operator<< (std::ostream & out, const TiXmlNode & base)
1615 {
1616 TiXmlPrinter printer;
1617 printer.SetStreamPrinting();
1618 base.Accept( &printer );
1619 out << printer.Str();
1620
1621 return out;
1622 }
1623
1624
operator <<(std::string & out,const TiXmlNode & base)1625 std::string& operator<< (std::string& out, const TiXmlNode& base )
1626 {
1627 TiXmlPrinter printer;
1628 printer.SetStreamPrinting();
1629 base.Accept( &printer );
1630 out.append( printer.Str() );
1631
1632 return out;
1633 }
1634 #endif
1635
1636
FirstChild() const1637 TiXmlHandle TiXmlHandle::FirstChild() const
1638 {
1639 if ( node )
1640 {
1641 TiXmlNode* child = node->FirstChild();
1642 if ( child )
1643 return TiXmlHandle( child );
1644 }
1645 return TiXmlHandle( 0 );
1646 }
1647
1648
FirstChild(const char * value) const1649 TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1650 {
1651 if ( node )
1652 {
1653 TiXmlNode* child = node->FirstChild( value );
1654 if ( child )
1655 return TiXmlHandle( child );
1656 }
1657 return TiXmlHandle( 0 );
1658 }
1659
1660
FirstChildElement() const1661 TiXmlHandle TiXmlHandle::FirstChildElement() const
1662 {
1663 if ( node )
1664 {
1665 TiXmlElement* child = node->FirstChildElement();
1666 if ( child )
1667 return TiXmlHandle( child );
1668 }
1669 return TiXmlHandle( 0 );
1670 }
1671
1672
FirstChildElement(const char * value) const1673 TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1674 {
1675 if ( node )
1676 {
1677 TiXmlElement* child = node->FirstChildElement( value );
1678 if ( child )
1679 return TiXmlHandle( child );
1680 }
1681 return TiXmlHandle( 0 );
1682 }
1683
1684
Child(int count) const1685 TiXmlHandle TiXmlHandle::Child( int count ) const
1686 {
1687 if ( node )
1688 {
1689 int i;
1690 TiXmlNode* child = node->FirstChild();
1691 for ( i=0;
1692 child && i<count;
1693 child = child->NextSibling(), ++i )
1694 {
1695 // nothing
1696 }
1697 if ( child )
1698 return TiXmlHandle( child );
1699 }
1700 return TiXmlHandle( 0 );
1701 }
1702
1703
Child(const char * value,int count) const1704 TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1705 {
1706 if ( node )
1707 {
1708 int i;
1709 TiXmlNode* child = node->FirstChild( value );
1710 for ( i=0;
1711 child && i<count;
1712 child = child->NextSibling( value ), ++i )
1713 {
1714 // nothing
1715 }
1716 if ( child )
1717 return TiXmlHandle( child );
1718 }
1719 return TiXmlHandle( 0 );
1720 }
1721
1722
ChildElement(int count) const1723 TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1724 {
1725 if ( node )
1726 {
1727 int i;
1728 TiXmlElement* child = node->FirstChildElement();
1729 for ( i=0;
1730 child && i<count;
1731 child = child->NextSiblingElement(), ++i )
1732 {
1733 // nothing
1734 }
1735 if ( child )
1736 return TiXmlHandle( child );
1737 }
1738 return TiXmlHandle( 0 );
1739 }
1740
1741
ChildElement(const char * value,int count) const1742 TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1743 {
1744 if ( node )
1745 {
1746 int i;
1747 TiXmlElement* child = node->FirstChildElement( value );
1748 for ( i=0;
1749 child && i<count;
1750 child = child->NextSiblingElement( value ), ++i )
1751 {
1752 // nothing
1753 }
1754 if ( child )
1755 return TiXmlHandle( child );
1756 }
1757 return TiXmlHandle( 0 );
1758 }
1759
1760
VisitEnter(const TiXmlDocument &)1761 bool TiXmlPrinter::VisitEnter( const TiXmlDocument& )
1762 {
1763 return true;
1764 }
1765
VisitExit(const TiXmlDocument &)1766 bool TiXmlPrinter::VisitExit( const TiXmlDocument& )
1767 {
1768 return true;
1769 }
1770
VisitEnter(const TiXmlElement & element,const TiXmlAttribute * firstAttribute)1771 bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute )
1772 {
1773 DoIndent();
1774 buffer += "<";
1775 buffer += element.Value();
1776
1777 for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() )
1778 {
1779 buffer += " ";
1780 attrib->Print( 0, 0, &buffer );
1781 }
1782
1783 if ( !element.FirstChild() )
1784 {
1785 buffer += " />";
1786 DoLineBreak();
1787 }
1788 else
1789 {
1790 buffer += ">";
1791 if ( element.FirstChild()->ToText()
1792 && element.LastChild() == element.FirstChild()
1793 && element.FirstChild()->ToText()->CDATA() == false )
1794 {
1795 simpleTextPrint = true;
1796 // no DoLineBreak()!
1797 }
1798 else
1799 {
1800 DoLineBreak();
1801 }
1802 }
1803 ++depth;
1804 return true;
1805 }
1806
1807
VisitExit(const TiXmlElement & element)1808 bool TiXmlPrinter::VisitExit( const TiXmlElement& element )
1809 {
1810 --depth;
1811 if ( !element.FirstChild() )
1812 {
1813 // nothing.
1814 }
1815 else
1816 {
1817 if ( simpleTextPrint )
1818 {
1819 simpleTextPrint = false;
1820 }
1821 else
1822 {
1823 DoIndent();
1824 }
1825 buffer += "</";
1826 buffer += element.Value();
1827 buffer += ">";
1828 DoLineBreak();
1829 }
1830 return true;
1831 }
1832
1833
Visit(const TiXmlText & text)1834 bool TiXmlPrinter::Visit( const TiXmlText& text )
1835 {
1836 if ( text.CDATA() )
1837 {
1838 DoIndent();
1839 buffer += "<![CDATA[";
1840 buffer += text.Value();
1841 buffer += "]]>";
1842 DoLineBreak();
1843 }
1844 else if ( simpleTextPrint )
1845 {
1846 TIXML_STRING str;
1847 TiXmlBase::EncodeString( text.ValueTStr(), &str );
1848 buffer += str;
1849 }
1850 else
1851 {
1852 DoIndent();
1853 TIXML_STRING str;
1854 TiXmlBase::EncodeString( text.ValueTStr(), &str );
1855 buffer += str;
1856 DoLineBreak();
1857 }
1858 return true;
1859 }
1860
1861
Visit(const TiXmlDeclaration & declaration)1862 bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration )
1863 {
1864 DoIndent();
1865 declaration.Print( 0, 0, &buffer );
1866 DoLineBreak();
1867 return true;
1868 }
1869
1870
Visit(const TiXmlComment & comment)1871 bool TiXmlPrinter::Visit( const TiXmlComment& comment )
1872 {
1873 DoIndent();
1874 buffer += "<!--";
1875 buffer += comment.Value();
1876 buffer += "-->";
1877 DoLineBreak();
1878 return true;
1879 }
1880
1881
Visit(const TiXmlUnknown & unknown)1882 bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown )
1883 {
1884 DoIndent();
1885 buffer += "<";
1886 buffer += unknown.Value();
1887 buffer += ">";
1888 DoLineBreak();
1889 return true;
1890 }
1891
1892