void Composite::Visit(void* instance, Visitor& visitor) const { if (!instance) { return; } DynArray< Field >::ConstIterator itr = m_Fields.Begin(); DynArray< Field >::ConstIterator end = m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; if ( !visitor.VisitField( instance, field ) ) { continue; } DataPtr data = field->CreateData(); data->ConnectField( instance, field ); data->Accept( visitor ); data->Disconnect(); } }
void ArchiveBinary::SerializeFields( Object* object ) { const Composite* composite = object->GetClass(); std::stack< const Composite* > bases; for ( const Composite* current = composite; current != NULL; current = current->m_Base ) { bases.push( current ); } while ( !bases.empty() ) { const Composite* current = bases.top(); bases.pop(); DynArray< Field >::ConstIterator itr = current->m_Fields.Begin(); DynArray< Field >::ConstIterator end = current->m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; // check to see if we should serialize (will return non-null if we are gtg) DataPtr data = object->ShouldSerialize( field ); if ( data ) { uint32_t fieldNameCrc = Crc32( field->m_Name ); m_Stream->Write(&fieldNameCrc); #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Get(stdout); Log::Print(TXT("Serializing field %s (class %s)\n"), field->m_Name, field->m_DataClass->m_Name); m_Indent.Push(); #endif object->PreSerialize( field ); SerializeInstance( data ); object->PostSerialize( field ); // might be useful to cache the data object here data->Disconnect(); #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Pop(); #endif // we wrote a field, so increment our count HELIUM_ASSERT(m_FieldStack.size() > 0); m_FieldStack.top().m_Count++; } } } const int32_t terminator = -1; m_Stream->Write(&terminator); }
void Composite::Copy( void* source, void* destination ) const { if ( source != destination ) { #pragma TODO("This should be inside a virtual function (like CopyTo) instead of a type check conditional") if ( IsType( GetClass<Data>() ) ) { Data* src = static_cast<Data*>(source); Data* dest = static_cast<Data*>(destination); dest->Set( src ); } else { DynArray< Field >::ConstIterator itr = m_Fields.Begin(); DynArray< Field >::ConstIterator end = m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; // create data objects DataPtr lhs = field->CreateData(); DataPtr rhs = field->CreateData(); // connnect lhs->ConnectField(destination, field); rhs->ConnectField(source, field); // for normal data types, run overloaded assignement operator via data's vtable // for reference container types, this deep copies containers (which is bad for // non-cloneable (FieldFlags::Share) reference containers) bool result = lhs->Set(rhs, field->m_Flags & FieldFlags::Share ? DataFlags::Shallow : 0); HELIUM_ASSERT(result); // disconnect lhs->Disconnect(); rhs->Disconnect(); } } } }
bool Composite::Equals(void* a, void* b) const { if (a == b) { return true; } if (!a || !b) { return false; } DynArray< Field >::ConstIterator itr = m_Fields.Begin(); DynArray< Field >::ConstIterator end = m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; // create data objects DataPtr aData = field->CreateData(); DataPtr bData = field->CreateData(); // connnect aData->ConnectField(a, field); bData->ConnectField(b, field); bool equality = aData->Equals( bData ); // disconnect aData->Disconnect(); bData->Disconnect(); if ( !equality ) { return false; } } return true; }
void ArchiveXML::SerializeFields( void* structure, const Structure* type ) { DynArray< Field >::ConstIterator itr = type->m_Fields.Begin(); DynArray< Field >::ConstIterator end = type->m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; DataPtr data = field->ShouldSerialize( structure ); if ( data ) { SerializeInstance( data, field->m_Name ); // might be useful to cache the data object here data->Disconnect(); } } }
void ArchiveXML::SerializeFields( Object* object ) { const Class* type = object->GetClass(); HELIUM_ASSERT(type != NULL); DynArray< Field >::ConstIterator itr = type->m_Fields.Begin(); DynArray< Field >::ConstIterator end = type->m_Fields.End(); for ( ; itr != end; ++itr ) { const Field* field = &*itr; DataPtr data = object->ShouldSerialize( field ); if ( data ) { object->PreSerialize( field ); SerializeInstance( data, field->m_Name ); object->PostSerialize( field ); // might be useful to cache the data object here data->Disconnect(); } } }
void ArchiveXML::DeserializeFields( void* structure, const Structure* type ) { if ( m_Iterator.GetCurrent()->GetFirstChild() ) { // advance to the first child m_Iterator.Advance(); for ( XMLElement* sibling = m_Iterator.GetCurrent(); sibling != NULL; sibling = sibling->GetNextSibling() ) { HELIUM_ASSERT( m_Iterator.GetCurrent() == sibling ); const String* fieldNameStr = sibling->GetAttributeValue( Name( TXT("Name") ) ); uint32_t fieldNameCrc = fieldNameStr ? Crc32( fieldNameStr->GetData() ) : 0x0; const Field* field = type->FindFieldByName(fieldNameCrc); if ( field ) { #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Get(stdout); Log::Debug(TXT("Deserializing field %s\n"), field->m_Name); m_Indent.Push(); #endif // pull and structure and downcast to data DataPtr latentData = SafeCast<Data>( Allocate() ); if (!latentData.ReferencesObject()) { // this should never happen, the type id read from the file is bogus throw Reflect::TypeInformationException( TXT( "Unknown data for field %s (%s)" ), field->m_Name, m_Path.c_str() ); #pragma TODO("Support blind data") } // if the types match we are a natural fit to just deserialize directly into the field data if ( field->m_DataClass == field->m_DataClass ) { // set data pointer latentData->ConnectField( structure, field ); // process natively DeserializeInstance( (ObjectPtr&)latentData ); // disconnect latentData->Disconnect(); } else // else the type does not match, deserialize it into temp data then attempt to cast it into the field data { REFLECT_SCOPE_TIMER(("Casting")); // construct current serialization structure ObjectPtr currentObject = Registry::GetInstance()->CreateInstance( field->m_DataClass ); // downcast to data DataPtr currentData = SafeCast<Data>(currentObject); if (!currentData.ReferencesObject()) { // this should never happen, the type id in the rtti data is bogus throw Reflect::TypeInformationException( TXT( "Invalid type id for field %s (%s)" ), field->m_Name, m_Path.c_str() ); } // process into temporary memory currentData->ConnectField(structure, field); // process natively DeserializeInstance( (ObjectPtr&)latentData ); // attempt cast data into new definition Data::CastValue( latentData, currentData, DataFlags::Shallow ); // disconnect currentData->Disconnect(); } } #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Pop(); #endif } } else { // advance to the next element m_Iterator.Advance(); } }
void ArchiveBinary::DeserializeFields( void* structure, const Structure* type ) { int32_t fieldCount = -1; m_Stream->Read(&fieldCount); for (int i=0; i<fieldCount; i++) { uint32_t fieldNameCrc = BeginCrc32(); m_Stream->Read( &fieldNameCrc ); const Field* field = type->FindFieldByName(fieldNameCrc); if ( field ) { #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Get(stdout); Log::Print(TXT("Deserializing field %s\n"), field->m_Name); m_Indent.Push(); #endif // pull and structure and downcast to data DataPtr latentData = SafeCast<Data>( Allocate() ); if (!latentData.ReferencesObject()) { // this should never happen, the type id read from the file is bogus throw Reflect::TypeInformationException( TXT( "Unknown data for field %s (%s)" ), field->m_Name, m_Path.c_str() ); #pragma TODO("Support blind data") } // if the types match we are a natural fit to just deserialize directly into the field data if ( field->m_DataClass == field->m_DataClass ) { // set data pointer latentData->ConnectField( structure, field ); // process natively DeserializeInstance( (ObjectPtr&)latentData ); // disconnect latentData->Disconnect(); } else // else the type does not match, deserialize it into temp data then attempt to cast it into the field data { REFLECT_SCOPE_TIMER(("Casting")); // construct current serialization structure ObjectPtr currentObject = Registry::GetInstance()->CreateInstance( field->m_DataClass ); // downcast to data DataPtr currentData = SafeCast<Data>(currentObject); if (!currentData.ReferencesObject()) { // this should never happen, the type id in the rtti data is bogus throw Reflect::TypeInformationException( TXT( "Invalid type id for field %s (%s)" ), field->m_Name, m_Path.c_str() ); } // process into temporary memory currentData->ConnectField(structure, field); // process natively DeserializeInstance( (ObjectPtr&)latentData ); // attempt cast data into new definition Data::CastValue( latentData, currentData, DataFlags::Shallow ); // disconnect currentData->Disconnect(); } } #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Pop(); #endif } int32_t terminator = -1; m_Stream->Read(&terminator); if (terminator != -1) { throw Reflect::DataFormatException( TXT( "Unterminated field array block (%s)" ), m_Path.c_str() ); } }
void ArchiveBinary::DeserializeFields(Object* object) { int32_t fieldCount = -1; m_Stream->Read(&fieldCount); for (int i=0; i<fieldCount; i++) { uint32_t fieldNameCrc = BeginCrc32(); m_Stream->Read( &fieldNameCrc ); const Class* type = object->GetClass(); HELIUM_ASSERT( type ); ObjectPtr unknown; const Field* field = type->FindFieldByName(fieldNameCrc); if ( field ) { #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Get(stdout); Log::Print(TXT("Deserializing field %s\n"), field->m_Name); m_Indent.Push(); #endif // pull and object and downcast to data DataPtr latentData = SafeCast<Data>( Allocate() ); if (!latentData.ReferencesObject()) { // this should never happen, the type id read from the file is bogus throw Reflect::TypeInformationException( TXT( "Unknown data for field %s (%s)" ), field->m_Name, m_Path.c_str() ); #pragma TODO("Support blind data") } // if the types match we are a natural fit to just deserialize directly into the field data if ( field->m_DataClass == field->m_DataClass ) { // set data pointer latentData->ConnectField( object, field ); // process natively object->PreDeserialize( field ); DeserializeInstance( (ObjectPtr&)latentData ); object->PostDeserialize( field ); // disconnect latentData->Disconnect(); } else // else the type does not match, deserialize it into temp data then attempt to cast it into the field data { REFLECT_SCOPE_TIMER(("Casting")); // construct current serialization object ObjectPtr currentObject = Registry::GetInstance()->CreateInstance( field->m_DataClass ); // downcast to data DataPtr currentData = SafeCast<Data>(currentObject); if (!currentData.ReferencesObject()) { // this should never happen, the type id in the rtti data is bogus throw Reflect::TypeInformationException( TXT( "Invalid type id for field %s (%s)" ), field->m_Name, m_Path.c_str() ); } // process into temporary memory currentData->ConnectField(object, field); // process natively object->PreDeserialize( field ); DeserializeInstance( (ObjectPtr&)latentData ); // attempt cast data into new definition if ( !Data::CastValue( latentData, currentData, DataFlags::Shallow ) ) { // handle as unknown unknown = latentData; } else { // post process object->PostDeserialize( field ); } // disconnect currentData->Disconnect(); } } else // else the field does not exist in the current class anymore { try { DeserializeInstance( unknown ); } catch (Reflect::LogisticException& ex) { Log::Debug( TXT( "Unable to deserialize %s::%s, discarding: %s\n" ), type->m_Name, field->m_Name, ex.What()); } } if ( unknown.ReferencesObject() ) { // attempt processing object->ProcessUnknown( unknown, field ? Crc32( field->m_Name ) : 0 ); } #ifdef REFLECT_ARCHIVE_VERBOSE m_Indent.Pop(); #endif } int32_t terminator = -1; m_Stream->Read(&terminator); if (terminator != -1) { throw Reflect::DataFormatException( TXT( "Unterminated field array block (%s)" ), m_Path.c_str() ); } }