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