ticpp.h

Go to the documentation of this file.
00001 /*
00002 http://code.google.com/p/ticpp/
00003 Copyright (c) 2006 Ryan Pusztai, Ryan Mulder
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy of
00006 this software and associated documentation files (the "Software"), to deal in
00007 the Software without restriction, including without limitation the rights to
00008 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
00009 the Software, and to permit persons to whom the Software is furnished to do so,
00010 subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in all
00013 copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
00017 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
00018 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
00019 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 */
00022 
00040 #ifdef TIXML_USE_TICPP
00041 
00042 #ifndef TICPP_INCLUDED
00043 #define TICPP_INCLUDED
00044 
00045 #include "tinyxml.h"
00046 #include <sstream>
00047 #include <vector>
00048 #include <memory>
00049 
00060 namespace ticpp
00061 {
00065     class Exception
00066     {
00067     public:
00068         Exception( const std::string& details );
00069 
00070         std::string m_details; 
00071     };
00072 
00077     #define THROW( message )                                                                                    \
00078         std::stringstream hopefullyThisNameWontConflictWithOtherVariables;                                      \
00079         std::string file( __FILE__ );                                                                           \
00080         file = file.substr( file.find_last_of( "\\/" ) + 1 );                                                   \
00081         hopefullyThisNameWontConflictWithOtherVariables << message << " <" << file << "@" << __LINE__ << ">";   \
00082         throw Exception( hopefullyThisNameWontConflictWithOtherVariables.str() );
00083 
00085     class Base
00086     {
00087     public:
00088 
00094         template < class T >
00095             std::string ToString( const T& value )
00096         {
00097             std::stringstream convert;
00098             convert << value;
00099             if ( convert.fail() )
00100             {
00101                 THROW( "Could not convert value to text" );
00102             }
00103             return convert.str();
00104         }
00105 
00106         std::string ToString( const std::string& value )
00107         {
00108             return value;
00109         }
00110 
00117         template < class T >
00118             void FromString( const std::string& temp, T* out )
00119         {
00120             std::istringstream val( temp );
00121             val >> *out;
00122 
00123             if ( val.fail() )
00124             {
00125                 THROW( "Could not convert \"" << temp << "\" to target type" );
00126             }
00127         }
00128 
00132         void FromString( const std::string& temp, std::string* out )
00133         {
00134             *out = temp;
00135         }
00136 
00141         int Row()
00142         {
00143             return GetBasePointer()->Row();
00144         }
00145 
00150         int Column()
00151         {
00152             return GetBasePointer()->Column();
00153         }
00154 
00158         virtual ~Base()
00159         {
00160             DeleteSpawnedWrappers();
00161         }
00162 
00163     protected:
00164         TiCppRCImp* m_impRC;    
00166         std::vector< Base* > m_spawnedWrappers; 
00174         void SetImpRC( TiXmlBase* node )
00175         {
00176             m_impRC = node->m_tiRC;
00177         }
00178 
00179         void ValidatePointer()
00180         {
00181             if ( m_impRC->IsNull() )
00182             {
00183                 THROW( "Internal TiXml Pointer is NULL" );
00184             }
00185         }
00186 
00191         void DeleteSpawnedWrappers()
00192         {
00193             std::vector< Base* >::reverse_iterator wrapper;
00194             for ( wrapper = m_spawnedWrappers.rbegin(); wrapper != m_spawnedWrappers.rend(); ++wrapper )
00195             {
00196                 delete *wrapper;
00197             }
00198             m_spawnedWrappers.clear();
00199         }
00200 
00205         virtual TiXmlBase* GetBasePointer() = 0;
00206     };
00207 
00211     class Attribute : public Base
00212     {
00213     private:
00214         TiXmlAttribute* m_tiXmlPointer;
00215         TiXmlBase* GetBasePointer()
00216         {
00217             ValidatePointer();
00218             return m_tiXmlPointer;
00219         }
00220 
00221     public:
00225         Attribute();
00226 
00233         Attribute( const std::string& name, const std::string& value );
00234 
00241         Attribute( TiXmlAttribute* attribute );
00242 
00250         template < class T >
00251             void GetValue( T* value )
00252         {
00253             ValidatePointer();
00254             FromString( m_tiXmlPointer->ValueStr(), value );
00255         }
00256 
00263         std::string Value();
00264 
00271         template < class T >
00272             void SetValue( const T& value )
00273         {
00274             ValidatePointer();
00275             m_tiXmlPointer->SetValue( ToString( value ) );
00276         }
00277 
00285         template < class T >
00286             void GetName( T* name )
00287         {
00288             ValidatePointer();
00289             FromString( m_tiXmlPointer->Name(), name );
00290         }
00291 
00298         std::string Name();
00299 
00306         template < class T >
00307             void SetName( const T& name )
00308         {
00309             ValidatePointer();
00310             m_tiXmlPointer->SetName( ToString( name ) );
00311         }
00312 
00317         void operator=( const Attribute& copy );
00318 
00323         Attribute( const Attribute& copy );
00324 
00325         /*
00326         Decrements reference count.
00327         */
00328         ~Attribute();
00329 
00333         Attribute* Next( bool throwIfNoAttribute = true );
00334 
00338         Attribute* Previous( bool throwIfNoAttribute = true );
00339 
00347         void IterateNext( const std::string&, Attribute** next );
00348 
00356         void IteratePrevious( const std::string&, Attribute** previous );
00357 
00361         virtual void Print( FILE* file, int depth );
00362 
00363     private:
00364 
00372         void SetTiXmlPointer( TiXmlAttribute* newPointer );
00373     };
00374 
00375     // Forward Declaration so Node can return Element* and Document*
00376     class Element;
00377     class Document;
00378     class Text;
00379     class Comment;
00380     class Declaration;
00381 
00385     class Node : public Base
00386     {
00387     public:
00388 
00396         template < class T >
00397             void GetValue( T* value)
00398         {
00399             FromString( GetTiXmlPointer()->ValueStr(), value );
00400         }
00401 
00408         std::string Value();
00409 
00416         template < class T >
00417             void SetValue( const T& value )
00418         {
00419             GetTiXmlPointer()->SetValue( ToString( value ) );
00420         }
00421 
00426         void Clear();
00427 
00436         Node* Parent( bool throwIfNoParent = true );
00437 
00447         Node* FirstChild( bool throwIfNoChildren = true );
00448 
00459         Node* FirstChild( const char* value, bool throwIfNoChildren = true );
00460 
00470         Node* FirstChild( const std::string& value, bool throwIfNoChildren = true );
00471 
00481         Node* LastChild( bool throwIfNoChildren = true );
00482 
00493         Node* LastChild( const char* value, bool throwIfNoChildren = true );
00494 
00504         Node* LastChild( const std::string& value, bool throwIfNoChildren = true );
00505 
00512         Node* IterateChildren( Node* previous );
00513 
00521         Node* IterateChildren( const std::string& value, Node* previous );
00522 
00534         Node* InsertEndChild( Node& addThis );
00535 
00546         Node* LinkEndChild( Node* childNode );
00547 
00559         Node* InsertBeforeChild( Node* beforeThis, Node& addThis );
00560 
00572         Node* InsertAfterChild( Node* afterThis, Node& addThis );
00573 
00584         Node* ReplaceChild( Node* replaceThis, Node& withThis );
00585 
00594         void RemoveChild( Node* removeThis );
00595 
00604         Node* PreviousSibling( bool throwIfNoSiblings = true );
00605 
00615         Node* PreviousSibling( const std::string& value, bool throwIfNoSiblings = true );
00616 
00627         Node* PreviousSibling( const char* value, bool throwIfNoSiblings = true );
00628 
00637         Node* NextSibling( bool throwIfNoSiblings = true );
00638 
00648         Node* NextSibling( const std::string& value, bool throwIfNoSiblings = true );
00649 
00660         Node* NextSibling( const char* value, bool throwIfNoSiblings = true );
00661 
00669         template < class T >
00670             void IterateNext( const std::string& value, T** next )
00671         {
00672             Node* sibling = NextSibling( value, false );
00673             *next = dynamic_cast< T* >( sibling );
00674 
00675             while ( ( NULL != sibling ) && ( NULL == *next ) )
00676             {
00677                 sibling = sibling->NextSibling( value, false );
00678                 *next = dynamic_cast< T* >( sibling );
00679             }
00680         }
00681 
00689         template < class T >
00690             void IteratePrevious( const std::string& value, T** previous  )
00691         {
00692             Node* sibling = PreviousSibling( value, false );
00693             *previous = dynamic_cast< T* >( sibling );
00694 
00695             while ( ( NULL != sibling ) && ( NULL == *previous ) )
00696             {
00697                 sibling = sibling->PreviousSibling( value, false );
00698                 *previous = dynamic_cast< T* >( sibling );
00699             }
00700         }
00701 
00710         Element* NextSiblingElement( bool throwIfNoSiblings = true );
00711 
00720         Element* NextSiblingElement( const std::string& value, bool throwIfNoSiblings = true );
00721 
00732         Element* NextSiblingElement( const char* value, bool throwIfNoSiblings = true );
00733 
00743         Element* FirstChildElement( bool throwIfNoChildren = true );
00744 
00755         Element* FirstChildElement( const char* value, bool throwIfNoChildren = true );
00756 
00766         Element* FirstChildElement( const std::string& value, bool throwIfNoChildren = true );
00767 
00771         int Type();
00772 
00780         Document* GetDocument( bool throwIfNoDocument = true );
00781 
00787         bool NoChildren();
00788 
00795         template < class T >
00796             T* To()
00797         {
00798             T* pointer = dynamic_cast< T* >( this );
00799             if ( NULL == pointer )
00800             {
00801                 std::string thisType = typeid( this ).name();
00802                 std::string targetType = typeid( T ).name();
00803                 std::string thatType = typeid( *this ).name();
00804                 THROW( "The " << thisType.substr( 6 ) << " could not be casted to a " << targetType.substr( 6 )
00805                     << " *, because the target object is not a " << targetType.substr( 6 ) << ". (It is a " << thatType.substr( 6 ) << ")" );
00806             }
00807             return pointer;
00808         }
00809 
00815         Document* ToDocument();
00816 
00822         Element* ToElement();
00823 
00829         Comment* ToComment();
00830 
00836         Text* ToText();
00837 
00843         Declaration* ToDeclaration();
00844 
00862         std::auto_ptr< Node > Clone();
00863 
00864 
00865     protected:
00870         virtual TiXmlNode* GetTiXmlPointer() = 0;
00871 
00872         TiXmlBase* GetBasePointer()
00873         {
00874             return GetTiXmlPointer();
00875         }
00876 
00881         Node* NodeFactory( TiXmlNode* tiXmlNode, bool throwIfNull = true, bool rememberSpawnedWrapper = true );
00882 
00883     };
00884 
00886     template < class T = Node >
00887         class Iterator
00888     {
00889     private:
00890         T* m_p;                 
00891         std::string m_value;    
00893     public:
00894 
00898         T* end()
00899         {
00900             return NULL;
00901         }
00902 
00904         Iterator( const std::string& value = "" )
00905             : m_p( NULL ), m_value( value )
00906         {
00907         }
00908 
00910         Iterator( T* node, const std::string& value = "" )
00911             : m_p( node ), m_value( value )
00912         {
00913         }
00914 
00916         Iterator( const Iterator& it, const std::string& value  = "" )
00917             : m_p( it.m_p ), m_value( value )
00918         {
00919         }
00920 
00925         T* Get()
00926         {
00927             return m_p;
00928         }
00929 
00931         Iterator& operator=( const Iterator& it )
00932         {
00933             m_p = it.m_p;
00934             return *this;
00935         }
00936 
00938         Iterator& operator=( T* p )
00939         {
00940             m_p = p;
00941             return *this;
00942         }
00943 
00945         Iterator& operator++()
00946         {
00947             m_p->IterateNext( m_value, &m_p );
00948             return *this;
00949         }
00950 
00952         Iterator& operator++(int)
00953         {
00954             return this->operator ++();
00955         }
00956 
00958         Iterator& operator--()
00959         {
00960             m_p->IteratePrevious( m_value, &m_p );
00961             return *this;
00962         }
00963 
00965         Iterator& operator--(int)
00966         {
00967             return this->operator --();
00968         }
00969 
00971         bool operator!=( T* p )
00972         {
00973             return m_p != p;
00974         }
00975 
00977         bool operator!=( const Iterator& it )
00978         {
00979             return m_p != it.m_p;
00980         }
00981 
00983         bool operator==( T* p )
00984         {
00985             return m_p == p;
00986         }
00987 
00989         bool operator==( const Iterator& it )
00990         {
00991             return m_p == it.m_p;
00992         }
00993 
00995         T* operator->()
00996         {
00997             return m_p;
00998         }
00999 
01001         T& operator*()
01002         {
01003             return *m_p;
01004         }
01005     };
01006 
01008     template < class T >
01009         class NodeImp : public Node
01010     {
01011     protected:
01012 
01013         T* m_tiXmlPointer;      
01021         TiXmlNode* GetTiXmlPointer()
01022         {
01023             ValidatePointer();
01024             return m_tiXmlPointer;
01025         }
01026 
01034         void SetTiXmlPointer( T* newPointer )
01035         {
01036             m_tiXmlPointer = newPointer;
01037             SetImpRC( newPointer );
01038         }
01039 
01044         NodeImp( T* tiXmlPointer )
01045         {
01046             // Check for NULL pointers
01047             if ( NULL == tiXmlPointer )
01048             {
01049                 THROW( "Can not create a " << typeid( T ).name() );
01050             }
01051             SetTiXmlPointer( tiXmlPointer );
01052             m_impRC->IncRef();
01053         }
01054 
01060         virtual void operator=( const NodeImp<T>& copy )
01061         {
01062             DeleteSpawnedWrappers();
01063 
01064             // Dropping the reference to the old object
01065             this->m_impRC->DecRef();
01066 
01067             // Pointing to the new Object
01068             SetTiXmlPointer( copy.m_tiXmlPointer );
01069 
01070             // The internal tixml pointer changed in the above line
01071             this->m_impRC->IncRef();
01072         }
01073 
01079         NodeImp( const NodeImp<T>& copy ) : Node()
01080         {
01081             DeleteSpawnedWrappers();
01082 
01083             // Dropping the reference to the old object
01084             this->m_impRC->DecRef();
01085 
01086             // Pointing to the new Object
01087             SetTiXmlPointer( copy.m_tiXmlPointer );
01088 
01089             // The internal tixml pointer changed in the above line
01090             this->m_impRC->IncRef();
01091         }
01092 
01093     public:
01094 
01095         /*
01096         Deletes the spawned wrapper objects.
01097         Decrements reference count.
01098         */
01099         virtual ~NodeImp()
01100         {
01101             // The spawnedWrappers need to be deleted before m_tiXmlPointer
01102             DeleteSpawnedWrappers();
01103             m_impRC->DecRef();
01104         }
01105     };
01106 
01108     class Comment : public NodeImp< TiXmlComment >
01109     {
01110     public:
01111 
01115         Comment();
01116 
01120         Comment( TiXmlComment* comment );
01121 
01125         Comment( const std::string& comment );
01126     };
01127 
01129     class Text : public NodeImp< TiXmlText >
01130     {
01131     public:
01132 
01136         Text();
01137 
01142         Text( TiXmlText* text );
01143 
01148         Text( const std::string& value );
01149 
01159         template < class T >
01160             Text( const T& value )
01161                 : NodeImp< TiXmlText >( new TiXmlText( ToString( value ) ) )
01162         {
01163             m_impRC->InitRef();
01164         }
01165     };
01166 
01168     class Document : public NodeImp< TiXmlDocument >
01169     {
01170     public:
01175         Document();
01176 
01180         Document( TiXmlDocument* document );
01181 
01185         Document( const char* documentName );
01186 
01193         Document( const std::string& documentName );
01194 
01199         std::string GetAsString();
01200 
01208         void LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
01209 
01215         void SaveFile() const;
01216 
01225         void LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
01226 
01233         void SaveFile( const std::string& filename ) const;
01234 
01235     };
01236 
01238     class Element : public NodeImp< TiXmlElement >
01239     {
01240     public:
01244         Element();
01245 
01249         Element( const std::string& value );
01250 
01254         Element( TiXmlElement* element );
01255 
01262         Attribute* FirstAttribute( bool throwIfNoAttributes = true );
01263 
01270         Attribute* LastAttribute( bool throwIfNoAttributes = true );
01271 
01279         template < class T >
01280             void SetAttribute ( const std::string& name, const T& value )
01281         {
01282             ValidatePointer();
01283             m_tiXmlPointer->SetAttribute( name, ToString( value ) );
01284         }
01285 
01298         std::string GetText( bool throwIfNotFound = true )
01299         {
01300             // Get the element's text value as a std::string
01301             std::string temp;
01302             if ( !GetTextImp( &temp ) )
01303             {
01304                 if ( throwIfNotFound )
01305                 {
01306                     THROW( "Text does not exists in the current element" );
01307                 }
01308             }
01309 
01310             return temp;
01311         }
01312 
01324         std::string GetTextOrDefault( const std::string& defaultValue )
01325         {
01326             // Get the element's text value as a std::string
01327             std::string temp;
01328             if ( !GetTextImp( &temp ) )
01329             {
01330                 return defaultValue;
01331             }
01332 
01333             return temp;
01334         }
01335 
01350         template < class T, class DefaultT >
01351             void GetTextOrDefault( T* value, const DefaultT& defaultValue )
01352         {
01353             // Get the element's text value as a std::string
01354             std::string temp;
01355             if ( !GetTextImp( &temp ) )
01356             {
01357                 // The text value does not exist - set value to the default
01358                 *value = defaultValue;
01359                 return;
01360             }
01361 
01362             // Stream the value from the string to T
01363             FromString( temp, value );
01364         }
01365 
01381         template< class T >
01382             void GetText( T* value, bool throwIfNotFound = true )
01383         {
01384             // Get the element's text value as a std::string
01385             std::string temp;
01386             if ( !GetTextImp( &temp ) )
01387             {
01388                 if ( throwIfNotFound )
01389                 {
01390                     THROW( "Text does not exists in the current element" );
01391                 }
01392                 else
01393                 {
01394                     return;
01395                 }
01396             }
01397 
01398             // Stream the value from the string to T
01399             FromString( temp, value );
01400         }
01401 
01409         template < class T >
01410             void SetText( const T& value )
01411         {
01412             ValidatePointer();
01413             std::string temp = ToString( value );
01414 
01415             if ( m_tiXmlPointer->NoChildren() )
01416             {
01417                 m_tiXmlPointer->LinkEndChild( new TiXmlText( temp ) );
01418             }
01419             else
01420             {
01421                 if ( NULL == m_tiXmlPointer->GetText() )
01422                 {
01423                     m_tiXmlPointer->InsertBeforeChild( m_tiXmlPointer->FirstChild(), TiXmlText( temp ) );
01424                 }
01425                 else
01426                 {
01427                     // There already is text, so change it
01428                     m_tiXmlPointer->FirstChild()->SetValue( temp );
01429                 }
01430             }
01431         }
01432 
01444         template < class T, class DefaulT >
01445             void GetAttributeOrDefault( const std::string& name, T* value, const DefaulT& defaultValue )
01446         {
01447             // Get the attribute's value as a std::string
01448             std::string temp;
01449             if ( !GetAttributeImp( name, &temp ) )
01450             {
01451                 // The attribute does not exist - set value to the default
01452                 *value = defaultValue;
01453                 return;
01454             }
01455 
01456             // Stream the value from the string to T
01457             FromString( temp, value );
01458         }
01459 
01471         template< class T >
01472             void GetAttribute( const std::string& name, T* value, bool throwIfNotFound = true )
01473         {
01474             // Get the attribute's value as a std::string
01475             std::string temp;
01476             if ( !GetAttributeImp( name, &temp ) )
01477             {
01478                 if ( throwIfNotFound )
01479                 {
01480                     THROW( "Attribute does not exist" );
01481                 }
01482                 else
01483                 {
01484                     return;
01485                 }
01486             }
01487 
01488             // Stream the value from the string to T
01489             FromString( temp, value );
01490         }
01491 
01492     private:
01493 
01498         bool GetAttributeImp( const std::string& name, std::string* value );
01499 
01504         bool GetTextImp( std::string* value );
01505     };
01506 
01508     class Declaration : public NodeImp< TiXmlDeclaration >
01509     {
01510     public:
01514         Declaration( void );
01515 
01519         Declaration( TiXmlDeclaration* declaration );
01520 
01524         Declaration( const std::string& version, const std::string& encoding, const std::string& standalone );
01525 
01529         std::string Version( void );
01530 
01534         std::string Encoding( void );
01535 
01539         std::string Standalone( void );
01540     };
01541 }
01542 
01543 #endif  // TICPP_INCLUDED
01544 
01545 #endif // TIXML_USE_TICPP

Generated on Thu Sep 7 14:23:32 2006 for TinyXml by  doxygen 1.4.7