Exemplo n.º 1
0
/// @copydoc Serializer::SerializeWideString()
void BinarySerializer::SerializeWideString( WideString& rValue )
{
    if( ShouldSerializeCurrentProperty() )
    {
        HELIUM_ASSERT( rValue.GetSize() <= UINT32_MAX );
        uint32_t stringLength = static_cast< uint32_t >( rValue.GetSize() );
        m_pPropertyStream->Write( &stringLength, sizeof( stringLength ), 1 );

        m_pPropertyStream->Write( rValue.GetData(), sizeof( wchar_t ), stringLength );
    }
}
Exemplo n.º 2
0
/// Copy constructor.
///
/// When copying, only the memory needed to hold onto the used contents of the source string will be allocated (i.e.
/// if the source string has 10 elements but a capacity of 20, only memory for the 10 used elements will be
/// allocated for this copy).
///
/// @param[in] rSource  String from which to copy.
WideString::WideString( const WideString& rSource )
    : StringBase( rSource.GetData(), rSource.GetSize() )
{
}
Exemplo n.º 3
0
/// Add or update an entry in the cache.
///
/// @param[in] path          GameObject path.
/// @param[in] subDataIndex  Sub-data index associated with the cached data.
/// @param[in] pData         Data to cache.
/// @param[in] timestamp     Timestamp value to associate with the entry in the cache.
/// @param[in] size          Number of bytes to cache.
///
/// @return  True if the cache was updated successfully, false if not.
bool Cache::CacheEntry(
                       GameObjectPath path,
                       uint32_t subDataIndex,
                       const void* pData,
                       int64_t timestamp,
                       uint32_t size )
{
    HELIUM_ASSERT( pData || size == 0 );

    Path cacheFile( m_cacheFileName.GetData() );
    int64_t cacheFileSize = cacheFile.Size();
    uint64_t entryOffset = ( cacheFileSize == -1 ? 0 : static_cast< uint64_t >( cacheFileSize ) );

    HELIUM_ASSERT( m_pEntryPool );
    Entry* pEntryUpdate = m_pEntryPool->Allocate();
    HELIUM_ASSERT( pEntryUpdate );
    pEntryUpdate->offset = entryOffset;
    pEntryUpdate->timestamp = timestamp;
    pEntryUpdate->path = path;
    pEntryUpdate->subDataIndex = subDataIndex;
    pEntryUpdate->size = size;

    uint64_t originalOffset = 0;
    int64_t originalTimestamp = 0;
    uint32_t originalSize = 0;

    EntryKey key;
    key.path = path;
    key.subDataIndex = subDataIndex;

    EntryMapType::Accessor entryAccessor;
    bool bNewEntry = m_entryMap.Insert( entryAccessor, KeyValue< EntryKey, Entry* >( key, pEntryUpdate ) );
    if( bNewEntry )
    {
        HELIUM_TRACE( TRACE_INFO, TXT( "Cache: Adding \"%s\" to cache \"%s\".\n" ), *path.ToString(), *m_cacheFileName );

        m_entries.Push( pEntryUpdate );
    }
    else
    {
        HELIUM_TRACE( TRACE_INFO, TXT( "Cache: Updating \"%s\" in cache \"%s\".\n" ), *path.ToString(), *m_cacheFileName );

        m_pEntryPool->Release( pEntryUpdate );

        pEntryUpdate = entryAccessor->Second();
        HELIUM_ASSERT( pEntryUpdate );

        originalOffset = pEntryUpdate->offset;
        originalTimestamp = pEntryUpdate->timestamp;
        originalSize = pEntryUpdate->size;

        if( originalSize < size )
        {
            pEntryUpdate->offset = entryOffset;
        }
        else
        {
            entryOffset = originalOffset;
        }

        pEntryUpdate->timestamp = timestamp;
        pEntryUpdate->size = size;
    }

    AsyncLoader& rLoader = AsyncLoader::GetStaticInstance();

    rLoader.Lock();

    bool bCacheSuccess = true;

    FileStream* pCacheStream = File::Open( m_cacheFileName, FileStream::MODE_WRITE, false );
    if( !pCacheStream )
    {
        HELIUM_TRACE( TRACE_ERROR, TXT( "Cache: Failed to open cache \"%s\" for writing.\n" ), *m_cacheFileName );

        bCacheSuccess = false;
    }
    else
    {
        HELIUM_TRACE(
            TRACE_INFO,
            TXT( "Cache: Caching \"%s\" to \"%s\" (%" ) TPRIu32 TXT( " bytes @ offset %" ) TPRIu64 TXT( ").\n" ),
            *path.ToString(),
            *m_cacheFileName,
            size,
            entryOffset );

        uint64_t seekOffset = static_cast< uint64_t >( pCacheStream->Seek(
            static_cast< int64_t >( entryOffset ),
            SeekOrigins::SEEK_ORIGIN_BEGIN ) );
        if( seekOffset != entryOffset )
        {
            HELIUM_TRACE( TRACE_ERROR, TXT( "Cache: Cache file offset seek failed.\n" ) );

            if( bNewEntry )
            {
                m_entries.Pop();
                m_entryMap.Remove( entryAccessor );
                m_pEntryPool->Release( pEntryUpdate );
            }
            else
            {
                pEntryUpdate->offset = originalOffset;
                pEntryUpdate->timestamp = originalTimestamp;
                pEntryUpdate->size = originalSize;
            }

            bCacheSuccess = false;
        }
        else
        {
            size_t writeSize = pCacheStream->Write( pData, 1, size );
            if( writeSize != size )
            {
                HELIUM_TRACE(
                    TRACE_ERROR,
                    ( TXT( "Cache: Failed to write %" ) TPRIu32 TXT( " bytes to cache \"%s\" (%" ) TPRIuSZ
                    TXT( " bytes written).\n" ) ),
                    size,
                    *m_cacheFileName,
                    writeSize );

                if( bNewEntry )
                {
                    m_entries.Pop();
                    m_entryMap.Remove( entryAccessor );
                    m_pEntryPool->Release( pEntryUpdate );
                }
                else
                {
                    pEntryUpdate->offset = originalOffset;
                    pEntryUpdate->timestamp = originalTimestamp;
                    pEntryUpdate->size = originalSize;
                }

                bCacheSuccess = false;
            }
            else
            {
                HELIUM_TRACE( TRACE_INFO, TXT( "Cache: Rewriting TOC file \"%s\".\n" ), *m_tocFileName );

                FileStream* pTocStream = File::Open( m_tocFileName, FileStream::MODE_WRITE, true );
                if( !pTocStream )
                {
                    HELIUM_TRACE( TRACE_ERROR, TXT( "Cache: Failed to open TOC \"%s\" for writing.\n" ), *m_tocFileName );
                }
                else
                {
                    BufferedStream* pBufferedStream = new BufferedStream( pTocStream );
                    HELIUM_ASSERT( pBufferedStream );

                    pBufferedStream->Write( &TOC_MAGIC, sizeof( TOC_MAGIC ), 1 );
                    pBufferedStream->Write( &sm_Version, sizeof( sm_Version ), 1 );

                    uint32_t entryCount = static_cast< uint32_t >( m_entries.GetSize() );
                    pBufferedStream->Write( &entryCount, sizeof( entryCount ), 1 );

                    WideString entryPath;
#if !HELIUM_UNICODE
                    CharString entryPathCharString;
#endif
                    uint_fast32_t entryCountFast = entryCount;
                    for( uint_fast32_t entryIndex = 0; entryIndex < entryCountFast; ++entryIndex )
                    {
                        Entry* pEntry = m_entries[ entryIndex ];
                        HELIUM_ASSERT( pEntry );

#if HELIUM_UNICODE
                        pEntry->path.ToString( entryPath );
#else
                        pEntry->path.ToString( entryPathCharString );
                        StringConverter< char, wchar_t >::Convert( entryPath, entryPathCharString );
#endif

                        HELIUM_ASSERT( entryPath.GetSize() < UINT16_MAX );
                        uint16_t pathSize = static_cast< uint16_t >( entryPath.GetSize() );
                        pBufferedStream->Write( &pathSize, sizeof( pathSize ), 1 );

                        pBufferedStream->Write( *entryPath, sizeof( tchar_t ), pathSize );

                        pBufferedStream->Write( &pEntry->subDataIndex, sizeof( pEntry->subDataIndex ), 1 );

                        pBufferedStream->Write( &pEntry->offset, sizeof( pEntry->offset ), 1 );
                        pBufferedStream->Write( &pEntry->timestamp, sizeof( pEntry->timestamp ), 1 );
                        pBufferedStream->Write( &pEntry->size, sizeof( pEntry->size ), 1 );
                    }

                    delete pBufferedStream;
                    delete pTocStream;
                }
            }
        }

        delete pCacheStream;
    }

    rLoader.Unlock();

    return bCacheSuccess;
}