示例#1
0
uint32_t BasicBuffer::AddBuffer( const SmartBufferPtr& buffer, bool add_fixups )
{
    // platform types have to match
    HELIUM_ASSERT(buffer->GetByteOrder() == m_ByteOrder);

    // first bring in all the data from the incoming buffer
    uint32_t return_val = AddBuffer( buffer->GetData(), buffer->GetSize() );

    if (add_fixups)
    {
        // inherit all the incoming / outgoing fixups from this buffer with out new offset
        InheritFixups( buffer, return_val );
    }

    return return_val;
}
示例#2
0
bool BufferSerializer::ReadFromStream( tistream& strm ) 
{
    //uint32_t starting_offset = strm.tellp();

    // read a ChunkFileHeader
    ChunkFileHeader file_header;
    strm.read( (tchar_t*)&file_header, sizeof( ChunkFileHeader ) );

    uint32_t test1 = (uint32_t)strm.tellg();

    bool swizzle = false;

    // check that the header looks valid
    if ( file_header.m_Magic != CHUNK_MAGIC_LITTLE_ENDIAN )
    {
        uint32_t magic = ConvertEndian(file_header.m_Magic, true);

        if ( magic == CHUNK_MAGIC_BIG_ENDIAN )
        {
            swizzle = true;
        }
        else
        {
            return false;
        }
    }

    file_header.m_Version = ConvertEndian(file_header.m_Version, swizzle);
    file_header.m_ChunkCount = ConvertEndian(file_header.m_ChunkCount, swizzle);

    uint32_t alignment;
    switch( file_header.m_Version )
    {
    case CHUNK_VERSION_128_ALIGN:
        alignment = 128;
        break;

    case CHUNK_VERSION_16_ALIGN:
        alignment = 16;
        break;

    default:
        return false;
    }

    // 
    std::vector< ChunkHeader > chunk_headers( file_header.m_ChunkCount );
    std::vector< SmartBufferPtr > chunks( file_header.m_ChunkCount );
    std::map< uint32_t, uint32_t, std::greater<uint32_t> > chunk_map;

    // read each chunk header
    for ( uint32_t chunk_index = 0; chunk_index < file_header.m_ChunkCount; ++chunk_index )
    {
        strm.read( (tchar_t*)&chunk_headers[ chunk_index ], sizeof( ChunkHeader ) );
        chunk_headers[ chunk_index ].m_Type = ConvertEndian(chunk_headers[ chunk_index ].m_Type, swizzle);
        chunk_headers[ chunk_index ].m_Offset = ConvertEndian(chunk_headers[ chunk_index ].m_Offset, swizzle);
        chunk_headers[ chunk_index ].m_Size = ConvertEndian(chunk_headers[ chunk_index ].m_Size, swizzle);
    }

    // create and read each chunk
    for ( uint32_t chunk_index = 0; chunk_index < file_header.m_ChunkCount; ++chunk_index )
    {
        const ChunkHeader& header = chunk_headers[ chunk_index ];
        SmartBufferPtr buffer = new SmartBuffer();
        buffer->SetByteOrder( swizzle ? ByteOrders::BigEndian : ByteOrders::LittleEndian );

        //HELIUM_ASSERT( header.m_Offset == ( strm.tellp() - starting_offset ) );
        chunks[ chunk_index ] = buffer;

        buffer->Resize( header.m_Size );
        buffer->SetType( header.m_Type );
        strm.read( (tchar_t*)buffer->GetData(), buffer->GetSize() );

        HELIUM_ASSERT( chunk_map.find( header.m_Offset ) == chunk_map.end() );
        chunk_map[ header.m_Offset ] = chunk_index;

        //  is the buffer aligned?
        if ( swizzle && (buffer->GetSize() & ( alignment - 1 )) != 0 )
        {
            uint32_t pad = alignment - (buffer->GetSize() & ( alignment - 1 ) );
            strm.seekg( pad, std::ios_base::cur );
        }
    }

    uint32_t test = (uint32_t)strm.tellg();

    // read the fixups
    uint32_t num_fixups;
    strm.read( (tchar_t*)&num_fixups, sizeof( num_fixups ) );
    num_fixups = ConvertEndian(num_fixups, swizzle);

    for ( uint32_t fixup_index = 0; fixup_index < num_fixups; ++fixup_index )
    {
        uint32_t source_offset;
        strm.read( (tchar_t*)&source_offset, sizeof( source_offset ) );
        source_offset = ConvertEndian(source_offset, swizzle);

        // figure out which buffer this fixup starts in
        std::map< uint32_t, uint32_t, std::greater<uint32_t> >::iterator source_itr = chunk_map.lower_bound( source_offset );
        HELIUM_ASSERT( source_itr != chunk_map.end() );

        // get the necessary source data
        const ChunkHeader& source_header = chunk_headers[ (*source_itr).second ];
        SmartBufferPtr source_buffer = chunks[ (*source_itr).second ];

        uint32_t* source_data = (uint32_t*)(source_buffer->GetData() + ( source_offset - source_header.m_Offset ) );
        uint32_t  dest_offset = *source_data;
        dest_offset = ConvertEndian(dest_offset, swizzle);

        // figure out which buffer this fixup ends in
        std::map< uint32_t, uint32_t, std::greater<uint32_t> >::iterator dest_itr = chunk_map.lower_bound( dest_offset );
        HELIUM_ASSERT( dest_itr != chunk_map.end() );

        // get the necessary dest data
        const ChunkHeader& dest_header = chunk_headers[ (*dest_itr).second ];
        SmartBufferPtr dest_buffer = chunks[ (*dest_itr).second ];

        // do the fixup
        SmartBuffer::AddPointerFixup( source_buffer->GetOffsetLocation( source_offset - source_header.m_Offset ),
            dest_buffer->GetOffsetLocation  ( dest_offset   - dest_header.m_Offset ), 4 );
    }

    // read the fixups
    uint32_t num_fixups_64;
    strm.read( (tchar_t*)&num_fixups_64, sizeof( num_fixups_64 ) );
    num_fixups_64 = ConvertEndian(num_fixups_64, swizzle);

    if (!strm.eof())
    {
        for ( uint32_t fixup_index = 0; fixup_index < num_fixups_64; ++fixup_index )
        {
            uint32_t source_offset;
            strm.read( (tchar_t*)&source_offset, sizeof( source_offset ) );
            source_offset = ConvertEndian(source_offset, swizzle);

            // figure out which buffer this fixup starts in
            std::map< uint32_t, uint32_t, std::greater<uint32_t> >::iterator source_itr = chunk_map.lower_bound( source_offset );
            HELIUM_ASSERT( source_itr != chunk_map.end() );

            // get the necessary source data
            const ChunkHeader& source_header = chunk_headers[ (*source_itr).second ];
            SmartBufferPtr source_buffer = chunks[ (*source_itr).second ];

            uint32_t* source_data = (uint32_t*)(source_buffer->GetData() + ( source_offset - source_header.m_Offset ) );
            uint32_t  dest_offset = *source_data;
            dest_offset = ConvertEndian(dest_offset, swizzle);

            // figure out which buffer this fixup ends in
            std::map< uint32_t, uint32_t, std::greater<uint32_t> >::iterator dest_itr = chunk_map.lower_bound( dest_offset );
            HELIUM_ASSERT( dest_itr != chunk_map.end() );

            // get the necessary dest data
            const ChunkHeader& dest_header = chunk_headers[ (*dest_itr).second ];
            SmartBufferPtr dest_buffer = chunks[ (*dest_itr).second ];

            // do the fixup
            SmartBuffer::AddPointerFixup( source_buffer->GetOffsetLocation( source_offset - source_header.m_Offset - 4),
                dest_buffer->GetOffsetLocation  ( dest_offset   - dest_header.m_Offset ), 8 );
        }
    }

    // store the chunks
    m_Buffers.clear();

    {
        std::vector< SmartBufferPtr >::const_iterator itr = chunks.begin();
        std::vector< SmartBufferPtr >::const_iterator end = chunks.end();
        for ( ; itr != end; ++itr )
        {
			if ( std::find( m_Buffers.begin(), m_Buffers.end(), *itr ) == m_Buffers.end() )
			{
	            m_Buffers.push_back( *itr );
			}
        }
    }

    return true;
}