comparison 3rdparty/tinyxml/tinyxml.cpp @ 0:a4671277546c tip

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