Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/tinyxml/tinyxml.h @ 5689

Last change on this file since 5689 was 4491, checked in by bensch, 19 years ago

orxonox/trunk: new tinyXML-lib installed (v-2.3.4)

File size: 48.4 KB
Line 
1/*
2www.sourceforge.net/projects/tinyxml
3Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
4
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any
7damages arising from the use of this software.
8
9Permission is granted to anyone to use this software for any
10purpose, including commercial applications, and to alter it and
11redistribute it freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must
14not claim that you wrote the original software. If you use this
15software in a product, an acknowledgment in the product documentation
16would be appreciated but is not required.
17
182. Altered source versions must be plainly marked as such, and
19must not be misrepresented as being the original software.
20
213. This notice may not be removed or altered from any source
22distribution.
23*/
24
25
26#ifndef TINYXML_INCLUDED
27#define TINYXML_INCLUDED
28
29#ifdef _MSC_VER
30#pragma warning( disable : 4530 )
31#pragma warning( disable : 4786 )
32#endif
33
34#include <ctype.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <assert.h>
39
40// Help out windows:
41#if defined( _DEBUG ) && !defined( DEBUG )
42#define DEBUG
43#endif
44
45#if defined( DEBUG ) && defined( _MSC_VER )
46#include <windows.h>
47#define TIXML_LOG OutputDebugString
48#else
49#define TIXML_LOG printf
50#endif
51
52#ifdef TIXML_USE_STL
53        #include <string>
54        #include <iostream>
55        #define TIXML_STRING    std::string
56        #define TIXML_ISTREAM   std::istream
57        #define TIXML_OSTREAM   std::ostream
58#else
59        #include "tinystr.h"
60        #define TIXML_STRING    TiXmlString
61        #define TIXML_OSTREAM   TiXmlOutStream
62#endif
63
64class TiXmlDocument;
65class TiXmlElement;
66class TiXmlComment;
67class TiXmlUnknown;
68class TiXmlAttribute;
69class TiXmlText;
70class TiXmlDeclaration;
71class TiXmlParsingData;
72
73const int TIXML_MAJOR_VERSION = 2;
74const int TIXML_MINOR_VERSION = 3;
75const int TIXML_PATCH_VERSION = 4;
76
77/*      Internal structure for tracking location of items
78        in the XML file.
79*/
80struct TiXmlCursor
81{
82        TiXmlCursor()           { Clear(); }
83        void Clear()            { row = col = -1; }
84
85        int row;        // 0 based.
86        int col;        // 0 based.
87};
88
89
90// Only used by Attribute::Query functions
91enum 
92{ 
93        TIXML_SUCCESS,
94        TIXML_NO_ATTRIBUTE,
95        TIXML_WRONG_TYPE
96};
97
98
99// Used by the parsing routines.
100enum TiXmlEncoding
101{
102        TIXML_ENCODING_UNKNOWN,
103        TIXML_ENCODING_UTF8,
104        TIXML_ENCODING_LEGACY
105};
106
107const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN;
108
109/** TiXmlBase is a base class for every class in TinyXml.
110        It does little except to establish that TinyXml classes
111        can be printed and provide some utility functions.
112
113        In XML, the document and elements can contain
114        other elements and other types of nodes.
115
116        @verbatim
117        A Document can contain: Element (container or leaf)
118                                                        Comment (leaf)
119                                                        Unknown (leaf)
120                                                        Declaration( leaf )
121
122        An Element can contain: Element (container or leaf)
123                                                        Text    (leaf)
124                                                        Attributes (not on tree)
125                                                        Comment (leaf)
126                                                        Unknown (leaf)
127
128        A Decleration contains: Attributes (not on tree)
129        @endverbatim
130*/
131class TiXmlBase
132{
133        friend class TiXmlNode;
134        friend class TiXmlElement;
135        friend class TiXmlDocument;
136
137public:
138        TiXmlBase()     :       userData(0) {}
139        virtual ~TiXmlBase()                                    {}
140
141        /**     All TinyXml classes can print themselves to a filestream.
142                This is a formatted print, and will insert tabs and newlines.
143               
144                (For an unformatted stream, use the << operator.)
145        */
146        virtual void Print( FILE* cfile, int depth ) const = 0;
147
148        /**     The world does not agree on whether white space should be kept or
149                not. In order to make everyone happy, these global, static functions
150                are provided to set whether or not TinyXml will condense all white space
151                into a single space or not. The default is to condense. Note changing this
152                values is not thread safe.
153        */
154        static void SetCondenseWhiteSpace( bool condense )              { condenseWhiteSpace = condense; }
155
156        /// Return the current white space setting.
157        static bool IsWhiteSpaceCondensed()                                             { return condenseWhiteSpace; }
158
159        /** Return the position, in the original source file, of this node or attribute.
160                The row and column are 1-based. (That is the first row and first column is
161                1,1). If the returns values are 0 or less, then the parser does not have
162                a row and column value.
163
164                Generally, the row and column value will be set when the TiXmlDocument::Load(),
165                TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
166                when the DOM was created from operator>>.
167
168                The values reflect the initial load. Once the DOM is modified programmatically
169                (by adding or changing nodes and attributes) the new values will NOT update to
170                reflect changes in the document.
171
172                There is a minor performance cost to computing the row and column. Computation
173                can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
174
175                @sa TiXmlDocument::SetTabSize()
176        */
177        int Row() const                 { return location.row + 1; }
178        int Column() const              { return location.col + 1; }    ///< See Row()
179
180        void  SetUserData( void* user )                 { userData = user; }
181        void* GetUserData()                                             { return userData; }
182
183        // Table that returs, for a given lead byte, the total number of bytes
184        // in the UTF-8 sequence.
185        static const int utf8ByteTable[256];
186
187        virtual const char* Parse(      const char* p, 
188                                                                TiXmlParsingData* data, 
189                                                                TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0;
190
191        enum
192        {
193                TIXML_NO_ERROR = 0,
194                TIXML_ERROR,
195                TIXML_ERROR_OPENING_FILE,
196                TIXML_ERROR_OUT_OF_MEMORY,
197                TIXML_ERROR_PARSING_ELEMENT,
198                TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
199                TIXML_ERROR_READING_ELEMENT_VALUE,
200                TIXML_ERROR_READING_ATTRIBUTES,
201                TIXML_ERROR_PARSING_EMPTY,
202                TIXML_ERROR_READING_END_TAG,
203                TIXML_ERROR_PARSING_UNKNOWN,
204                TIXML_ERROR_PARSING_COMMENT,
205                TIXML_ERROR_PARSING_DECLARATION,
206                TIXML_ERROR_DOCUMENT_EMPTY,
207                TIXML_ERROR_EMBEDDED_NULL,
208
209                TIXML_ERROR_STRING_COUNT
210        };
211
212protected:
213
214        // See STL_STRING_BUG
215        // Utility class to overcome a bug.
216        class StringToBuffer
217        {
218          public:
219                StringToBuffer( const TIXML_STRING& str );
220                ~StringToBuffer();
221                char* buffer;
222        };
223
224        static const char*      SkipWhiteSpace( const char*, TiXmlEncoding encoding );
225        inline static bool      IsWhiteSpace( char c )         
226        { 
227                return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); 
228        }
229
230        virtual void StreamOut (TIXML_OSTREAM *) const = 0;
231
232        #ifdef TIXML_USE_STL
233            static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
234            static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
235        #endif
236
237        /*      Reads an XML name into the string provided. Returns
238                a pointer just past the last character of the name,
239                or 0 if the function has an error.
240        */
241        static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding );
242
243        /*      Reads text. Returns a pointer past the given end tag.
244                Wickedly complex options, but it keeps the (sensitive) code in one place.
245        */
246        static const char* ReadText(    const char* in,                         // where to start
247                                                                        TIXML_STRING* text,                     // the string read
248                                                                        bool ignoreWhiteSpace,          // whether to keep the white space
249                                                                        const char* endTag,                     // what ends this text
250                                                                        bool ignoreCase,                        // whether to ignore case in the end tag
251                                                                        TiXmlEncoding encoding );       // the current encoding
252
253        // If an entity has been found, transform it into a character.
254        static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding );
255
256        // Get a character, while interpreting entities.
257        // The length can be from 0 to 4 bytes.
258        inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding )
259        {
260                assert( p );
261                if ( encoding == TIXML_ENCODING_UTF8 )
262                {
263                        *length = utf8ByteTable[ *((unsigned char*)p) ];
264                        assert( *length >= 0 && *length < 5 );
265                }
266                else
267                {
268                        *length = 1;
269                }
270
271                if ( *length == 1 )
272                {
273                        if ( *p == '&' )
274                                return GetEntity( p, _value, length, encoding );
275                        *_value = *p;
276                        return p+1;
277                }
278                else if ( *length )
279                {
280                        strncpy( _value, p, *length );
281                        return p + (*length);
282                }
283                else
284                {
285                        // Not valid text.
286                        return 0;
287                }
288        }
289
290        // Puts a string to a stream, expanding entities as it goes.
291        // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
292        static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
293
294        static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
295
296        // Return true if the next characters in the stream are any of the endTag sequences.
297        // Ignore case only works for english, and should only be relied on when comparing
298        // to Engilish words: StringEqual( p, "version", true ) is fine.
299        static bool StringEqual(        const char* p,
300                                                                const char* endTag,
301                                                                bool ignoreCase,
302                                                                TiXmlEncoding encoding );
303
304        static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
305
306        TiXmlCursor location;
307
308    /// Field containing a generic user pointer
309        void*                   userData;
310       
311        // None of these methods are reliable for any language except English.
312        // Good for approximation, not great for accuracy.
313        static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding );
314        static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding );
315        inline static int ToLower( int v, TiXmlEncoding encoding )
316        {
317                if ( encoding == TIXML_ENCODING_UTF8 )
318                {
319                        if ( v < 128 ) return tolower( v );
320                        return v;
321                }
322                else
323                {
324                        return tolower( v );
325                }
326        }
327        static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );
328
329private:
330        TiXmlBase( const TiXmlBase& );                          // not implemented.
331        void operator=( const TiXmlBase& base );        // not allowed.
332
333        struct Entity
334        {
335                const char*     str;
336                unsigned int    strLength;
337                char                chr;
338        };
339        enum
340        {
341                NUM_ENTITY = 5,
342                MAX_ENTITY_LENGTH = 6
343
344        };
345        static Entity entity[ NUM_ENTITY ];
346        static bool condenseWhiteSpace;
347};
348
349
350/** The parent class for everything in the Document Object Model.
351        (Except for attributes).
352        Nodes have siblings, a parent, and children. A node can be
353        in a document, or stand on its own. The type of a TiXmlNode
354        can be queried, and it can be cast to its more defined type.
355*/
356class TiXmlNode : public TiXmlBase
357{
358        friend class TiXmlDocument;
359        friend class TiXmlElement;
360
361public:
362        #ifdef TIXML_USE_STL   
363
364            /** An input stream operator, for every class. Tolerant of newlines and
365                    formatting, but doesn't expect them.
366            */
367            friend std::istream& operator >> (std::istream& in, TiXmlNode& base);
368
369            /** An output stream operator, for every class. Note that this outputs
370                    without any newlines or formatting, as opposed to Print(), which
371                    includes tabs and new lines.
372
373                    The operator<< and operator>> are not completely symmetric. Writing
374                    a node to a stream is very well defined. You'll get a nice stream
375                    of output, without any extra whitespace or newlines.
376                   
377                    But reading is not as well defined. (As it always is.) If you create
378                    a TiXmlElement (for example) and read that from an input stream,
379                    the text needs to define an element or junk will result. This is
380                    true of all input streams, but it's worth keeping in mind.
381
382                    A TiXmlDocument will read nodes until it reads a root element, and
383                        all the children of that root element.
384            */ 
385            friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base);
386
387                /// Appends the XML node or attribute to a std::string.
388                friend std::string& operator<< (std::string& out, const TiXmlNode& base );
389
390        #else
391            // Used internally, not part of the public API.
392            friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiXmlNode& base);
393        #endif
394
395        /** The types of XML nodes supported by TinyXml. (All the
396                        unsupported types are picked up by UNKNOWN.)
397        */
398        enum NodeType
399        {
400                DOCUMENT,
401                ELEMENT,
402                COMMENT,
403                UNKNOWN,
404                TEXT,
405                DECLARATION,
406                TYPECOUNT
407        };
408
409        virtual ~TiXmlNode();
410
411        /** The meaning of 'value' changes for the specific type of
412                TiXmlNode.
413                @verbatim
414                Document:       filename of the xml file
415                Element:        name of the element
416                Comment:        the comment text
417                Unknown:        the tag contents
418                Text:           the text string
419                @endverbatim
420
421                The subclasses will wrap this function.
422        */
423        const char * Value() const { return value.c_str (); }
424
425        /** Changes the value of the node. Defined as:
426                @verbatim
427                Document:       filename of the xml file
428                Element:        name of the element
429                Comment:        the comment text
430                Unknown:        the tag contents
431                Text:           the text string
432                @endverbatim
433        */
434        void SetValue(const char * _value) { value = _value;}
435
436    #ifdef TIXML_USE_STL
437        /// STL std::string form.
438        void SetValue( const std::string& _value )   
439        {         
440                StringToBuffer buf( _value );
441                SetValue( buf.buffer ? buf.buffer : "" );       
442        }       
443        #endif
444
445        /// Delete all the children of this node. Does not affect 'this'.
446        void Clear();
447
448        /// One step up the DOM.
449        TiXmlNode* Parent()                                                     { return parent; }
450        const TiXmlNode* Parent() const                         { return parent; }
451
452        const TiXmlNode* FirstChild()   const   { return firstChild; }          ///< The first child of this node. Will be null if there are no children.
453        TiXmlNode* FirstChild()                                 { return firstChild; }
454        const TiXmlNode* FirstChild( const char * value ) const;                        ///< The first child of this node with the matching 'value'. Will be null if none found.
455        TiXmlNode* FirstChild( const char * value );                                            ///< The first child of this node with the matching 'value'. Will be null if none found.
456
457        const TiXmlNode* LastChild() const      { return lastChild; }           /// The last child of this node. Will be null if there are no children.
458        TiXmlNode* LastChild()  { return lastChild; }
459        const TiXmlNode* LastChild( const char * value ) const;                 /// The last child of this node matching 'value'. Will be null if there are no children.
460        TiXmlNode* LastChild( const char * value );     
461
462    #ifdef TIXML_USE_STL
463        const TiXmlNode* FirstChild( const std::string& _value ) const  {       return FirstChild (_value.c_str ());    }       ///< STL std::string form.
464        TiXmlNode* FirstChild( const std::string& _value )                              {       return FirstChild (_value.c_str ());    }       ///< STL std::string form.
465        const TiXmlNode* LastChild( const std::string& _value ) const   {       return LastChild (_value.c_str ());     }       ///< STL std::string form.
466        TiXmlNode* LastChild( const std::string& _value )                               {       return LastChild (_value.c_str ());     }       ///< STL std::string form.
467        #endif
468
469        /** An alternate way to walk the children of a node.
470                One way to iterate over nodes is:
471                @verbatim
472                        for( child = parent->FirstChild(); child; child = child->NextSibling() )
473                @endverbatim
474
475                IterateChildren does the same thing with the syntax:
476                @verbatim
477                        child = 0;
478                        while( child = parent->IterateChildren( child ) )
479                @endverbatim
480
481                IterateChildren takes the previous child as input and finds
482                the next one. If the previous child is null, it returns the
483                first. IterateChildren will return null when done.
484        */
485        const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const;
486        TiXmlNode* IterateChildren( TiXmlNode* previous );
487
488        /// This flavor of IterateChildren searches for children with a particular 'value'
489        const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const;
490        TiXmlNode* IterateChildren( const char * value, TiXmlNode* previous );
491
492    #ifdef TIXML_USE_STL
493        const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const  {       return IterateChildren (_value.c_str (), previous);     }       ///< STL std::string form.
494        TiXmlNode* IterateChildren( const std::string& _value, TiXmlNode* previous ) {  return IterateChildren (_value.c_str (), previous);     }       ///< STL std::string form.
495        #endif
496
497        /** Add a new node related to this. Adds a child past the LastChild.
498                Returns a pointer to the new object or NULL if an error occured.
499        */
500        TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
501
502
503        /** Add a new node related to this. Adds a child past the LastChild.
504
505                NOTE: the node to be added is passed by pointer, and will be
506                henceforth owned (and deleted) by tinyXml. This method is efficient
507                and avoids an extra copy, but should be used with care as it
508                uses a different memory model than the other insert functions.
509
510                @sa InsertEndChild
511        */
512        TiXmlNode* LinkEndChild( TiXmlNode* addThis );
513
514        /** Add a new node related to this. Adds a child before the specified child.
515                Returns a pointer to the new object or NULL if an error occured.
516        */
517        TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
518
519        /** Add a new node related to this. Adds a child after the specified child.
520                Returns a pointer to the new object or NULL if an error occured.
521        */
522        TiXmlNode* InsertAfterChild(  TiXmlNode* afterThis, const TiXmlNode& addThis );
523
524        /** Replace a child of this node.
525                Returns a pointer to the new object or NULL if an error occured.
526        */
527        TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
528
529        /// Delete a child of this node.
530        bool RemoveChild( TiXmlNode* removeThis );
531
532        /// Navigate to a sibling node.
533        const TiXmlNode* PreviousSibling() const                        { return prev; }
534        TiXmlNode* PreviousSibling()                                            { return prev; }
535
536        /// Navigate to a sibling node.
537        const TiXmlNode* PreviousSibling( const char * ) const;
538        TiXmlNode* PreviousSibling( const char * );
539
540    #ifdef TIXML_USE_STL
541        const TiXmlNode* PreviousSibling( const std::string& _value ) const     {       return PreviousSibling (_value.c_str ());       }       ///< STL std::string form.
542        TiXmlNode* PreviousSibling( const std::string& _value )                         {       return PreviousSibling (_value.c_str ());       }       ///< STL std::string form.
543        const TiXmlNode* NextSibling( const std::string& _value) const          {       return NextSibling (_value.c_str ());   }       ///< STL std::string form.
544        TiXmlNode* NextSibling( const std::string& _value)                                      {       return NextSibling (_value.c_str ());   }       ///< STL std::string form.
545        #endif
546
547        /// Navigate to a sibling node.
548        const TiXmlNode* NextSibling() const                            { return next; }
549        TiXmlNode* NextSibling()                                                        { return next; }
550
551        /// Navigate to a sibling node with the given 'value'.
552        const TiXmlNode* NextSibling( const char * ) const;
553        TiXmlNode* NextSibling( const char * );
554
555        /** Convenience function to get through elements.
556                Calls NextSibling and ToElement. Will skip all non-Element
557                nodes. Returns 0 if there is not another element.
558        */
559        const TiXmlElement* NextSiblingElement() const;
560        TiXmlElement* NextSiblingElement();
561
562        /** Convenience function to get through elements.
563                Calls NextSibling and ToElement. Will skip all non-Element
564                nodes. Returns 0 if there is not another element.
565        */
566        const TiXmlElement* NextSiblingElement( const char * ) const;
567        TiXmlElement* NextSiblingElement( const char * );
568
569    #ifdef TIXML_USE_STL
570        const TiXmlElement* NextSiblingElement( const std::string& _value) const        {       return NextSiblingElement (_value.c_str ());    }       ///< STL std::string form.
571        TiXmlElement* NextSiblingElement( const std::string& _value)                            {       return NextSiblingElement (_value.c_str ());    }       ///< STL std::string form.
572        #endif
573
574        /// Convenience function to get through elements.
575        const TiXmlElement* FirstChildElement() const;
576        TiXmlElement* FirstChildElement();
577
578        /// Convenience function to get through elements.
579        const TiXmlElement* FirstChildElement( const char * value ) const;
580        TiXmlElement* FirstChildElement( const char * value );
581
582    #ifdef TIXML_USE_STL
583        const TiXmlElement* FirstChildElement( const std::string& _value ) const        {       return FirstChildElement (_value.c_str ());     }       ///< STL std::string form.
584        TiXmlElement* FirstChildElement( const std::string& _value )                            {       return FirstChildElement (_value.c_str ());     }       ///< STL std::string form.
585        #endif
586
587        /** Query the type (as an enumerated value, above) of this node.
588                The possible types are: DOCUMENT, ELEMENT, COMMENT,
589                                                                UNKNOWN, TEXT, and DECLARATION.
590        */
591        virtual int Type() const        { return type; }
592
593        /** Return a pointer to the Document this node lives in.
594                Returns null if not in a document.
595        */
596        const TiXmlDocument* GetDocument() const;
597        TiXmlDocument* GetDocument();
598
599        /// Returns true if this node has no children.
600        bool NoChildren() const                                         { return !firstChild; }
601
602        const TiXmlDocument* ToDocument()       const           { return ( this && type == DOCUMENT ) ? (const TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
603        const TiXmlElement*  ToElement() const                  { return ( this && type == ELEMENT  ) ? (const TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
604        const TiXmlComment*  ToComment() const                  { return ( this && type == COMMENT  ) ? (const TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
605        const TiXmlUnknown*  ToUnknown() const                  { return ( this && type == UNKNOWN  ) ? (const TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
606        const TiXmlText*           ToText()    const            { return ( this && type == TEXT     ) ? (const TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
607        const TiXmlDeclaration* ToDeclaration() const   { return ( this && type == DECLARATION ) ? (const TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
608
609        TiXmlDocument* ToDocument()                     { return ( this && type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
610        TiXmlElement*  ToElement()                      { return ( this && type == ELEMENT  ) ? (TiXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
611        TiXmlComment*  ToComment()                      { return ( this && type == COMMENT  ) ? (TiXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
612        TiXmlUnknown*  ToUnknown()                      { return ( this && type == UNKNOWN  ) ? (TiXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
613        TiXmlText*         ToText()                     { return ( this && type == TEXT     ) ? (TiXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
614        TiXmlDeclaration* ToDeclaration()       { return ( this && type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
615
616        /** Create an exact duplicate of this node and return it. The memory must be deleted
617                by the caller.
618        */
619        virtual TiXmlNode* Clone() const = 0;
620
621protected:
622        TiXmlNode( NodeType _type );
623
624        // Copy to the allocated object. Shared functionality between Clone, Copy constructor,
625        // and the assignment operator.
626        void CopyTo( TiXmlNode* target ) const;
627
628        #ifdef TIXML_USE_STL
629            // The real work of the input operator.
630            virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
631        #endif
632
633        // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
634        TiXmlNode* Identify( const char* start, TiXmlEncoding encoding );
635
636        // Internal Value function returning a TIXML_STRING
637        const TIXML_STRING& SValue() const      { return value ; }
638
639        TiXmlNode*              parent;
640        NodeType                type;
641
642        TiXmlNode*              firstChild;
643        TiXmlNode*              lastChild;
644
645        TIXML_STRING    value;
646
647        TiXmlNode*              prev;
648        TiXmlNode*              next;
649
650private:
651        TiXmlNode( const TiXmlNode& );                          // not implemented.
652        void operator=( const TiXmlNode& base );        // not allowed.
653};
654
655
656/** An attribute is a name-value pair. Elements have an arbitrary
657        number of attributes, each with a unique name.
658
659        @note The attributes are not TiXmlNodes, since they are not
660                  part of the tinyXML document object model. There are other
661                  suggested ways to look at this problem.
662*/
663class TiXmlAttribute : public TiXmlBase
664{
665        friend class TiXmlAttributeSet;
666
667public:
668        /// Construct an empty attribute.
669        TiXmlAttribute() : TiXmlBase()
670        {
671                document = 0;
672                prev = next = 0;
673        }
674
675        #ifdef TIXML_USE_STL
676        /// std::string constructor.
677        TiXmlAttribute( const std::string& _name, const std::string& _value )
678        {
679                name = _name;
680                value = _value;
681                document = 0;
682                prev = next = 0;
683        }
684        #endif
685
686        /// Construct an attribute with a name and value.
687        TiXmlAttribute( const char * _name, const char * _value )
688        {
689                name = _name;
690                value = _value;
691                document = 0;
692                prev = next = 0;
693        }
694
695        const char*             Name()  const           { return name.c_str (); }               ///< Return the name of this attribute.
696        const char*             Value() const           { return value.c_str (); }              ///< Return the value of this attribute.
697        const int       IntValue() const;                                                                       ///< Return the value of this attribute, converted to an integer.
698        const double    DoubleValue() const;                                                            ///< Return the value of this attribute, converted to a double.
699
700        /** QueryIntValue examines the value string. It is an alternative to the
701                IntValue() method with richer error checking.
702                If the value is an integer, it is stored in 'value' and
703                the call returns TIXML_SUCCESS. If it is not
704                an integer, it returns TIXML_WRONG_TYPE.
705
706                A specialized but useful call. Note that for success it returns 0,
707                which is the opposite of almost all other TinyXml calls.
708        */
709        int QueryIntValue( int* value ) const;
710        /// QueryDoubleValue examines the value string. See QueryIntValue().
711        int QueryDoubleValue( double* value ) const;
712
713        void SetName( const char* _name )       { name = _name; }                               ///< Set the name of this attribute.
714        void SetValue( const char* _value )     { value = _value; }                             ///< Set the value.
715
716        void SetIntValue( int value );                                                                          ///< Set the value from an integer.
717        void SetDoubleValue( double value );                                                            ///< Set the value from a double.
718
719    #ifdef TIXML_USE_STL
720        /// STL std::string form.
721        void SetName( const std::string& _name )       
722        {       
723                StringToBuffer buf( _name );
724                SetName ( buf.buffer ? buf.buffer : "error" ); 
725        }
726        /// STL std::string form.       
727        void SetValue( const std::string& _value )     
728        {       
729                StringToBuffer buf( _value );
730                SetValue( buf.buffer ? buf.buffer : "error" ); 
731        }
732        #endif
733
734        /// Get the next sibling attribute in the DOM. Returns null at end.
735        const TiXmlAttribute* Next() const;
736        TiXmlAttribute* Next();
737        /// Get the previous sibling attribute in the DOM. Returns null at beginning.
738        const TiXmlAttribute* Previous() const;
739        TiXmlAttribute* Previous();
740
741        bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
742        bool operator<( const TiXmlAttribute& rhs )      const { return name < rhs.name; }
743        bool operator>( const TiXmlAttribute& rhs )  const { return name > rhs.name; }
744
745        /*      Attribute parsing starts: first letter of the name
746                                                 returns: the next char after the value end quote
747        */
748        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
749
750        // Prints this Attribute to a FILE stream.
751        virtual void Print( FILE* cfile, int depth ) const;
752
753        virtual void StreamOut( TIXML_OSTREAM * out ) const;
754        // [internal use]
755        // Set the document pointer so the attribute can report errors.
756        void SetDocument( TiXmlDocument* doc )  { document = doc; }
757
758private:
759        TiXmlAttribute( const TiXmlAttribute& );                                // not implemented.
760        void operator=( const TiXmlAttribute& base );   // not allowed.
761
762        TiXmlDocument*  document;       // A pointer back to a document, for error reporting.
763        TIXML_STRING name;
764        TIXML_STRING value;
765        TiXmlAttribute* prev;
766        TiXmlAttribute* next;
767};
768
769
770/*      A class used to manage a group of attributes.
771        It is only used internally, both by the ELEMENT and the DECLARATION.
772       
773        The set can be changed transparent to the Element and Declaration
774        classes that use it, but NOT transparent to the Attribute
775        which has to implement a next() and previous() method. Which makes
776        it a bit problematic and prevents the use of STL.
777
778        This version is implemented with circular lists because:
779                - I like circular lists
780                - it demonstrates some independence from the (typical) doubly linked list.
781*/
782class TiXmlAttributeSet
783{
784public:
785        TiXmlAttributeSet();
786        ~TiXmlAttributeSet();
787
788        void Add( TiXmlAttribute* attribute );
789        void Remove( TiXmlAttribute* attribute );
790
791        const TiXmlAttribute* First()   const   { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
792        TiXmlAttribute* First()                                 { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
793        const TiXmlAttribute* Last() const              { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
794        TiXmlAttribute* Last()                                  { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
795
796        const TiXmlAttribute*   Find( const char * name ) const;
797        TiXmlAttribute* Find( const char * name );
798
799private:
800        //*ME:  Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element),
801        //*ME:  this class must be also use a hidden/disabled copy-constructor !!!
802        TiXmlAttributeSet( const TiXmlAttributeSet& );  // not allowed
803        void operator=( const TiXmlAttributeSet& );     // not allowed (as TiXmlAttribute)
804
805        TiXmlAttribute sentinel;
806};
807
808
809/** The element is a container class. It has a value, the element name,
810        and can contain other elements, text, comments, and unknowns.
811        Elements also contain an arbitrary number of attributes.
812*/
813class TiXmlElement : public TiXmlNode
814{
815public:
816        /// Construct an element.
817        TiXmlElement (const char * in_value);
818
819        #ifdef TIXML_USE_STL
820        /// std::string constructor.
821        TiXmlElement( const std::string& _value );
822        #endif
823
824        TiXmlElement( const TiXmlElement& );
825
826        void operator=( const TiXmlElement& base );
827
828        virtual ~TiXmlElement();
829
830        /** Given an attribute name, Attribute() returns the value
831                for the attribute of that name, or null if none exists.
832        */
833        const char* Attribute( const char* name ) const;
834
835        /** Given an attribute name, Attribute() returns the value
836                for the attribute of that name, or null if none exists.
837                If the attribute exists and can be converted to an integer,
838                the integer value will be put in the return 'i', if 'i'
839                is non-null.
840        */
841        const char* Attribute( const char* name, int* i ) const;
842
843        /** Given an attribute name, Attribute() returns the value
844                for the attribute of that name, or null if none exists.
845                If the attribute exists and can be converted to an double,
846                the double value will be put in the return 'd', if 'd'
847                is non-null.
848        */
849        const char* Attribute( const char* name, double* d ) const;
850
851        /** QueryIntAttribute examines the attribute - it is an alternative to the
852                Attribute() method with richer error checking.
853                If the attribute is an integer, it is stored in 'value' and
854                the call returns TIXML_SUCCESS. If it is not
855                an integer, it returns TIXML_WRONG_TYPE. If the attribute
856                does not exist, then TIXML_NO_ATTRIBUTE is returned.
857        */     
858        int QueryIntAttribute( const char* name, int* value ) const;
859        /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
860        int QueryDoubleAttribute( const char* name, double* value ) const;
861        /// QueryFloatAttribute examines the attribute - see QueryIntAttribute().
862        int QueryDoubleAttribute( const char* name, float* value ) const {
863                double d;
864                int result = QueryDoubleAttribute( name, &d );
865                *value = (float)d;
866                return result;
867        }
868
869        /** Sets an attribute of name to a given value. The attribute
870                will be created if it does not exist, or changed if it does.
871        */
872        void SetAttribute( const char* name, const char * value );
873
874    #ifdef TIXML_USE_STL
875        const char* Attribute( const std::string& name ) const                          { return Attribute( name.c_str() ); }
876        const char* Attribute( const std::string& name, int* i ) const          { return Attribute( name.c_str(), i ); }
877        const char* Attribute( const std::string& name, double* d ) const       { return Attribute( name.c_str(), d ); }
878        int QueryIntAttribute( const std::string& name, int* value ) const      { return QueryIntAttribute( name.c_str(), value ); }
879        int QueryDoubleAttribute( const std::string& name, double* value ) const { return QueryDoubleAttribute( name.c_str(), value ); }
880
881        /// STL std::string form.
882        void SetAttribute( const std::string& name, const std::string& _value ) 
883        {       
884                StringToBuffer n( name );
885                StringToBuffer v( _value );
886                if ( n.buffer && v.buffer )
887                        SetAttribute (n.buffer, v.buffer );     
888        }       
889        ///< STL std::string form.
890        void SetAttribute( const std::string& name, int _value )       
891        {       
892                StringToBuffer n( name );
893                if ( n.buffer )
894                        SetAttribute (n.buffer, _value);       
895        }       
896        #endif
897
898        /** Sets an attribute of name to a given value. The attribute
899                will be created if it does not exist, or changed if it does.
900        */
901        void SetAttribute( const char * name, int value );
902
903        /** Sets an attribute of name to a given value. The attribute
904                will be created if it does not exist, or changed if it does.
905        */
906        void SetDoubleAttribute( const char * name, double value );
907
908        /** Deletes an attribute with the given name.
909        */
910        void RemoveAttribute( const char * name );
911    #ifdef TIXML_USE_STL
912        void RemoveAttribute( const std::string& name ) {       RemoveAttribute (name.c_str ());        }       ///< STL std::string form.
913        #endif
914
915        const TiXmlAttribute* FirstAttribute() const    { return attributeSet.First(); }                ///< Access the first attribute in this element.
916        TiXmlAttribute* FirstAttribute()                                { return attributeSet.First(); }
917        const TiXmlAttribute* LastAttribute()   const   { return attributeSet.Last(); }         ///< Access the last attribute in this element.
918        TiXmlAttribute* LastAttribute()                                 { return attributeSet.Last(); }
919
920        /// Creates a new Element and returns it - the returned element is a copy.
921        virtual TiXmlNode* Clone() const;
922        // Print the Element to a FILE stream.
923        virtual void Print( FILE* cfile, int depth ) const;
924
925        /*      Attribtue parsing starts: next char past '<'
926                                                 returns: next char past '>'
927        */
928        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
929
930protected:
931
932        void CopyTo( TiXmlElement* target ) const;
933        void ClearThis();       // like clear, but initializes 'this' object as well
934
935        // Used to be public [internal use]
936        #ifdef TIXML_USE_STL
937            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
938        #endif
939        virtual void StreamOut( TIXML_OSTREAM * out ) const;
940
941        /*      [internal use]
942                Reads the "value" of the element -- another element, or text.
943                This should terminate with the current end tag.
944        */
945        const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding );
946
947private:
948
949        TiXmlAttributeSet attributeSet;
950};
951
952
953/**     An XML comment.
954*/
955class TiXmlComment : public TiXmlNode
956{
957public:
958        /// Constructs an empty comment.
959        TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
960        TiXmlComment( const TiXmlComment& );
961        void operator=( const TiXmlComment& base );
962
963        virtual ~TiXmlComment() {}
964
965        /// Returns a copy of this Comment.
966        virtual TiXmlNode* Clone() const;
967        /// Write this Comment to a FILE stream.
968        virtual void Print( FILE* cfile, int depth ) const;
969
970        /*      Attribtue parsing starts: at the ! of the !--
971                                                 returns: next char past '>'
972        */
973        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
974
975protected:
976        void CopyTo( TiXmlComment* target ) const;
977
978        // used to be public
979        #ifdef TIXML_USE_STL
980            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
981        #endif
982        virtual void StreamOut( TIXML_OSTREAM * out ) const;
983
984private:
985
986};
987
988
989/** XML text. Contained in an element.
990*/
991class TiXmlText : public TiXmlNode
992{
993        friend class TiXmlElement;
994public:
995        /// Constructor.
996        TiXmlText (const char * initValue) : TiXmlNode (TiXmlNode::TEXT)
997        {
998                SetValue( initValue );
999        }
1000        virtual ~TiXmlText() {}
1001
1002        #ifdef TIXML_USE_STL
1003        /// Constructor.
1004        TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT)
1005        {
1006                SetValue( initValue );
1007        }
1008        #endif
1009
1010        TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT )       { copy.CopyTo( this ); }
1011        void operator=( const TiXmlText& base )                                                         { base.CopyTo( this ); }
1012
1013        /// Write this text object to a FILE stream.
1014        virtual void Print( FILE* cfile, int depth ) const;
1015
1016        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1017
1018protected :
1019        ///  [internal use] Creates a new Element and returns it.
1020        virtual TiXmlNode* Clone() const;
1021        void CopyTo( TiXmlText* target ) const;
1022
1023        virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1024        bool Blank() const;     // returns true if all white space and new lines
1025        // [internal use]
1026        #ifdef TIXML_USE_STL
1027            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1028        #endif
1029
1030private:
1031};
1032
1033
1034/** In correct XML the declaration is the first entry in the file.
1035        @verbatim
1036                <?xml version="1.0" standalone="yes"?>
1037        @endverbatim
1038
1039        TinyXml will happily read or write files without a declaration,
1040        however. There are 3 possible attributes to the declaration:
1041        version, encoding, and standalone.
1042
1043        Note: In this version of the code, the attributes are
1044        handled as special cases, not generic attributes, simply
1045        because there can only be at most 3 and they are always the same.
1046*/
1047class TiXmlDeclaration : public TiXmlNode
1048{
1049public:
1050        /// Construct an empty declaration.
1051        TiXmlDeclaration()   : TiXmlNode( TiXmlNode::DECLARATION ) {}
1052
1053#ifdef TIXML_USE_STL
1054        /// Constructor.
1055        TiXmlDeclaration(       const std::string& _version,
1056                                                const std::string& _encoding,
1057                                                const std::string& _standalone );
1058#endif
1059
1060        /// Construct.
1061        TiXmlDeclaration(       const char* _version,
1062                                                const char* _encoding,
1063                                                const char* _standalone );
1064
1065        TiXmlDeclaration( const TiXmlDeclaration& copy );
1066        void operator=( const TiXmlDeclaration& copy );
1067
1068        virtual ~TiXmlDeclaration()     {}
1069
1070        /// Version. Will return an empty string if none was found.
1071        const char *Version() const                     { return version.c_str (); }
1072        /// Encoding. Will return an empty string if none was found.
1073        const char *Encoding() const            { return encoding.c_str (); }
1074        /// Is this a standalone document?
1075        const char *Standalone() const          { return standalone.c_str (); }
1076
1077        /// Creates a copy of this Declaration and returns it.
1078        virtual TiXmlNode* Clone() const;
1079        /// Print this declaration to a FILE stream.
1080        virtual void Print( FILE* cfile, int depth ) const;
1081
1082        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1083
1084protected:
1085        void CopyTo( TiXmlDeclaration* target ) const;
1086        // used to be public
1087        #ifdef TIXML_USE_STL
1088            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1089        #endif
1090        virtual void StreamOut ( TIXML_OSTREAM * out) const;
1091
1092private:
1093
1094        TIXML_STRING version;
1095        TIXML_STRING encoding;
1096        TIXML_STRING standalone;
1097};
1098
1099
1100/** Any tag that tinyXml doesn't recognize is saved as an
1101        unknown. It is a tag of text, but should not be modified.
1102        It will be written back to the XML, unchanged, when the file
1103        is saved.
1104
1105        DTD tags get thrown into TiXmlUnknowns.
1106*/
1107class TiXmlUnknown : public TiXmlNode
1108{
1109public:
1110        TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN )        {}
1111        virtual ~TiXmlUnknown() {}
1112
1113        TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN )              { copy.CopyTo( this ); }
1114        void operator=( const TiXmlUnknown& copy )                                                                              { copy.CopyTo( this ); }
1115
1116        /// Creates a copy of this Unknown and returns it.
1117        virtual TiXmlNode* Clone() const;
1118        /// Print this Unknown to a FILE stream.
1119        virtual void Print( FILE* cfile, int depth ) const;
1120
1121        virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding );
1122
1123protected:
1124        void CopyTo( TiXmlUnknown* target ) const;
1125
1126        #ifdef TIXML_USE_STL
1127            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1128        #endif
1129        virtual void StreamOut ( TIXML_OSTREAM * out ) const;
1130
1131private:
1132
1133};
1134
1135
1136/** Always the top level node. A document binds together all the
1137        XML pieces. It can be saved, loaded, and printed to the screen.
1138        The 'value' of a document node is the xml file name.
1139*/
1140class TiXmlDocument : public TiXmlNode
1141{
1142public:
1143        /// Create an empty document, that has no name.
1144        TiXmlDocument();
1145        /// Create a document with a name. The name of the document is also the filename of the xml.
1146        TiXmlDocument( const char * documentName );
1147
1148        #ifdef TIXML_USE_STL
1149        /// Constructor.
1150        TiXmlDocument( const std::string& documentName );
1151        #endif
1152
1153        TiXmlDocument( const TiXmlDocument& copy );
1154        void operator=( const TiXmlDocument& copy );
1155
1156        virtual ~TiXmlDocument() {}
1157
1158        /** Load a file using the current document value.
1159                Returns true if successful. Will delete any existing
1160                document data before loading.
1161        */
1162        bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1163        /// Save a file using the current document value. Returns true if successful.
1164        bool SaveFile() const;
1165        /// Load a file using the given filename. Returns true if successful.
1166        bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1167        /// Save a file using the given filename. Returns true if successful.
1168        bool SaveFile( const char * filename ) const;
1169
1170        #ifdef TIXML_USE_STL
1171        bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING )                   ///< STL std::string version.
1172        {
1173                StringToBuffer f( filename );
1174                return ( f.buffer && LoadFile( f.buffer, encoding ));
1175        }
1176        bool SaveFile( const std::string& filename ) const              ///< STL std::string version.
1177        {
1178                StringToBuffer f( filename );
1179                return ( f.buffer && SaveFile( f.buffer ));
1180        }
1181        #endif
1182
1183        /** Parse the given null terminated block of xml data. Passing in an encoding to this
1184                method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml
1185                to use that encoding, regardless of what TinyXml might otherwise try to detect.
1186        */
1187        virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
1188
1189        /** Get the root element -- the only top level element -- of the document.
1190                In well formed XML, there should only be one. TinyXml is tolerant of
1191                multiple elements at the document level.
1192        */
1193        const TiXmlElement* RootElement() const         { return FirstChildElement(); }
1194        TiXmlElement* RootElement()                                     { return FirstChildElement(); }
1195
1196        /** If an error occurs, Error will be set to true. Also,
1197                - The ErrorId() will contain the integer identifier of the error (not generally useful)
1198                - The ErrorDesc() method will return the name of the error. (very useful)
1199                - The ErrorRow() and ErrorCol() will return the location of the error (if known)
1200        */     
1201        bool Error() const                                              { return error; }
1202
1203        /// Contains a textual (english) description of the error if one occurs.
1204        const char * ErrorDesc() const  { return errorDesc.c_str (); }
1205
1206        /** Generally, you probably want the error string ( ErrorDesc() ). But if you
1207                prefer the ErrorId, this function will fetch it.
1208        */
1209        const int ErrorId()     const                           { return errorId; }
1210
1211        /** Returns the location (if known) of the error. The first column is column 1,
1212                and the first row is row 1. A value of 0 means the row and column wasn't applicable
1213                (memory errors, for example, have no row/column) or the parser lost the error. (An
1214                error in the error reporting, in that case.)
1215
1216                @sa SetTabSize, Row, Column
1217        */
1218        int ErrorRow()  { return errorLocation.row+1; }
1219        int ErrorCol()  { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow()
1220
1221        /** By calling this method, with a tab size
1222                greater than 0, the row and column of each node and attribute is stored
1223                when the file is loaded. Very useful for tracking the DOM back in to
1224                the source file.
1225
1226                The tab size is required for calculating the location of nodes. If not
1227                set, the default of 4 is used. The tabsize is set per document. Setting
1228                the tabsize to 0 disables row/column tracking.
1229
1230                Note that row and column tracking is not supported when using operator>>.
1231
1232                The tab size needs to be enabled before the parse or load. Correct usage:
1233                @verbatim
1234                TiXmlDocument doc;
1235                doc.SetTabSize( 8 );
1236                doc.Load( "myfile.xml" );
1237                @endverbatim
1238
1239                @sa Row, Column
1240        */
1241        void SetTabSize( int _tabsize )         { tabsize = _tabsize; }
1242
1243        int TabSize() const     { return tabsize; }
1244
1245        /** If you have handled the error, it can be reset with this call. The error
1246                state is automatically cleared if you Parse a new XML block.
1247        */
1248        void ClearError()                                               {       error = false; 
1249                                                                                                errorId = 0; 
1250                                                                                                errorDesc = ""; 
1251                                                                                                errorLocation.row = errorLocation.col = 0; 
1252                                                                                                //errorLocation.last = 0;
1253                                                                                        }
1254
1255        /** Dump the document to standard out. */
1256        void Print() const                                              { Print( stdout, 0 ); }
1257
1258        /// Print this Document to a FILE stream.
1259        virtual void Print( FILE* cfile, int depth = 0 ) const;
1260        // [internal use]
1261        void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding );
1262
1263protected :
1264        virtual void StreamOut ( TIXML_OSTREAM * out) const;
1265        // [internal use]
1266        virtual TiXmlNode* Clone() const;
1267        #ifdef TIXML_USE_STL
1268            virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
1269        #endif
1270
1271private:
1272        void CopyTo( TiXmlDocument* target ) const;
1273
1274        bool error;
1275        int  errorId;
1276        TIXML_STRING errorDesc;
1277        int tabsize;
1278        TiXmlCursor errorLocation;
1279};
1280
1281
1282/**
1283        A TiXmlHandle is a class that wraps a node pointer with null checks; this is
1284        an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
1285        DOM structure. It is a separate utility class.
1286
1287        Take an example:
1288        @verbatim
1289        <Document>
1290                <Element attributeA = "valueA">
1291                        <Child attributeB = "value1" />
1292                        <Child attributeB = "value2" />
1293                </Element>
1294        <Document>
1295        @endverbatim
1296
1297        Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
1298        easy to write a *lot* of code that looks like:
1299
1300        @verbatim
1301        TiXmlElement* root = document.FirstChildElement( "Document" );
1302        if ( root )
1303        {
1304                TiXmlElement* element = root->FirstChildElement( "Element" );
1305                if ( element )
1306                {
1307                        TiXmlElement* child = element->FirstChildElement( "Child" );
1308                        if ( child )
1309                        {
1310                                TiXmlElement* child2 = child->NextSiblingElement( "Child" );
1311                                if ( child2 )
1312                                {
1313                                        // Finally do something useful.
1314        @endverbatim
1315
1316        And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
1317        of such code. A TiXmlHandle checks for null     pointers so it is perfectly safe
1318        and correct to use:
1319
1320        @verbatim
1321        TiXmlHandle docHandle( &document );
1322        TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
1323        if ( child2 )
1324        {
1325                // do something useful
1326        @endverbatim
1327
1328        Which is MUCH more concise and useful.
1329
1330        It is also safe to copy handles - internally they are nothing more than node pointers.
1331        @verbatim
1332        TiXmlHandle handleCopy = handle;
1333        @endverbatim
1334
1335        What they should not be used for is iteration:
1336
1337        @verbatim
1338        int i=0;
1339        while ( true )
1340        {
1341                TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
1342                if ( !child )
1343                        break;
1344                // do something
1345                ++i;
1346        }
1347        @endverbatim
1348
1349        It seems reasonable, but it is in fact two embedded while loops. The Child method is
1350        a linear walk to find the element, so this code would iterate much more than it needs
1351        to. Instead, prefer:
1352
1353        @verbatim
1354        TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
1355
1356        for( child; child; child=child->NextSiblingElement() )
1357        {
1358                // do something
1359        }
1360        @endverbatim
1361*/
1362class TiXmlHandle
1363{
1364public:
1365        /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
1366        TiXmlHandle( TiXmlNode* node )                                  { this->node = node; }
1367        /// Copy constructor
1368        TiXmlHandle( const TiXmlHandle& ref )                   { this->node = ref.node; }
1369        TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; }
1370
1371        /// Return a handle to the first child node.
1372        TiXmlHandle FirstChild() const;
1373        /// Return a handle to the first child node with the given name.
1374        TiXmlHandle FirstChild( const char * value ) const;
1375        /// Return a handle to the first child element.
1376        TiXmlHandle FirstChildElement() const;
1377        /// Return a handle to the first child element with the given name.
1378        TiXmlHandle FirstChildElement( const char * value ) const;
1379
1380        /** Return a handle to the "index" child with the given name.
1381                The first child is 0, the second 1, etc.
1382        */
1383        TiXmlHandle Child( const char* value, int index ) const;
1384        /** Return a handle to the "index" child.
1385                The first child is 0, the second 1, etc.
1386        */
1387        TiXmlHandle Child( int index ) const;
1388        /** Return a handle to the "index" child element with the given name.
1389                The first child element is 0, the second 1, etc. Note that only TiXmlElements
1390                are indexed: other types are not counted.
1391        */
1392        TiXmlHandle ChildElement( const char* value, int index ) const;
1393        /** Return a handle to the "index" child element.
1394                The first child element is 0, the second 1, etc. Note that only TiXmlElements
1395                are indexed: other types are not counted.
1396        */
1397        TiXmlHandle ChildElement( int index ) const;
1398
1399        #ifdef TIXML_USE_STL
1400        TiXmlHandle FirstChild( const std::string& _value ) const                               { return FirstChild( _value.c_str() ); }
1401        TiXmlHandle FirstChildElement( const std::string& _value ) const                { return FirstChildElement( _value.c_str() ); }
1402
1403        TiXmlHandle Child( const std::string& _value, int index ) const                 { return Child( _value.c_str(), index ); }
1404        TiXmlHandle ChildElement( const std::string& _value, int index ) const  { return ChildElement( _value.c_str(), index ); }
1405        #endif
1406
1407        /// Return the handle as a TiXmlNode. This may return null.
1408        TiXmlNode* Node() const                 { return node; } 
1409        /// Return the handle as a TiXmlElement. This may return null.
1410        TiXmlElement* Element() const   { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
1411        /// Return the handle as a TiXmlText. This may return null.
1412        TiXmlText* Text() const                 { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
1413        /// Return the handle as a TiXmlUnknown. This may return null;
1414        TiXmlUnknown* Unknown() const                   { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); }
1415
1416private:
1417        TiXmlNode* node;
1418};
1419
1420#ifdef _MSC_VER
1421#pragma warning( default : 4530 )
1422#pragma warning( default : 4786 )
1423#endif
1424
1425#endif
1426
Note: See TracBrowser for help on using the repository browser.