#include "DiskFile.h" #include const int c_nBufferSize = 1024 * 32; // 32k cache CDiskFileReader::CDiskFileReader() : m_pFile( NULL ) , m_pBuffer( NULL ) , m_uiBufferAllocSize( 0 ) , m_uiBufferReadSize( 0 ) , m_uiBufferBeginPos( 0 ) , m_uiFilePos( 0 ) , m_bGood( false ) , m_nFileSize( 0 ) , m_nFileBeginPos( 0 ) { m_pBuffer = new BYTE[c_nBufferSize]; m_uiBufferAllocSize = c_nBufferSize; } CDiskFileReader::~CDiskFileReader() { if ( m_pBuffer ) { delete [] m_pBuffer; m_pBuffer = NULL; } } void CDiskFileReader::SetFileInfo( FILE* pFile, unsigned int nFileSize, unsigned int nFileBeginPos ) { if ( m_pFile != pFile ) { m_uiBufferReadSize = 0; m_uiFilePos = 0; m_uiBufferBeginPos = 0; } m_nFileSize = nFileSize; m_nFileBeginPos = nFileBeginPos; m_pFile = pFile; m_bGood = m_pFile != NULL; } void CDiskFileReader::Seek( int iOffset, int iWhence) { if (m_bGood) { unsigned int uiNewPos = 0; switch ( iWhence ) { case SEEK_CUR: uiNewPos = (int)m_uiFilePos + iOffset; break; case SEEK_SET: uiNewPos = iOffset; break; case SEEK_END: uiNewPos = (int)m_nFileBeginPos + (int)m_nFileSize - iOffset; break; } if ( uiNewPos < m_uiBufferBeginPos || uiNewPos > m_uiBufferBeginPos + m_uiBufferReadSize ) { Flush(); } m_uiFilePos = uiNewPos; } } void CDiskFileReader::Seek( int iOffset ) { Seek( iOffset, SEEK_CUR ); } unsigned int CDiskFileReader::Read( void* pBuffer, unsigned int uiBytes ) { if (m_bGood) { unsigned int uiRead = 0; //uiAvailBufferBytes = m_uiBufferReadSize - m_uiPos; int nAvailBufferBytes = (int)m_uiBufferBeginPos + (int)m_uiBufferReadSize - (int)m_uiFilePos; if ( nAvailBufferBytes < 0 ) nAvailBufferBytes = 0; if ( nAvailBufferBytes > (int)m_uiBufferReadSize ) { nAvailBufferBytes = 0; } int nPos = m_uiFilePos - m_uiBufferBeginPos; if ( nPos < 0 ) { return 0; } if (uiBytes > (unsigned int )nAvailBufferBytes) { if (nAvailBufferBytes > 0) { memcpy_s(pBuffer, uiBytes, &m_pBuffer[nPos], nAvailBufferBytes); pBuffer = &(((char *) pBuffer)[nAvailBufferBytes]); uiBytes -= nAvailBufferBytes; uiRead = nAvailBufferBytes; m_uiFilePos += uiRead; } Flush(); nPos = 0; if (uiBytes > m_uiBufferAllocSize) { return uiRead + DiskRead(pBuffer, uiBytes); } else { m_uiBufferReadSize = DiskRead(m_pBuffer, m_uiBufferAllocSize); if (m_uiBufferReadSize < uiBytes) { uiBytes = m_uiBufferReadSize; } } } if ( uiBytes > 0 ) { memcpy_s( pBuffer, uiBytes, m_pBuffer + nPos, uiBytes ); } m_uiFilePos += uiBytes; return uiRead + uiBytes; } else { return 0; } } void CDiskFileReader::Flush() { m_uiBufferBeginPos = 0; m_uiBufferReadSize = 0; } unsigned int CDiskFileReader::DiskRead(void* pBuffer, unsigned int uiBytes) { if ( fseek( m_pFile, m_uiFilePos, SEEK_SET ) != 0 ) { m_bGood = false; return 0; } m_uiBufferBeginPos = m_uiFilePos; return (unsigned int)fread(pBuffer, 1, uiBytes, m_pFile); }