// Copyright Epic Games, Inc. All Rights Reserved. #include #include #include namespace zen { BufferedOpenFile::BufferedOpenFile(const std::filesystem::path Path, std::atomic& OpenReadCount, std::atomic& CurrentOpenFileCount, std::atomic& ReadCount, std::atomic& ReadByteCount) : m_Source(Path, BasicFile::Mode::kRead) , m_SourceSize(m_Source.FileSize()) , m_OpenReadCount(OpenReadCount) , m_CurrentOpenFileCount(CurrentOpenFileCount) , m_ReadCount(ReadCount) , m_ReadByteCount(ReadByteCount) { m_OpenReadCount++; m_CurrentOpenFileCount++; } BufferedOpenFile::~BufferedOpenFile() { m_CurrentOpenFileCount--; } CompositeBuffer BufferedOpenFile::GetRange(uint64_t Offset, uint64_t Size) { ZEN_TRACE_CPU("BufferedOpenFile::GetRange"); ZEN_ASSERT((m_CacheBlockIndex == (uint64_t)-1) || m_Cache); auto _ = MakeGuard([&]() { ZEN_ASSERT((m_CacheBlockIndex == (uint64_t)-1) || m_Cache); }); ZEN_ASSERT((Offset + Size) <= m_SourceSize); const uint64_t BlockIndexStart = Offset / BlockSize; const uint64_t BlockIndexEnd = (Offset + Size - 1) / BlockSize; std::vector BufferRanges; BufferRanges.reserve(BlockIndexEnd - BlockIndexStart + 1); uint64_t ReadOffset = Offset; for (uint64_t BlockIndex = BlockIndexStart; BlockIndex <= BlockIndexEnd; BlockIndex++) { const uint64_t BlockStartOffset = BlockIndex * BlockSize; if (m_CacheBlockIndex != BlockIndex) { uint64_t CacheSize = Min(BlockSize, m_SourceSize - BlockStartOffset); ZEN_ASSERT(CacheSize > 0); m_Cache = IoBuffer(CacheSize); m_Source.Read(m_Cache.GetMutableView().GetData(), CacheSize, BlockStartOffset); m_ReadCount++; m_ReadByteCount += CacheSize; m_CacheBlockIndex = BlockIndex; } const uint64_t BytesRead = ReadOffset - Offset; ZEN_ASSERT(BlockStartOffset <= ReadOffset); const uint64_t OffsetIntoBlock = ReadOffset - BlockStartOffset; ZEN_ASSERT(OffsetIntoBlock < m_Cache.GetSize()); const uint64_t BlockBytes = Min(m_Cache.GetSize() - OffsetIntoBlock, Size - BytesRead); BufferRanges.emplace_back(SharedBuffer(IoBuffer(m_Cache, OffsetIntoBlock, BlockBytes))); ReadOffset += BlockBytes; } CompositeBuffer Result(std::move(BufferRanges)); ZEN_ASSERT(Result.GetSize() == Size); return Result; } } // namespace zen