Skip to content

Commit ff07f22

Browse files
committed
[New] Light-weight cross-platform memory-mapped file.
1 parent 4b0506e commit ff07f22

File tree

4 files changed

+86
-1
lines changed

4 files changed

+86
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169

170170
### System
171171

172+
- [FileAsMem.h](include/bux/FileAsMem.h) - [Memory-mapped file](https://en.wikipedia.org/wiki/Memory-mapped_file)
172173
- [FsUtil.h](include/bux/FsUtil.h) - Utilities solely related to [\<filesystem\>](https://en.cppreference.com/w/cpp/header/filesystem)
173174
- [XConsole.h](include/bux/XConsole.h) - Cross-platform console functions.
174175
- [XPlatform.h](include/bux/XPlatform.h) - Conditionally defined macros, types, functions for as many platforms as possible.

include/bux/FileAsMem.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
#ifdef _WIN32
3+
#include <windows.h>
4+
#endif
5+
#include <filesystem>
6+
7+
namespace bux {
8+
9+
class C_FileAsMemory
10+
{
11+
public:
12+
13+
// Nonvirtuals
14+
C_FileAsMemory(const std::filesystem::path& path);
15+
~C_FileAsMemory();
16+
const char* data() const { return m_data; }
17+
18+
private:
19+
20+
// Data
21+
char* m_data{};
22+
#ifdef _WIN32
23+
HANDLE m_handle{};
24+
#else
25+
size_t m_bytes{};
26+
int m_fd = -1;
27+
#endif
28+
};
29+
30+
} // namespace bux

src/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ message(DEBUG "XCONSOLE_CPP = ${XCONSOLE_CPP}")
88
add_library(bux STATIC
99
AtomiX.cpp
1010
EZArgs.cpp EZScape.cpp
11-
FA.cpp FileLog.cpp
11+
FA.cpp FileAsMem.cpp FileLog.cpp
1212
LexBase.cpp LogStream.cpp LR1.cpp GLR.cpp ParserBase.cpp Logger.cpp ParaLog.cpp
1313
ScannerBase.cpp Serialize.cpp StrUtil.cpp SyncLog.cpp
1414
UnicodeCvt.cpp

src/FileAsMem.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "FileAsMem.h"
2+
#ifndef _WIN32
3+
#include <sys/mman.h> // mmap(), munmap()
4+
#include <fcntl.h> // open()
5+
#include <unistd.h> // lseek()
6+
#endif
7+
#include <stdexcept> // std::runtime_error
8+
9+
namespace bux {
10+
11+
C_FileAsMemory::C_FileAsMemory(const std::filesystem::path& path)
12+
{
13+
#ifdef _WIN32
14+
const auto hFile = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
15+
if (hFile == INVALID_HANDLE_VALUE)
16+
throw std::runtime_error{"Failed to open \" + path.string() + \" for read-only"};
17+
18+
m_handle = CreateFileMappingW(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr);
19+
CloseHandle(hFile);
20+
if (!m_handle)
21+
throw std::runtime_error{"Failed to create file mapping"};
22+
23+
m_data = static_cast<char*>(MapViewOfFile(m_handle, FILE_MAP_READ, 0, 0, 0));
24+
if (!m_data)
25+
CloseHandle(m_handle);
26+
#else
27+
m_fd = open(path.c_str(), O_RDONLY);
28+
if (m_fd == -1)
29+
throw std::runtime_error{"Failed to open \"" + path.string() + "\" for read-only"};
30+
31+
m_bytes = (size_t)lseek(m_fd, 0, SEEK_END);
32+
auto data = mmap(nullptr, m_bytes, PROT_READ, MAP_PRIVATE, m_fd, 0);
33+
if (data != MAP_FAILED)
34+
m_data = static_cast<char*>(data);
35+
else
36+
close(m_fd);
37+
#endif
38+
}
39+
40+
C_FileAsMemory::~C_FileAsMemory()
41+
{
42+
if (m_data)
43+
{
44+
#ifdef _WIN32
45+
UnmapViewOfFile(m_data);
46+
CloseHandle(m_handle);
47+
#else
48+
munmap(m_data, m_bytes);
49+
close(m_fd);
50+
#endif
51+
}
52+
}
53+
54+
} // namespace bux

0 commit comments

Comments
 (0)