blob: 5f84decb66f10d343e7a736c563ea0f9ae5a8b7b [file] [log] [blame]
The Android Open Source Project562be062009-03-03 19:30:48 -08001/*
2www.sourceforge.net/projects/tinyxml
Dan Albert0238a202014-08-22 00:52:41 +00003Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
The Android Open Source Project562be062009-03-03 19:30:48 -08004
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any
7damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any
10purpose, including commercial applications, and to alter it and
11redistribute it freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must
14not claim that you wrote the original software. If you use this
15software in a product, an acknowledgment in the product documentation
16would be appreciated but is not required.
17
182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
24
25#include <ctype.h>
Dan Albert0238a202014-08-22 00:52:41 +000026#include "tinyxml.h"
The Android Open Source Project562be062009-03-03 19:30:48 -080027
28#ifdef TIXML_USE_STL
29#include <sstream>
30#endif
31
32
33bool TiXmlBase::condenseWhiteSpace = true;
34
Dan Albert0238a202014-08-22 00:52:41 +000035void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
The Android Open Source Project562be062009-03-03 19:30:48 -080036{
Dan Albert0238a202014-08-22 00:52:41 +000037 TIXML_STRING buffer;
38 PutString( str, &buffer );
39 (*stream) << buffer;
The Android Open Source Project562be062009-03-03 19:30:48 -080040}
41
Dan Albert0238a202014-08-22 00:52:41 +000042void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
The Android Open Source Project562be062009-03-03 19:30:48 -080043{
44 int i=0;
45
46 while( i<(int)str.length() )
47 {
48 unsigned char c = (unsigned char) str[i];
49
50 if ( c == '&'
51 && i < ( (int)str.length() - 2 )
52 && str[i+1] == '#'
53 && str[i+2] == 'x' )
54 {
55 // Hexadecimal character reference.
56 // Pass through unchanged.
57 // &#xA9; -- copyright symbol, for example.
58 //
59 // The -1 is a bug fix from Rob Laveaux. It keeps
60 // an overflow from happening if there is no ';'.
61 // There are actually 2 ways to exit this loop -
62 // while fails (error case) and break (semicolon found).
63 // However, there is no mechanism (currently) for
64 // this function to return an error.
65 while ( i<(int)str.length()-1 )
66 {
67 outString->append( str.c_str() + i, 1 );
68 ++i;
69 if ( str[i] == ';' )
70 break;
71 }
72 }
73 else if ( c == '&' )
74 {
75 outString->append( entity[0].str, entity[0].strLength );
76 ++i;
77 }
78 else if ( c == '<' )
79 {
80 outString->append( entity[1].str, entity[1].strLength );
81 ++i;
82 }
83 else if ( c == '>' )
84 {
85 outString->append( entity[2].str, entity[2].strLength );
86 ++i;
87 }
88 else if ( c == '\"' )
89 {
90 outString->append( entity[3].str, entity[3].strLength );
91 ++i;
92 }
93 else if ( c == '\'' )
94 {
95 outString->append( entity[4].str, entity[4].strLength );
96 ++i;
97 }
98 else if ( c < 32 )
99 {
100 // Easy pass at non-alpha/numeric/symbol
101 // Below 32 is symbolic.
102 char buf[ 32 ];
103
104 #if defined(TIXML_SNPRINTF)
105 TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
106 #else
107 sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
108 #endif
109
110 //*ME: warning C4267: convert 'size_t' to 'int'
111 //*ME: Int-Cast to make compiler happy ...
112 outString->append( buf, (int)strlen( buf ) );
113 ++i;
114 }
115 else
116 {
117 //char realc = (char) c;
118 //outString->append( &realc, 1 );
119 *outString += (char) c; // somewhat more efficient function call.
120 ++i;
121 }
122 }
123}
124
125
Dan Albert0238a202014-08-22 00:52:41 +0000126// <-- Strange class for a bug fix. Search for STL_STRING_BUG
127TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
128{
129 buffer = new char[ str.length()+1 ];
130 if ( buffer )
131 {
132 strcpy( buffer, str.c_str() );
133 }
134}
135
136
137TiXmlBase::StringToBuffer::~StringToBuffer()
138{
139 delete [] buffer;
140}
141// End strange bug fix. -->
142
143
The Android Open Source Project562be062009-03-03 19:30:48 -0800144TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
145{
146 parent = 0;
147 type = _type;
148 firstChild = 0;
149 lastChild = 0;
150 prev = 0;
151 next = 0;
152}
153
154
155TiXmlNode::~TiXmlNode()
156{
157 TiXmlNode* node = firstChild;
158 TiXmlNode* temp = 0;
159
160 while ( node )
161 {
162 temp = node;
163 node = node->next;
164 delete temp;
165 }
166}
167
168
169void TiXmlNode::CopyTo( TiXmlNode* target ) const
170{
171 target->SetValue (value.c_str() );
172 target->userData = userData;
173}
174
175
176void TiXmlNode::Clear()
177{
178 TiXmlNode* node = firstChild;
179 TiXmlNode* temp = 0;
180
181 while ( node )
182 {
183 temp = node;
184 node = node->next;
185 delete temp;
186 }
187
188 firstChild = 0;
189 lastChild = 0;
190}
191
192
193TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
194{
195 node->parent = this;
196
197 node->prev = lastChild;
198 node->next = 0;
199
200 if ( lastChild )
201 lastChild->next = node;
202 else
203 firstChild = node; // it was an empty list.
204
205 lastChild = node;
206 return node;
207}
208
209
210TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
211{
212 TiXmlNode* node = addThis.Clone();
213 if ( !node )
214 return 0;
215
216 return LinkEndChild( node );
217}
218
219
220TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
221{
Dan Albert0238a202014-08-22 00:52:41 +0000222 if ( !beforeThis || beforeThis->parent != this )
The Android Open Source Project562be062009-03-03 19:30:48 -0800223 return 0;
224
225 TiXmlNode* node = addThis.Clone();
226 if ( !node )
227 return 0;
228 node->parent = this;
229
230 node->next = beforeThis;
231 node->prev = beforeThis->prev;
232 if ( beforeThis->prev )
233 {
234 beforeThis->prev->next = node;
235 }
236 else
237 {
238 assert( firstChild == beforeThis );
239 firstChild = node;
240 }
241 beforeThis->prev = node;
242 return node;
243}
244
245
246TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
247{
Dan Albert0238a202014-08-22 00:52:41 +0000248 if ( !afterThis || afterThis->parent != this )
The Android Open Source Project562be062009-03-03 19:30:48 -0800249 return 0;
250
251 TiXmlNode* node = addThis.Clone();
252 if ( !node )
253 return 0;
254 node->parent = this;
255
256 node->prev = afterThis;
257 node->next = afterThis->next;
258 if ( afterThis->next )
259 {
260 afterThis->next->prev = node;
261 }
262 else
263 {
264 assert( lastChild == afterThis );
265 lastChild = node;
266 }
267 afterThis->next = node;
268 return node;
269}
270
271
272TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
273{
274 if ( replaceThis->parent != this )
275 return 0;
276
277 TiXmlNode* node = withThis.Clone();
278 if ( !node )
279 return 0;
280
281 node->next = replaceThis->next;
282 node->prev = replaceThis->prev;
283
284 if ( replaceThis->next )
285 replaceThis->next->prev = node;
286 else
287 lastChild = node;
288
289 if ( replaceThis->prev )
290 replaceThis->prev->next = node;
291 else
292 firstChild = node;
293
294 delete replaceThis;
295 node->parent = this;
296 return node;
297}
298
299
300bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
301{
302 if ( removeThis->parent != this )
303 {
304 assert( 0 );
305 return false;
306 }
307
308 if ( removeThis->next )
309 removeThis->next->prev = removeThis->prev;
310 else
311 lastChild = removeThis->prev;
312
313 if ( removeThis->prev )
314 removeThis->prev->next = removeThis->next;
315 else
316 firstChild = removeThis->next;
317
318 delete removeThis;
319 return true;
320}
321
322const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
323{
324 const TiXmlNode* node;
325 for ( node = firstChild; node; node = node->next )
326 {
327 if ( strcmp( node->Value(), _value ) == 0 )
328 return node;
329 }
330 return 0;
331}
332
333
Dan Albert0238a202014-08-22 00:52:41 +0000334TiXmlNode* TiXmlNode::FirstChild( const char * _value )
335{
336 TiXmlNode* node;
337 for ( node = firstChild; node; node = node->next )
338 {
339 if ( strcmp( node->Value(), _value ) == 0 )
340 return node;
341 }
342 return 0;
343}
344
345
The Android Open Source Project562be062009-03-03 19:30:48 -0800346const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
347{
348 const TiXmlNode* node;
349 for ( node = lastChild; node; node = node->prev )
350 {
351 if ( strcmp( node->Value(), _value ) == 0 )
352 return node;
353 }
354 return 0;
355}
356
Dan Albert0238a202014-08-22 00:52:41 +0000357TiXmlNode* TiXmlNode::LastChild( const char * _value )
358{
359 TiXmlNode* node;
360 for ( node = lastChild; node; node = node->prev )
361 {
362 if ( strcmp( node->Value(), _value ) == 0 )
363 return node;
364 }
365 return 0;
366}
The Android Open Source Project562be062009-03-03 19:30:48 -0800367
368const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
369{
370 if ( !previous )
371 {
372 return FirstChild();
373 }
374 else
375 {
376 assert( previous->parent == this );
377 return previous->NextSibling();
378 }
379}
380
Dan Albert0238a202014-08-22 00:52:41 +0000381TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
382{
383 if ( !previous )
384 {
385 return FirstChild();
386 }
387 else
388 {
389 assert( previous->parent == this );
390 return previous->NextSibling();
391 }
392}
The Android Open Source Project562be062009-03-03 19:30:48 -0800393
394const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
395{
396 if ( !previous )
397 {
398 return FirstChild( val );
399 }
400 else
401 {
402 assert( previous->parent == this );
403 return previous->NextSibling( val );
404 }
405}
406
Dan Albert0238a202014-08-22 00:52:41 +0000407TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
408{
409 if ( !previous )
410 {
411 return FirstChild( val );
412 }
413 else
414 {
415 assert( previous->parent == this );
416 return previous->NextSibling( val );
417 }
418}
The Android Open Source Project562be062009-03-03 19:30:48 -0800419
420const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const
421{
422 const TiXmlNode* node;
423 for ( node = next; node; node = node->next )
424 {
425 if ( strcmp( node->Value(), _value ) == 0 )
426 return node;
427 }
428 return 0;
429}
430
Dan Albert0238a202014-08-22 00:52:41 +0000431TiXmlNode* TiXmlNode::NextSibling( const char * _value )
432{
433 TiXmlNode* node;
434 for ( node = next; node; node = node->next )
435 {
436 if ( strcmp( node->Value(), _value ) == 0 )
437 return node;
438 }
439 return 0;
440}
The Android Open Source Project562be062009-03-03 19:30:48 -0800441
442const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
443{
444 const TiXmlNode* node;
445 for ( node = prev; node; node = node->prev )
446 {
447 if ( strcmp( node->Value(), _value ) == 0 )
448 return node;
449 }
450 return 0;
451}
452
Dan Albert0238a202014-08-22 00:52:41 +0000453TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
454{
455 TiXmlNode* node;
456 for ( node = prev; node; node = node->prev )
457 {
458 if ( strcmp( node->Value(), _value ) == 0 )
459 return node;
460 }
461 return 0;
462}
The Android Open Source Project562be062009-03-03 19:30:48 -0800463
464void TiXmlElement::RemoveAttribute( const char * name )
465{
466 TiXmlAttribute* node = attributeSet.Find( name );
467 if ( node )
468 {
469 attributeSet.Remove( node );
470 delete node;
471 }
472}
473
474const TiXmlElement* TiXmlNode::FirstChildElement() const
475{
476 const TiXmlNode* node;
477
478 for ( node = FirstChild();
479 node;
480 node = node->NextSibling() )
481 {
482 if ( node->ToElement() )
483 return node->ToElement();
484 }
485 return 0;
486}
487
Dan Albert0238a202014-08-22 00:52:41 +0000488TiXmlElement* TiXmlNode::FirstChildElement()
489{
490 TiXmlNode* node;
491
492 for ( node = FirstChild();
493 node;
494 node = node->NextSibling() )
495 {
496 if ( node->ToElement() )
497 return node->ToElement();
498 }
499 return 0;
500}
The Android Open Source Project562be062009-03-03 19:30:48 -0800501
502const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
503{
504 const TiXmlNode* node;
505
506 for ( node = FirstChild( _value );
507 node;
508 node = node->NextSibling( _value ) )
509 {
510 if ( node->ToElement() )
511 return node->ToElement();
512 }
513 return 0;
514}
515
Dan Albert0238a202014-08-22 00:52:41 +0000516TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
The Android Open Source Project562be062009-03-03 19:30:48 -0800517{
Dan Albert0238a202014-08-22 00:52:41 +0000518 TiXmlNode* node;
The Android Open Source Project562be062009-03-03 19:30:48 -0800519
Dan Albert0238a202014-08-22 00:52:41 +0000520 for ( node = FirstChild( _value );
Dan Albertc3bbea32014-08-21 15:48:37 -0700521 node;
Dan Albert0238a202014-08-22 00:52:41 +0000522 node = node->NextSibling( _value ) )
The Android Open Source Project562be062009-03-03 19:30:48 -0800523 {
524 if ( node->ToElement() )
525 return node->ToElement();
526 }
527 return 0;
528}
529
Dan Albert0238a202014-08-22 00:52:41 +0000530const TiXmlElement* TiXmlNode::NextSiblingElement() const
531{
532 const TiXmlNode* node;
533
534 for ( node = NextSibling();
535 node;
536 node = node->NextSibling() )
537 {
538 if ( node->ToElement() )
539 return node->ToElement();
540 }
541 return 0;
542}
543
544TiXmlElement* TiXmlNode::NextSiblingElement()
545{
546 TiXmlNode* node;
547
548 for ( node = NextSibling();
549 node;
550 node = node->NextSibling() )
551 {
552 if ( node->ToElement() )
553 return node->ToElement();
554 }
555 return 0;
556}
The Android Open Source Project562be062009-03-03 19:30:48 -0800557
558const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
559{
560 const TiXmlNode* node;
561
562 for ( node = NextSibling( _value );
Dan Albert0238a202014-08-22 00:52:41 +0000563 node;
564 node = node->NextSibling( _value ) )
565 {
566 if ( node->ToElement() )
567 return node->ToElement();
568 }
569 return 0;
570}
571
572TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
573{
574 TiXmlNode* node;
575
576 for ( node = NextSibling( _value );
577 node;
578 node = node->NextSibling( _value ) )
The Android Open Source Project562be062009-03-03 19:30:48 -0800579 {
580 if ( node->ToElement() )
581 return node->ToElement();
582 }
583 return 0;
584}
585
586
587const TiXmlDocument* TiXmlNode::GetDocument() const
588{
589 const TiXmlNode* node;
590
591 for( node = this; node; node = node->parent )
592 {
593 if ( node->ToDocument() )
594 return node->ToDocument();
595 }
596 return 0;
597}
598
Dan Albert0238a202014-08-22 00:52:41 +0000599TiXmlDocument* TiXmlNode::GetDocument()
600{
601 TiXmlNode* node;
602
603 for( node = this; node; node = node->parent )
604 {
605 if ( node->ToDocument() )
606 return node->ToDocument();
607 }
608 return 0;
609}
The Android Open Source Project562be062009-03-03 19:30:48 -0800610
611TiXmlElement::TiXmlElement (const char * _value)
Dan Albert0238a202014-08-22 00:52:41 +0000612 : TiXmlNode( TiXmlNode::ELEMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800613{
614 firstChild = lastChild = 0;
615 value = _value;
616}
617
618
619#ifdef TIXML_USE_STL
620TiXmlElement::TiXmlElement( const std::string& _value )
Dan Albert0238a202014-08-22 00:52:41 +0000621 : TiXmlNode( TiXmlNode::ELEMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800622{
623 firstChild = lastChild = 0;
624 value = _value;
625}
626#endif
627
628
629TiXmlElement::TiXmlElement( const TiXmlElement& copy)
Dan Albert0238a202014-08-22 00:52:41 +0000630 : TiXmlNode( TiXmlNode::ELEMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800631{
632 firstChild = lastChild = 0;
633 copy.CopyTo( this );
634}
635
636
Dan Albert0238a202014-08-22 00:52:41 +0000637void TiXmlElement::operator=( const TiXmlElement& base )
The Android Open Source Project562be062009-03-03 19:30:48 -0800638{
639 ClearThis();
640 base.CopyTo( this );
641}
642
643
644TiXmlElement::~TiXmlElement()
645{
646 ClearThis();
647}
648
649
650void TiXmlElement::ClearThis()
651{
652 Clear();
653 while( attributeSet.First() )
654 {
655 TiXmlAttribute* node = attributeSet.First();
656 attributeSet.Remove( node );
657 delete node;
658 }
659}
660
661
Dan Albert0238a202014-08-22 00:52:41 +0000662const char * TiXmlElement::Attribute( const char * name ) const
The Android Open Source Project562be062009-03-03 19:30:48 -0800663{
664 const TiXmlAttribute* node = attributeSet.Find( name );
Dan Albert0238a202014-08-22 00:52:41 +0000665
The Android Open Source Project562be062009-03-03 19:30:48 -0800666 if ( node )
667 return node->Value();
Dan Albert0238a202014-08-22 00:52:41 +0000668
The Android Open Source Project562be062009-03-03 19:30:48 -0800669 return 0;
670}
671
672
Dan Albert0238a202014-08-22 00:52:41 +0000673const char * TiXmlElement::Attribute( const char * name, int* i ) const
The Android Open Source Project562be062009-03-03 19:30:48 -0800674{
Dan Albert0238a202014-08-22 00:52:41 +0000675 const char * s = Attribute( name );
676 if ( i )
677 {
678 if ( s )
679 *i = atoi( s );
680 else
681 *i = 0;
The Android Open Source Project562be062009-03-03 19:30:48 -0800682 }
Dan Albert0238a202014-08-22 00:52:41 +0000683 return s;
The Android Open Source Project562be062009-03-03 19:30:48 -0800684}
685
686
Dan Albert0238a202014-08-22 00:52:41 +0000687const char * TiXmlElement::Attribute( const char * name, double* d ) const
The Android Open Source Project562be062009-03-03 19:30:48 -0800688{
Dan Albert0238a202014-08-22 00:52:41 +0000689 const char * s = Attribute( name );
690 if ( d )
691 {
692 if ( s )
693 *d = atof( s );
694 else
695 *d = 0;
The Android Open Source Project562be062009-03-03 19:30:48 -0800696 }
Dan Albert0238a202014-08-22 00:52:41 +0000697 return s;
The Android Open Source Project562be062009-03-03 19:30:48 -0800698}
699
700
701int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
702{
703 const TiXmlAttribute* node = attributeSet.Find( name );
704 if ( !node )
705 return TIXML_NO_ATTRIBUTE;
706
Dan Albert0238a202014-08-22 00:52:41 +0000707 return node->QueryIntValue( ival );
The Android Open Source Project562be062009-03-03 19:30:48 -0800708}
709
710
711int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
712{
Dan Albert0238a202014-08-22 00:52:41 +0000713 const TiXmlAttribute* node = attributeSet.Find( name );
714 if ( !node )
The Android Open Source Project562be062009-03-03 19:30:48 -0800715 return TIXML_NO_ATTRIBUTE;
The Android Open Source Project562be062009-03-03 19:30:48 -0800716
Dan Albert0238a202014-08-22 00:52:41 +0000717 return node->QueryDoubleValue( dval );
Dan Albertc3bbea32014-08-21 15:48:37 -0700718}
Dan Albertc3bbea32014-08-21 15:48:37 -0700719
720
The Android Open Source Project562be062009-03-03 19:30:48 -0800721void TiXmlElement::SetAttribute( const char * name, int val )
722{
Dan Albert0238a202014-08-22 00:52:41 +0000723 char buf[64];
724 #if defined(TIXML_SNPRINTF)
725 TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
726 #else
727 sprintf( buf, "%d", val );
728 #endif
729 SetAttribute( name, buf );
The Android Open Source Project562be062009-03-03 19:30:48 -0800730}
731
732
733void TiXmlElement::SetDoubleAttribute( const char * name, double val )
734{
Dan Albert0238a202014-08-22 00:52:41 +0000735 char buf[256];
736 #if defined(TIXML_SNPRINTF)
737 TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
738 #else
739 sprintf( buf, "%f", val );
740 #endif
741 SetAttribute( name, buf );
The Android Open Source Project562be062009-03-03 19:30:48 -0800742}
743
744
Dan Albert0238a202014-08-22 00:52:41 +0000745void TiXmlElement::SetAttribute( const char * name, const char * _value )
The Android Open Source Project562be062009-03-03 19:30:48 -0800746{
Dan Albert0238a202014-08-22 00:52:41 +0000747 TiXmlAttribute* node = attributeSet.Find( name );
748 if ( node )
749 {
750 node->SetValue( _value );
751 return;
752 }
753
754 TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
755 if ( attrib )
756 {
757 attributeSet.Add( attrib );
758 }
759 else
760 {
761 TiXmlDocument* document = GetDocument();
762 if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
The Android Open Source Project562be062009-03-03 19:30:48 -0800763 }
764}
765
766void TiXmlElement::Print( FILE* cfile, int depth ) const
767{
768 int i;
Dan Albert0238a202014-08-22 00:52:41 +0000769 for ( i=0; i<depth; i++ )
770 {
The Android Open Source Project562be062009-03-03 19:30:48 -0800771 fprintf( cfile, " " );
772 }
773
774 fprintf( cfile, "<%s", value.c_str() );
775
776 const TiXmlAttribute* attrib;
777 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
778 {
779 fprintf( cfile, " " );
780 attrib->Print( cfile, depth );
781 }
782
783 // There are 3 different formatting approaches:
784 // 1) An element without children is printed as a <foo /> node
785 // 2) An element with only a text child is printed as <foo> text </foo>
786 // 3) An element with children is printed on multiple lines.
787 TiXmlNode* node;
788 if ( !firstChild )
789 {
790 fprintf( cfile, " />" );
791 }
792 else if ( firstChild == lastChild && firstChild->ToText() )
793 {
794 fprintf( cfile, ">" );
795 firstChild->Print( cfile, depth + 1 );
796 fprintf( cfile, "</%s>", value.c_str() );
797 }
798 else
799 {
800 fprintf( cfile, ">" );
801
802 for ( node = firstChild; node; node=node->NextSibling() )
803 {
804 if ( !node->ToText() )
805 {
806 fprintf( cfile, "\n" );
807 }
808 node->Print( cfile, depth+1 );
809 }
810 fprintf( cfile, "\n" );
Dan Albert0238a202014-08-22 00:52:41 +0000811 for( i=0; i<depth; ++i )
812 fprintf( cfile, " " );
Dan Albertc3bbea32014-08-21 15:48:37 -0700813 fprintf( cfile, "</%s>", value.c_str() );
The Android Open Source Project562be062009-03-03 19:30:48 -0800814 }
815}
816
Dan Albert0238a202014-08-22 00:52:41 +0000817void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
818{
819 (*stream) << "<" << value;
820
821 const TiXmlAttribute* attrib;
822 for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
823 {
824 (*stream) << " ";
825 attrib->StreamOut( stream );
826 }
827
828 // If this node has children, give it a closing tag. Else
829 // make it an empty tag.
830 TiXmlNode* node;
831 if ( firstChild )
832 {
833 (*stream) << ">";
834
835 for ( node = firstChild; node; node=node->NextSibling() )
836 {
837 node->StreamOut( stream );
838 }
839 (*stream) << "</" << value << ">";
840 }
841 else
842 {
843 (*stream) << " />";
844 }
845}
846
The Android Open Source Project562be062009-03-03 19:30:48 -0800847
848void TiXmlElement::CopyTo( TiXmlElement* target ) const
849{
850 // superclass:
851 TiXmlNode::CopyTo( target );
852
853 // Element class:
854 // Clone the attributes, then clone the children.
855 const TiXmlAttribute* attribute = 0;
856 for( attribute = attributeSet.First();
857 attribute;
858 attribute = attribute->Next() )
859 {
860 target->SetAttribute( attribute->Name(), attribute->Value() );
861 }
862
863 TiXmlNode* node = 0;
864 for ( node = firstChild; node; node = node->NextSibling() )
865 {
866 target->LinkEndChild( node->Clone() );
867 }
868}
869
870
871TiXmlNode* TiXmlElement::Clone() const
872{
873 TiXmlElement* clone = new TiXmlElement( Value() );
874 if ( !clone )
875 return 0;
876
877 CopyTo( clone );
878 return clone;
879}
880
881
882const char* TiXmlElement::GetText() const
883{
884 const TiXmlNode* child = this->FirstChild();
885 if ( child ) {
886 const TiXmlText* childText = child->ToText();
887 if ( childText ) {
888 return childText->Value();
889 }
890 }
891 return 0;
892}
893
894
Dan Albert0238a202014-08-22 00:52:41 +0000895TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800896{
897 tabsize = 4;
898 useMicrosoftBOM = false;
899 ClearError();
900}
901
Dan Albert0238a202014-08-22 00:52:41 +0000902TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800903{
904 tabsize = 4;
905 useMicrosoftBOM = false;
906 value = documentName;
907 ClearError();
908}
909
910
911#ifdef TIXML_USE_STL
Dan Albert0238a202014-08-22 00:52:41 +0000912TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800913{
914 tabsize = 4;
915 useMicrosoftBOM = false;
916 value = documentName;
917 ClearError();
918}
919#endif
920
921
Dan Albert0238a202014-08-22 00:52:41 +0000922TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -0800923{
924 copy.CopyTo( this );
925}
926
927
Dan Albert0238a202014-08-22 00:52:41 +0000928void TiXmlDocument::operator=( const TiXmlDocument& copy )
The Android Open Source Project562be062009-03-03 19:30:48 -0800929{
930 Clear();
931 copy.CopyTo( this );
932}
933
934
935bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
936{
Dan Albert0238a202014-08-22 00:52:41 +0000937 // See STL_STRING_BUG below.
938 StringToBuffer buf( value );
939
940 if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
941 return true;
942
943 return false;
The Android Open Source Project562be062009-03-03 19:30:48 -0800944}
945
946
947bool TiXmlDocument::SaveFile() const
948{
Dan Albert0238a202014-08-22 00:52:41 +0000949 // See STL_STRING_BUG below.
950 StringToBuffer buf( value );
951
952 if ( buf.buffer && SaveFile( buf.buffer ) )
953 return true;
954
955 return false;
The Android Open Source Project562be062009-03-03 19:30:48 -0800956}
957
Dan Albert0238a202014-08-22 00:52:41 +0000958bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
The Android Open Source Project562be062009-03-03 19:30:48 -0800959{
960 // Delete the existing data:
961 Clear();
962 location.Clear();
963
Dan Albert0238a202014-08-22 00:52:41 +0000964 // There was a really terrifying little bug here. The code:
965 // value = filename
966 // in the STL case, cause the assignment method of the std::string to
967 // be called. What is strange, is that the std::string had the same
968 // address as it's c_str() method, and so bad things happen. Looks
969 // like a bug in the Microsoft STL implementation.
970 // See STL_STRING_BUG above.
971 // Fixed with the StringToBuffer class.
972 value = filename;
The Android Open Source Project562be062009-03-03 19:30:48 -0800973
Dan Albert0238a202014-08-22 00:52:41 +0000974 // reading in binary mode so that tinyxml can normalize the EOL
975 FILE* file = fopen( value.c_str (), "rb" );
976
977 if ( file )
The Android Open Source Project562be062009-03-03 19:30:48 -0800978 {
Dan Albert0238a202014-08-22 00:52:41 +0000979 // Get the file size, so we can pre-allocate the string. HUGE speed impact.
980 long length = 0;
981 fseek( file, 0, SEEK_END );
982 length = ftell( file );
983 fseek( file, 0, SEEK_SET );
Dan Albertc3bbea32014-08-21 15:48:37 -0700984
Dan Albert0238a202014-08-22 00:52:41 +0000985 // Strange case, but good to handle up front.
986 if ( length == 0 )
987 {
988 fclose( file );
989 return false;
990 }
Dan Albertc3bbea32014-08-21 15:48:37 -0700991
Dan Albert0238a202014-08-22 00:52:41 +0000992 // If we have a file, assume it is all one big XML file, and read it in.
993 // The document parser may decide the document ends sooner than the entire file, however.
994 TIXML_STRING data;
995 data.reserve( length );
Dan Albertc3bbea32014-08-21 15:48:37 -0700996
Dan Albert0238a202014-08-22 00:52:41 +0000997 // Subtle bug here. TinyXml did use fgets. But from the XML spec:
998 // 2.11 End-of-Line Handling
999 // <snip>
1000 // <quote>
1001 // ...the XML processor MUST behave as if it normalized all line breaks in external
1002 // parsed entities (including the document entity) on input, before parsing, by translating
1003 // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
1004 // a single #xA character.
1005 // </quote>
1006 //
1007 // It is not clear fgets does that, and certainly isn't clear it works cross platform.
1008 // Generally, you expect fgets to translate from the convention of the OS to the c/unix
1009 // convention, and not work generally.
Dan Albertc3bbea32014-08-21 15:48:37 -07001010
Dan Albert0238a202014-08-22 00:52:41 +00001011 /*
1012 while( fgets( buf, sizeof(buf), file ) )
1013 {
1014 data += buf;
1015 }
1016 */
Dan Albertc3bbea32014-08-21 15:48:37 -07001017
Dan Albert0238a202014-08-22 00:52:41 +00001018 char* buf = new char[ length+1 ];
1019 buf[0] = 0;
Dan Albertc3bbea32014-08-21 15:48:37 -07001020
Dan Albert0238a202014-08-22 00:52:41 +00001021 if ( fread( buf, length, 1, file ) != 1 ) {
1022 //if ( fread( buf, 1, length, file ) != (size_t)length ) {
1023 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1024 fclose( file );
1025 return false;
1026 }
1027 fclose( file );
Dan Albertc3bbea32014-08-21 15:48:37 -07001028
Dan Albert0238a202014-08-22 00:52:41 +00001029 const char* lastPos = buf;
1030 const char* p = buf;
Dan Albertc3bbea32014-08-21 15:48:37 -07001031
Dan Albert0238a202014-08-22 00:52:41 +00001032 buf[length] = 0;
1033 while( *p ) {
1034 assert( p < (buf+length) );
1035 if ( *p == 0xa ) {
1036 // Newline character. No special rules for this. Append all the characters
1037 // since the last string, and include the newline.
1038 data.append( lastPos, p-lastPos+1 ); // append, include the newline
1039 ++p; // move past the newline
1040 lastPos = p; // and point to the new buffer (may be 0)
1041 assert( p <= (buf+length) );
1042 }
1043 else if ( *p == 0xd ) {
1044 // Carriage return. Append what we have so far, then
1045 // handle moving forward in the buffer.
1046 if ( (p-lastPos) > 0 ) {
1047 data.append( lastPos, p-lastPos ); // do not add the CR
1048 }
1049 data += (char)0xa; // a proper newline
1050
1051 if ( *(p+1) == 0xa ) {
1052 // Carriage return - new line sequence
1053 p += 2;
1054 lastPos = p;
1055 assert( p <= (buf+length) );
1056 }
1057 else {
1058 // it was followed by something else...that is presumably characters again.
1059 ++p;
1060 lastPos = p;
1061 assert( p <= (buf+length) );
1062 }
1063 }
1064 else {
1065 ++p;
Dan Albertc3bbea32014-08-21 15:48:37 -07001066 }
1067 }
Dan Albert0238a202014-08-22 00:52:41 +00001068 // Handle any left over characters.
1069 if ( p-lastPos ) {
1070 data.append( lastPos, p-lastPos );
1071 }
1072 delete [] buf;
1073 buf = 0;
1074
1075 Parse( data.c_str(), 0, encoding );
1076
1077 if ( Error() )
1078 return false;
1079 else
1080 return true;
Dan Albertc3bbea32014-08-21 15:48:37 -07001081 }
Dan Albert0238a202014-08-22 00:52:41 +00001082 SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
1083 return false;
The Android Open Source Project562be062009-03-03 19:30:48 -08001084}
1085
1086bool TiXmlDocument::SaveFile( const char * filename ) const
1087{
1088 // The old c stuff lives on...
Dan Albert0238a202014-08-22 00:52:41 +00001089 FILE* fp = fopen( filename, "w" );
The Android Open Source Project562be062009-03-03 19:30:48 -08001090 if ( fp )
1091 {
Dan Albert0238a202014-08-22 00:52:41 +00001092 if ( useMicrosoftBOM )
1093 {
1094 const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
1095 const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
1096 const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
1097
1098 fputc( TIXML_UTF_LEAD_0, fp );
1099 fputc( TIXML_UTF_LEAD_1, fp );
1100 fputc( TIXML_UTF_LEAD_2, fp );
1101 }
1102 Print( fp, 0 );
The Android Open Source Project562be062009-03-03 19:30:48 -08001103 fclose( fp );
Dan Albert0238a202014-08-22 00:52:41 +00001104 return true;
The Android Open Source Project562be062009-03-03 19:30:48 -08001105 }
1106 return false;
1107}
1108
1109
1110void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
1111{
1112 TiXmlNode::CopyTo( target );
1113
1114 target->error = error;
Dan Albert0238a202014-08-22 00:52:41 +00001115 target->errorDesc = errorDesc.c_str ();
The Android Open Source Project562be062009-03-03 19:30:48 -08001116
1117 TiXmlNode* node = 0;
1118 for ( node = firstChild; node; node = node->NextSibling() )
1119 {
1120 target->LinkEndChild( node->Clone() );
1121 }
1122}
1123
1124
1125TiXmlNode* TiXmlDocument::Clone() const
1126{
1127 TiXmlDocument* clone = new TiXmlDocument();
1128 if ( !clone )
1129 return 0;
1130
1131 CopyTo( clone );
1132 return clone;
1133}
1134
1135
1136void TiXmlDocument::Print( FILE* cfile, int depth ) const
1137{
Dan Albert0238a202014-08-22 00:52:41 +00001138 const TiXmlNode* node;
1139 for ( node=FirstChild(); node; node=node->NextSibling() )
The Android Open Source Project562be062009-03-03 19:30:48 -08001140 {
1141 node->Print( cfile, depth );
1142 fprintf( cfile, "\n" );
1143 }
1144}
1145
Dan Albert0238a202014-08-22 00:52:41 +00001146void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
Dan Albertc3bbea32014-08-21 15:48:37 -07001147{
Dan Albert0238a202014-08-22 00:52:41 +00001148 const TiXmlNode* node;
1149 for ( node=FirstChild(); node; node=node->NextSibling() )
Dan Albertc3bbea32014-08-21 15:48:37 -07001150 {
Dan Albert0238a202014-08-22 00:52:41 +00001151 node->StreamOut( out );
1152
1153 // Special rule for streams: stop after the root element.
1154 // The stream in code will only read one element, so don't
1155 // write more than one.
1156 if ( node->ToElement() )
1157 break;
The Android Open Source Project562be062009-03-03 19:30:48 -08001158 }
1159}
1160
1161
1162const TiXmlAttribute* TiXmlAttribute::Next() const
1163{
1164 // We are using knowledge of the sentinel. The sentinel
1165 // have a value or name.
1166 if ( next->value.empty() && next->name.empty() )
1167 return 0;
1168 return next;
1169}
1170
1171TiXmlAttribute* TiXmlAttribute::Next()
1172{
1173 // We are using knowledge of the sentinel. The sentinel
1174 // have a value or name.
1175 if ( next->value.empty() && next->name.empty() )
1176 return 0;
1177 return next;
1178}
1179
1180const TiXmlAttribute* TiXmlAttribute::Previous() const
1181{
1182 // We are using knowledge of the sentinel. The sentinel
1183 // have a value or name.
1184 if ( prev->value.empty() && prev->name.empty() )
1185 return 0;
1186 return prev;
1187}
1188
1189TiXmlAttribute* TiXmlAttribute::Previous()
1190{
1191 // We are using knowledge of the sentinel. The sentinel
1192 // have a value or name.
1193 if ( prev->value.empty() && prev->name.empty() )
1194 return 0;
1195 return prev;
1196}
1197
Dan Albert0238a202014-08-22 00:52:41 +00001198void TiXmlAttribute::Print( FILE* cfile, int /*depth*/ ) const
The Android Open Source Project562be062009-03-03 19:30:48 -08001199{
1200 TIXML_STRING n, v;
1201
Dan Albert0238a202014-08-22 00:52:41 +00001202 PutString( name, &n );
1203 PutString( value, &v );
The Android Open Source Project562be062009-03-03 19:30:48 -08001204
Dan Albert0238a202014-08-22 00:52:41 +00001205 if (value.find ('\"') == TIXML_STRING::npos)
1206 fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
1207 else
1208 fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
The Android Open Source Project562be062009-03-03 19:30:48 -08001209}
1210
Dan Albertc3bbea32014-08-21 15:48:37 -07001211
Dan Albert0238a202014-08-22 00:52:41 +00001212void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
1213{
1214 if (value.find( '\"' ) != TIXML_STRING::npos)
1215 {
1216 PutString( name, stream );
1217 (*stream) << "=" << "'";
1218 PutString( value, stream );
1219 (*stream) << "'";
1220 }
1221 else
1222 {
1223 PutString( name, stream );
1224 (*stream) << "=" << "\"";
1225 PutString( value, stream );
1226 (*stream) << "\"";
1227 }
1228}
1229
The Android Open Source Project562be062009-03-03 19:30:48 -08001230int TiXmlAttribute::QueryIntValue( int* ival ) const
1231{
Dan Albert0238a202014-08-22 00:52:41 +00001232 if ( sscanf( value.c_str(), "%d", ival ) == 1 )
The Android Open Source Project562be062009-03-03 19:30:48 -08001233 return TIXML_SUCCESS;
1234 return TIXML_WRONG_TYPE;
1235}
1236
1237int TiXmlAttribute::QueryDoubleValue( double* dval ) const
1238{
Dan Albert0238a202014-08-22 00:52:41 +00001239 if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
The Android Open Source Project562be062009-03-03 19:30:48 -08001240 return TIXML_SUCCESS;
1241 return TIXML_WRONG_TYPE;
1242}
1243
1244void TiXmlAttribute::SetIntValue( int _value )
1245{
1246 char buf [64];
1247 #if defined(TIXML_SNPRINTF)
1248 TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
1249 #else
1250 sprintf (buf, "%d", _value);
1251 #endif
1252 SetValue (buf);
1253}
1254
1255void TiXmlAttribute::SetDoubleValue( double _value )
1256{
1257 char buf [256];
1258 #if defined(TIXML_SNPRINTF)
Dan Albert0238a202014-08-22 00:52:41 +00001259 TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
The Android Open Source Project562be062009-03-03 19:30:48 -08001260 #else
Dan Albert0238a202014-08-22 00:52:41 +00001261 sprintf (buf, "%lf", _value);
The Android Open Source Project562be062009-03-03 19:30:48 -08001262 #endif
1263 SetValue (buf);
1264}
1265
1266int TiXmlAttribute::IntValue() const
1267{
1268 return atoi (value.c_str ());
1269}
1270
1271double TiXmlAttribute::DoubleValue() const
1272{
1273 return atof (value.c_str ());
1274}
1275
1276
Dan Albert0238a202014-08-22 00:52:41 +00001277TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
The Android Open Source Project562be062009-03-03 19:30:48 -08001278{
1279 copy.CopyTo( this );
1280}
1281
1282
Dan Albert0238a202014-08-22 00:52:41 +00001283void TiXmlComment::operator=( const TiXmlComment& base )
The Android Open Source Project562be062009-03-03 19:30:48 -08001284{
1285 Clear();
1286 base.CopyTo( this );
1287}
1288
1289
1290void TiXmlComment::Print( FILE* cfile, int depth ) const
1291{
1292 for ( int i=0; i<depth; i++ )
1293 {
Dan Albert0238a202014-08-22 00:52:41 +00001294 fputs( " ", cfile );
The Android Open Source Project562be062009-03-03 19:30:48 -08001295 }
1296 fprintf( cfile, "<!--%s-->", value.c_str() );
1297}
1298
Dan Albert0238a202014-08-22 00:52:41 +00001299void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
1300{
1301 (*stream) << "<!--";
1302 //PutString( value, stream );
1303 (*stream) << value;
1304 (*stream) << "-->";
1305}
1306
The Android Open Source Project562be062009-03-03 19:30:48 -08001307
1308void TiXmlComment::CopyTo( TiXmlComment* target ) const
1309{
1310 TiXmlNode::CopyTo( target );
1311}
1312
1313
1314TiXmlNode* TiXmlComment::Clone() const
1315{
1316 TiXmlComment* clone = new TiXmlComment();
1317
1318 if ( !clone )
1319 return 0;
1320
1321 CopyTo( clone );
1322 return clone;
1323}
1324
1325
1326void TiXmlText::Print( FILE* cfile, int depth ) const
1327{
1328 if ( cdata )
1329 {
1330 int i;
1331 fprintf( cfile, "\n" );
1332 for ( i=0; i<depth; i++ ) {
1333 fprintf( cfile, " " );
1334 }
Dan Albert0238a202014-08-22 00:52:41 +00001335 fprintf( cfile, "<![CDATA[\n" );
1336
1337 fprintf( cfile, "%s", value.c_str() ); // unformatted output
1338
1339 fprintf( cfile, "\n" );
1340 for ( i=0; i<depth; i++ ) {
1341 fprintf( cfile, " " );
1342 }
1343 fprintf( cfile, "]]>\n" );
The Android Open Source Project562be062009-03-03 19:30:48 -08001344 }
1345 else
1346 {
1347 TIXML_STRING buffer;
Dan Albert0238a202014-08-22 00:52:41 +00001348 PutString( value, &buffer );
The Android Open Source Project562be062009-03-03 19:30:48 -08001349 fprintf( cfile, "%s", buffer.c_str() );
1350 }
1351}
1352
1353
Dan Albert0238a202014-08-22 00:52:41 +00001354void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
1355{
1356 if ( cdata )
1357 {
1358 (*stream) << "<![CDATA[" << value << "]]>";
1359 }
1360 else
1361 {
1362 PutString( value, stream );
1363 }
1364}
1365
1366
The Android Open Source Project562be062009-03-03 19:30:48 -08001367void TiXmlText::CopyTo( TiXmlText* target ) const
1368{
1369 TiXmlNode::CopyTo( target );
1370 target->cdata = cdata;
1371}
1372
1373
1374TiXmlNode* TiXmlText::Clone() const
1375{
1376 TiXmlText* clone = 0;
1377 clone = new TiXmlText( "" );
1378
1379 if ( !clone )
1380 return 0;
1381
1382 CopyTo( clone );
1383 return clone;
1384}
1385
1386
1387TiXmlDeclaration::TiXmlDeclaration( const char * _version,
1388 const char * _encoding,
1389 const char * _standalone )
Dan Albert0238a202014-08-22 00:52:41 +00001390 : TiXmlNode( TiXmlNode::DECLARATION )
The Android Open Source Project562be062009-03-03 19:30:48 -08001391{
1392 version = _version;
1393 encoding = _encoding;
1394 standalone = _standalone;
1395}
1396
1397
1398#ifdef TIXML_USE_STL
1399TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
1400 const std::string& _encoding,
1401 const std::string& _standalone )
Dan Albert0238a202014-08-22 00:52:41 +00001402 : TiXmlNode( TiXmlNode::DECLARATION )
The Android Open Source Project562be062009-03-03 19:30:48 -08001403{
1404 version = _version;
1405 encoding = _encoding;
1406 standalone = _standalone;
1407}
1408#endif
1409
1410
1411TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
Dan Albert0238a202014-08-22 00:52:41 +00001412 : TiXmlNode( TiXmlNode::DECLARATION )
The Android Open Source Project562be062009-03-03 19:30:48 -08001413{
1414 copy.CopyTo( this );
1415}
1416
1417
Dan Albert0238a202014-08-22 00:52:41 +00001418void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
The Android Open Source Project562be062009-03-03 19:30:48 -08001419{
1420 Clear();
1421 copy.CopyTo( this );
1422}
1423
1424
Dan Albert0238a202014-08-22 00:52:41 +00001425void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ ) const
The Android Open Source Project562be062009-03-03 19:30:48 -08001426{
Dan Albert0238a202014-08-22 00:52:41 +00001427 fprintf (cfile, "<?xml ");
The Android Open Source Project562be062009-03-03 19:30:48 -08001428
Dan Albert0238a202014-08-22 00:52:41 +00001429 if ( !version.empty() )
1430 fprintf (cfile, "version=\"%s\" ", version.c_str ());
1431 if ( !encoding.empty() )
1432 fprintf (cfile, "encoding=\"%s\" ", encoding.c_str ());
1433 if ( !standalone.empty() )
1434 fprintf (cfile, "standalone=\"%s\" ", standalone.c_str ());
1435 fprintf (cfile, "?>");
1436}
1437
1438void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
1439{
1440 (*stream) << "<?xml ";
1441
1442 if ( !version.empty() )
1443 {
1444 (*stream) << "version=\"";
1445 PutString( version, stream );
1446 (*stream) << "\" ";
The Android Open Source Project562be062009-03-03 19:30:48 -08001447 }
Dan Albert0238a202014-08-22 00:52:41 +00001448 if ( !encoding.empty() )
1449 {
1450 (*stream) << "encoding=\"";
1451 PutString( encoding, stream );
1452 (*stream ) << "\" ";
The Android Open Source Project562be062009-03-03 19:30:48 -08001453 }
Dan Albert0238a202014-08-22 00:52:41 +00001454 if ( !standalone.empty() )
1455 {
1456 (*stream) << "standalone=\"";
1457 PutString( standalone, stream );
1458 (*stream) << "\" ";
The Android Open Source Project562be062009-03-03 19:30:48 -08001459 }
Dan Albert0238a202014-08-22 00:52:41 +00001460 (*stream) << "?>";
The Android Open Source Project562be062009-03-03 19:30:48 -08001461}
1462
1463
1464void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
1465{
1466 TiXmlNode::CopyTo( target );
1467
1468 target->version = version;
1469 target->encoding = encoding;
1470 target->standalone = standalone;
1471}
1472
1473
1474TiXmlNode* TiXmlDeclaration::Clone() const
1475{
1476 TiXmlDeclaration* clone = new TiXmlDeclaration();
1477
1478 if ( !clone )
1479 return 0;
1480
1481 CopyTo( clone );
1482 return clone;
1483}
1484
1485
1486void TiXmlUnknown::Print( FILE* cfile, int depth ) const
1487{
1488 for ( int i=0; i<depth; i++ )
1489 fprintf( cfile, " " );
1490 fprintf( cfile, "<%s>", value.c_str() );
1491}
1492
1493
Dan Albert0238a202014-08-22 00:52:41 +00001494void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
The Android Open Source Project562be062009-03-03 19:30:48 -08001495{
Dan Albert0238a202014-08-22 00:52:41 +00001496 (*stream) << "<" << value << ">"; // Don't use entities here! It is unknown.
The Android Open Source Project562be062009-03-03 19:30:48 -08001497}
1498
1499
Dan Albert0238a202014-08-22 00:52:41 +00001500void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
Dan Albertc3bbea32014-08-21 15:48:37 -07001501{
Dan Albert0238a202014-08-22 00:52:41 +00001502 TiXmlNode::CopyTo( target );
Dan Albertc3bbea32014-08-21 15:48:37 -07001503}
1504
1505
The Android Open Source Project562be062009-03-03 19:30:48 -08001506TiXmlNode* TiXmlUnknown::Clone() const
1507{
1508 TiXmlUnknown* clone = new TiXmlUnknown();
1509
1510 if ( !clone )
1511 return 0;
1512
1513 CopyTo( clone );
1514 return clone;
1515}
1516
1517
1518TiXmlAttributeSet::TiXmlAttributeSet()
1519{
1520 sentinel.next = &sentinel;
1521 sentinel.prev = &sentinel;
1522}
1523
1524
1525TiXmlAttributeSet::~TiXmlAttributeSet()
1526{
1527 assert( sentinel.next == &sentinel );
1528 assert( sentinel.prev == &sentinel );
1529}
1530
1531
1532void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
1533{
1534 assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
1535
1536 addMe->next = &sentinel;
1537 addMe->prev = sentinel.prev;
1538
1539 sentinel.prev->next = addMe;
1540 sentinel.prev = addMe;
1541}
1542
1543void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
1544{
1545 TiXmlAttribute* node;
1546
1547 for( node = sentinel.next; node != &sentinel; node = node->next )
1548 {
1549 if ( node == removeMe )
1550 {
1551 node->prev->next = node->next;
1552 node->next->prev = node->prev;
1553 node->next = 0;
1554 node->prev = 0;
1555 return;
1556 }
1557 }
1558 assert( 0 ); // we tried to remove a non-linked attribute.
1559}
1560
Dan Albert0238a202014-08-22 00:52:41 +00001561const TiXmlAttribute* TiXmlAttributeSet::Find( const char * name ) const
Dan Albertc3bbea32014-08-21 15:48:37 -07001562{
Dan Albert0238a202014-08-22 00:52:41 +00001563 const TiXmlAttribute* node;
1564
1565 for( node = sentinel.next; node != &sentinel; node = node->next )
The Android Open Source Project562be062009-03-03 19:30:48 -08001566 {
1567 if ( node->name == name )
1568 return node;
1569 }
1570 return 0;
1571}
1572
Dan Albert0238a202014-08-22 00:52:41 +00001573TiXmlAttribute* TiXmlAttributeSet::Find( const char * name )
The Android Open Source Project562be062009-03-03 19:30:48 -08001574{
Dan Albert0238a202014-08-22 00:52:41 +00001575 TiXmlAttribute* node;
The Android Open Source Project562be062009-03-03 19:30:48 -08001576
Dan Albert0238a202014-08-22 00:52:41 +00001577 for( node = sentinel.next; node != &sentinel; node = node->next )
The Android Open Source Project562be062009-03-03 19:30:48 -08001578 {
Dan Albert0238a202014-08-22 00:52:41 +00001579 if ( node->name == name )
The Android Open Source Project562be062009-03-03 19:30:48 -08001580 return node;
1581 }
1582 return 0;
1583}
1584
1585#ifdef TIXML_USE_STL
Dan Albert0238a202014-08-22 00:52:41 +00001586TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
The Android Open Source Project562be062009-03-03 19:30:48 -08001587{
1588 TIXML_STRING tag;
1589 tag.reserve( 8 * 1000 );
1590 base.StreamIn( &in, &tag );
1591
1592 base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
1593 return in;
1594}
1595#endif
1596
1597
Dan Albert0238a202014-08-22 00:52:41 +00001598TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
The Android Open Source Project562be062009-03-03 19:30:48 -08001599{
Dan Albert0238a202014-08-22 00:52:41 +00001600 base.StreamOut (& out);
The Android Open Source Project562be062009-03-03 19:30:48 -08001601 return out;
1602}
1603
1604
Dan Albert0238a202014-08-22 00:52:41 +00001605#ifdef TIXML_USE_STL
1606std::string & operator<< (std::string& out, const TiXmlNode& base )
The Android Open Source Project562be062009-03-03 19:30:48 -08001607{
Dan Albert0238a202014-08-22 00:52:41 +00001608 std::ostringstream os_stream( std::ostringstream::out );
1609 base.StreamOut( &os_stream );
1610
1611 out.append( os_stream.str() );
1612 return out;
The Android Open Source Project562be062009-03-03 19:30:48 -08001613}
1614#endif
1615
1616
1617TiXmlHandle TiXmlHandle::FirstChild() const
1618{
1619 if ( node )
1620 {
1621 TiXmlNode* child = node->FirstChild();
1622 if ( child )
1623 return TiXmlHandle( child );
1624 }
1625 return TiXmlHandle( 0 );
1626}
1627
1628
1629TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
1630{
1631 if ( node )
1632 {
1633 TiXmlNode* child = node->FirstChild( value );
1634 if ( child )
1635 return TiXmlHandle( child );
1636 }
1637 return TiXmlHandle( 0 );
1638}
1639
1640
1641TiXmlHandle TiXmlHandle::FirstChildElement() const
1642{
1643 if ( node )
1644 {
1645 TiXmlElement* child = node->FirstChildElement();
1646 if ( child )
1647 return TiXmlHandle( child );
1648 }
1649 return TiXmlHandle( 0 );
1650}
1651
1652
1653TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
1654{
1655 if ( node )
1656 {
1657 TiXmlElement* child = node->FirstChildElement( value );
1658 if ( child )
1659 return TiXmlHandle( child );
1660 }
1661 return TiXmlHandle( 0 );
1662}
1663
1664
1665TiXmlHandle TiXmlHandle::Child( int count ) const
1666{
1667 if ( node )
1668 {
1669 int i;
1670 TiXmlNode* child = node->FirstChild();
1671 for ( i=0;
1672 child && i<count;
1673 child = child->NextSibling(), ++i )
1674 {
1675 // nothing
1676 }
1677 if ( child )
1678 return TiXmlHandle( child );
1679 }
1680 return TiXmlHandle( 0 );
1681}
1682
1683
1684TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
1685{
1686 if ( node )
1687 {
1688 int i;
1689 TiXmlNode* child = node->FirstChild( value );
1690 for ( i=0;
1691 child && i<count;
1692 child = child->NextSibling( value ), ++i )
1693 {
1694 // nothing
1695 }
1696 if ( child )
1697 return TiXmlHandle( child );
1698 }
1699 return TiXmlHandle( 0 );
1700}
1701
1702
1703TiXmlHandle TiXmlHandle::ChildElement( int count ) const
1704{
1705 if ( node )
1706 {
1707 int i;
1708 TiXmlElement* child = node->FirstChildElement();
1709 for ( i=0;
1710 child && i<count;
1711 child = child->NextSiblingElement(), ++i )
1712 {
1713 // nothing
1714 }
1715 if ( child )
1716 return TiXmlHandle( child );
1717 }
1718 return TiXmlHandle( 0 );
1719}
1720
1721
1722TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
1723{
1724 if ( node )
1725 {
1726 int i;
1727 TiXmlElement* child = node->FirstChildElement( value );
1728 for ( i=0;
1729 child && i<count;
1730 child = child->NextSiblingElement( value ), ++i )
1731 {
1732 // nothing
1733 }
1734 if ( child )
1735 return TiXmlHandle( child );
1736 }
1737 return TiXmlHandle( 0 );
1738}