~hikiko/nux/arb-srgba-shader

« back to all changes in this revision

Viewing changes to NuxCore/TinyXML/tinyxml.cpp

  • Committer: Neil Jagdish Patel
  • Date: 2010-09-02 03:28:11 UTC
  • Revision ID: neil.patel@canonical.com-20100902032811-i2m18tfb6pkasnvt
Remove Win EOL chars

Show diffs side-by-side

added added

removed removed

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