13 #ifndef WIN32_LEAN_AND_MEAN
14 #define WIN32_LEAN_AND_MEAN
33 result.file_handle_ = CreateFileW(
39 FILE_ATTRIBUTE_NORMAL,
42 if (result.file_handle_ == INVALID_HANDLE_VALUE) {
43 result.file_handle_ =
nullptr;
46 "Failed to open file: " + path.string());
50 LARGE_INTEGER file_size;
51 if (!GetFileSizeEx(result.file_handle_, &file_size)) {
52 CloseHandle(result.file_handle_);
53 result.file_handle_ =
nullptr;
56 "Failed to get file size: " + path.string());
59 result.
size_ =
static_cast<std::size_t
>(file_size.QuadPart);
61 if (result.
size_ == 0) {
62 CloseHandle(result.file_handle_);
63 result.file_handle_ =
nullptr;
66 "File is empty: " + path.string());
70 result.mapping_handle_ = CreateFileMappingW(
77 if (result.mapping_handle_ ==
nullptr) {
78 CloseHandle(result.file_handle_);
79 result.file_handle_ =
nullptr;
82 "Failed to create file mapping: " + path.string());
86 auto* mapped = MapViewOfFile(
87 result.mapping_handle_,
92 if (mapped ==
nullptr) {
93 CloseHandle(result.mapping_handle_);
94 CloseHandle(result.file_handle_);
95 result.mapping_handle_ =
nullptr;
96 result.file_handle_ =
nullptr;
99 "Failed to map file into memory: " + path.string());
102 result.
data_ =
static_cast<const std::uint8_t*
>(mapped);
106 result.
fd_ = ::open(path.c_str(), O_RDONLY);
107 if (result.
fd_ < 0) {
110 "Failed to open file: " + path.string());
115 if (::fstat(result.
fd_, &st) != 0) {
120 "Failed to stat file: " + path.string());
123 result.
size_ =
static_cast<std::size_t
>(st.st_size);
125 if (result.
size_ == 0) {
130 "File is empty: " + path.string());
134 auto* mapped = ::mmap(
nullptr, result.
size_, PROT_READ, MAP_PRIVATE,
136 if (mapped == MAP_FAILED) {
141 "Failed to mmap file: " + path.string());
144 result.
data_ =
static_cast<const std::uint8_t*
>(mapped);
166 , file_handle_{other.file_handle_}
167 , mapping_handle_{other.mapping_handle_}
172 other.data_ =
nullptr;
175 other.file_handle_ =
nullptr;
176 other.mapping_handle_ =
nullptr;
184 if (
this != &other) {
190 file_handle_ = other.file_handle_;
191 mapping_handle_ = other.mapping_handle_;
192 other.file_handle_ =
nullptr;
193 other.mapping_handle_ =
nullptr;
198 other.data_ =
nullptr;
209 if (
data_ ==
nullptr) {
214 UnmapViewOfFile(
data_);
215 if (mapping_handle_ !=
nullptr) {
216 CloseHandle(mapping_handle_);
218 if (file_handle_ !=
nullptr) {
219 CloseHandle(file_handle_);
221 mapping_handle_ =
nullptr;
222 file_handle_ =
nullptr;
224 ::munmap(
const_cast<std::uint8_t*
>(
data_),
size_);
const std::uint8_t * data_
static auto open(const std::filesystem::path &path) -> kcenon::pacs::Result< memory_mapped_file >
Open and memory-map a file for reading.
auto as_span() const noexcept -> std::span< const std::uint8_t >
Get a span over the mapped data.
auto size() const noexcept -> std::size_t
Get the size of the mapped file.
auto operator=(const memory_mapped_file &) -> memory_mapped_file &=delete
memory_mapped_file()=default
auto data() const noexcept -> const std::uint8_t *
Get pointer to the mapped data.
RAII wrapper for memory-mapped file I/O.
constexpr int file_read_error
constexpr int invalid_dicom_file
constexpr int file_not_found
@ other
Unknown or other category.
Result< T > pacs_error(int code, const std::string &message, const std::string &details="")
Create a PACS error result with module context.