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