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