Example #1
0
void ArchiveXML::DeserializeInstance(ObjectPtr& object)
{
    //
    // If we don't have an object allocated for deserialization, pull one from the stream
    //

    if (!object.ReferencesObject())
    {
        object = Allocate();
    }

    //
    // We should now have an instance (unless data was skipped)
    //

    if (object.ReferencesObject())
    {
#ifdef REFLECT_ARCHIVE_VERBOSE
        m_Indent.Get(stdout);
        Log::Print(TXT("Deserializing %s\n"), object->GetClass()->m_Name);
        m_Indent.Push();
#endif

        object->PreDeserialize( NULL );

        Data* data = SafeCast<Data>(object);

        if ( data )
        {
#pragma TODO("Make sure this string copy goes away when replace the stl stream APIs")
            tstring body ( m_Iterator.GetCurrent()->m_Body.GetData(), m_Iterator.GetCurrent()->m_Body.GetSize() );
            tstringstream stringStream ( body );
            TCharStream stream ( &stringStream, false );

            m_Body = &stream;
            data->Deserialize(*this);
            m_Body = NULL;

            m_Iterator.Advance( true );
        }
        else
        {
            DeserializeFields(object);
        }

        object->PostDeserialize( NULL );

#ifdef REFLECT_ARCHIVE_VERBOSE
        m_Indent.Pop();
#endif
    }
}
Example #2
0
void ArchiveXML::DeserializeArray( ArrayPusher& push, uint32_t flags )
{
    if ( m_Iterator.GetCurrent()->GetFirstChild() )
    {
        // advance to the first child (the first array element)
        m_Iterator.Advance();

#ifdef REFLECT_ARCHIVE_VERBOSE
        m_Indent.Get(stdout);
        Log::Print(TXT("Deserializing objects\n"));
        m_Indent.Push();
#endif

        for ( XMLElement* sibling = m_Iterator.GetCurrent(); sibling != NULL; sibling = sibling->GetNextSibling() )
        {
            HELIUM_ASSERT( m_Iterator.GetCurrent() == sibling );

            ObjectPtr object;
            DeserializeInstance(object);

            if (object.ReferencesObject())
            {
                if ( object->IsClass( m_SearchClass ) )
                {
                    m_Skip = true;
                }

                if ( flags & ArchiveFlags::Status )
                {
                    ArchiveStatus info( *this, ArchiveStates::ObjectProcessed );
#pragma TODO("Update progress value for inter-array processing")
                    //info.m_Progress = (int)(((float)(current - start_offset) / (float)m_Size) * 100.0f);
                    e_Status.Raise( info );

                    m_Abort |= info.m_Abort;
                }
            }

            push( object );
        }
    }
    else
    {
        // advance to the next element
        m_Iterator.Advance();
    }

#ifdef REFLECT_ARCHIVE_VERBOSE
    m_Indent.Pop();
#endif

    if ( flags & ArchiveFlags::Status )
    {
        ArchiveStatus info( *this, ArchiveStates::ObjectProcessed );
        info.m_Progress = 100;
        e_Status.Raise( info );
    }
}
Example #3
0
void ArchiveBinary::DeserializeInstance(ObjectPtr& object)
{
    //
    // If we don't have an object allocated for deserialization, pull one from the stream
    //

    if (!object.ReferencesObject())
    {
        object = Allocate();
    }

    //
    // We should now have an instance (unless data was skipped)
    //

    if (object.ReferencesObject())
    {
#ifdef REFLECT_ARCHIVE_VERBOSE
        m_Indent.Get(stdout);
        Log::Print(TXT("Deserializing %s\n"), object->GetClass()->m_Name);
        m_Indent.Push();
#endif

        object->PreDeserialize( NULL );

        Data* data = SafeCast<Data>(object);

        if ( data )
        {
            data->Deserialize(*this);
        }
        else
        {
            DeserializeFields(object);
        }

        object->PostDeserialize( NULL );

#ifdef REFLECT_ARCHIVE_VERBOSE
        m_Indent.Pop();
#endif
    }
}
Example #4
0
ObjectPtr ArchiveBinary::Allocate()
{
    ObjectPtr object;

    // read type string
    uint32_t typeCrc = Helium::BeginCrc32();
    m_Stream->Read(&typeCrc);

    // A null type name CRC indicates that a null reference was serialized, so no type lookup needs to be performed.
    const Class* type = NULL;
    if ( typeCrc != 0 )
    {
        type = Reflect::Registry::GetInstance()->GetClass( typeCrc );
    }

    // read length info if we have it
    uint32_t length = 0;
    m_Stream->Read(&length);

    if ( m_Skip || typeCrc == 0 )
    {
        // skip it, but account for already reading the length from the stream
        m_Stream->SeekRead(length - sizeof(uint32_t), std::ios_base::cur);
    }
    else
    {
        if (type)
        {
            // allocate instance by name
            object = Registry::GetInstance()->CreateInstance( type );
        }

        // if we failed
        if (!object.ReferencesObject())
        {
            // skip it, but account for already reading the length from the stream
            m_Stream->SeekRead(length - sizeof(uint32_t), std::ios_base::cur);

            // if you see this, then data is being lost because:
            //  1 - a type was completely removed from the codebase
            //  2 - a type was not found because its type library is not registered
            Log::Debug( TXT( "Unable to create object of type %s, size %d, skipping...\n" ), type ? type->m_Name : TXT("Unknown"), length);
#pragma TODO("Support blind data")
        }
    }

    return object;
}
Example #5
0
DataPtr Field::CreateData() const
{
    DataPtr data;

    if ( m_DataClass != NULL )
    {
        ObjectPtr object = Registry::GetInstance()->CreateInstance( m_DataClass );

        if (object.ReferencesObject())
        {
            data = AssertCast<Data>(object);
        }
    }

    return data;
}
Example #6
0
ObjectPtr ArchiveXML::Allocate()
{
    ObjectPtr object;

    // find type
    const String* typeStr = m_Iterator.GetCurrent()->GetAttributeValue( Name( TXT("Type") ) );
    uint32_t typeCrc = typeStr ? Crc32( typeStr->GetData() ) : 0x0;

    // A null type name CRC indicates that a null reference was serialized, so no type lookup needs to be performed.
    const Class* type = NULL;
    if ( typeCrc != 0 )
    {
        type = Reflect::Registry::GetInstance()->GetClass( typeCrc );
    }

    if (type)
    {
        // allocate instance by name
        object = Registry::GetInstance()->CreateInstance( type );
    }

    // if we failed
    if (!object.ReferencesObject())
    {
        // if you see this, then data is being lost because:
        //  1 - a type was completely removed from the codebase
        //  2 - a type was not found because its type library is not registered
        Log::Debug( TXT( "Unable to create object of type %s, skipping...\n" ), type ? type->m_Name : TXT("Unknown") );

        // skip past this object, skipping our children
        m_Iterator.Advance( true );
#pragma TODO("Support blind data")
    }

    return object;
}
Example #7
0
void ArchiveXML::DeserializeFields(Object* object)
{
    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 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
        }
    }
    else
    {
        // advance to the next element
        m_Iterator.Advance();
    }
}
Example #8
0
void ArchiveBinary::DeserializeArray( ArrayPusher& push, uint32_t flags )
{
    uint32_t start_offset = (uint32_t)m_Stream->TellRead();

    int32_t element_count = -1;
    m_Stream->Read(&element_count); 

#ifdef REFLECT_ARCHIVE_VERBOSE
    m_Indent.Get(stdout);
    Log::Debug(TXT("Deserializing %d objects\n"), element_count);
    m_Indent.Push();
#endif

    if (element_count > 0)
    {
        for (int i=0; i<element_count && !m_Abort; i++)
        {
            ObjectPtr object;
            DeserializeInstance(object);

            if (object.ReferencesObject())
            {
                if ( object->IsClass( m_SearchClass ) )
                {
                    m_Skip = true;
                }

                if ( flags & ArchiveFlags::Status )
                {
                    uint32_t current = (uint32_t)m_Stream->TellRead();

                    ArchiveStatus info( *this, ArchiveStates::ObjectProcessed );
                    info.m_Progress = (int)(((float)(current - start_offset) / (float)m_Size) * 100.0f);
                    e_Status.Raise( info );

                    m_Abort |= info.m_Abort;
                }
            }

            push( object );
        }
    }

#ifdef REFLECT_ARCHIVE_VERBOSE
    m_Indent.Pop();
#endif

    if (!m_Abort)
    {
        int32_t terminator = -1;
        m_Stream->Read(&terminator);
        if (terminator != -1)
        {
            throw Reflect::DataFormatException( TXT( "Unterminated object array block (%s)" ), m_Path.c_str() );
        }
    }

    if ( flags & ArchiveFlags::Status )
    {
        ArchiveStatus info( *this, ArchiveStates::ObjectProcessed );
        info.m_Progress = 100;
        e_Status.Raise( info );
    }
}