ultimatepp/uppsrc/Core/FileMapping.cpp
2024-04-10 18:15:00 +02:00

175 lines
3.6 KiB
C++

#include "Core.h"
#ifdef PLATFORM_POSIX
#include <sys/mman.h>
#endif
namespace Upp {
int FileMapping::MappingGranularity()
{
static int mg = 0;
#ifdef PLATFORM_WIN32
ONCELOCK {
SYSTEM_INFO info;
GetSystemInfo(&info);
mg = info.dwAllocationGranularity;
}
#else
ONCELOCK {
mg = getpagesize();
}
#endif
return mg;
}
FileMapping::FileMapping(const char *file_)
{
#ifdef PLATFORM_WIN32
hfile = INVALID_HANDLE_VALUE;
hmap = NULL;
#endif
#ifdef PLATFORM_POSIX
hfile = -1;
#endif
base = rawbase = NULL;
size = rawsize = 0;
offset = rawoffset = 0;
filesize = -1;
write = false;
if(file_)
Open(file_);
}
#ifdef PLATFORM_WIN32
bool FileMapping::Open(const char *filename, dword mode, int64 wsize)
#else
bool FileMapping::Open(const char *filename, dword mode, int64 wsize, mode_t acm)
#endif
{
Close();
write = (mode & FileStream::MODEMASK) != FileStream::READ;
#ifdef PLATFORM_WIN32
if(!FileStream::OpenHandle(filename, mode, hfile, filesize))
return false;
if((mode & FileStream::MODEMASK) == FileStream::CREATE)
filesize = wsize;
else
wsize = 0;
hmap = CreateFileMapping(hfile, NULL, write ? PAGE_READWRITE : PAGE_READONLY, HIDWORD(wsize), LODWORD(wsize), NULL);
if(!hmap) {
Close();
return false;
}
#else
if(!FileStream::OpenHandle(filename, mode, hfile, filesize, acm))
return false;
if((mode & FileStream::MODEMASK) == FileStream::CREATE) {
ftruncate(hfile, wsize);
filesize = wsize;
}
#endif
return true;
}
bool FileMapping::Create(const char *file, int64 filesize, bool delete_share)
{
return Open(file, FileStream::CREATE | (delete_share ? FileStream::DELETESHARE : 0), filesize);
}
byte *FileMapping::Map(int64 mapoffset, size_t maplen)
{
ASSERT(IsOpen());
Unmap();
mapoffset = minmax<int64>(mapoffset, 0, filesize);
int gran = MappingGranularity();
int64 rawoff = mapoffset & -gran;
maplen = (size_t)min<int64>(maplen, filesize - mapoffset);
size_t rawsz = (size_t)min<int64>((maplen + (size_t)(mapoffset - rawoff) + gran - 1) & -gran, filesize - rawoff);
rawoffset = rawoff;
rawsize = rawsz;
#ifdef PLATFORM_WIN32
rawbase = (byte *)MapViewOfFile(hmap, write ? FILE_MAP_WRITE : FILE_MAP_READ,
HIDWORD(rawoffset), LODWORD(rawoffset), rawsize);
#else
rawbase = (byte *)mmap(0, rawsize,
PROT_READ | (write ? PROT_WRITE : 0),
#ifdef PLATFORM_FREEBSD
MAP_NOSYNC,
#else
MAP_SHARED,
#endif
hfile, rawoffset);
#endif
#ifdef PLATFORM_POSIX
if(rawbase == (byte *)-1)
#else
if(!rawbase)
#endif
return NULL;
offset = mapoffset;
size = maplen;
base = rawbase + (int)(offset - rawoffset);
return base;
}
bool FileMapping::Unmap()
{
bool ok = true;
if(rawbase) {
#ifdef PLATFORM_WIN32
ok = !!UnmapViewOfFile(rawbase);
#endif
#ifdef PLATFORM_POSIX
ok = (munmap((void *)rawbase, rawsize) == 0);
#endif
}
base = rawbase = NULL;
size = 0;
return ok;
}
bool FileMapping::Close()
{
bool ok = Unmap();
#ifdef PLATFORM_WIN32
if(hmap) {
if(!CloseHandle(hmap)) ok = false;
hmap = NULL;
}
if(IsOpen()) {
if(!CloseHandle(hfile)) ok = false;
hfile = INVALID_HANDLE_VALUE;
}
#endif
#ifdef PLATFORM_POSIX
if(IsOpen()) {
if(close(hfile) != 0) ok = false;
hfile = -1;
}
#endif
filesize = -1;
offset = 0;
size = 0;
write = false;
return ok;
}
Time FileMapping::GetTime() const
{
ASSERT(IsOpen());
#ifdef PLATFORM_WIN32
FileTime ft;
GetFileTime(hfile, NULL, NULL, &ft);
return ft;
#endif
#ifdef PLATFORM_POSIX
struct stat st;
fstat(hfile, st);
return Time(st.st_mtime);
#endif
}
}