Main Page Modules Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# tinyxml.h

Go to the documentation of this file.

    00001 /*
    00002 www.sourceforge.net/projects/tinyxml
    00003 Original code (2.0 and earlier )copyright (c) 2000-2002 Lee Thomason (www.grinninglizard.com)
    00004
    00005 This software is provided 'as-is', without any express or implied
    00006 warranty. In no event will the authors be held liable for any
    00007 damages arising from the use of this software.
    00008
    00009 Permission is granted to anyone to use this software for any
    00010 purpose, including commercial applications, and to alter it and
    00011 redistribute it freely, subject to the following restrictions:
    00012
    00013 1. The origin of this software must not be misrepresented; you must
    00014 not claim that you wrote the original software. If you use this
    00015 software in a product, an acknowledgment in the product documentation
    00016 would be appreciated but is not required.
    00017
    00018 2. Altered source versions must be plainly marked as such, and
    00019 must not be misrepresented as being the original software.
    00020
    00021 3. This notice may not be removed or altered from any source
    00022 distribution.
    00023 */
    00024
    00025 /*
    00026 In accordance with item 2 of the above license,
    00027 this file has been modified from the original version,
    00028 to provide a minimal pull-parse back-end that cuts
    00029 down on the memory footprint when doing read-only operations.
    00030 */
    00031
    00032
    00033 #ifndef TINYXML_INCLUDED
    00034 #define TINYXML_INCLUDED
    00035
    00036 #ifdef _MSC_VER
    00037 #pragma warning( disable : 4530 )
    00038 #pragma warning( disable : 4786 )
    00039 #endif
    00040
    00041 #include <cctype>
    00042 #include <cstdio>
    00043 #include <cstdlib>
    00044 #include <cstring>
    00045 #include <cassert>
    00046 #include <deque>
    00047
    00048 // Help out windows:
    00049 #if defined( _DEBUG ) && !defined( DEBUG )
    00050 #define DEBUG
    00051 #endif
    00052
    00053 #if defined( DEBUG ) && defined( _MSC_VER )
    00054 #include <windows.h>
    00055 #define TIXML_LOG OutputDebugString
    00056 #else
    00057 #define TIXML_LOG printf
    00058 #endif
    00059
    00060 #ifdef TIXML_USE_STL
    00061     #include <string>
    00062     #include <iostream>
    00063     //#include <ostream>
    00064     #define TIXML_STRING    std::string
    00065     #define TIXML_ISTREAM   std::istream
    00066     #define TIXML_OSTREAM   std::ostream
    00067 #else
    00068     #include "tinystr.h"
    00069     #define TIXML_STRING    TiXmlString
    00070     #define TIXML_OSTREAM   TiXmlOutStream
    00071 #endif
    00072
    00073 class TiPullXmlDocument;
    00074 class TiPullXmlElement;
    00075 class TiPullXmlComment;
    00076 class TiPullXmlUnknown;
    00077 class TiPullXmlAttribute;
    00078 class TiPullXmlText;
    00079 class TiPullXmlDeclaration;
    00080
    00081 class TiPullXmlParsingData;
    00082
    00083 /*  Internal structure for tracking location of items
    00084     in the XML file.
    00085 */
    00086 struct TiPullXmlCursor
    00087 {
    00088     TiPullXmlCursor()       { Clear(); }
    00089     TiPullXmlCursor(int pos) : filepos(pos) { }
    00090     void Clear()        { filepos = -1; }
    00091     bool operator==(const TiPullXmlCursor& ref) const
    00092     { return (filepos == ref.filepos); }
    00093
    00094     int filepos;
    00095 };
    00096
    00097
    00098 // Only used by Attribute::Query functions
    00099 enum
    00100 {
    00101     TIXML_SUCCESS,
    00102     TIXML_NO_ATTRIBUTE,
    00103     TIXML_WRONG_TYPE
    00104 };
    00105
    00106 /** TiXmlBase is a base class for every class in TinyXml.
    00107     It does little except to establish that TinyXml classes
    00108     can be printed and provide some utility functions.
    00109
    00110     In XML, the document and elements can contain
    00111     other elements and other types of nodes.
    00112
    00113     @verbatim
    00114     A Document can contain: Element (container or leaf)
    00115                             Comment (leaf)
    00116                             Unknown (leaf)
    00117                             Declaration( leaf )
    00118
    00119     An Element can contain: Element (container or leaf)
    00120                             Text    (leaf)
    00121                             Attributes (not on tree)
    00122                             Comment (leaf)
    00123                             Unknown (leaf)
    00124
    00125     A Decleration contains: Attributes (not on tree)
    00126     @endverbatim
    00127 */
    00128 class TiPullXmlBase
    00129 {
    00130     friend class TiPullXmlNode;
    00131     friend class TiPullXmlElement;
    00132     friend class TiPullXmlDocument;
    00133
    00134 public:
    00135     TiPullXmlBase()                             {}
    00136     virtual ~TiPullXmlBase()                    {}
    00137
    00138     struct ParsePosition
    00139     {
    00140         ParsePosition() : data(0), pos(0) { }
    00141         ParsePosition(const char* data_, int pos_) : data(data_), pos(pos_) { }
    00142         const char* data;
    00143         TiPullXmlCursor pos;
    00144     };
    00145
    00146     /** All TinyXml classes can print themselves to a filestream.
    00147         This is a formatted print, and will insert tabs and newlines.
    00148
    00149         (For an unformatted stream, use the << operator.)
    00150     */
    00151     virtual void Print( FILE* cfile, int depth ) const = 0;
    00152
    00153     /** The world does not agree on whether white space should be kept or
    00154         not. In order to make everyone happy, these global, static functions
    00155         are provided to set whether or not TinyXml will condense all white space
    00156         into a single space or not. The default is to condense. Note changing this
    00157         values is not thread safe.
    00158     */
    00159     static void SetCondenseWhiteSpace( bool condense )      { condenseWhiteSpace = condense; }
    00160
    00161     /// Return the current white space setting.
    00162     static bool IsWhiteSpaceCondensed()                     { return condenseWhiteSpace; }
    00163
    00164 protected:
    00165     // See STL_STRING_BUG
    00166     // Utility class to overcome a bug.
    00167     class StringToBuffer
    00168     {
    00169       public:
    00170         StringToBuffer( const TIXML_STRING& str );
    00171         ~StringToBuffer();
    00172         char* buffer;
    00173     };
    00174
    00175     inline static bool  IsWhiteSpace( int c )       { return ( isspace( c ) || c == '\n' || c == '\r' ); }
    00176
    00177     virtual void StreamOut (TIXML_OSTREAM *) const = 0;
    00178
    00179     #ifdef TIXML_USE_STL
    00180         static bool StreamWhiteSpace( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00181         static bool StreamTo( TIXML_ISTREAM * in, int character, TIXML_STRING * tag );
    00182     #endif
    00183
    00184     /*  Reads an XML name into the string provided. Returns
    00185         a pointer just past the last character of the name,
    00186         or 0 if the function has an error.
    00187     */
    00188     static const char* ReadName( const char* p, TIXML_STRING* name );
    00189
    00190     /*  Reads text. Returns a pointer past the given end tag.
    00191         Wickedly complex options, but it keeps the (sensitive) code in one place.
    00192     */
    00193     static const char* ReadText(    const char* in,             // where to start
    00194                                     TIXML_STRING* text,         // the string read
    00195                                     bool ignoreWhiteSpace,      // whether to keep the white space
    00196                                     const char* endTag,         // what ends this text
    00197                                     bool ignoreCase );          // whether to ignore case in the end tag
    00198
    00199     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway ) = 0;
    00200
    00201     // If an entity has been found, transform it into a character.
    00202     static const char* GetEntity( const char* in, char* value );
    00203
    00204     // Get a character, while interpreting entities.
    00205     inline static const char* GetChar( const char* p, char* _value )
    00206     {
    00207         assert( p );
    00208         if ( *p == '&' )
    00209         {
    00210             return GetEntity( p, _value );
    00211         }
    00212         else
    00213         {
    00214             *_value = *p;
    00215             return p+1;
    00216         }
    00217     }
    00218
    00219     // Puts a string to a stream, expanding entities as it goes.
    00220     // Note this should not contian the '<', '>', etc, or they will be transformed into entities!
    00221     static void PutString( const TIXML_STRING& str, TIXML_OSTREAM* out );
    00222
    00223     static void PutString( const TIXML_STRING& str, TIXML_STRING* out );
    00224
    00225     // Return true if the next characters in the stream are any of the endTag sequences.
    00226     static bool StringEqual(    const char* p,
    00227                                 const char* endTag,
    00228                                 bool ignoreCase );
    00229
    00230
    00231     enum
    00232     {
    00233         TIXML_NO_ERROR = 0,
    00234         TIXML_ERROR,
    00235         TIXML_ERROR_OPENING_FILE,
    00236         TIXML_ERROR_OUT_OF_MEMORY,
    00237         TIXML_ERROR_PARSING_ELEMENT,
    00238         TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
    00239         TIXML_ERROR_READING_ELEMENT_VALUE,
    00240         TIXML_ERROR_READING_ATTRIBUTES,
    00241         TIXML_ERROR_PARSING_EMPTY,
    00242         TIXML_ERROR_READING_END_TAG,
    00243         TIXML_ERROR_PARSING_UNKNOWN,
    00244         TIXML_ERROR_PARSING_COMMENT,
    00245         TIXML_ERROR_PARSING_DECLARATION,
    00246         TIXML_ERROR_DOCUMENT_EMPTY,
    00247
    00248         TIXML_ERROR_STRING_COUNT
    00249     };
    00250     static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
    00251
    00252     TiPullXmlCursor startPos;
    00253
    00254 private:
    00255     struct Entity
    00256     {
    00257         const char*     str;
    00258         unsigned int    strLength;
    00259         char            chr;
    00260     };
    00261     enum
    00262     {
    00263         NUM_ENTITY = 5,
    00264         MAX_ENTITY_LENGTH = 6
    00265
    00266     };
    00267     static Entity entity[ NUM_ENTITY ];
    00268     static bool condenseWhiteSpace;
    00269 };
    00270
    00271
    00272 /** The parent class for everything in the Document Object Model.
    00273     (Except for attributes).
    00274     Nodes have siblings, a parent, and children. A node can be
    00275     in a document, or stand on its own. The type of a TiXmlNode
    00276     can be queried, and it can be cast to its more defined type.
    00277 */
    00278 class TiPullXmlNode : public TiPullXmlBase
    00279 {
    00280     friend class TiPullXmlDocument;
    00281     friend class TiPullXmlElement;
    00282
    00283 public:
    00284     #ifdef TIXML_USE_STL
    00285
    00286         /** An input stream operator, for every class. Tolerant of newlines and
    00287             formatting, but doesn't expect them.
    00288         */
    00289         friend std::istream& operator >> (std::istream& in, TiPullXmlNode& base);
    00290
    00291         /** An output stream operator, for every class. Note that this outputs
    00292             without any newlines or formatting, as opposed to Print(), which
    00293             includes tabs and new lines.
    00294
    00295             The operator<< and operator>> are not completely symmetric. Writing
    00296             a node to a stream is very well defined. You'll get a nice stream
    00297             of output, without any extra whitespace or newlines.
    00298
    00299             But reading is not as well defined. (As it always is.) If you create
    00300             a TiXmlElement (for example) and read that from an input stream,
    00301             the text needs to define an element or junk will result. This is
    00302             true of all input streams, but it's worth keeping in mind.
    00303
    00304             A TiXmlDocument will read nodes until it reads a root element, and
    00305             all the children of that root element.
    00306         */
    00307         friend std::ostream& operator<< (std::ostream& out, const TiPullXmlNode& base);
    00308
    00309         /// Appends the XML node or attribute to a std::string.
    00310         friend std::string& operator<< (std::string& out, const TiPullXmlNode& base );
    00311
    00312     #else
    00313         // Used internally, not part of the public API.
    00314         friend TIXML_OSTREAM& operator<< (TIXML_OSTREAM& out, const TiPullXmlNode& base);
    00315     #endif
    00316
    00317     /** The types of XML nodes supported by TinyXml. (All the
    00318             unsupported types are picked up by UNKNOWN.)
    00319     */
    00320     enum NodeType
    00321     {
    00322         DOCUMENT,
    00323         ELEMENT,
    00324         COMMENT,
    00325         UNKNOWN,
    00326         TEXT,
    00327         DECLARATION,
    00328         TYPECOUNT
    00329     };
    00330
    00331     virtual ~TiPullXmlNode();
    00332
    00333     /** The meaning of 'value' changes for the specific type of
    00334         TiPullXmlNode.
    00335         @verbatim
    00336         Document:   filename of the xml file
    00337         Element:    name of the element
    00338         Comment:    the comment text
    00339         Unknown:    the tag contents
    00340         Text:       the text string
    00341         @endverbatim
    00342
    00343         The subclasses will wrap this function.
    00344     */
    00345     const char * Value() const { return value.c_str (); }
    00346
    00347     void SetValue(const char* val) {}
    00348     #ifdef TIXML_USE_STL
    00349     void SetValue(const std::string& _value) {}
    00350     #endif
    00351
    00352     TiPullXmlNode* LinkActiveChild(TiPullXmlNode* node);
    00353
    00354     /// One step up the DOM.
    00355     TiPullXmlNode* Parent() const                   { return parent; }
    00356
    00357     TiPullXmlNode* FirstChild( );           ///< The first child of this node with the matching 'value'. Will be null if none found.
    00358
    00359     TiPullXmlNode* FirstChild( const char * value, NodeType _type );            ///< The first child of this node with the matching 'value'. Will be null if none found.
    00360
    00361     #ifdef TIXML_USE_STL
    00362     TiPullXmlNode* FirstChild( const std::string& _value, NodeType _type )
    00363     {   return FirstChild (_value.c_str(), _type);  }   ///< STL std::string form.
    00364     #endif
    00365
    00366     TiPullXmlNode* NextSibling( ) ;
    00367
    00368     /// Navigate to a sibling node with the given 'value'.
    00369     TiPullXmlNode* NextSibling( const char * _value, NodeType _type ) ;
    00370
    00371     #ifdef TIXML_USE_STL
    00372     TiPullXmlNode* NextSibling( const std::string& _value, NodeType _type )
    00373     {   return NextSibling (_value.c_str(), _type); }   ///< STL std::string form.
    00374     #endif
    00375
    00376     /** Convenience function to get through elements.
    00377         Calls NextSibling and ToElement. Will skip all non-Element
    00378         nodes. Returns 0 if there is not another element.
    00379     */
    00380     TiPullXmlElement* NextSiblingElement( ) ;
    00381     TiPullXmlElement* NextSiblingElement( const char * _value )
    00382     { TiPullXmlNode* n = NextSibling(_value, ELEMENT); return n ? n->ToElement() : 0; }
    00383
    00384     #ifdef TIXML_USE_STL
    00385     TiPullXmlElement* NextSiblingElement( const std::string& _value)
    00386     {   return NextSiblingElement (_value.c_str ());    }   ///< STL std::string form.
    00387     #endif
    00388
    00389     /// Convenience function to get through elements.
    00390     TiPullXmlElement* FirstChildElement( ) ;
    00391
    00392     /// Convenience function to get through elements.
    00393     TiPullXmlElement* FirstChildElement( const char * _value )
    00394     { TiPullXmlNode* n = FirstChild(_value, ELEMENT); return n ? n->ToElement() : 0; }
    00395
    00396     #ifdef TIXML_USE_STL
    00397     TiPullXmlElement* FirstChildElement( const std::string& _value ) const
    00398     {   return FirstChildElement (_value.c_str ()); }   ///< STL std::string form.
    00399     #endif
    00400
    00401     /** Query the type (as an enumerated value, above) of this node.
    00402         The possible types are: DOCUMENT, ELEMENT, COMMENT,
    00403                                 UNKNOWN, TEXT, and DECLARATION.
    00404     */
    00405     virtual NodeType Type() const   { return type; }
    00406
    00407     bool hasChildren() const { return (endPosOpen.filepos >= 0); }
    00408
    00409     /** Return a pointer to the Document this node lives in.
    00410         Returns null if not in a document.
    00411     */
    00412     TiPullXmlDocument* GetDocument() const;
    00413
    00414     TiPullXmlDocument* ToDocument()const        { return ( this && type == DOCUMENT ) ? (TiPullXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00415     TiPullXmlElement*  ToElement() const        { return ( this && type == ELEMENT  ) ? (TiPullXmlElement*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00416     TiPullXmlComment*  ToComment() const        { return ( this && type == COMMENT  ) ? (TiPullXmlComment*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00417     TiPullXmlUnknown*  ToUnknown() const        { return ( this && type == UNKNOWN  ) ? (TiPullXmlUnknown*)  this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00418     TiPullXmlText*     ToText()     const       { return ( this && type == TEXT     ) ? (TiPullXmlText*)     this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00419     TiPullXmlDeclaration* ToDeclaration()const  { return ( this && type == DECLARATION ) ? (TiPullXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
    00420
    00421     /** Return the position, in the original source file, of this node or attribute.
    00422         The row and column are 1-based. (That is the first row and first column is
    00423         1,1). If the returns values are 0 or less, then the parser does not have
    00424         a row and column value.
    00425
    00426         Generally, the row and column value will be set when the TiXmlDocument::Load(),
    00427         TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set
    00428         when the DOM was created from operator>>.
    00429
    00430         The values reflect the initial load. Once the DOM is modified programmatically
    00431         (by adding or changing nodes and attributes) the new values will NOT update to
    00432         reflect changes in the document.
    00433
    00434         There is a minor performance cost to computing the row and column. Computation
    00435         can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value.
    00436
    00437         @sa TiXmlDocument::SetTabSize()
    00438     */
    00439     int Row() const;
    00440     int Column() const;
    00441
    00442 protected:
    00443     TiPullXmlNode( NodeType type );
    00444
    00445     #ifdef TIXML_USE_STL
    00446         // The real work of the input operator.
    00447         virtual void StreamIn( TIXML_ISTREAM* in, TIXML_STRING* tag ) = 0;
    00448     #endif
    00449
    00450     // Figure out what is at *p, and parse it. Returns null if it is not an xml node.
    00451     TiPullXmlNode* Identify( const char* start ) const;
    00452
    00453     bool FindElementClose(ParsePosition in, const char* &out);
    00454
    00455     // Internal Value function returning a TIXML_STRING
    00456     TIXML_STRING SValue() const { return value ; }
    00457
    00458     TiPullXmlNode*      parent;
    00459     TiPullXmlNode*      activeChild;
    00460     NodeType const      type;
    00461
    00462     TiPullXmlCursor     endPosOpen;
    00463     TiPullXmlCursor     endPosClose;
    00464
    00465     TIXML_STRING        value;
    00466 };
    00467
    00468
    00469 /** An attribute is a name-value pair. Elements have an arbitrary
    00470     number of attributes, each with a unique name.
    00471
    00472     @note The attributes are not TiXmlNodes, since they are not
    00473           part of the tinyXML document object model. There are other
    00474           suggested ways to look at this problem.
    00475 */
    00476 class TiPullXmlAttribute : public TiPullXmlBase
    00477 {
    00478     friend class TiPullXmlAttributeSet;
    00479
    00480 public:
    00481     /// Construct an empty attribute.
    00482     TiPullXmlAttribute()
    00483     {
    00484         document = 0;
    00485         prev = next = 0;
    00486     }
    00487
    00488     #ifdef TIXML_USE_STL
    00489     /// std::string constructor.
    00490     TiPullXmlAttribute( const std::string& _name, const std::string& _value )
    00491     {
    00492         name = _name;
    00493         value = _value;
    00494         document = 0;
    00495         prev = next = 0;
    00496     }
    00497     #endif
    00498
    00499     /// Construct an attribute with a name and value.
    00500     TiPullXmlAttribute( const char * _name, const char * _value )
    00501     {
    00502         name = _name;
    00503         value = _value;
    00504         document = 0;
    00505         prev = next = 0;
    00506     }
    00507
    00508     const char*     Name()  const       { return name.c_str (); }       ///< Return the name of this attribute.
    00509     const char*     Value() const       { return value.c_str (); }      ///< Return the value of this attribute.
    00510     const int       IntValue() const;                                   ///< Return the value of this attribute, converted to an integer.
    00511     const double    DoubleValue() const;                                ///< Return the value of this attribute, converted to a double.
    00512
    00513     /** QueryIntValue examines the value string. It is an alternative to the
    00514         IntValue() method with richer error checking.
    00515         If the value is an integer, it is stored in 'value' and
    00516         the call returns TIXML_SUCCESS. If it is not
    00517         an integer, it returns TIXML_WRONG_TYPE.
    00518
    00519         A specialized but useful call. Note that for success it returns 0,
    00520         which is the opposite of almost all other TinyXml calls.
    00521     */
    00522     int QueryIntValue( int* value ) const;
    00523     /// QueryDoubleValue examines the value string. See QueryIntValue().
    00524     int QueryDoubleValue( double* value ) const;
    00525
    00526     void SetName( const char* _name )   { name = _name; }               ///< Set the name of this attribute.
    00527     void SetValue( const char* _value ) { value = _value; }             ///< Set the value.
    00528
    00529     void SetIntValue( int value );                                      ///< Set the value from an integer.
    00530     void SetDoubleValue( double value );                                ///< Set the value from a double.
    00531
    00532     #ifdef TIXML_USE_STL
    00533     /// STL std::string form.
    00534     void SetName( const std::string& _name )
    00535     {
    00536         StringToBuffer buf( _name );
    00537         SetName ( buf.buffer ? buf.buffer : "error" );
    00538     }
    00539     /// STL std::string form.
    00540     void SetValue( const std::string& _value )
    00541     {
    00542         StringToBuffer buf( _value );
    00543         SetValue( buf.buffer ? buf.buffer : "error" );
    00544     }
    00545     #endif
    00546
    00547     /// Get the next sibling attribute in the DOM. Returns null at end.
    00548     TiPullXmlAttribute* Next() const;
    00549     /// Get the previous sibling attribute in the DOM. Returns null at beginning.
    00550     TiPullXmlAttribute* Previous() const;
    00551
    00552     bool operator==( const TiPullXmlAttribute& rhs ) const { return rhs.name == name; }
    00553     bool operator<( const TiPullXmlAttribute& rhs )  const { return name < rhs.name; }
    00554     bool operator>( const TiPullXmlAttribute& rhs )  const { return name > rhs.name; }
    00555
    00556     /*  [internal use]
    00557         Attribtue parsing starts: first letter of the name
    00558                          returns: the next char after the value end quote
    00559     */
    00560     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00561
    00562     // [internal use]
    00563     virtual void Print( FILE* cfile, int depth ) const;
    00564
    00565     virtual void StreamOut( TIXML_OSTREAM * out ) const;
    00566     // [internal use]
    00567     // Set the document pointer so the attribute can report errors.
    00568     void SetDocument( TiPullXmlDocument* doc )  { document = doc; }
    00569
    00570 private:
    00571     TiPullXmlDocument*  document;   // A pointer back to a document, for error reporting.
    00572     TIXML_STRING name;
    00573     TIXML_STRING value;
    00574     TiPullXmlAttribute* prev;
    00575     TiPullXmlAttribute* next;
    00576 };
    00577
    00578
    00579 /*  A class used to manage a group of attributes.
    00580     It is only used internally, both by the ELEMENT and the DECLARATION.
    00581
    00582     The set can be changed transparent to the Element and Declaration
    00583     classes that use it, but NOT transparent to the Attribute
    00584     which has to implement a next() and previous() method. Which makes
    00585     it a bit problematic and prevents the use of STL.
    00586
    00587     This version is implemented with circular lists because:
    00588         - I like circular lists
    00589         - it demonstrates some independence from the (typical) doubly linked list.
    00590 */
    00591 class TiPullXmlAttributeSet
    00592 {
    00593 public:
    00594     TiPullXmlAttributeSet();
    00595     ~TiPullXmlAttributeSet();
    00596
    00597     void Add( TiPullXmlAttribute* attribute );
    00598     void Remove( TiPullXmlAttribute* attribute );
    00599
    00600     TiPullXmlAttribute* First() const   { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
    00601     TiPullXmlAttribute* Last()  const   { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
    00602     TiPullXmlAttribute* Find( const char * name ) const;
    00603
    00604 private:
    00605     TiPullXmlAttribute sentinel;
    00606 };
    00607
    00608
    00609 /** The element is a container class. It has a value, the element name,
    00610     and can contain other elements, text, comments, and unknowns.
    00611     Elements also contain an arbitrary number of attributes.
    00612 */
    00613 class TiPullXmlElement : public TiPullXmlNode
    00614 {
    00615 public:
    00616     /// Construct an element.
    00617     TiPullXmlElement (const char * in_value);
    00618
    00619     #ifdef TIXML_USE_STL
    00620     /// std::string constructor.
    00621     TiPullXmlElement( const std::string& _value ) :     TiPullXmlNode( TiPullXmlNode::ELEMENT )
    00622     {
    00623         firstChild = lastChild = 0;
    00624         value = _value;
    00625     }
    00626     #endif
    00627
    00628     virtual ~TiPullXmlElement();
    00629
    00630     /** Given an attribute name, Attribute() returns the value
    00631         for the attribute of that name, or null if none exists.
    00632     */
    00633     const char* Attribute( const char* name ) const;
    00634
    00635     /** Given an attribute name, Attribute() returns the value
    00636         for the attribute of that name, or null if none exists.
    00637         If the attribute exists and can be converted to an integer,
    00638         the integer value will be put in the return 'i', if 'i'
    00639         is non-null.
    00640     */
    00641     const char* Attribute( const char* name, int* i ) const;
    00642
    00643     /** Given an attribute name, Attribute() returns the value
    00644         for the attribute of that name, or null if none exists.
    00645         If the attribute exists and can be converted to an double,
    00646         the double value will be put in the return 'd', if 'd'
    00647         is non-null.
    00648     */
    00649     const char* Attribute( const char* name, double* d ) const;
    00650
    00651     /** QueryIntAttribute examines the attribute - it is an alternative to the
    00652         Attribute() method with richer error checking.
    00653         If the attribute is an integer, it is stored in 'value' and
    00654         the call returns TIXML_SUCCESS. If it is not
    00655         an integer, it returns TIXML_WRONG_TYPE. If the attribute
    00656         does not exist, then TIXML_NO_ATTRIBUTE is returned.
    00657     */
    00658     int QueryIntAttribute( const char* name, int* value ) const;
    00659     /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute().
    00660     int QueryDoubleAttribute( const char* name, double* value ) const;
    00661
    00662     #ifdef TIXML_USE_STL
    00663     const char* Attribute( const std::string& name ) const              { return Attribute( name.c_str() ); }
    00664     const char* Attribute( const std::string& name, int* i ) const      { return Attribute( name.c_str(), i ); }
    00665     #endif
    00666
    00667     TiPullXmlAttribute* FirstAttribute() const  { return attributeSet.First(); }        ///< Access the first attribute in this element.
    00668     TiPullXmlAttribute* LastAttribute() const   { return attributeSet.Last(); }     ///< Access the last attribute in this element.
    00669
    00670     // [internal use]
    00671
    00672     virtual void Print( FILE* cfile, int depth ) const;
    00673
    00674 protected:
    00675
    00676     // Used to be public [internal use]
    00677     #ifdef TIXML_USE_STL
    00678         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00679     #endif
    00680     virtual void StreamOut( TIXML_OSTREAM * out ) const;
    00681
    00682     /*  [internal use]
    00683         Attribtue parsing starts: next char past '<'
    00684                          returns: next char past '>'
    00685     */
    00686     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00687
    00688 private:
    00689     TiPullXmlAttributeSet attributeSet;
    00690 };
    00691
    00692
    00693 /** An XML comment.
    00694 */
    00695 class TiPullXmlComment : public TiPullXmlNode
    00696 {
    00697 public:
    00698     /// Constructs an empty comment.
    00699     TiPullXmlComment() : TiPullXmlNode( TiPullXmlNode::COMMENT ) {}
    00700     virtual ~TiPullXmlComment() {}
    00701
    00702     // [internal use]
    00703     virtual void Print( FILE* cfile, int depth ) const;
    00704 protected:
    00705     // used to be public
    00706     #ifdef TIXML_USE_STL
    00707         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00708     #endif
    00709     virtual void StreamOut( TIXML_OSTREAM * out ) const;
    00710     /*  [internal use]
    00711         Attribtue parsing starts: at the ! of the !--
    00712                          returns: next char past '>'
    00713     */
    00714     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00715 };
    00716
    00717
    00718 /** XML text. Contained in an element.
    00719 */
    00720 class TiPullXmlText : public TiPullXmlNode
    00721 {
    00722     friend class TiPullXmlElement;
    00723 public:
    00724     TiPullXmlText( ) : TiPullXmlNode (TiPullXmlNode::TEXT)
    00725     { }
    00726     /// Constructor.
    00727     TiPullXmlText (const char * initValue) : TiPullXmlNode (TiPullXmlNode::TEXT)
    00728     { SetValue( initValue ); }
    00729     virtual ~TiPullXmlText() {}
    00730
    00731     #ifdef TIXML_USE_STL
    00732     /// Constructor.
    00733     TiPullXmlText( const std::string& initValue ) : TiPullXmlNode (TiPullXmlNode::TEXT)
    00734     { SetValue( initValue ); }
    00735     #endif
    00736
    00737     // [internal use]
    00738     virtual void Print( FILE* cfile, int depth ) const;
    00739
    00740 protected :
    00741     virtual void StreamOut ( TIXML_OSTREAM * out ) const;
    00742     // [internal use]
    00743     bool Blank() const; // returns true if all white space and new lines
    00744     /*  [internal use]
    00745             Attribtue parsing starts: First char of the text
    00746                              returns: next char past '>'
    00747     */
    00748     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00749     // [internal use]
    00750     #ifdef TIXML_USE_STL
    00751         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00752     #endif
    00753 };
    00754
    00755
    00756 /** In correct XML the declaration is the first entry in the file.
    00757     @verbatim
    00758         <?xml version="1.0" standalone="yes"?>
    00759     @endverbatim
    00760
    00761     TinyXml will happily read or write files without a declaration,
    00762     however. There are 3 possible attributes to the declaration:
    00763     version, encoding, and standalone.
    00764
    00765     Note: In this version of the code, the attributes are
    00766     handled as special cases, not generic attributes, simply
    00767     because there can only be at most 3 and they are always the same.
    00768 */
    00769 class TiPullXmlDeclaration : public TiPullXmlNode
    00770 {
    00771 public:
    00772     /// Construct an empty declaration.
    00773     TiPullXmlDeclaration()   : TiPullXmlNode( TiPullXmlNode::DECLARATION ) {}
    00774
    00775 #ifdef TIXML_USE_STL
    00776     /// Constructor.
    00777     TiPullXmlDeclaration(   const std::string& _version,
    00778                         const std::string& _encoding,
    00779                         const std::string& _standalone )
    00780             : TiPullXmlNode( TiPullXmlNode::DECLARATION )
    00781     {
    00782         version = _version;
    00783         encoding = _encoding;
    00784         standalone = _standalone;
    00785     }
    00786 #endif
    00787
    00788     /// Construct.
    00789     TiPullXmlDeclaration(   const char* _version,
    00790                         const char* _encoding,
    00791                         const char* _standalone );
    00792
    00793     virtual ~TiPullXmlDeclaration() {}
    00794
    00795     /// Version. Will return empty if none was found.
    00796     const char * Version() const        { return version.c_str (); }
    00797     /// Encoding. Will return empty if none was found.
    00798     const char * Encoding() const       { return encoding.c_str (); }
    00799     /// Is this a standalone document?
    00800     const char * Standalone() const     { return standalone.c_str (); }
    00801
    00802     // [internal use]
    00803     virtual void Print( FILE* cfile, int depth ) const;
    00804
    00805 protected:
    00806     // used to be public
    00807     #ifdef TIXML_USE_STL
    00808         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00809     #endif
    00810     virtual void StreamOut ( TIXML_OSTREAM * out) const;
    00811     //  [internal use]
    00812     //  Attribtue parsing starts: next char past '<'
    00813     //                   returns: next char past '>'
    00814
    00815     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00816
    00817 private:
    00818     TIXML_STRING version;
    00819     TIXML_STRING encoding;
    00820     TIXML_STRING standalone;
    00821 };
    00822
    00823
    00824 /** Any tag that tinyXml doesn't recognize is saved as an
    00825     unknown. It is a tag of text, but should not be modified.
    00826     It will be written back to the XML, unchanged, when the file
    00827     is saved.
    00828 */
    00829 class TiPullXmlUnknown : public TiPullXmlNode
    00830 {
    00831 public:
    00832     TiPullXmlUnknown() : TiPullXmlNode( TiPullXmlNode::UNKNOWN ) {}
    00833     virtual ~TiPullXmlUnknown() {}
    00834
    00835     // [internal use]
    00836     virtual void Print( FILE* cfile, int depth ) const;
    00837 protected:
    00838     #ifdef TIXML_USE_STL
    00839         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00840     #endif
    00841     virtual void StreamOut ( TIXML_OSTREAM * out ) const;
    00842     /*  [internal use]
    00843         Attribute parsing starts: First char of the text
    00844                          returns: next char past '>'
    00845     */
    00846     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00847 };
    00848
    00849
    00850 /** Always the top level node. A document binds together all the
    00851     XML pieces. It can be saved, loaded, and printed to the screen.
    00852     The 'value' of a document node is the xml file name.
    00853 */
    00854 class TiPullXmlDocument : public TiPullXmlNode
    00855 {
    00856     friend class TiPullXmlNode;
    00857 public:
    00858     /// Create an empty document, that has no name.
    00859     TiPullXmlDocument();
    00860     /// Create a document with a name. The name of the document is also the filename of the xml.
    00861     TiPullXmlDocument( const char * documentName );
    00862
    00863     #ifdef TIXML_USE_STL
    00864     /// Constructor.
    00865     TiPullXmlDocument( const std::string& documentName ) :
    00866         TiPullXmlNode( TiPullXmlNode::DOCUMENT )
    00867     {
    00868         value = documentName;
    00869         error = false;
    00870     }
    00871     #endif
    00872
    00873     virtual ~TiPullXmlDocument() {}
    00874
    00875     /** Load a file using the current document value.
    00876         Returns true if successful. Will delete any existing
    00877         document data before loading.
    00878     */
    00879     bool LoadFile();
    00880     /// Save a file using the current document value. Returns true if successful.
    00881     bool SaveFile() const;
    00882     /// Load a file using the given filename. Returns true if successful.
    00883     bool LoadFile( const char * filename );
    00884     /// Save a file using the given filename. Returns true if successful.
    00885     bool SaveFile( const char * filename ) const;
    00886
    00887     #ifdef TIXML_USE_STL
    00888     bool LoadFile( const std::string& filename )            ///< STL std::string version.
    00889     {
    00890         StringToBuffer f( filename );
    00891         return ( f.buffer && LoadFile( f.buffer ));
    00892     }
    00893     bool SaveFile( const std::string& filename ) const      ///< STL std::string version.
    00894     {
    00895         StringToBuffer f( filename );
    00896         return ( f.buffer && SaveFile( f.buffer ));
    00897     }
    00898     #endif
    00899
    00900     /** Parse the given null terminated block of xml data.
    00901     */
    00902     virtual bool Parse( ParsePosition in, const char* &out, bool throwaway );
    00903
    00904     /** Get the root element -- the only top level element -- of the document.
    00905         In well formed XML, there should only be one. TinyXml is tolerant of
    00906         multiple elements at the document level.
    00907     */
    00908     TiPullXmlElement* RootElement()         { return FirstChildElement(); }
    00909
    00910     /** If an error occurs, Error will be set to true. Also,
    00911         - The ErrorId() will contain the integer identifier of the error (not generally useful)
    00912         - The ErrorDesc() method will return the name of the error. (very useful)
    00913         - The ErrorRow() and ErrorCol() will return the location of the error (if known)
    00914     */
    00915     bool Error() const                      { return error; }
    00916
    00917     /// Contains a textual (english) description of the error if one occurs.
    00918     const char * ErrorDesc() const  { return errorDesc.c_str (); }
    00919
    00920     /** Generally, you probably want the error string ( ErrorDesc() ). But if you
    00921         prefer the ErrorId, this function will fetch it.
    00922     */
    00923     const int ErrorId() const               { return errorId; }
    00924
    00925     /** Returns the location (if known) of the error. The first column is column 1,
    00926         and the first row is row 1. A value of 0 means the row and column wasn't applicable
    00927         (memory errors, for example, have no row/column) or the parser lost the error. (An
    00928         error in the error reporting, in that case.)
    00929
    00930         @sa SetTabSize, Row, Column
    00931     */
    00932     int ErrorRow() const;
    00933     int ErrorCol() const;
    00934
    00935     /** By calling this method, with a tab size
    00936         greater than 0, the row and column of each node and attribute is stored
    00937         when the file is loaded. Very useful for tracking the DOM back in to
    00938         the source file.
    00939
    00940         The tab size is required for calculating the location of nodes. If not
    00941         set, the default of 4 is used. The tabsize is set per document. Setting
    00942         the tabsize to 0 disables row/column tracking.
    00943
    00944         Note that row and column tracking is not supported when using operator>>.
    00945
    00946         The tab size needs to be enabled before the parse or load. Correct usage:
    00947         @verbatim
    00948         TiPullXmlDocument doc;
    00949         doc.SetTabSize( 8 );
    00950         doc.Load( "myfile.xml" );
    00951         @endverbatim
    00952
    00953         @sa Row, Column
    00954     */
    00955     void SetTabSize( int _tabsize )     { tabsize = _tabsize; }
    00956
    00957     int TabSize() const { return tabsize; }
    00958
    00959     /** If you have handled the error, it can be reset with this call. The error
    00960         state is automatically cleared if you Parse a new XML block.
    00961     */
    00962     void ClearError()                       {   error = false;
    00963                                                 errorId = 0;
    00964                                                 errorDesc = "";
    00965                                                 errorLocation.Clear();
    00966                                                 //errorLocation.last = 0;
    00967                                             }
    00968
    00969     /** Dump the document to standard out. */
    00970     void Print() const                      { Print( stdout, 0 ); }
    00971
    00972     // [internal use]
    00973     virtual void Print( FILE* cfile, int depth = 0 ) const;
    00974     // [internal use]
    00975     void SetError( int err, const char* errorLocation, TiPullXmlParsingData* prevData );
    00976
    00977     const char* getFileBuffer() const { return fileBuffer; }
    00978     void setFileBuffer(const char* buf) { fileBuffer = buf; }
    00979
    00980 protected :
    00981     virtual void StreamOut ( TIXML_OSTREAM * out) const;
    00982     #ifdef TIXML_USE_STL
    00983         virtual void StreamIn( TIXML_ISTREAM * in, TIXML_STRING * tag );
    00984     #endif
    00985
    00986     void FindAllLineStarts( const char* p );
    00987     int FindLine(TiPullXmlCursor location) const;
    00988
    00989 private:
    00990     bool error;
    00991     int  errorId;
    00992     TIXML_STRING errorDesc;
    00993     int tabsize;
    00994     TiPullXmlCursor errorLocation;
    00995     std::deque<int> lineStarts;
    00996     const char* fileBuffer;
    00997 };
    00998
    00999
    01000 /**
    01001     A TiXmlHandle is a class that wraps a node pointer with null checks; this is
    01002     an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml
    01003     DOM structure. It is a separate utility class.
    01004
    01005     Take an example:
    01006     @verbatim
    01007     <Document>
    01008         <Element attributeA = "valueA">
    01009             <Child attributeB = "value1" />
    01010             <Child attributeB = "value2" />
    01011         </Element>
    01012     <Document>
    01013     @endverbatim
    01014
    01015     Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very
    01016     easy to write a *lot* of code that looks like:
    01017
    01018     @verbatim
    01019     TiXmlElement* root = document.FirstChildElement( "Document" );
    01020     if ( root )
    01021     {
    01022         TiXmlElement* element = root->FirstChildElement( "Element" );
    01023         if ( element )
    01024         {
    01025             TiXmlElement* child = element->FirstChildElement( "Child" );
    01026             if ( child )
    01027             {
    01028                 TiXmlElement* child2 = child->NextSiblingElement( "Child" );
    01029                 if ( child2 )
    01030                 {
    01031                     // Finally do something useful.
    01032     @endverbatim
    01033
    01034     And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity
    01035     of such code. A TiXmlHandle checks for null pointers so it is perfectly safe
    01036     and correct to use:
    01037
    01038     @verbatim
    01039     TiXmlHandle docHandle( &document );
    01040     TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).Element();
    01041     if ( child2 )
    01042     {
    01043         // do something useful
    01044     @endverbatim
    01045
    01046     Which is MUCH more concise and useful.
    01047
    01048     It is also safe to copy handles - internally they are nothing more than node pointers.
    01049     @verbatim
    01050     TiXmlHandle handleCopy = handle;
    01051     @endverbatim
    01052
    01053     What they should not be used for is iteration:
    01054
    01055     @verbatim
    01056     int i=0;
    01057     while ( true )
    01058     {
    01059         TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).Element();
    01060         if ( !child )
    01061             break;
    01062         // do something
    01063         ++i;
    01064     }
    01065     @endverbatim
    01066
    01067     It seems reasonable, but it is in fact two embedded while loops. The Child method is
    01068     a linear walk to find the element, so this code would iterate much more than it needs
    01069     to. Instead, prefer:
    01070
    01071     @verbatim
    01072     TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).Element();
    01073
    01074     for( child; child; child=child->NextSiblingElement() )
    01075     {
    01076         // do something
    01077     }
    01078     @endverbatim
    01079 */
    01080 class TiPullXmlHandle
    01081 {
    01082 public:
    01083     /// Create a handle from any node (at any depth of the tree.) This can be a null pointer.
    01084     TiPullXmlHandle( TiPullXmlNode* node )          { this->node = node; }
    01085     /// Copy constructor
    01086     TiPullXmlHandle( const TiPullXmlHandle& ref )   { this->node = ref.node; }
    01087
    01088     /// Return a handle to the first child node.
    01089     TiPullXmlHandle FirstChild() const;
    01090     /// Return a handle to the first child node with the given name.
    01091     TiPullXmlHandle FirstChild( const char * value, TiPullXmlNode::NodeType nType ) const;
    01092     /// Return a handle to the first child element.
    01093     TiPullXmlHandle FirstChildElement() const;
    01094     /// Return a handle to the first child element with the given name.
    01095     TiPullXmlHandle FirstChildElement( const char * value ) const;
    01096
    01097     /** Return a handle to the "index" child with the given name.
    01098         The first child is 0, the second 1, etc.
    01099     */
    01100 //  TiPullXmlHandle Child( const char* value, int index ) const;
    01101     /** Return a handle to the "index" child.
    01102         The first child is 0, the second 1, etc.
    01103     */
    01104     TiPullXmlHandle Child( int index ) const;
    01105     /** Return a handle to the "index" child element with the given name.
    01106         The first child element is 0, the second 1, etc. Note that only TiPullXmlElements
    01107         are indexed: other types are not counted.
    01108     */
    01109     TiPullXmlHandle ChildElement( const char* value, int index ) const;
    01110     /** Return a handle to the "index" child element.
    01111         The first child element is 0, the second 1, etc. Note that only TiPullXmlElements
    01112         are indexed: other types are not counted.
    01113     */
    01114     TiPullXmlHandle ChildElement( int index ) const;
    01115
    01116     #ifdef TIXML_USE_STL
    01117     TiPullXmlHandle FirstChild( const std::string& _value ) const           { return FirstChild( _value.c_str() ); }
    01118     TiPullXmlHandle FirstChildElement( const std::string& _value ) const        { return FirstChildElement( _value.c_str() ); }
    01119
    01120     TiPullXmlHandle Child( const std::string& _value, int index ) const         { return Child( _value.c_str(), index ); }
    01121     TiPullXmlHandle ChildElement( const std::string& _value, int index ) const  { return ChildElement( _value.c_str(), index ); }
    01122     #endif
    01123
    01124     /// Return the handle as a TiPullXmlNode. This may return null.
    01125     TiPullXmlNode* Node() const         { return node; }
    01126     /// Return the handle as a TiPullXmlElement. This may return null.
    01127     TiPullXmlElement* Element() const   { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); }
    01128     /// Return the handle as a TiPullXmlText. This may return null.
    01129     TiPullXmlText* Text() const         { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); }
    01130
    01131 private:
    01132     TiPullXmlNode* node;
    01133 };
    01134
    01135 // typedefs back to the old interface class names
    01136 typedef TiPullXmlDocument       TiXmlDocument;
    01137 typedef TiPullXmlElement        TiXmlElement;
    01138 typedef TiPullXmlComment        TiXmlComment;
    01139 typedef TiPullXmlUnknown        TiXmlUnknown;
    01140 typedef TiPullXmlAttribute      TiXmlAttribute;
    01141 typedef TiPullXmlText           TiXmlText;
    01142 typedef TiPullXmlDeclaration    TiXmlDeclaration;
    01143 typedef TiPullXmlHandle         TiXmlHandle;
    01144
    01145
    01146
    01147 #endif // TINYXML_INCLUDED
    01148