Add MemMappedFile
This commit is contained in:
127
openVulkanoCpp/IO/MemMappedFile.cpp
Normal file
127
openVulkanoCpp/IO/MemMappedFile.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "MemMappedFile.hpp"
|
||||
#include "Base/Logger.hpp"
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
class MemMappedFile::Internal final
|
||||
{
|
||||
public:
|
||||
void* address = nullptr;
|
||||
size_t size = 0;
|
||||
#ifdef _MSC_VER
|
||||
HANDLE fileHandle;
|
||||
HANDLE fileMappingHandle;
|
||||
|
||||
Internal(const char* file, FileMode fileMode)
|
||||
{ //TODO handle other file modes than read
|
||||
fileHandle = CreateFile(
|
||||
TEXT(file), // file to open
|
||||
GENERIC_READ, // open for reading
|
||||
0, // do not share
|
||||
NULL, // default security
|
||||
OPEN_EXISTING, // existing file only
|
||||
FILE_ATTRIBUTE_NORMAL, // normal file
|
||||
NULL); // no attribute template
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to open file: {}", file);
|
||||
return;
|
||||
}
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(fileHandle, &fileSize))
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to get size of file: {}", file);
|
||||
CloseHandle(fileHandle);
|
||||
return;
|
||||
}
|
||||
size = fileSize;
|
||||
|
||||
fileMappingHandle = CreateFileMapping(
|
||||
fileHandle,
|
||||
NULL, // default security
|
||||
PAGE_READONLY, // read-only access
|
||||
0, // maximum object size (high-order)
|
||||
0, // maximum object size (low-order)
|
||||
NULL); // name of the mapping object
|
||||
if (fileMappingHandle == 0)
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to create file mapping handle: {}", file);
|
||||
CloseHandle(fileHandle);
|
||||
size = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
address = MapViewOfFile(
|
||||
fileMappingHandle, // handle to the map object
|
||||
FILE_MAP_READ, // read access
|
||||
0, // max. object size
|
||||
0, // size of the hFile
|
||||
0); // map the entire file
|
||||
|
||||
if (address == nullptr)
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to create file mapping: {}", file);
|
||||
CloseHandle(fileMappingHandle);
|
||||
CloseHandle(fileHandle);
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~Internal()
|
||||
{
|
||||
UnmapViewOfFile(lpMapAddress);
|
||||
CloseHandle(fileMappingHandle);
|
||||
CloseHandle(fileHandle);
|
||||
}
|
||||
#else
|
||||
int fileHandle;
|
||||
struct stat fileStat;
|
||||
|
||||
Internal(const char* file, FileMode fileMode)
|
||||
{
|
||||
fileHandle = open(file, fileMode);
|
||||
if (fstat(fileHandle, &fileStat) == -1)
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to query stats for file: {}", file);
|
||||
return;
|
||||
}
|
||||
address = mmap(nullptr, fileStat.st_size, fileMode, MAP_PRIVATE, fileHandle, 0);
|
||||
if (address == MAP_FAILED)
|
||||
{
|
||||
Logger::FILESYS->critical("Failed to memory map file: {}", file);
|
||||
address = nullptr;
|
||||
}
|
||||
size = fileStat.st_size;
|
||||
}
|
||||
|
||||
~Internal()
|
||||
{
|
||||
munmap(address, fileStat.st_size);
|
||||
close(fileHandle);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
MemMappedFile::MemMappedFile(const std::filesystem::path& path, FileMode fileMode)
|
||||
{
|
||||
m_internal = std::make_shared<Internal>(path.c_str(), fileMode);
|
||||
m_data = m_internal->address;
|
||||
m_size = (m_data) ? m_internal->size : 0;
|
||||
}
|
||||
}
|
||||
34
openVulkanoCpp/IO/MemMappedFile.hpp
Normal file
34
openVulkanoCpp/IO/MemMappedFile.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace OpenVulkano
|
||||
{
|
||||
class MemMappedFile
|
||||
{
|
||||
class Internal;
|
||||
|
||||
std::shared_ptr<Internal> m_internal;
|
||||
void* m_data;
|
||||
size_t m_size;
|
||||
|
||||
public:
|
||||
enum FileMode : int { READ_ONLY = 0, WRITE_ONLY, READ_WRITE };
|
||||
|
||||
MemMappedFile(const std::filesystem::path& path, FileMode fileMode = READ_ONLY);
|
||||
|
||||
[[nodiscard]] bool IsOpen() const { return m_data; }
|
||||
|
||||
[[nodiscard]] operator bool() const { return m_data; }
|
||||
|
||||
[[nodiscard]] size_t Size() const { return m_size; }
|
||||
|
||||
[[nodiscard]] void* Data() const { return m_data; }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user