Beispiel #1
0
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();
    }
}
Beispiel #2
0
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); 
}
Beispiel #3
0
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();
            }
        }
    }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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();
        }
    }
}
Beispiel #6
0
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();
        }
    }
}
Beispiel #7
0
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();
    }
}
Beispiel #8
0
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() );
    }
}
Beispiel #9
0
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() );
    }
}