#include <string>
#include <iostream>
#ifdef _WIN32
# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
# include <windows.h>
#else
# include <fcntl.h>
# include <unistd.h>
# include <sys/mman.h>
#endif
#include "MemoryMapping.h"
BEGIN_NAMESPACE
#ifdef _WIN32
struct MemoryMappingData
{
HANDLE m_fileHandle;
DWORD m_fileSizeHigh;
DWORD m_fileSizeLow;
HANDLE m_mappingHandle;
void* m_mapping;
};
MemoryMappingData* MemoryMapping_Open(const char* filename)
{
OFSTRUCT of;
HANDLE hFile = (HANDLE)OpenFile(filename, &of, OF_READ);
DWORD fileSizeLow = 0;
DWORD fileSizeHigh = 0;
if ((int)hFile == -1)
{
std::cerr << "Problem opening file " << filename << std::endl;
return 0;
}
fileSizeLow = GetFileSize(hFile, &fileSizeHigh);
HANDLE hMMFile = CreateFileMapping(hFile, 0, PAGE_READONLY, fileSizeHigh, fileSizeLow, 0);
if (!hMMFile)
{
std::cerr << "Problem creating mapping to file " << filename << std::endl;
CloseHandle(hFile);
return 0;
}
MemoryMappingData* mapping = new MemoryMappingData;
mapping->m_fileHandle = hFile;
mapping->m_fileSizeHigh = fileSizeHigh;
mapping->m_fileSizeLow = fileSizeLow;
mapping->m_mappingHandle = hMMFile;
mapping->m_mapping = MapViewOfFile(hMMFile, FILE_MAP_READ, 0, 0, 0);
return mapping;
}
void* MemoryMapping_GetAddress(MemoryMappingData* mapping)
{
if (!mapping)
return 0;
return mapping->m_mapping;
}
uint64_t MemoryMapping_GetSize(MemoryMappingData* mapping)
{
if (!mapping)
return 0;
return (uint64_t(mapping->m_fileSizeHigh) << 32) | mapping->m_fileSizeLow;
}
void MemoryMapping_Close(MemoryMappingData* mapping)
{
if (!mapping)
return;
UnmapViewOfFile(mapping->m_mapping);
CloseHandle(mapping->m_mappingHandle);
CloseHandle(mapping->m_fileHandle);
delete mapping;
}
MemoryMapping::MemoryMapping(const char* a_filename)
{
m_data = MemoryMapping_Open(a_filename);
}
MemoryMapping::~MemoryMapping()
{
MemoryMapping_Close(m_data);
}
void* MemoryMapping::address()
{
return MemoryMapping_GetAddress(m_data);
}
uint64_t MemoryMapping::size()
{
return MemoryMapping_GetSize(m_data);
}
#else
struct MemoryMappingData
{
int m_fileHandle;
uint64_t m_fileSize;
int m_mappingHandle;
void* m_mapping;
};
MemoryMappingData* MemoryMapping_Open(const char* filename)
{
int file = open(filename, O_RDONLY);
if (file == -1)
{
std::cerr << "Problem openning file " << filename << std::endl;
return 0;
}
MemoryMappingData* mapping = new MemoryMappingData;
mapping->m_fileHandle = file;
mapping->m_fileSize = lseek(file, 0L, SEEK_END);
lseek(file, 0L, SEEK_SET); // go back to beginning of the file (is this needed in this case?)
mapping->m_mapping = mmap(nullptr, mapping->m_fileSize, PROT_READ, MAP_FILE | MAP_PRIVATE, file, 0L);
if (!mapping->m_mapping || mapping->m_mapping == MAP_FAILED)
{
std::cerr << "Problem creating mapping to file " << filename << std::endl;
close(file);
delete mapping;
return 0;
}
return mapping;
}
void* MemoryMapping_GetAddress(MemoryMappingData* mapping)
{
if (!mapping)
return 0;
return mapping->m_mapping;
}
uint64_t MemoryMapping_GetSize(MemoryMappingData* mapping)
{
if (!mapping)
return 0;
return mapping->m_fileSize;
}
void MemoryMapping_Close(MemoryMappingData* mapping)
{
if (!mapping)
return;
munmap(mapping->m_mapping, mapping->m_fileSize);
close(mapping->m_fileHandle);
delete mapping;
}
MemoryMapping::MemoryMapping(const char* a_filename)
{
m_data = MemoryMapping_Open(a_filename);
}
MemoryMapping::~MemoryMapping()
{
MemoryMapping_Close(m_data);
}
void* MemoryMapping::address()
{
return MemoryMapping_GetAddress(m_data);
}
uint64_t MemoryMapping::size()
{
return MemoryMapping_GetSize(m_data);
}
#endif
END_NAMESPACE