Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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