VPersistence.h
Engine/source/Verve/Core/Persistence/VPersistence.h
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