VPersistence.h

Engine/source/Verve/Core/Persistence/VPersistence.h

More...

Namespaces:

namespace

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Verve
  4// Copyright (C) 2014 - Violent Tulip
  5//
  6// Permission is hereby granted, free of charge, to any person obtaining a copy
  7// of this software and associated documentation files (the "Software"), to
  8// deal in the Software without restriction, including without limitation the
  9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10// sell copies of the Software, and to permit persons to whom the Software is
 11// furnished to do so, subject to the following conditions:
 12//
 13// The above copyright notice and this permission notice shall be included in
 14// all copies or substantial portions of the Software.
 15//
 16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 22// IN THE SOFTWARE.
 23//-----------------------------------------------------------------------------
 24#ifndef _VT_VPERSISTENCE_H_
 25#define _VT_VPERSISTENCE_H_
 26
 27#ifndef TINYXML_INCLUDED
 28#include "tinyxml/tinyxml.h"
 29#endif
 30
 31#ifndef _SIMOBJECT_H_
 32#include "console/simObject.h"
 33#endif
 34
 35#ifndef _VT_VOBJECT_H_
 36#include "Verve/Core/VObject.h"
 37#endif
 38
 39//-----------------------------------------------------------------------------
 40
 41namespace VPersistence
 42{
 43    static const char *VSFVersionString = "0.0.0a";
 44
 45    // This object is used to filter fields which belong to SimObject's.
 46    // There is no need to serialize these fields, so they are skipped
 47    // entirely.
 48    static SimObject DummySimObject;
 49
 50    //-------------------------------------------------------------------------
 51
 52    template <class T> bool write( TiXmlElement *pElement, T *pObject );
 53    
 54    template <class T> bool writeFile( const char* pFileName, T *pObject )
 55    {
 56        // Create Doc.
 57        TiXmlDocument xmlDocument;
 58        TiXmlDeclaration *xmlDeclaration = new TiXmlDeclaration( "1.0", "", "" );
 59        xmlDocument.LinkEndChild( xmlDeclaration );
 60
 61        // Create Root.
 62        TiXmlElement *xmlRoot = new TiXmlElement( "VerveControllerSequence" );
 63        xmlDocument.LinkEndChild( xmlRoot );
 64
 65        // Write Version.
 66        xmlRoot->SetAttribute( "Version", VSFVersionString );
 67
 68        // Write Object.
 69        if ( !write( xmlRoot, pObject ) )
 70        {
 71            Con::errorf( "VPersistence::writeFile() - Unable to Write Object." );
 72            return false;
 73        }
 74
 75        // Save File.
 76        return xmlDocument.SaveFile( pFileName );
 77    };
 78
 79    
 80    template <class T> bool writeProperties( TiXmlElement *pElement, T *pObject )
 81    {
 82        const AbstractClassRep::FieldList &fieldList = pObject->getFieldList();
 83        const AbstractClassRep::Field     *field     = NULL;
 84
 85        // Create Property Root.
 86        TiXmlElement *propertyRoot = new TiXmlElement( "Properties" );
 87        pElement->LinkEndChild( propertyRoot );
 88
 89        const S32 fieldCount = fieldList.size();
 90        for ( S32 i = 0; i < fieldCount; i++ )
 91        {
 92            field = &fieldList[i];
 93            
 94            if ( field->type >= AbstractClassRep::ARCFirstCustomField )
 95            {
 96                // Ignore Special Fields.
 97                continue;
 98            }
 99
100            // Fetch the Field Name.
101            const char *fieldName = field->pFieldname;
102            // SimObject Field?
103            if ( DummySimObject.findField( fieldName ) != NULL )
104            {
105                // Skip SimObject Fields.
106                continue;
107            }
108
109            // Fetch the Field Value.
110            const char *fieldValue = ( *field->getDataFn )( pObject, Con::getData( field->type, ( void * ) ( ( ( const char * )pObject ) + field->offset ), 0, field->table, field->flag ) );
111
112            if ( fieldValue )
113            {
114                // Create Element.
115                TiXmlElement *propertyElement = new TiXmlElement( fieldName );  
116
117                // Apply Value.
118                propertyElement->InsertEndChild( TiXmlText( fieldValue ) );
119
120                // Add.
121                propertyRoot->LinkEndChild( propertyElement );
122            }
123        }
124
125        // Valid Write.
126        return true;
127    };
128
129    template <class T> bool writeObjects( TiXmlElement *pElement, T *pObject )
130    {
131        for ( ITreeNode *node = pObject->mChildNode; node != NULL; node = node->mSiblingNextNode )
132        {
133            // Write Group.
134            if ( !write( pElement, ( VObject* )node ) )
135            {
136                // Invalid Write.
137                return false;
138            }
139        }
140
141        // Valid Write.
142        return true;
143    }
144
145    //-------------------------------------------------------------------------
146    
147    template <class T> bool read( TiXmlElement *pElement, T *pObject );
148    
149    template <class T> bool readFile( const char* pFileName, T *pObject )
150    {
151        TiXmlDocument xmlDocument;
152        if ( !xmlDocument.LoadFile( pFileName ) )
153        {
154            Con::errorf( "VPersistence::readFile() - Unable to load file '%s'.", pFileName );
155            return false;
156        }
157
158        TiXmlElement *rootElement = xmlDocument.RootElement();
159        if ( !rootElement )
160        {
161            Con::errorf( "VPersistence::readFile() - Invalid Document '%s'.", pFileName );
162            return false;
163        }
164
165        const char *docVersion = rootElement->Attribute( "Version" );
166        if ( !docVersion || String::compare( VSFVersionString, docVersion ) != 0 )
167        {
168            Con::errorf( "VPersistence::readFile() - Invalid file version." );
169            return false;
170        }
171
172        // Read Object.
173        if ( !read( rootElement, pObject ) )
174        {
175            // Invalid Read.
176            return false;
177        }
178
179        // Valid.
180        return true;
181    };
182
183    template <class T> bool readProperties( TiXmlElement *pElement, T *pObject )
184    {
185        TiXmlElement *propertyRoot = pElement->FirstChildElement( "Properties" );
186        if ( propertyRoot )
187        {
188            for ( TiXmlElement *child = propertyRoot->FirstChildElement(); child != NULL; child = child->NextSiblingElement() )
189            {
190                // Get Field Data.
191                const char *fieldName  = child->Value();
192                const char *fieldValue = child->GetText();
193
194                if ( !fieldValue )
195                {
196                    // Clear Value.
197                    pObject->setField( fieldName, "" );
198                }
199                else
200                {
201                    // Apply Field Value.
202                    if ( !pObject->setField( fieldName, fieldValue ) )
203                    {
204                        // Invalid.
205                        Con::warnf( "VPersistence::readProperties() - Invalid property '%s'", fieldName );
206                    }
207                }
208            }
209        }
210        
211        // Valid Read.
212        return true;
213    };
214
215    template <class T> bool readObjects( TiXmlElement *pElement, T *pObject )
216    {
217        for ( TiXmlElement *child = pElement->FirstChildElement( "VObject" ); child != NULL; child = child->NextSiblingElement( "VObject" ) )
218        {
219            // Get Object Type.
220            const char *type = child->Attribute( "Type" );
221            if ( !type || !AbstractClassRep::findClassRep( type ) )
222            {
223                // Invalid Type.
224                Con::errorf( "VController::readObjects() - Invalid object type specified '%s'.", ( ( type ) ? type : "NULL" ) );
225
226                // Invalid Read.
227                return false;
228            }
229
230            // Create Object.
231            VObject *object = dynamic_cast<VObject*>( ConsoleObject::create( type ) );
232
233#ifdef VT_EDITOR
234            // Register SimObject.
235            if ( !object->registerObject() )
236            {
237                // Delete.
238                delete object;
239
240                // Invalid Read.
241                return false;
242            }
243#endif
244
245            // Add Reference.
246            object->addTo( pObject );
247
248#ifdef VT_EDITOR
249            // Valid Method?
250            if ( object->isMethod( "onAdd" ) )
251            {
252                // Callback.
253                const char *retValue = Con::executef( object, "onAdd" );
254                if ( !dAtob( retValue ) )
255                {
256                    // Delete.
257                    object->deleteObject();
258
259                    // Invalid Read.
260                    return false;
261                }
262            }
263#endif
264
265            // Read Object.
266            if ( !read( child, object ) )
267            {
268#ifdef VT_EDITOR
269                // Delete.
270                object->deleteObject();
271#else
272                // Delete.
273                delete object;
274#endif
275
276                // Invalid Read.
277                return false;
278            }
279        }
280
281        // Valid Read.
282        return true;
283    };
284};
285
286//-----------------------------------------------------------------------------
287
288#endif // _VT_VPERSISTENCE_H_
289