68 static constexpr size_t map_entire_file = 0;
71 using file_handle_type =
void*;
73 using file_handle_type =
int;
76 const inline file_handle_type invalid_handle = (file_handle_type)-1;
79 template <
typename VALUE_TYPE>
81 struct basic_mmap_base
83 static_assert(
sizeof(VALUE_TYPE) ==
sizeof(std::byte));
85 using value_type = VALUE_TYPE;
87 using reference = value_type&;
88 using const_reference =
const value_type&;
89 using pointer = value_type*;
90 using const_pointer =
const value_type*;
91 using difference_type = std::ptrdiff_t;
92 using iterator = pointer;
93 using const_iterator = const_pointer;
94 using reverse_iterator = std::reverse_iterator<iterator>;
95 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
96 using iterator_category = std::random_access_iterator_tag;
97 using handle_type = file_handle_type;
104 , file_handle_(std::
exchange(
other.file_handle_, invalid_handle))
105 , file_mapping_handle_(std::
exchange(
other.file_mapping_handle_, invalid_handle))
109 handle_type file_handle()
const noexcept {
return file_handle_; }
110 handle_type mapping_handle()
const noexcept {
return file_mapping_handle_ == invalid_handle ? file_handle_ : file_mapping_handle_; }
112 bool is_open()
const noexcept {
return file_handle_ != invalid_handle; }
119 return file_mapping_handle_ != invalid_handle;
125 template <
typename T = VALUE_TYPE>
126 std::span<T const> to_span()
const noexcept {
return {
reinterpret_cast<T
const*
>(data()), size() }; }
130 size_type mapped_length()
const noexcept {
return mapped_length_; }
134 return mapped_length_ - length_;
142 const_iterator end()
const noexcept {
return data() + length(); }
143 const_iterator cend()
const noexcept {
return data() + length(); }
147 return const_reverse_iterator(end());
152 return const_reverse_iterator(end());
157 return const_reverse_iterator(begin());
161 return const_reverse_iterator(begin());
164 const_reference operator[](
const size_type
i)
const noexcept {
return data_[
i]; }
166 void swap(basic_mmap_base&
other)
noexcept
171 swap(data_,
other.data_);
172 swap(file_handle_,
other.file_handle_);
173 swap(file_mapping_handle_,
other.file_mapping_handle_);
174 swap(length_,
other.length_);
175 swap(mapped_length_,
other.mapped_length_);
188 file_handle_type file_mapping_handle;
191 pointer data_ =
nullptr;
193 size_type length_ = 0;
194 size_type mapped_length_ = 0;
196 handle_type file_handle_ = invalid_handle;
197 handle_type file_mapping_handle_ = invalid_handle;
201 return !data() ?
nullptr : data() - mapping_offset();
206 template <
typename CRTP,
typename VALUE_TYPE = std::
byte>
207 struct basic_mmap :
public basic_mmap_base<VALUE_TYPE>
209 using typename basic_mmap_base<VALUE_TYPE>::size_type;
210 using typename basic_mmap_base<VALUE_TYPE>::handle_type;
211 using typename basic_mmap_base<VALUE_TYPE>::pointer;
216 std::error_code
error;
218 if (
error) {
throw std::system_error{
error }; }
220 basic_mmap(
const handle_type handle,
const size_type
offset = 0,
const size_type length = map_entire_file)
222 std::error_code
error;
224 if (
error) {
throw std::system_error{
error }; }
227 basic_mmap(
const basic_mmap&) =
delete;
236 this->data_ = std::exchange(
other.data_,
nullptr);
237 this->length_ = std::exchange(
other.length_, 0);
238 this->mapped_length_ = std::exchange(
other.mapped_length_, 0);
239 this->file_handle_ = std::exchange(
other.file_handle_, invalid_handle);
240 this->file_mapping_handle_ = std::exchange(
other.file_mapping_handle_, invalid_handle);
247 static_cast<CRTP*
>(
this)->conditional_sync();
253 void map(
const std::filesystem::path& path,
const size_type
offset,
const size_type length, std::error_code&
error)
noexcept
258 error = std::make_error_code(std::errc::invalid_argument);
263 const auto file_size = std::filesystem::file_size(path,
error);
269 error = std::make_error_code(std::errc::file_too_large);
274 const auto handle =
static_cast<CRTP*
>(
this)->open_file(path,
error);
279 if (handle == invalid_handle)
281 error = std::make_error_code(std::errc::bad_file_descriptor);
285 if (
offset + length > file_size)
287 error = std::make_error_code(std::errc::invalid_argument);
291 const auto ctx =
static_cast<CRTP*
>(
this)->memory_map(handle,
offset, length == map_entire_file ? (file_size -
offset) : length,
error);
301 this->file_handle_ = handle;
302 this->data_ =
reinterpret_cast<pointer
>(
ctx.data);
303 this->length_ =
ctx.length;
304 this->mapped_length_ =
ctx.mapped_length;
305 this->file_mapping_handle_ =
ctx.file_mapping_handle;
309 void map(
const std::filesystem::path& path, std::error_code&
error)
noexcept
311 this->map(path, 0, map_entire_file,
error);
321 template <
typename VALUE_TYPE = std::
byte>
322 struct mmap_source :
public basic_mmap<mmap_source<VALUE_TYPE>, VALUE_TYPE>
327 template <
typename VALUE_TYPE_>
328 friend mmap_source<VALUE_TYPE_> make_mmap_source(
const std::filesystem::path& path,
typename mmap_source<VALUE_TYPE_>::size_type
offset,
typename mmap_source<VALUE_TYPE_>::size_type length, std::error_code&
error)
noexcept;
332 friend struct basic_mmap<
mmap_source<VALUE_TYPE>, VALUE_TYPE>;
334 static file_handle_type open_file(
const std::filesystem::path& path, std::error_code&
error)
noexcept;
336 static mmap_context memory_map(
const file_handle_type file_handle,
const int64_t offset,
const int64_t length, std::error_code&
error)
noexcept;
338 void conditional_sync() {}
348 template <
typename VALUE_TYPE = std::
byte>
349 struct mmap_sink :
public basic_mmap<mmap_sink<VALUE_TYPE>, VALUE_TYPE>
360 reference operator[](
const size_type
i)
const noexcept {
return this->data_[
i]; }
365 pointer data()
noexcept {
return this->data_; }
368 iterator begin()
noexcept {
return this->data(); }
371 iterator end()
noexcept {
return this->data() + this->length(); }
374 reverse_iterator rbegin()
noexcept {
return reverse_iterator(this->end()); }
377 reverse_iterator rend()
noexcept {
return reverse_iterator(this->begin()); }
379 void sync(std::error_code&
error)
noexcept;
383 friend struct basic_mmap<
mmap_sink<VALUE_TYPE>, VALUE_TYPE>;
385 static file_handle_type open_file(
const std::filesystem::path& path, std::error_code&
error)
noexcept;
387 static mmap_context memory_map(
const file_handle_type file_handle,
const int64_t offset,
const int64_t length, std::error_code&
error)
noexcept;
389 pointer get_mapping_start()
noexcept
391 return !this->data() ?
nullptr : this->data() - this->mapping_offset();
394 void conditional_sync()
401 template <
typename VALUE_TYPE>
402 inline mmap_source<VALUE_TYPE> make_mmap_source(
const std::filesystem::path& path,
typename mmap_source<VALUE_TYPE>::size_type
offset,
typename mmap_source<VALUE_TYPE>::size_type length, std::error_code&
error)
noexcept
409 template <
typename VALUE_TYPE>
415 template <
typename VALUE_TYPE>
416 inline mmap_source<VALUE_TYPE> make_mmap_source(
const std::filesystem::path& path,
typename mmap_source<VALUE_TYPE>::size_type
offset,
typename mmap_source<VALUE_TYPE>::size_type length)
421 template <
typename VALUE_TYPE>
427 template <
typename VALUE_TYPE>
428 inline mmap_sink<VALUE_TYPE> make_mmap_sink(
const std::filesystem::path& path,
typename mmap_sink<VALUE_TYPE>::size_type
offset,
typename mmap_sink<VALUE_TYPE>::size_type length, std::error_code&
error)
noexcept
435 template <
typename VALUE_TYPE>
441 template <
typename VALUE_TYPE>
442 inline mmap_sink<VALUE_TYPE> make_mmap_sink(
const std::filesystem::path& path,
typename mmap_sink<VALUE_TYPE>::size_type
offset,
typename mmap_sink<VALUE_TYPE>::size_type length)
447 template <
typename VALUE_TYPE>
constexpr auto bit_count
Equal to the number of bits in the type.
Primary namespace for everything in this library.
A read-write view over a file.
A read-only memory view over a file.