diff --git a/openVulkanoCpp/IO/MemMappedFile.cpp b/openVulkanoCpp/IO/MemMappedFile.cpp new file mode 100644 index 0000000..9db06d2 --- /dev/null +++ b/openVulkanoCpp/IO/MemMappedFile.cpp @@ -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 +#else +#include +#include +#include +#include +#include +#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(path.c_str(), fileMode); + m_data = m_internal->address; + m_size = (m_data) ? m_internal->size : 0; + } +} \ No newline at end of file diff --git a/openVulkanoCpp/IO/MemMappedFile.hpp b/openVulkanoCpp/IO/MemMappedFile.hpp new file mode 100644 index 0000000..42ae856 --- /dev/null +++ b/openVulkanoCpp/IO/MemMappedFile.hpp @@ -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 + +namespace OpenVulkano +{ + class MemMappedFile + { + class Internal; + + std::shared_ptr 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; } + }; +} \ No newline at end of file