// Platform implementation of EterBase/MappedFile.h (40250 EterBase/MappedFile.cpp). Everything but Map/Unmap // is the 40250 code; the view is a POSIX mmap (CreateFileMapping/MapViewOfFile on Windows) of the CFileBase // stream, aligned down to the allocation granularity exactly as 40250 does. #include "EterBase/StdAfx.h" #include "EterBase/MappedFile.h" #include "EterBase/Debug.h" #include #if defined(_WIN32) #include #else #include #include #endif static DWORD allocation_granularity() { #if defined(_WIN32) SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); return SysInfo.dwAllocationGranularity; #else return static_cast(sysconf(_SC_PAGESIZE)); #endif } CMappedFile::CMappedFile() : m_hFM(NULL), m_lpMapData(NULL), m_dataOffset(0), m_mapSize(0), m_seekPosition(0), m_pLZObj(NULL), m_pbBufLinkData(NULL), m_dwBufLinkSize(0), m_pbAppendResultDataBlock(NULL), m_dwAppendResultDataSize(0) { } CMappedFile::~CMappedFile() { Destroy(); } BOOL CMappedFile::Create(const char * filename) { Destroy(); return CFileBase::Create(filename, FILEMODE_READ); } BOOL CMappedFile::Create(const char * filename, const void** dest, int offset, int size) { if (!CMappedFile::Create(filename)) return FALSE; int ret = Map(dest, offset, size); return (ret) > 0; } LPCVOID CMappedFile::Get() { return m_lpData; } void CMappedFile::Link(DWORD dwBufSize, const void* c_pvBufData) { m_dwBufLinkSize=dwBufSize; m_pbBufLinkData=(BYTE*)c_pvBufData; } void CMappedFile::BindLZObject(CLZObject * pLZObj) { assert(m_pLZObj == NULL); m_pLZObj = pLZObj; Link(m_pLZObj->GetSize(), m_pLZObj->GetBuffer()); } void CMappedFile::BindLZObjectWithBufferedSize(CLZObject * pLZObj) { assert(m_pLZObj == NULL); m_pLZObj = pLZObj; Link(m_pLZObj->GetBufferSize(), m_pLZObj->GetBuffer()); } BYTE* CMappedFile::AppendDataBlock( const void* pBlock, DWORD dwBlockSize ) { if( m_pbAppendResultDataBlock ) { delete []m_pbAppendResultDataBlock; } //realloc m_dwAppendResultDataSize = m_dwBufLinkSize+dwBlockSize; m_pbAppendResultDataBlock = new BYTE[m_dwAppendResultDataSize]; memcpy(m_pbAppendResultDataBlock, m_pbBufLinkData, m_dwBufLinkSize ); memcpy(m_pbAppendResultDataBlock + m_dwBufLinkSize, pBlock, dwBlockSize ); //redirect Link(m_dwAppendResultDataSize, m_pbAppendResultDataBlock); return m_pbAppendResultDataBlock; } void CMappedFile::Destroy() { if (m_pLZObj) { delete m_pLZObj; m_pLZObj = NULL; } if (NULL != m_lpMapData) { Unmap(m_lpMapData); m_lpMapData = NULL; } #if defined(_WIN32) if (NULL != m_hFM) { CloseHandle(m_hFM); m_hFM = NULL; } #endif if( m_pbAppendResultDataBlock ) { delete []m_pbAppendResultDataBlock; m_pbAppendResultDataBlock = NULL; } m_dwAppendResultDataSize = 0; m_pbBufLinkData = NULL; m_dwBufLinkSize = 0; m_seekPosition = 0; m_dataOffset = 0; m_mapSize = 0; CFileBase::Destroy(); } int CMappedFile::Seek(DWORD offset, int iSeekType) { switch (iSeekType) { case SEEK_TYPE_BEGIN: if (offset > m_dwSize) offset = m_dwSize; m_seekPosition = offset; break; case SEEK_TYPE_CURRENT: m_seekPosition = min(m_seekPosition + offset, Size()); break; case SEEK_TYPE_END: m_seekPosition = max(0, Size() - offset); break; } return m_seekPosition; } int CMappedFile::Map(const void **dest, int offset, int size) { m_dataOffset = offset; if (size == 0) m_mapSize = m_dwSize; else m_mapSize = size; if (m_dataOffset + m_mapSize > m_dwSize) return 0; DWORD dwSysGran = allocation_granularity(); DWORD dwFileMapStart = (m_dataOffset / dwSysGran) * dwSysGran; DWORD dwMapViewSize = (m_dataOffset % dwSysGran) + m_mapSize; INT iViewDelta = m_dataOffset - dwFileMapStart; FILE* fp = static_cast(m_hFile); #if defined(_WIN32) m_hFM = CreateFileMapping((HANDLE) _get_osfhandle(_fileno(fp)), NULL, PAGE_READONLY, 0, m_dataOffset + m_mapSize, NULL); if (!m_hFM) { OutputDebugString("CMappedFile::Map !m_hFM\n"); return 0; } m_lpMapData = MapViewOfFile(m_hFM, FILE_MAP_READ, 0, dwFileMapStart, dwMapViewSize); if (!m_lpMapData) { TraceError("CMappedFile::Map !m_lpMapData %lu", GetLastError()); return 0; } #else // A zero-length view (empty file) is a valid 40250 map; mmap rejects length 0. if (dwMapViewSize == 0) dwMapViewSize = 1; void* p = mmap(NULL, dwMapViewSize, PROT_READ, MAP_PRIVATE, fileno(fp), static_cast(dwFileMapStart)); if (p == MAP_FAILED) { TraceError("CMappedFile::Map !m_lpMapData %s", GetFileName()); return 0; } m_lpMapData = p; #endif m_lpData = (char*) m_lpMapData + iViewDelta; *dest = (char*) m_lpData; m_seekPosition = 0; Link(m_mapSize, m_lpData); return (m_mapSize); } BYTE * CMappedFile::GetCurrentSeekPoint() { return m_pbBufLinkData+m_seekPosition; } DWORD CMappedFile::Size() { return m_dwBufLinkSize; } DWORD CMappedFile::GetPosition() { return m_dataOffset; } BOOL CMappedFile::Read(void * dest, int bytes) { if (m_seekPosition + bytes > Size()) return FALSE; memcpy(dest, GetCurrentSeekPoint(), bytes); m_seekPosition += bytes; return TRUE; } DWORD CMappedFile::GetSeekPosition(void) { return m_seekPosition; } void CMappedFile::Unmap(LPCVOID data) { #if defined(_WIN32) if (!UnmapViewOfFile(data)) TraceError("CMappedFile::Unmap - Error"); #else // Same view length Map computed from the (unchanged) offset and size. const DWORD dwSysGran = allocation_granularity(); DWORD dwMapViewSize = (m_dataOffset % dwSysGran) + m_mapSize; if (dwMapViewSize == 0) dwMapViewSize = 1; if (munmap(const_cast(data), dwMapViewSize) != 0) TraceError("CMappedFile::Unmap - Error"); #endif m_lpData = NULL; }