#include "File.h" #include #include #include #include using namespace ISO9660; CFile::CFile(CBlockProvider* blockProvider, uint64 start) : m_blockProvider(blockProvider) , m_start(start) , m_end(ULLONG_MAX) { InitBlock(); } CFile::CFile(CBlockProvider* blockProvider, uint64 start, uint64 size) : m_blockProvider(blockProvider) , m_start(start) , m_end(start + size) { InitBlock(); } void CFile::Seek(int64 amount, Framework::STREAM_SEEK_DIRECTION whence) { uint64 size = (m_end != ULLONG_MAX) ? (m_end - m_start) : ULLONG_MAX; switch(whence) { case Framework::STREAM_SEEK_SET: m_position = amount; break; case Framework::STREAM_SEEK_CUR: m_position += amount; break; case Framework::STREAM_SEEK_END: //Cannot seek from end with unbounded files assert(m_end != ULLONG_MAX); m_position = size + amount; break; } m_position = std::max(m_position, 0); m_position = std::min(m_position, size); m_isEof = false; } uint64 CFile::Tell() { return m_position; } uint64 CFile::Read(void* data, uint64 length) { if(length == 0) return 0; //Pre-condition assert(m_position <= (m_end - m_start)); //Check if we're at the end of the file uint64 offset = m_start + m_position; if(offset >= m_end) { m_isEof = true; return 0; } uint64 remainFileSize = m_end - offset; length = std::min(length, remainFileSize); uint64 total = length; //Read what's remaining of this block while(1) { SyncBlock(); uint64 blockPosition = (m_start + m_position) % CBlockProvider::BLOCKSIZE; uint64 blockRemain = CBlockProvider::BLOCKSIZE - blockPosition; uint64 toRead = (length > blockRemain) ? (blockRemain) : (length); memcpy(data, m_block + blockPosition, static_cast(toRead)); m_position += toRead; length -= toRead; data = reinterpret_cast(data) + toRead; if(length == 0) break; } //Post-condition assert(m_position <= (m_end - m_start)); return total; } uint64 CFile::Write(const void* pData, uint64 nLength) { return -1; } bool CFile::IsEOF() { return m_isEof; } void CFile::InitBlock() { m_blockPosition = static_cast(m_start / CBlockProvider::BLOCKSIZE); m_blockProvider->ReadBlock(m_blockPosition, m_block); } void CFile::SyncBlock() { uint32 position = static_cast((m_start + m_position) / CBlockProvider::BLOCKSIZE); if(position == m_blockPosition) return; m_blockProvider->ReadBlock(position, m_block); m_blockPosition = position; }