pyxcp 0.21.9__cp312-cp312-win_amd64.whl → 0.22.23__cp312-cp312-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyxcp might be problematic. Click here for more details.
- pyxcp/__init__.py +12 -20
- pyxcp/aml/EtasCANMonitoring.a2l +82 -83
- pyxcp/aml/XCP_Common.aml +0 -1
- pyxcp/aml/XCPonUSB.aml +1 -1
- pyxcp/aml/ifdata_CAN.a2l +0 -1
- pyxcp/aml/ifdata_Eth.a2l +0 -1
- pyxcp/aml/ifdata_Flx.a2l +0 -1
- pyxcp/aml/ifdata_SxI.a2l +0 -1
- pyxcp/aml/ifdata_USB.a2l +0 -1
- pyxcp/asam/types.py +4 -4
- pyxcp/asamkeydll.c +0 -1
- pyxcp/checksum.py +0 -1
- pyxcp/cmdline.py +32 -50
- pyxcp/config/__init__.py +1100 -0
- pyxcp/config/legacy.py +120 -0
- pyxcp/constants.py +12 -13
- pyxcp/cpp_ext/__init__.py +0 -0
- pyxcp/cpp_ext/bin.hpp +104 -0
- pyxcp/cpp_ext/blockmem.hpp +58 -0
- pyxcp/cpp_ext/cpp_ext.cp310-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp311-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp312-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp38-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/cpp_ext.cp39-win_amd64.pyd +0 -0
- pyxcp/cpp_ext/daqlist.hpp +200 -0
- pyxcp/cpp_ext/event.hpp +67 -0
- pyxcp/cpp_ext/extension_wrapper.cpp +96 -0
- pyxcp/cpp_ext/helper.hpp +280 -0
- pyxcp/cpp_ext/mcobject.hpp +246 -0
- pyxcp/cpp_ext/tsqueue.hpp +46 -0
- pyxcp/daq_stim/__init__.py +228 -0
- pyxcp/daq_stim/optimize/__init__.py +67 -0
- pyxcp/daq_stim/optimize/binpacking.py +41 -0
- pyxcp/daq_stim/scheduler.cpp +28 -0
- pyxcp/daq_stim/scheduler.hpp +75 -0
- pyxcp/daq_stim/stim.cp310-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp311-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp312-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp38-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cp39-win_amd64.pyd +0 -0
- pyxcp/daq_stim/stim.cpp +13 -0
- pyxcp/daq_stim/stim.hpp +604 -0
- pyxcp/daq_stim/stim_wrapper.cpp +48 -0
- pyxcp/dllif.py +21 -18
- pyxcp/errormatrix.py +5 -3
- pyxcp/examples/conf_can.toml +4 -2
- pyxcp/examples/conf_can_vector.json +9 -9
- pyxcp/examples/conf_can_vector.toml +4 -2
- pyxcp/examples/conf_eth.toml +5 -2
- pyxcp/examples/conf_nixnet.json +18 -18
- pyxcp/examples/conf_sxi.json +7 -7
- pyxcp/examples/ex_arrow.py +109 -0
- pyxcp/examples/ex_csv.py +85 -0
- pyxcp/examples/ex_excel.py +95 -0
- pyxcp/examples/ex_mdf.py +124 -0
- pyxcp/examples/ex_sqlite.py +128 -0
- pyxcp/examples/run_daq.py +148 -0
- pyxcp/examples/xcp_policy.py +6 -7
- pyxcp/examples/xcp_read_benchmark.py +8 -6
- pyxcp/examples/xcp_skel.py +0 -2
- pyxcp/examples/xcp_unlock.py +1 -1
- pyxcp/examples/xcp_user_supplied_driver.py +1 -2
- pyxcp/examples/xcphello.py +6 -3
- pyxcp/examples/xcphello_recorder.py +4 -4
- pyxcp/master/__init__.py +1 -2
- pyxcp/master/errorhandler.py +107 -74
- pyxcp/master/master.py +196 -114
- pyxcp/py.typed +0 -0
- pyxcp/recorder/__init__.py +27 -6
- pyxcp/recorder/converter/__init__.py +37 -0
- pyxcp/recorder/lz4.c +129 -51
- pyxcp/recorder/lz4.h +45 -28
- pyxcp/recorder/lz4hc.c +560 -156
- pyxcp/recorder/lz4hc.h +1 -1
- pyxcp/recorder/mio.hpp +721 -767
- pyxcp/recorder/reader.hpp +139 -0
- pyxcp/recorder/reco.py +5 -8
- pyxcp/recorder/rekorder.cp310-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp311-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp312-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp38-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cp39-win_amd64.pyd +0 -0
- pyxcp/recorder/rekorder.cpp +18 -22
- pyxcp/recorder/rekorder.hpp +200 -587
- pyxcp/recorder/setup.py +11 -10
- pyxcp/recorder/test_reko.py +2 -3
- pyxcp/recorder/unfolder.hpp +1332 -0
- pyxcp/recorder/wrap.cpp +171 -9
- pyxcp/recorder/writer.hpp +302 -0
- pyxcp/scripts/pyxcp_probe_can_drivers.py +0 -2
- pyxcp/scripts/xcp_examples.py +64 -0
- pyxcp/scripts/xcp_fetch_a2l.py +15 -10
- pyxcp/scripts/xcp_id_scanner.py +2 -6
- pyxcp/scripts/xcp_info.py +101 -63
- pyxcp/scripts/xcp_profile.py +27 -0
- pyxcp/stim/__init__.py +0 -0
- pyxcp/tests/test_asam_types.py +2 -2
- pyxcp/tests/test_binpacking.py +186 -0
- pyxcp/tests/test_can.py +1132 -38
- pyxcp/tests/test_checksum.py +2 -1
- pyxcp/tests/test_daq.py +193 -0
- pyxcp/tests/test_frame_padding.py +6 -3
- pyxcp/tests/test_master.py +42 -31
- pyxcp/tests/test_transport.py +12 -12
- pyxcp/tests/test_utils.py +2 -5
- pyxcp/timing.py +0 -2
- pyxcp/transport/__init__.py +9 -9
- pyxcp/transport/base.py +149 -127
- pyxcp/transport/base_transport.hpp +0 -0
- pyxcp/transport/can.py +194 -167
- pyxcp/transport/eth.py +80 -82
- pyxcp/transport/sxi.py +106 -60
- pyxcp/transport/transport_wrapper.cpp +0 -0
- pyxcp/transport/usb_transport.py +65 -83
- pyxcp/types.py +69 -20
- pyxcp/utils.py +47 -16
- pyxcp/vector/map.py +1 -3
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/METADATA +28 -23
- pyxcp-0.22.23.dist-info/RECORD +140 -0
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/WHEEL +1 -1
- {pyxcp-0.21.9.dist-info → pyxcp-0.22.23.dist-info}/entry_points.txt +2 -0
- pyxcp/config.py +0 -57
- pyxcp/cxx/asynchiofactory.hpp +0 -24
- pyxcp/cxx/blocking_client.cpp +0 -44
- pyxcp/cxx/blocking_socket.cpp +0 -43
- pyxcp/cxx/blocking_socket.hpp +0 -558
- pyxcp/cxx/concurrent_queue.hpp +0 -60
- pyxcp/cxx/eth.hpp +0 -57
- pyxcp/cxx/exceptions.hpp +0 -30
- pyxcp/cxx/iasyncioservice.hpp +0 -31
- pyxcp/cxx/iresource.hpp +0 -17
- pyxcp/cxx/isocket.hpp +0 -22
- pyxcp/cxx/linux/epoll.cpp +0 -51
- pyxcp/cxx/linux/epoll.hpp +0 -87
- pyxcp/cxx/linux/lit_tester.cpp +0 -19
- pyxcp/cxx/linux/socket.hpp +0 -234
- pyxcp/cxx/linux/timeout.hpp +0 -81
- pyxcp/cxx/memoryblock.hpp +0 -42
- pyxcp/cxx/pool.hpp +0 -81
- pyxcp/cxx/poolmgr.cpp +0 -6
- pyxcp/cxx/poolmgr.hpp +0 -31
- pyxcp/cxx/test_queue.cpp +0 -69
- pyxcp/cxx/timestamp.hpp +0 -84
- pyxcp/cxx/utils.cpp +0 -38
- pyxcp/cxx/utils.hpp +0 -29
- pyxcp/cxx/win/iocp.cpp +0 -242
- pyxcp/cxx/win/iocp.hpp +0 -42
- pyxcp/cxx/win/perhandledata.hpp +0 -24
- pyxcp/cxx/win/periodata.hpp +0 -97
- pyxcp/cxx/win/socket.hpp +0 -185
- pyxcp/cxx/win/timeout.hpp +0 -83
- pyxcp/examples/conf_can.json +0 -20
- pyxcp/examples/conf_eth.json +0 -8
- pyxcp/logger.py +0 -67
- pyxcp/tests/test_config.py +0 -62
- pyxcp/transport/candriver/__init__.py +0 -2
- pyxcp/transport/candriver/pc_canalystii.py +0 -27
- pyxcp/transport/candriver/pc_etas.py +0 -25
- pyxcp/transport/candriver/pc_gsusb.py +0 -23
- pyxcp/transport/candriver/pc_iscan.py +0 -23
- pyxcp/transport/candriver/pc_ixxat.py +0 -27
- pyxcp/transport/candriver/pc_kvaser.py +0 -39
- pyxcp/transport/candriver/pc_neovi.py +0 -31
- pyxcp/transport/candriver/pc_nican.py +0 -23
- pyxcp/transport/candriver/pc_nixnet.py +0 -23
- pyxcp/transport/candriver/pc_pcan.py +0 -25
- pyxcp/transport/candriver/pc_seeed.py +0 -28
- pyxcp/transport/candriver/pc_serial.py +0 -27
- pyxcp/transport/candriver/pc_slcan.py +0 -29
- pyxcp/transport/candriver/pc_socketcan.py +0 -23
- pyxcp/transport/candriver/pc_systec.py +0 -29
- pyxcp/transport/candriver/pc_usb2can.py +0 -30
- pyxcp/transport/candriver/pc_vector.py +0 -34
- pyxcp/transport/candriver/python_can.py +0 -101
- pyxcp/transport/cxx_ext/CMakeLists.txt +0 -51
- pyxcp/transport/cxx_ext/setup.py +0 -49
- pyxcp/transport/cxx_ext/tests/test_basic_socket.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_pool.cpp +0 -39
- pyxcp/transport/cxx_ext/tests/test_timestamp.cpp +0 -27
- pyxcp-0.21.9.dist-info/RECORD +0 -147
- rekorder.cp312-win_amd64.pyd +0 -0
- {pyxcp-0.21.9.dist-info/licenses → pyxcp-0.22.23.dist-info}/LICENSE +0 -0
pyxcp/recorder/mio.hpp
CHANGED
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
45
|
#ifndef MIO_PAGE_HEADER
|
|
46
|
-
#define MIO_PAGE_HEADER
|
|
46
|
+
#define MIO_PAGE_HEADER
|
|
47
47
|
|
|
48
|
-
#ifdef _WIN32
|
|
49
|
-
#
|
|
50
|
-
#else
|
|
51
|
-
#
|
|
52
|
-
#endif
|
|
48
|
+
#ifdef _WIN32
|
|
49
|
+
#include <windows.h>
|
|
50
|
+
#else
|
|
51
|
+
#include <unistd.h>
|
|
52
|
+
#endif
|
|
53
53
|
|
|
54
54
|
namespace mio {
|
|
55
55
|
|
|
@@ -57,8 +57,7 @@ namespace mio {
|
|
|
57
57
|
* This is used by `basic_mmap` to determine whether to create a read-only or
|
|
58
58
|
* a read-write memory mapping.
|
|
59
59
|
*/
|
|
60
|
-
enum class access_mode
|
|
61
|
-
{
|
|
60
|
+
enum class access_mode {
|
|
62
61
|
read,
|
|
63
62
|
write
|
|
64
63
|
};
|
|
@@ -70,17 +69,15 @@ enum class access_mode
|
|
|
70
69
|
* to determine the page size, caches the value, and returns it. Any subsequent call to
|
|
71
70
|
* this function serves the cached value, so no further syscalls are made.
|
|
72
71
|
*/
|
|
73
|
-
inline size_t page_size()
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
{
|
|
77
|
-
#ifdef _WIN32
|
|
72
|
+
inline size_t page_size() {
|
|
73
|
+
static const size_t page_size = [] {
|
|
74
|
+
#ifdef _WIN32
|
|
78
75
|
SYSTEM_INFO SystemInfo;
|
|
79
76
|
GetSystemInfo(&SystemInfo);
|
|
80
77
|
return SystemInfo.dwAllocationGranularity;
|
|
81
|
-
#else
|
|
78
|
+
#else
|
|
82
79
|
return sysconf(_SC_PAGE_SIZE);
|
|
83
|
-
#endif
|
|
80
|
+
#endif
|
|
84
81
|
}();
|
|
85
82
|
return page_size;
|
|
86
83
|
}
|
|
@@ -90,37 +87,37 @@ inline size_t page_size()
|
|
|
90
87
|
* difference until the nearest page boundary before `offset`, or does nothing if
|
|
91
88
|
* `offset` is already page aligned.
|
|
92
89
|
*/
|
|
93
|
-
inline size_t make_offset_page_aligned(size_t offset) noexcept
|
|
94
|
-
{
|
|
90
|
+
inline size_t make_offset_page_aligned(size_t offset) noexcept {
|
|
95
91
|
const size_t page_size_ = page_size();
|
|
96
92
|
// Use integer division to round down to the nearest page alignment.
|
|
97
93
|
return offset / page_size_ * page_size_;
|
|
98
94
|
}
|
|
99
95
|
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
#endif // MIO_PAGE_HEADER
|
|
96
|
+
} // namespace mio
|
|
103
97
|
|
|
98
|
+
#endif // MIO_PAGE_HEADER
|
|
104
99
|
|
|
100
|
+
#include <cstdint>
|
|
105
101
|
#include <iterator>
|
|
106
102
|
#include <string>
|
|
107
103
|
#include <system_error>
|
|
108
|
-
#include <cstdint>
|
|
109
104
|
|
|
110
105
|
#ifdef _WIN32
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#else
|
|
116
|
-
#
|
|
117
|
-
#endif
|
|
106
|
+
#ifndef WIN32_LEAN_AND_MEAN
|
|
107
|
+
#define WIN32_LEAN_AND_MEAN
|
|
108
|
+
#endif // WIN32_LEAN_AND_MEAN
|
|
109
|
+
#include <windows.h>
|
|
110
|
+
#else // ifdef _WIN32
|
|
111
|
+
#define INVALID_HANDLE_VALUE -1
|
|
112
|
+
#endif // ifdef _WIN32
|
|
118
113
|
|
|
119
114
|
namespace mio {
|
|
120
115
|
|
|
121
116
|
// This value may be provided as the `length` parameter to the constructor or
|
|
122
117
|
// `map`, in which case a memory mapping of the entire file is created.
|
|
123
|
-
enum {
|
|
118
|
+
enum {
|
|
119
|
+
map_entire_file = 0
|
|
120
|
+
};
|
|
124
121
|
|
|
125
122
|
#ifdef _WIN32
|
|
126
123
|
using file_handle_type = HANDLE;
|
|
@@ -133,31 +130,31 @@ using file_handle_type = int;
|
|
|
133
130
|
const static file_handle_type invalid_handle = INVALID_HANDLE_VALUE;
|
|
134
131
|
|
|
135
132
|
template<access_mode AccessMode, typename ByteT>
|
|
136
|
-
struct basic_mmap
|
|
137
|
-
|
|
138
|
-
using
|
|
139
|
-
using
|
|
140
|
-
using
|
|
141
|
-
using
|
|
142
|
-
using
|
|
143
|
-
using
|
|
144
|
-
using
|
|
145
|
-
using
|
|
146
|
-
using
|
|
147
|
-
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
133
|
+
struct basic_mmap {
|
|
134
|
+
using value_type = ByteT;
|
|
135
|
+
using size_type = size_t;
|
|
136
|
+
using reference = value_type&;
|
|
137
|
+
using const_reference = const value_type&;
|
|
138
|
+
using pointer = value_type*;
|
|
139
|
+
using const_pointer = const value_type*;
|
|
140
|
+
using difference_type = std::ptrdiff_t;
|
|
141
|
+
using iterator = pointer;
|
|
142
|
+
using const_iterator = const_pointer;
|
|
143
|
+
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
148
144
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
149
|
-
using iterator_category
|
|
150
|
-
using handle_type
|
|
145
|
+
using iterator_category = std::random_access_iterator_tag;
|
|
146
|
+
using handle_type = file_handle_type;
|
|
151
147
|
|
|
152
148
|
static_assert(sizeof(ByteT) == sizeof(char), "ByteT must be the same size as char.");
|
|
153
149
|
|
|
154
|
-
private:
|
|
150
|
+
private:
|
|
151
|
+
|
|
155
152
|
// Points to the first requested byte, and not to the actual start of the mapping.
|
|
156
153
|
pointer data_ = nullptr;
|
|
157
154
|
|
|
158
155
|
// Length--in bytes--requested by user (which may not be the length of the
|
|
159
156
|
// full mapping) and the length of the full mapping.
|
|
160
|
-
size_type length_
|
|
157
|
+
size_type length_ = 0;
|
|
161
158
|
size_type mapped_length_ = 0;
|
|
162
159
|
|
|
163
160
|
// Letting user map a file using both an existing file handle and a path
|
|
@@ -178,7 +175,8 @@ private:
|
|
|
178
175
|
// close `file_handle_`.
|
|
179
176
|
bool is_handle_internal_;
|
|
180
177
|
|
|
181
|
-
public:
|
|
178
|
+
public:
|
|
179
|
+
|
|
182
180
|
/**
|
|
183
181
|
* The default constructed mmap object is in a non-mapped state, that is,
|
|
184
182
|
* any operation that attempts to access nonexistent underlying data will
|
|
@@ -193,11 +191,12 @@ public:
|
|
|
193
191
|
* thrown.
|
|
194
192
|
*/
|
|
195
193
|
template<typename String>
|
|
196
|
-
basic_mmap(const String& path, const size_type offset = 0, const size_type length = map_entire_file)
|
|
197
|
-
{
|
|
194
|
+
basic_mmap(const String& path, const size_type offset = 0, const size_type length = map_entire_file) {
|
|
198
195
|
std::error_code error;
|
|
199
196
|
map(path, offset, length, error);
|
|
200
|
-
if(error) {
|
|
197
|
+
if (error) {
|
|
198
|
+
throw std::system_error(error);
|
|
199
|
+
}
|
|
201
200
|
}
|
|
202
201
|
|
|
203
202
|
/**
|
|
@@ -205,13 +204,14 @@ public:
|
|
|
205
204
|
* while establishing the mapping is wrapped in a `std::system_error` and is
|
|
206
205
|
* thrown.
|
|
207
206
|
*/
|
|
208
|
-
basic_mmap(const handle_type handle, const size_type offset = 0, const size_type length = map_entire_file)
|
|
209
|
-
{
|
|
207
|
+
basic_mmap(const handle_type handle, const size_type offset = 0, const size_type length = map_entire_file) {
|
|
210
208
|
std::error_code error;
|
|
211
209
|
map(handle, offset, length, error);
|
|
212
|
-
if(error) {
|
|
210
|
+
if (error) {
|
|
211
|
+
throw std::system_error(error);
|
|
212
|
+
}
|
|
213
213
|
}
|
|
214
|
-
#endif
|
|
214
|
+
#endif // __cpp_exceptions
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
217
|
* `basic_mmap` has single-ownership semantics, so transferring ownership
|
|
@@ -233,18 +233,25 @@ public:
|
|
|
233
233
|
* however, a mapped region of a file gets its own handle, which is returned by
|
|
234
234
|
* 'mapping_handle'.
|
|
235
235
|
*/
|
|
236
|
-
handle_type file_handle() const noexcept {
|
|
236
|
+
handle_type file_handle() const noexcept {
|
|
237
|
+
return file_handle_;
|
|
238
|
+
}
|
|
239
|
+
|
|
237
240
|
handle_type mapping_handle() const noexcept;
|
|
238
241
|
|
|
239
242
|
/** Returns whether a valid memory mapping has been created. */
|
|
240
|
-
bool is_open() const noexcept {
|
|
243
|
+
bool is_open() const noexcept {
|
|
244
|
+
return file_handle_ != invalid_handle;
|
|
245
|
+
}
|
|
241
246
|
|
|
242
247
|
/**
|
|
243
248
|
* Returns true if no mapping was established, that is, conceptually the
|
|
244
249
|
* same as though the length that was mapped was 0. This function is
|
|
245
250
|
* provided so that this class has Container semantics.
|
|
246
251
|
*/
|
|
247
|
-
bool empty() const noexcept {
|
|
252
|
+
bool empty() const noexcept {
|
|
253
|
+
return length() == 0;
|
|
254
|
+
}
|
|
248
255
|
|
|
249
256
|
/** Returns true if a mapping was established. */
|
|
250
257
|
bool is_mapped() const noexcept;
|
|
@@ -255,13 +262,20 @@ public:
|
|
|
255
262
|
* bytes that were mapped which is a multiple of the underlying operating system's
|
|
256
263
|
* page allocation granularity.
|
|
257
264
|
*/
|
|
258
|
-
size_type size() const noexcept {
|
|
259
|
-
|
|
260
|
-
|
|
265
|
+
size_type size() const noexcept {
|
|
266
|
+
return length();
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
size_type length() const noexcept {
|
|
270
|
+
return length_;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
size_type mapped_length() const noexcept {
|
|
274
|
+
return mapped_length_;
|
|
275
|
+
}
|
|
261
276
|
|
|
262
277
|
/** Returns the offset relative to the start of the mapping. */
|
|
263
|
-
size_type mapping_offset() const noexcept
|
|
264
|
-
{
|
|
278
|
+
size_type mapping_offset() const noexcept {
|
|
265
279
|
return mapped_length_ - length_;
|
|
266
280
|
}
|
|
267
281
|
|
|
@@ -269,68 +283,96 @@ public:
|
|
|
269
283
|
* Returns a pointer to the first requested byte, or `nullptr` if no memory mapping
|
|
270
284
|
* exists.
|
|
271
285
|
*/
|
|
272
|
-
template<
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
286
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
287
|
+
pointer data() noexcept {
|
|
288
|
+
return data_;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const_pointer data() const noexcept {
|
|
292
|
+
return data_;
|
|
293
|
+
}
|
|
277
294
|
|
|
278
295
|
/**
|
|
279
296
|
* Returns an iterator to the first requested byte, if a valid memory mapping
|
|
280
297
|
* exists, otherwise this function call is undefined behaviour.
|
|
281
298
|
*/
|
|
282
|
-
template<
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const_iterator
|
|
299
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
300
|
+
iterator begin() noexcept {
|
|
301
|
+
return data();
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const_iterator begin() const noexcept {
|
|
305
|
+
return data();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const_iterator cbegin() const noexcept {
|
|
309
|
+
return data();
|
|
310
|
+
}
|
|
288
311
|
|
|
289
312
|
/**
|
|
290
313
|
* Returns an iterator one past the last requested byte, if a valid memory mapping
|
|
291
314
|
* exists, otherwise this function call is undefined behaviour.
|
|
292
315
|
*/
|
|
293
|
-
template<
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const_iterator
|
|
316
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
317
|
+
iterator end() noexcept {
|
|
318
|
+
return data() + length();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const_iterator end() const noexcept {
|
|
322
|
+
return data() + length();
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const_iterator cend() const noexcept {
|
|
326
|
+
return data() + length();
|
|
327
|
+
}
|
|
299
328
|
|
|
300
329
|
/**
|
|
301
330
|
* Returns a reverse iterator to the last memory mapped byte, if a valid
|
|
302
331
|
* memory mapping exists, otherwise this function call is undefined
|
|
303
332
|
* behaviour.
|
|
304
333
|
*/
|
|
305
|
-
template<
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
334
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
335
|
+
reverse_iterator rbegin() noexcept {
|
|
336
|
+
return reverse_iterator(end());
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
const_reverse_iterator rbegin() const noexcept {
|
|
340
|
+
return const_reverse_iterator(end());
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const_reverse_iterator crbegin() const noexcept {
|
|
344
|
+
return const_reverse_iterator(end());
|
|
345
|
+
}
|
|
313
346
|
|
|
314
347
|
/**
|
|
315
348
|
* Returns a reverse iterator past the first mapped byte, if a valid memory
|
|
316
349
|
* mapping exists, otherwise this function call is undefined behaviour.
|
|
317
350
|
*/
|
|
318
|
-
template<
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
351
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
352
|
+
reverse_iterator rend() noexcept {
|
|
353
|
+
return reverse_iterator(begin());
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const_reverse_iterator rend() const noexcept {
|
|
357
|
+
return const_reverse_iterator(begin());
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const_reverse_iterator crend() const noexcept {
|
|
361
|
+
return const_reverse_iterator(begin());
|
|
362
|
+
}
|
|
326
363
|
|
|
327
364
|
/**
|
|
328
365
|
* Returns a reference to the `i`th byte from the first requested byte (as returned
|
|
329
366
|
* by `data`). If this is invoked when no valid memory mapping has been created
|
|
330
367
|
* prior to this call, undefined behaviour ensues.
|
|
331
368
|
*/
|
|
332
|
-
reference operator[](const size_type i) noexcept {
|
|
333
|
-
|
|
369
|
+
reference operator[](const size_type i) noexcept {
|
|
370
|
+
return data_[i];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const_reference operator[](const size_type i) const noexcept {
|
|
374
|
+
return data_[i];
|
|
375
|
+
}
|
|
334
376
|
|
|
335
377
|
/**
|
|
336
378
|
* Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the
|
|
@@ -353,8 +395,7 @@ public:
|
|
|
353
395
|
* case a mapping of the entire file is created.
|
|
354
396
|
*/
|
|
355
397
|
template<typename String>
|
|
356
|
-
void map(const String& path, const size_type offset,
|
|
357
|
-
const size_type length, std::error_code& error);
|
|
398
|
+
void map(const String& path, const size_type offset, const size_type length, std::error_code& error);
|
|
358
399
|
|
|
359
400
|
/**
|
|
360
401
|
* Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the
|
|
@@ -369,8 +410,7 @@ public:
|
|
|
369
410
|
* The entire file is mapped.
|
|
370
411
|
*/
|
|
371
412
|
template<typename String>
|
|
372
|
-
void map(const String& path, std::error_code& error)
|
|
373
|
-
{
|
|
413
|
+
void map(const String& path, std::error_code& error) {
|
|
374
414
|
map(path, 0, map_entire_file, error);
|
|
375
415
|
}
|
|
376
416
|
|
|
@@ -393,8 +433,7 @@ public:
|
|
|
393
433
|
* `length` is the number of bytes to map. It may be `map_entire_file`, in which
|
|
394
434
|
* case a mapping of the entire file is created.
|
|
395
435
|
*/
|
|
396
|
-
void map(const handle_type handle, const size_type offset,
|
|
397
|
-
const size_type length, std::error_code& error);
|
|
436
|
+
void map(const handle_type handle, const size_type offset, const size_type length, std::error_code& error);
|
|
398
437
|
|
|
399
438
|
/**
|
|
400
439
|
* Establishes a memory mapping with AccessMode. If the mapping is
|
|
@@ -407,8 +446,7 @@ public:
|
|
|
407
446
|
*
|
|
408
447
|
* The entire file is mapped.
|
|
409
448
|
*/
|
|
410
|
-
void map(const handle_type handle, std::error_code& error)
|
|
411
|
-
{
|
|
449
|
+
void map(const handle_type handle, std::error_code& error) {
|
|
412
450
|
map(handle, 0, map_entire_file, error);
|
|
413
451
|
}
|
|
414
452
|
|
|
@@ -427,25 +465,21 @@ public:
|
|
|
427
465
|
|
|
428
466
|
/** Flushes the memory mapped page to disk. Errors are reported via `error`. */
|
|
429
467
|
template<access_mode A = AccessMode>
|
|
430
|
-
typename std::enable_if<A == access_mode::write, void>::type
|
|
431
|
-
sync(std::error_code& error);
|
|
468
|
+
typename std::enable_if<A == access_mode::write, void>::type sync(std::error_code& error);
|
|
432
469
|
|
|
433
470
|
/**
|
|
434
471
|
* All operators compare the address of the first byte and size of the two mapped
|
|
435
472
|
* regions.
|
|
436
473
|
*/
|
|
437
474
|
|
|
438
|
-
private:
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
> pointer get_mapping_start() noexcept
|
|
443
|
-
{
|
|
475
|
+
private:
|
|
476
|
+
|
|
477
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
478
|
+
pointer get_mapping_start() noexcept {
|
|
444
479
|
return !data() ? nullptr : data() - mapping_offset();
|
|
445
480
|
}
|
|
446
481
|
|
|
447
|
-
const_pointer get_mapping_start() const noexcept
|
|
448
|
-
{
|
|
482
|
+
const_pointer get_mapping_start() const noexcept {
|
|
449
483
|
return !data() ? nullptr : data() - mapping_offset();
|
|
450
484
|
}
|
|
451
485
|
|
|
@@ -455,35 +489,28 @@ private:
|
|
|
455
489
|
* do SFINAE in a dedicated function, where one syncs and the other is a noop.
|
|
456
490
|
*/
|
|
457
491
|
template<access_mode A = AccessMode>
|
|
458
|
-
typename std::enable_if<A == access_mode::write, void>::type
|
|
459
|
-
conditional_sync();
|
|
492
|
+
typename std::enable_if<A == access_mode::write, void>::type conditional_sync();
|
|
460
493
|
template<access_mode A = AccessMode>
|
|
461
494
|
typename std::enable_if<A == access_mode::read, void>::type conditional_sync();
|
|
462
495
|
};
|
|
463
496
|
|
|
464
497
|
template<access_mode AccessMode, typename ByteT>
|
|
465
|
-
bool operator==(const basic_mmap<AccessMode, ByteT>& a,
|
|
466
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
498
|
+
bool operator==(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
467
499
|
|
|
468
500
|
template<access_mode AccessMode, typename ByteT>
|
|
469
|
-
bool operator!=(const basic_mmap<AccessMode, ByteT>& a,
|
|
470
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
501
|
+
bool operator!=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
471
502
|
|
|
472
503
|
template<access_mode AccessMode, typename ByteT>
|
|
473
|
-
bool operator<(const basic_mmap<AccessMode, ByteT>& a,
|
|
474
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
504
|
+
bool operator<(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
475
505
|
|
|
476
506
|
template<access_mode AccessMode, typename ByteT>
|
|
477
|
-
bool operator<=(const basic_mmap<AccessMode, ByteT>& a,
|
|
478
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
507
|
+
bool operator<=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
479
508
|
|
|
480
509
|
template<access_mode AccessMode, typename ByteT>
|
|
481
|
-
bool operator>(const basic_mmap<AccessMode, ByteT>& a,
|
|
482
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
510
|
+
bool operator>(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
483
511
|
|
|
484
512
|
template<access_mode AccessMode, typename ByteT>
|
|
485
|
-
bool operator>=(const basic_mmap<AccessMode, ByteT>& a,
|
|
486
|
-
const basic_mmap<AccessMode, ByteT>& b);
|
|
513
|
+
bool operator>=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b);
|
|
487
514
|
|
|
488
515
|
/**
|
|
489
516
|
* This is the basis for all read-only mmap objects and should be preferred over
|
|
@@ -503,22 +530,18 @@ using basic_mmap_sink = basic_mmap<access_mode::write, ByteT>;
|
|
|
503
530
|
* These aliases cover the most common use cases, both representing a raw byte stream
|
|
504
531
|
* (either with a char or an unsigned char/uint8_t).
|
|
505
532
|
*/
|
|
506
|
-
using mmap_source
|
|
533
|
+
using mmap_source = basic_mmap_source<char>;
|
|
507
534
|
using ummap_source = basic_mmap_source<unsigned char>;
|
|
508
535
|
|
|
509
|
-
using mmap_sink
|
|
536
|
+
using mmap_sink = basic_mmap_sink<char>;
|
|
510
537
|
using ummap_sink = basic_mmap_sink<unsigned char>;
|
|
511
538
|
|
|
512
539
|
/**
|
|
513
540
|
* Convenience factory method that constructs a mapping for any `basic_mmap` or
|
|
514
541
|
* `basic_mmap` type.
|
|
515
542
|
*/
|
|
516
|
-
template<
|
|
517
|
-
|
|
518
|
-
typename MappingToken
|
|
519
|
-
> MMap make_mmap(const MappingToken& token,
|
|
520
|
-
int64_t offset, int64_t length, std::error_code& error)
|
|
521
|
-
{
|
|
543
|
+
template< typename MMap, typename MappingToken >
|
|
544
|
+
MMap make_mmap(const MappingToken& token, int64_t offset, int64_t length, std::error_code& error) {
|
|
522
545
|
MMap mmap;
|
|
523
546
|
mmap.map(token, offset, length, error);
|
|
524
547
|
return mmap;
|
|
@@ -532,15 +555,14 @@ template<
|
|
|
532
555
|
* `mmap_source::handle_type`.
|
|
533
556
|
*/
|
|
534
557
|
template<typename MappingToken>
|
|
535
|
-
mmap_source make_mmap_source(
|
|
536
|
-
|
|
537
|
-
{
|
|
558
|
+
mmap_source make_mmap_source(
|
|
559
|
+
const MappingToken& token, mmap_source::size_type offset, mmap_source::size_type length, std::error_code& error
|
|
560
|
+
) {
|
|
538
561
|
return make_mmap<mmap_source>(token, offset, length, error);
|
|
539
562
|
}
|
|
540
563
|
|
|
541
564
|
template<typename MappingToken>
|
|
542
|
-
mmap_source make_mmap_source(const MappingToken& token, std::error_code& error)
|
|
543
|
-
{
|
|
565
|
+
mmap_source make_mmap_source(const MappingToken& token, std::error_code& error) {
|
|
544
566
|
return make_mmap_source(token, 0, map_entire_file, error);
|
|
545
567
|
}
|
|
546
568
|
|
|
@@ -552,19 +574,18 @@ mmap_source make_mmap_source(const MappingToken& token, std::error_code& error)
|
|
|
552
574
|
* `mmap_sink::handle_type`.
|
|
553
575
|
*/
|
|
554
576
|
template<typename MappingToken>
|
|
555
|
-
mmap_sink make_mmap_sink(
|
|
556
|
-
|
|
557
|
-
{
|
|
577
|
+
mmap_sink make_mmap_sink(
|
|
578
|
+
const MappingToken& token, mmap_sink::size_type offset, mmap_sink::size_type length, std::error_code& error
|
|
579
|
+
) {
|
|
558
580
|
return make_mmap<mmap_sink>(token, offset, length, error);
|
|
559
581
|
}
|
|
560
582
|
|
|
561
583
|
template<typename MappingToken>
|
|
562
|
-
mmap_sink make_mmap_sink(const MappingToken& token, std::error_code& error)
|
|
563
|
-
{
|
|
584
|
+
mmap_sink make_mmap_sink(const MappingToken& token, std::error_code& error) {
|
|
564
585
|
return make_mmap_sink(token, 0, map_entire_file, error);
|
|
565
586
|
}
|
|
566
587
|
|
|
567
|
-
}
|
|
588
|
+
} // namespace mio
|
|
568
589
|
|
|
569
590
|
// #include "detail/mmap.ipp"
|
|
570
591
|
/* Copyright 2017 https://github.com/mandreyel
|
|
@@ -588,615 +609,534 @@ mmap_sink make_mmap_sink(const MappingToken& token, std::error_code& error)
|
|
|
588
609
|
*/
|
|
589
610
|
|
|
590
611
|
#ifndef MIO_BASIC_MMAP_IMPL
|
|
591
|
-
#define MIO_BASIC_MMAP_IMPL
|
|
612
|
+
#define MIO_BASIC_MMAP_IMPL
|
|
592
613
|
|
|
593
|
-
// #include "mio/mmap.hpp"
|
|
614
|
+
// #include "mio/mmap.hpp"
|
|
594
615
|
|
|
595
|
-
// #include "mio/page.hpp"
|
|
616
|
+
// #include "mio/page.hpp"
|
|
596
617
|
|
|
597
|
-
// #include "mio/detail/string_util.hpp"
|
|
598
|
-
/* Copyright 2017 https://github.com/mandreyel
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
618
|
+
// #include "mio/detail/string_util.hpp"
|
|
619
|
+
/* Copyright 2017 https://github.com/mandreyel
|
|
620
|
+
*
|
|
621
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
622
|
+
* software and associated documentation files (the "Software"), to deal in the Software
|
|
623
|
+
* without restriction, including without limitation the rights to use, copy, modify,
|
|
624
|
+
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
|
625
|
+
* permit persons to whom the Software is furnished to do so, subject to the following
|
|
626
|
+
* conditions:
|
|
627
|
+
*
|
|
628
|
+
* The above copyright notice and this permission notice shall be included in all copies
|
|
629
|
+
* or substantial portions of the Software.
|
|
630
|
+
*
|
|
631
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
632
|
+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
633
|
+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
634
|
+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
635
|
+
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
636
|
+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
637
|
+
*/
|
|
617
638
|
|
|
618
|
-
#ifndef MIO_STRING_UTIL_HEADER
|
|
619
|
-
#define MIO_STRING_UTIL_HEADER
|
|
639
|
+
#ifndef MIO_STRING_UTIL_HEADER
|
|
640
|
+
#define MIO_STRING_UTIL_HEADER
|
|
620
641
|
|
|
621
|
-
#include <type_traits>
|
|
642
|
+
#include <type_traits>
|
|
622
643
|
|
|
623
644
|
namespace mio {
|
|
624
645
|
namespace detail {
|
|
625
646
|
|
|
626
|
-
template<
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
#
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
};
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
{
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
#
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
{
|
|
716
|
-
static constexpr bool value = is_c_str_helper<wchar_t, S>::value;
|
|
717
|
-
};
|
|
718
|
-
#endif // _WIN32
|
|
719
|
-
|
|
720
|
-
template<typename S>
|
|
721
|
-
struct is_c_str_or_c_wstr
|
|
722
|
-
{
|
|
723
|
-
static constexpr bool value = is_c_str<S>::value
|
|
724
|
-
#ifdef _WIN32
|
|
725
|
-
|| is_c_wstr<S>::value
|
|
726
|
-
#endif
|
|
727
|
-
;
|
|
728
|
-
};
|
|
729
|
-
|
|
730
|
-
template<
|
|
731
|
-
typename String,
|
|
732
|
-
typename = decltype(std::declval<String>().data()),
|
|
733
|
-
typename = typename std::enable_if<!is_c_str_or_c_wstr<String>::value>::type
|
|
734
|
-
> const typename char_type<String>::type* c_str(const String& path)
|
|
735
|
-
{
|
|
736
|
-
return path.data();
|
|
737
|
-
}
|
|
647
|
+
template<
|
|
648
|
+
typename S, typename C = typename std::decay<S>::type, typename = decltype(std::declval<C>().data()),
|
|
649
|
+
typename = typename std::enable_if<
|
|
650
|
+
std::is_same<typename C::value_type, char>::value
|
|
651
|
+
#ifdef _WIN32
|
|
652
|
+
|| std::is_same<typename C::value_type, wchar_t>::value
|
|
653
|
+
#endif
|
|
654
|
+
>::type >
|
|
655
|
+
struct char_type_helper {
|
|
656
|
+
using type = typename C::value_type;
|
|
657
|
+
};
|
|
658
|
+
|
|
659
|
+
template<class T>
|
|
660
|
+
struct char_type {
|
|
661
|
+
using type = typename char_type_helper<T>::type;
|
|
662
|
+
};
|
|
663
|
+
|
|
664
|
+
// TODO: can we avoid this brute force approach?
|
|
665
|
+
template<>
|
|
666
|
+
struct char_type<char*> {
|
|
667
|
+
using type = char;
|
|
668
|
+
};
|
|
669
|
+
|
|
670
|
+
template<>
|
|
671
|
+
struct char_type<const char*> {
|
|
672
|
+
using type = char;
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
template<size_t N>
|
|
676
|
+
struct char_type<char[N]> {
|
|
677
|
+
using type = char;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
template<size_t N>
|
|
681
|
+
struct char_type<const char[N]> {
|
|
682
|
+
using type = char;
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
#ifdef _WIN32
|
|
686
|
+
template<>
|
|
687
|
+
struct char_type<wchar_t*> {
|
|
688
|
+
using type = wchar_t;
|
|
689
|
+
};
|
|
690
|
+
|
|
691
|
+
template<>
|
|
692
|
+
struct char_type<const wchar_t*> {
|
|
693
|
+
using type = wchar_t;
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
template<size_t N>
|
|
697
|
+
struct char_type<wchar_t[N]> {
|
|
698
|
+
using type = wchar_t;
|
|
699
|
+
};
|
|
700
|
+
|
|
701
|
+
template<size_t N>
|
|
702
|
+
struct char_type<const wchar_t[N]> {
|
|
703
|
+
using type = wchar_t;
|
|
704
|
+
};
|
|
705
|
+
#endif // _WIN32
|
|
706
|
+
|
|
707
|
+
template<typename CharT, typename S>
|
|
708
|
+
struct is_c_str_helper {
|
|
709
|
+
static constexpr bool value = std::is_same<
|
|
710
|
+
CharT*,
|
|
711
|
+
// TODO: I'm so sorry for this... Can this be made cleaner?
|
|
712
|
+
typename std::add_pointer< typename std::remove_cv<
|
|
713
|
+
typename std::remove_pointer< typename std::decay< S >::type >::type >::type >::type >::value;
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
template<typename S>
|
|
717
|
+
struct is_c_str {
|
|
718
|
+
static constexpr bool value = is_c_str_helper<char, S>::value;
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
#ifdef _WIN32
|
|
722
|
+
template<typename S>
|
|
723
|
+
struct is_c_wstr {
|
|
724
|
+
static constexpr bool value = is_c_str_helper<wchar_t, S>::value;
|
|
725
|
+
};
|
|
726
|
+
#endif // _WIN32
|
|
727
|
+
|
|
728
|
+
template<typename S>
|
|
729
|
+
struct is_c_str_or_c_wstr {
|
|
730
|
+
static constexpr bool value = is_c_str<S>::value
|
|
731
|
+
#ifdef _WIN32
|
|
732
|
+
|| is_c_wstr<S>::value
|
|
733
|
+
#endif
|
|
734
|
+
;
|
|
735
|
+
};
|
|
738
736
|
|
|
739
|
-
template<
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
return path.empty();
|
|
746
|
-
}
|
|
737
|
+
template<
|
|
738
|
+
typename String, typename = decltype(std::declval<String>().data()),
|
|
739
|
+
typename = typename std::enable_if<!is_c_str_or_c_wstr<String>::value>::type >
|
|
740
|
+
const typename char_type<String>::type* c_str(const String& path) {
|
|
741
|
+
return path.data();
|
|
742
|
+
}
|
|
747
743
|
|
|
748
|
-
template<
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}
|
|
744
|
+
template<
|
|
745
|
+
typename String, typename = decltype(std::declval<String>().empty()),
|
|
746
|
+
typename = typename std::enable_if<!is_c_str_or_c_wstr<String>::value>::type >
|
|
747
|
+
bool empty(const String& path) {
|
|
748
|
+
return path.empty();
|
|
749
|
+
}
|
|
755
750
|
|
|
756
|
-
template<
|
|
757
|
-
typename String
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
{
|
|
761
|
-
return !path || (*path == 0);
|
|
762
|
-
}
|
|
751
|
+
template< typename String, typename = typename std::enable_if<is_c_str_or_c_wstr<String>::value>::type >
|
|
752
|
+
const typename char_type<String>::type* c_str(String path) {
|
|
753
|
+
return path;
|
|
754
|
+
}
|
|
763
755
|
|
|
764
|
-
|
|
765
|
-
|
|
756
|
+
template< typename String, typename = typename std::enable_if<is_c_str_or_c_wstr<String>::value>::type >
|
|
757
|
+
bool empty(String path) {
|
|
758
|
+
return !path || (*path == 0);
|
|
759
|
+
}
|
|
766
760
|
|
|
767
|
-
|
|
761
|
+
} // namespace detail
|
|
762
|
+
} // namespace mio
|
|
768
763
|
|
|
764
|
+
#endif // MIO_STRING_UTIL_HEADER
|
|
769
765
|
|
|
770
|
-
#include <algorithm>
|
|
766
|
+
#include <algorithm>
|
|
771
767
|
|
|
772
|
-
#ifndef _WIN32
|
|
773
|
-
#
|
|
774
|
-
#
|
|
775
|
-
#
|
|
776
|
-
#
|
|
777
|
-
#endif
|
|
768
|
+
#ifndef _WIN32
|
|
769
|
+
#include <fcntl.h>
|
|
770
|
+
#include <sys/mman.h>
|
|
771
|
+
#include <sys/stat.h>
|
|
772
|
+
#include <unistd.h>
|
|
773
|
+
#endif
|
|
778
774
|
|
|
779
775
|
namespace mio {
|
|
780
776
|
namespace detail {
|
|
781
777
|
|
|
782
|
-
#ifdef _WIN32
|
|
783
|
-
namespace win {
|
|
778
|
+
#ifdef _WIN32
|
|
779
|
+
namespace win {
|
|
784
780
|
|
|
785
|
-
/** Returns the 4 upper bytes of an 8-byte integer. */
|
|
786
|
-
inline DWORD int64_high(int64_t n) noexcept
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
}
|
|
790
|
-
|
|
791
|
-
/** Returns the 4 lower bytes of an 8-byte integer. */
|
|
792
|
-
inline DWORD int64_low(int64_t n) noexcept
|
|
793
|
-
{
|
|
794
|
-
return n & 0xffffffff;
|
|
795
|
-
}
|
|
781
|
+
/** Returns the 4 upper bytes of an 8-byte integer. */
|
|
782
|
+
inline DWORD int64_high(int64_t n) noexcept {
|
|
783
|
+
return n >> 32;
|
|
784
|
+
}
|
|
796
785
|
|
|
797
|
-
|
|
798
|
-
{
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
const auto s_length = static_cast<int>(s.length());
|
|
802
|
-
auto buf = std::vector<wchar_t>(s_length);
|
|
803
|
-
const auto wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s_length, buf.data(), s_length);
|
|
804
|
-
return std::wstring(buf.data(), wide_char_count);
|
|
805
|
-
}
|
|
786
|
+
/** Returns the 4 lower bytes of an 8-byte integer. */
|
|
787
|
+
inline DWORD int64_low(int64_t n) noexcept {
|
|
788
|
+
return n & 0xffffffff;
|
|
789
|
+
}
|
|
806
790
|
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
|
816
|
-
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
817
|
-
0,
|
|
818
|
-
OPEN_EXISTING,
|
|
819
|
-
FILE_ATTRIBUTE_NORMAL,
|
|
820
|
-
0);
|
|
821
|
-
}
|
|
791
|
+
std::wstring s_2_ws(const std::string& s) {
|
|
792
|
+
if (s.empty())
|
|
793
|
+
return {};
|
|
794
|
+
const auto s_length = static_cast<int>(s.length());
|
|
795
|
+
auto buf = std::vector<wchar_t>(s_length);
|
|
796
|
+
const auto wide_char_count = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), s_length, buf.data(), s_length);
|
|
797
|
+
return std::wstring(buf.data(), wide_char_count);
|
|
798
|
+
}
|
|
822
799
|
|
|
823
|
-
template<
|
|
824
|
-
typename
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
0,
|
|
833
|
-
OPEN_EXISTING,
|
|
834
|
-
FILE_ATTRIBUTE_NORMAL,
|
|
835
|
-
0);
|
|
836
|
-
}
|
|
800
|
+
template<
|
|
801
|
+
typename String,
|
|
802
|
+
typename = typename std::enable_if< std::is_same<typename char_type<String>::type, char>::value >::type >
|
|
803
|
+
file_handle_type open_file_helper(const String& path, const access_mode mode) {
|
|
804
|
+
return ::CreateFileW(
|
|
805
|
+
s_2_ws(path).c_str(), mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
|
806
|
+
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
|
|
807
|
+
);
|
|
808
|
+
}
|
|
837
809
|
|
|
838
|
-
|
|
839
|
-
|
|
810
|
+
template<typename String>
|
|
811
|
+
typename std::enable_if< std::is_same<typename char_type<String>::type, wchar_t>::value, file_handle_type >::type
|
|
812
|
+
open_file_helper(const String& path, const access_mode mode) {
|
|
813
|
+
return ::CreateFileW(
|
|
814
|
+
c_str(path), mode == access_mode::read ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
|
|
815
|
+
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
|
|
816
|
+
);
|
|
817
|
+
}
|
|
840
818
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
* GetLastError on Win) as a `std::error_code`.
|
|
844
|
-
*/
|
|
845
|
-
inline std::error_code last_error() noexcept
|
|
846
|
-
{
|
|
847
|
-
std::error_code error;
|
|
848
|
-
#ifdef _WIN32
|
|
849
|
-
error.assign(GetLastError(), std::system_category());
|
|
850
|
-
#else
|
|
851
|
-
error.assign(errno, std::system_category());
|
|
852
|
-
#endif
|
|
853
|
-
return error;
|
|
854
|
-
}
|
|
819
|
+
} // namespace win
|
|
820
|
+
#endif // _WIN32
|
|
855
821
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
error
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
#
|
|
867
|
-
|
|
868
|
-
#else // POSIX
|
|
869
|
-
const auto handle = ::open(c_str(path),
|
|
870
|
-
mode == access_mode::read ? O_RDONLY : O_RDWR);
|
|
871
|
-
#endif
|
|
872
|
-
if(handle == invalid_handle)
|
|
873
|
-
{
|
|
874
|
-
error = detail::last_error();
|
|
822
|
+
/**
|
|
823
|
+
* Returns the last platform specific system error (errno on POSIX and
|
|
824
|
+
* GetLastError on Win) as a `std::error_code`.
|
|
825
|
+
*/
|
|
826
|
+
inline std::error_code last_error() noexcept {
|
|
827
|
+
std::error_code error;
|
|
828
|
+
#ifdef _WIN32
|
|
829
|
+
error.assign(GetLastError(), std::system_category());
|
|
830
|
+
#else
|
|
831
|
+
error.assign(errno, std::system_category());
|
|
832
|
+
#endif
|
|
833
|
+
return error;
|
|
875
834
|
}
|
|
876
|
-
return handle;
|
|
877
|
-
}
|
|
878
835
|
|
|
879
|
-
|
|
880
|
-
{
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
#
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
return 0;
|
|
836
|
+
template<typename String>
|
|
837
|
+
file_handle_type open_file(const String& path, const access_mode mode, std::error_code& error) {
|
|
838
|
+
error.clear();
|
|
839
|
+
if (detail::empty(path)) {
|
|
840
|
+
error = std::make_error_code(std::errc::invalid_argument);
|
|
841
|
+
return invalid_handle;
|
|
842
|
+
}
|
|
843
|
+
#ifdef _WIN32
|
|
844
|
+
const auto handle = win::open_file_helper(path, mode);
|
|
845
|
+
#else // POSIX
|
|
846
|
+
const auto handle = ::open(c_str(path), mode == access_mode::read ? O_RDONLY : O_RDWR);
|
|
847
|
+
#endif
|
|
848
|
+
if (handle == invalid_handle) {
|
|
849
|
+
error = detail::last_error();
|
|
850
|
+
}
|
|
851
|
+
return handle;
|
|
896
852
|
}
|
|
897
|
-
return sbuf.st_size;
|
|
898
|
-
#endif
|
|
899
|
-
}
|
|
900
853
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
854
|
+
inline size_t query_file_size(file_handle_type handle, std::error_code& error) {
|
|
855
|
+
error.clear();
|
|
856
|
+
#ifdef _WIN32
|
|
857
|
+
LARGE_INTEGER file_size;
|
|
858
|
+
if (::GetFileSizeEx(handle, &file_size) == 0) {
|
|
859
|
+
error = detail::last_error();
|
|
860
|
+
return 0;
|
|
861
|
+
}
|
|
862
|
+
return static_cast<int64_t>(file_size.QuadPart);
|
|
863
|
+
#else // POSIX
|
|
864
|
+
struct stat sbuf;
|
|
865
|
+
if (::fstat(handle, &sbuf) == -1) {
|
|
866
|
+
error = detail::last_error();
|
|
867
|
+
return 0;
|
|
868
|
+
}
|
|
869
|
+
return sbuf.st_size;
|
|
870
|
+
#endif
|
|
871
|
+
}
|
|
910
872
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
file_handle,
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
873
|
+
struct mmap_context {
|
|
874
|
+
char* data;
|
|
875
|
+
int64_t length;
|
|
876
|
+
int64_t mapped_length;
|
|
877
|
+
#ifdef _WIN32
|
|
878
|
+
file_handle_type file_mapping_handle;
|
|
879
|
+
#endif
|
|
880
|
+
};
|
|
881
|
+
|
|
882
|
+
inline mmap_context memory_map(
|
|
883
|
+
const file_handle_type file_handle, const int64_t offset, const int64_t length, const access_mode mode,
|
|
884
|
+
std::error_code& error
|
|
885
|
+
) {
|
|
886
|
+
const int64_t aligned_offset = make_offset_page_aligned(offset);
|
|
887
|
+
const int64_t length_to_map = offset - aligned_offset + length;
|
|
888
|
+
#ifdef _WIN32
|
|
889
|
+
const int64_t max_file_size = offset + length;
|
|
890
|
+
const auto file_mapping_handle = ::CreateFileMapping(
|
|
891
|
+
file_handle, 0, mode == access_mode::read ? PAGE_READONLY : PAGE_READWRITE, win::int64_high(max_file_size),
|
|
892
|
+
win::int64_low(max_file_size), 0
|
|
893
|
+
);
|
|
894
|
+
if (file_mapping_handle == invalid_handle) {
|
|
895
|
+
error = detail::last_error();
|
|
896
|
+
return {};
|
|
897
|
+
}
|
|
898
|
+
char* mapping_start = static_cast<char*>(::MapViewOfFile(
|
|
899
|
+
file_mapping_handle, mode == access_mode::read ? FILE_MAP_READ : FILE_MAP_WRITE, win::int64_high(aligned_offset),
|
|
900
|
+
win::int64_low(aligned_offset), length_to_map
|
|
901
|
+
));
|
|
902
|
+
if (mapping_start == nullptr) {
|
|
903
|
+
// Close file handle if mapping it failed.
|
|
904
|
+
::CloseHandle(file_mapping_handle);
|
|
905
|
+
error = detail::last_error();
|
|
906
|
+
return {};
|
|
907
|
+
}
|
|
908
|
+
#else // POSIX
|
|
909
|
+
char* mapping_start = static_cast<char*>(::mmap(
|
|
910
|
+
0, // Don't give hint as to where to map.
|
|
911
|
+
length_to_map, mode == access_mode::read ? PROT_READ : PROT_WRITE, MAP_SHARED, file_handle, aligned_offset
|
|
912
|
+
));
|
|
913
|
+
if (mapping_start == MAP_FAILED) {
|
|
914
|
+
error = detail::last_error();
|
|
915
|
+
return {};
|
|
916
|
+
}
|
|
917
|
+
#endif
|
|
918
|
+
mmap_context ctx;
|
|
919
|
+
ctx.data = mapping_start + offset - aligned_offset;
|
|
920
|
+
ctx.length = length;
|
|
921
|
+
ctx.mapped_length = length_to_map;
|
|
922
|
+
#ifdef _WIN32
|
|
923
|
+
ctx.file_mapping_handle = file_mapping_handle;
|
|
924
|
+
#endif
|
|
925
|
+
return ctx;
|
|
955
926
|
}
|
|
956
|
-
#endif
|
|
957
|
-
mmap_context ctx;
|
|
958
|
-
ctx.data = mapping_start + offset - aligned_offset;
|
|
959
|
-
ctx.length = length;
|
|
960
|
-
ctx.mapped_length = length_to_map;
|
|
961
|
-
#ifdef _WIN32
|
|
962
|
-
ctx.file_mapping_handle = file_mapping_handle;
|
|
963
|
-
#endif
|
|
964
|
-
return ctx;
|
|
965
|
-
}
|
|
966
927
|
|
|
967
|
-
}
|
|
928
|
+
} // namespace detail
|
|
968
929
|
|
|
969
930
|
// -- basic_mmap --
|
|
970
931
|
|
|
971
932
|
template<access_mode AccessMode, typename ByteT>
|
|
972
|
-
basic_mmap<AccessMode, ByteT>::~basic_mmap()
|
|
973
|
-
{
|
|
933
|
+
basic_mmap<AccessMode, ByteT>::~basic_mmap() {
|
|
974
934
|
conditional_sync();
|
|
975
935
|
unmap();
|
|
976
936
|
}
|
|
977
937
|
|
|
978
938
|
template<access_mode AccessMode, typename ByteT>
|
|
979
|
-
basic_mmap<AccessMode, ByteT>::basic_mmap(basic_mmap&& other)
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
#ifdef _WIN32
|
|
985
|
-
,
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
other.
|
|
939
|
+
basic_mmap<AccessMode, ByteT>::basic_mmap(basic_mmap&& other) :
|
|
940
|
+
data_(std::move(other.data_)),
|
|
941
|
+
length_(std::move(other.length_)),
|
|
942
|
+
mapped_length_(std::move(other.mapped_length_)),
|
|
943
|
+
file_handle_(std::move(other.file_handle_))
|
|
944
|
+
#ifdef _WIN32
|
|
945
|
+
,
|
|
946
|
+
file_mapping_handle_(std::move(other.file_mapping_handle_))
|
|
947
|
+
#endif
|
|
948
|
+
,
|
|
949
|
+
is_handle_internal_(std::move(other.is_handle_internal_)) {
|
|
950
|
+
other.data_ = nullptr;
|
|
990
951
|
other.length_ = other.mapped_length_ = 0;
|
|
991
|
-
other.file_handle_
|
|
992
|
-
#ifdef _WIN32
|
|
952
|
+
other.file_handle_ = invalid_handle;
|
|
953
|
+
#ifdef _WIN32
|
|
993
954
|
other.file_mapping_handle_ = invalid_handle;
|
|
994
|
-
#endif
|
|
955
|
+
#endif
|
|
995
956
|
}
|
|
996
957
|
|
|
997
958
|
template<access_mode AccessMode, typename ByteT>
|
|
998
|
-
basic_mmap<AccessMode, ByteT>&
|
|
999
|
-
|
|
1000
|
-
{
|
|
1001
|
-
if(this != &other)
|
|
1002
|
-
{
|
|
959
|
+
basic_mmap<AccessMode, ByteT>& basic_mmap<AccessMode, ByteT>::operator=(basic_mmap&& other) {
|
|
960
|
+
if (this != &other) {
|
|
1003
961
|
// First the existing mapping needs to be removed.
|
|
1004
962
|
unmap();
|
|
1005
|
-
data_
|
|
1006
|
-
length_
|
|
963
|
+
data_ = std::move(other.data_);
|
|
964
|
+
length_ = std::move(other.length_);
|
|
1007
965
|
mapped_length_ = std::move(other.mapped_length_);
|
|
1008
|
-
file_handle_
|
|
1009
|
-
#ifdef _WIN32
|
|
966
|
+
file_handle_ = std::move(other.file_handle_);
|
|
967
|
+
#ifdef _WIN32
|
|
1010
968
|
file_mapping_handle_ = std::move(other.file_mapping_handle_);
|
|
1011
|
-
#endif
|
|
969
|
+
#endif
|
|
1012
970
|
is_handle_internal_ = std::move(other.is_handle_internal_);
|
|
1013
971
|
|
|
1014
972
|
// The moved from basic_mmap's fields need to be reset, because
|
|
1015
973
|
// otherwise other's destructor will unmap the same mapping that was
|
|
1016
974
|
// just moved into this.
|
|
1017
|
-
other.data_
|
|
975
|
+
other.data_ = nullptr;
|
|
1018
976
|
other.length_ = other.mapped_length_ = 0;
|
|
1019
|
-
other.file_handle_
|
|
1020
|
-
#ifdef _WIN32
|
|
977
|
+
other.file_handle_ = invalid_handle;
|
|
978
|
+
#ifdef _WIN32
|
|
1021
979
|
other.file_mapping_handle_ = invalid_handle;
|
|
1022
|
-
#endif
|
|
980
|
+
#endif
|
|
1023
981
|
other.is_handle_internal_ = false;
|
|
1024
982
|
}
|
|
1025
983
|
return *this;
|
|
1026
984
|
}
|
|
1027
985
|
|
|
1028
986
|
template<access_mode AccessMode, typename ByteT>
|
|
1029
|
-
typename basic_mmap<AccessMode, ByteT>::handle_type
|
|
1030
|
-
|
|
1031
|
-
{
|
|
1032
|
-
#ifdef _WIN32
|
|
987
|
+
typename basic_mmap<AccessMode, ByteT>::handle_type basic_mmap<AccessMode, ByteT>::mapping_handle() const noexcept {
|
|
988
|
+
#ifdef _WIN32
|
|
1033
989
|
return file_mapping_handle_;
|
|
1034
|
-
#else
|
|
990
|
+
#else
|
|
1035
991
|
return file_handle_;
|
|
1036
|
-
#endif
|
|
992
|
+
#endif
|
|
1037
993
|
}
|
|
1038
994
|
|
|
1039
995
|
template<access_mode AccessMode, typename ByteT>
|
|
1040
996
|
template<typename String>
|
|
1041
|
-
void basic_mmap<AccessMode, ByteT>::map(
|
|
1042
|
-
|
|
1043
|
-
{
|
|
997
|
+
void basic_mmap<AccessMode, ByteT>::map(
|
|
998
|
+
const String& path, const size_type offset, const size_type length, std::error_code& error
|
|
999
|
+
) {
|
|
1044
1000
|
error.clear();
|
|
1045
|
-
if(detail::empty(path))
|
|
1046
|
-
{
|
|
1001
|
+
if (detail::empty(path)) {
|
|
1047
1002
|
error = std::make_error_code(std::errc::invalid_argument);
|
|
1048
1003
|
return;
|
|
1049
1004
|
}
|
|
1050
1005
|
const auto handle = detail::open_file(path, AccessMode, error);
|
|
1051
|
-
if(error)
|
|
1052
|
-
{
|
|
1006
|
+
if (error) {
|
|
1053
1007
|
return;
|
|
1054
1008
|
}
|
|
1055
1009
|
|
|
1056
1010
|
map(handle, offset, length, error);
|
|
1057
1011
|
// This MUST be after the call to map, as that sets this to true.
|
|
1058
|
-
if(!error)
|
|
1059
|
-
{
|
|
1012
|
+
if (!error) {
|
|
1060
1013
|
is_handle_internal_ = true;
|
|
1061
1014
|
}
|
|
1062
1015
|
}
|
|
1063
1016
|
|
|
1064
1017
|
template<access_mode AccessMode, typename ByteT>
|
|
1065
|
-
void basic_mmap<AccessMode, ByteT>::map(
|
|
1066
|
-
|
|
1067
|
-
{
|
|
1018
|
+
void basic_mmap<AccessMode, ByteT>::map(
|
|
1019
|
+
const handle_type handle, const size_type offset, const size_type length, std::error_code& error
|
|
1020
|
+
) {
|
|
1068
1021
|
error.clear();
|
|
1069
|
-
if(handle == invalid_handle)
|
|
1070
|
-
{
|
|
1022
|
+
if (handle == invalid_handle) {
|
|
1071
1023
|
error = std::make_error_code(std::errc::bad_file_descriptor);
|
|
1072
1024
|
return;
|
|
1073
1025
|
}
|
|
1074
1026
|
|
|
1075
1027
|
const auto file_size = detail::query_file_size(handle, error);
|
|
1076
|
-
if(error)
|
|
1077
|
-
{
|
|
1028
|
+
if (error) {
|
|
1078
1029
|
return;
|
|
1079
1030
|
}
|
|
1080
1031
|
|
|
1081
|
-
if(offset + length > file_size)
|
|
1082
|
-
{
|
|
1032
|
+
if (offset + length > file_size) {
|
|
1083
1033
|
error = std::make_error_code(std::errc::invalid_argument);
|
|
1084
1034
|
return;
|
|
1085
1035
|
}
|
|
1086
1036
|
|
|
1087
|
-
const auto ctx =
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
if(!error)
|
|
1091
|
-
{
|
|
1037
|
+
const auto ctx =
|
|
1038
|
+
detail::memory_map(handle, offset, length == map_entire_file ? (file_size - offset) : length, AccessMode, error);
|
|
1039
|
+
if (!error) {
|
|
1092
1040
|
// We must unmap the previous mapping that may have existed prior to this call.
|
|
1093
1041
|
// Note that this must only be invoked after a new mapping has been created in
|
|
1094
1042
|
// order to provide the strong guarantee that, should the new mapping fail, the
|
|
1095
1043
|
// `map` function leaves this instance in a state as though the function had
|
|
1096
1044
|
// never been invoked.
|
|
1097
1045
|
unmap();
|
|
1098
|
-
file_handle_
|
|
1046
|
+
file_handle_ = handle;
|
|
1099
1047
|
is_handle_internal_ = false;
|
|
1100
|
-
data_
|
|
1101
|
-
length_
|
|
1102
|
-
mapped_length_
|
|
1103
|
-
#ifdef _WIN32
|
|
1048
|
+
data_ = std::bit_cast<pointer>(ctx.data);
|
|
1049
|
+
length_ = ctx.length;
|
|
1050
|
+
mapped_length_ = ctx.mapped_length;
|
|
1051
|
+
#ifdef _WIN32
|
|
1104
1052
|
file_mapping_handle_ = ctx.file_mapping_handle;
|
|
1105
|
-
#endif
|
|
1053
|
+
#endif
|
|
1106
1054
|
}
|
|
1107
1055
|
}
|
|
1108
1056
|
|
|
1109
1057
|
template<access_mode AccessMode, typename ByteT>
|
|
1110
1058
|
template<access_mode A>
|
|
1111
|
-
typename std::enable_if<A == access_mode::write, void>::type
|
|
1112
|
-
basic_mmap<AccessMode, ByteT>::sync(std::error_code& error)
|
|
1113
|
-
{
|
|
1059
|
+
typename std::enable_if<A == access_mode::write, void>::type basic_mmap<AccessMode, ByteT>::sync(std::error_code& error) {
|
|
1114
1060
|
error.clear();
|
|
1115
|
-
if(!is_open())
|
|
1116
|
-
{
|
|
1061
|
+
if (!is_open()) {
|
|
1117
1062
|
error = std::make_error_code(std::errc::bad_file_descriptor);
|
|
1118
1063
|
return;
|
|
1119
1064
|
}
|
|
1120
1065
|
|
|
1121
|
-
if(data())
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
#
|
|
1127
|
-
if(::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0)
|
|
1128
|
-
#endif
|
|
1066
|
+
if (data()) {
|
|
1067
|
+
#ifdef _WIN32
|
|
1068
|
+
if (::FlushViewOfFile(get_mapping_start(), mapped_length_) == 0 || ::FlushFileBuffers(file_handle_) == 0)
|
|
1069
|
+
#else // POSIX
|
|
1070
|
+
if (::msync(get_mapping_start(), mapped_length_, MS_SYNC) != 0)
|
|
1071
|
+
#endif
|
|
1129
1072
|
{
|
|
1130
1073
|
error = detail::last_error();
|
|
1131
1074
|
return;
|
|
1132
1075
|
}
|
|
1133
1076
|
}
|
|
1134
|
-
#ifdef _WIN32
|
|
1135
|
-
if(::FlushFileBuffers(file_handle_) == 0)
|
|
1136
|
-
{
|
|
1077
|
+
#ifdef _WIN32
|
|
1078
|
+
if (::FlushFileBuffers(file_handle_) == 0) {
|
|
1137
1079
|
error = detail::last_error();
|
|
1138
1080
|
}
|
|
1139
|
-
#endif
|
|
1081
|
+
#endif
|
|
1140
1082
|
}
|
|
1141
1083
|
|
|
1142
1084
|
template<access_mode AccessMode, typename ByteT>
|
|
1143
|
-
void basic_mmap<AccessMode, ByteT>::unmap()
|
|
1144
|
-
{
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
{
|
|
1085
|
+
void basic_mmap<AccessMode, ByteT>::unmap() {
|
|
1086
|
+
if (!is_open()) {
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
// TODO do we care about errors here?
|
|
1090
|
+
#ifdef _WIN32
|
|
1091
|
+
if (is_mapped()) {
|
|
1150
1092
|
::UnmapViewOfFile(get_mapping_start());
|
|
1151
1093
|
::CloseHandle(file_mapping_handle_);
|
|
1152
1094
|
}
|
|
1153
|
-
#else
|
|
1154
|
-
if(data_) {
|
|
1155
|
-
|
|
1095
|
+
#else // POSIX
|
|
1096
|
+
if (data_) {
|
|
1097
|
+
::munmap(const_cast<pointer>(get_mapping_start()), mapped_length_);
|
|
1098
|
+
}
|
|
1099
|
+
#endif
|
|
1156
1100
|
|
|
1157
1101
|
// If `file_handle_` was obtained by our opening it (when map is called with
|
|
1158
1102
|
// a path, rather than an existing file handle), we need to close it,
|
|
1159
1103
|
// otherwise it must not be closed as it may still be used outside this
|
|
1160
1104
|
// instance.
|
|
1161
|
-
if(is_handle_internal_)
|
|
1162
|
-
|
|
1163
|
-
#ifdef _WIN32
|
|
1105
|
+
if (is_handle_internal_) {
|
|
1106
|
+
#ifdef _WIN32
|
|
1164
1107
|
::CloseHandle(file_handle_);
|
|
1165
|
-
#else
|
|
1108
|
+
#else // POSIX
|
|
1166
1109
|
::close(file_handle_);
|
|
1167
|
-
#endif
|
|
1110
|
+
#endif
|
|
1168
1111
|
}
|
|
1169
1112
|
|
|
1170
1113
|
// Reset fields to their default values.
|
|
1171
|
-
data_
|
|
1114
|
+
data_ = nullptr;
|
|
1172
1115
|
length_ = mapped_length_ = 0;
|
|
1173
|
-
file_handle_
|
|
1174
|
-
#ifdef _WIN32
|
|
1116
|
+
file_handle_ = invalid_handle;
|
|
1117
|
+
#ifdef _WIN32
|
|
1175
1118
|
file_mapping_handle_ = invalid_handle;
|
|
1176
|
-
#endif
|
|
1119
|
+
#endif
|
|
1177
1120
|
}
|
|
1178
1121
|
|
|
1179
1122
|
template<access_mode AccessMode, typename ByteT>
|
|
1180
|
-
bool basic_mmap<AccessMode, ByteT>::is_mapped() const noexcept
|
|
1181
|
-
|
|
1182
|
-
#ifdef _WIN32
|
|
1123
|
+
bool basic_mmap<AccessMode, ByteT>::is_mapped() const noexcept {
|
|
1124
|
+
#ifdef _WIN32
|
|
1183
1125
|
return file_mapping_handle_ != invalid_handle;
|
|
1184
|
-
#else
|
|
1126
|
+
#else // POSIX
|
|
1185
1127
|
return is_open();
|
|
1186
|
-
#endif
|
|
1128
|
+
#endif
|
|
1187
1129
|
}
|
|
1188
1130
|
|
|
1189
1131
|
template<access_mode AccessMode, typename ByteT>
|
|
1190
|
-
void basic_mmap<AccessMode, ByteT>::swap(basic_mmap& other)
|
|
1191
|
-
{
|
|
1192
|
-
if(this != &other)
|
|
1193
|
-
{
|
|
1132
|
+
void basic_mmap<AccessMode, ByteT>::swap(basic_mmap& other) {
|
|
1133
|
+
if (this != &other) {
|
|
1194
1134
|
using std::swap;
|
|
1195
1135
|
swap(data_, other.data_);
|
|
1196
1136
|
swap(file_handle_, other.file_handle_);
|
|
1197
|
-
#ifdef _WIN32
|
|
1137
|
+
#ifdef _WIN32
|
|
1198
1138
|
swap(file_mapping_handle_, other.file_mapping_handle_);
|
|
1199
|
-
#endif
|
|
1139
|
+
#endif
|
|
1200
1140
|
swap(length_, other.length_);
|
|
1201
1141
|
swap(mapped_length_, other.mapped_length_);
|
|
1202
1142
|
swap(is_handle_internal_, other.is_handle_internal_);
|
|
@@ -1205,9 +1145,7 @@ void basic_mmap<AccessMode, ByteT>::swap(basic_mmap& other)
|
|
|
1205
1145
|
|
|
1206
1146
|
template<access_mode AccessMode, typename ByteT>
|
|
1207
1147
|
template<access_mode A>
|
|
1208
|
-
typename std::enable_if<A == access_mode::write, void>::type
|
|
1209
|
-
basic_mmap<AccessMode, ByteT>::conditional_sync()
|
|
1210
|
-
{
|
|
1148
|
+
typename std::enable_if<A == access_mode::write, void>::type basic_mmap<AccessMode, ByteT>::conditional_sync() {
|
|
1211
1149
|
// This is invoked from the destructor, so not much we can do about
|
|
1212
1150
|
// failures here.
|
|
1213
1151
|
std::error_code ec;
|
|
@@ -1216,63 +1154,51 @@ basic_mmap<AccessMode, ByteT>::conditional_sync()
|
|
|
1216
1154
|
|
|
1217
1155
|
template<access_mode AccessMode, typename ByteT>
|
|
1218
1156
|
template<access_mode A>
|
|
1219
|
-
typename std::enable_if<A == access_mode::read, void>::type
|
|
1220
|
-
basic_mmap<AccessMode, ByteT>::conditional_sync()
|
|
1221
|
-
{
|
|
1157
|
+
typename std::enable_if<A == access_mode::read, void>::type basic_mmap<AccessMode, ByteT>::conditional_sync() {
|
|
1222
1158
|
// noop
|
|
1223
1159
|
}
|
|
1224
1160
|
|
|
1225
1161
|
template<access_mode AccessMode, typename ByteT>
|
|
1226
|
-
bool operator==(const basic_mmap<AccessMode, ByteT>& a,
|
|
1227
|
-
|
|
1228
|
-
{
|
|
1229
|
-
return a.data() == b.data()
|
|
1230
|
-
&& a.size() == b.size();
|
|
1162
|
+
bool operator==(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1163
|
+
return a.data() == b.data() && a.size() == b.size();
|
|
1231
1164
|
}
|
|
1232
1165
|
|
|
1233
1166
|
template<access_mode AccessMode, typename ByteT>
|
|
1234
|
-
bool operator!=(const basic_mmap<AccessMode, ByteT>& a,
|
|
1235
|
-
const basic_mmap<AccessMode, ByteT>& b)
|
|
1236
|
-
{
|
|
1167
|
+
bool operator!=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1237
1168
|
return !(a == b);
|
|
1238
1169
|
}
|
|
1239
1170
|
|
|
1240
1171
|
template<access_mode AccessMode, typename ByteT>
|
|
1241
|
-
bool operator<(const basic_mmap<AccessMode, ByteT>& a,
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1172
|
+
bool operator<(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1173
|
+
if (a.data() == b.data()) {
|
|
1174
|
+
return a.size() < b.size();
|
|
1175
|
+
}
|
|
1245
1176
|
return a.data() < b.data();
|
|
1246
1177
|
}
|
|
1247
1178
|
|
|
1248
1179
|
template<access_mode AccessMode, typename ByteT>
|
|
1249
|
-
bool operator<=(const basic_mmap<AccessMode, ByteT>& a,
|
|
1250
|
-
const basic_mmap<AccessMode, ByteT>& b)
|
|
1251
|
-
{
|
|
1180
|
+
bool operator<=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1252
1181
|
return !(a > b);
|
|
1253
1182
|
}
|
|
1254
1183
|
|
|
1255
1184
|
template<access_mode AccessMode, typename ByteT>
|
|
1256
|
-
bool operator>(const basic_mmap<AccessMode, ByteT>& a,
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1185
|
+
bool operator>(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1186
|
+
if (a.data() == b.data()) {
|
|
1187
|
+
return a.size() > b.size();
|
|
1188
|
+
}
|
|
1260
1189
|
return a.data() > b.data();
|
|
1261
1190
|
}
|
|
1262
1191
|
|
|
1263
1192
|
template<access_mode AccessMode, typename ByteT>
|
|
1264
|
-
bool operator>=(const basic_mmap<AccessMode, ByteT>& a,
|
|
1265
|
-
const basic_mmap<AccessMode, ByteT>& b)
|
|
1266
|
-
{
|
|
1193
|
+
bool operator>=(const basic_mmap<AccessMode, ByteT>& a, const basic_mmap<AccessMode, ByteT>& b) {
|
|
1267
1194
|
return !(a < b);
|
|
1268
1195
|
}
|
|
1269
1196
|
|
|
1270
|
-
}
|
|
1197
|
+
} // namespace mio
|
|
1271
1198
|
|
|
1272
|
-
#endif
|
|
1199
|
+
#endif // MIO_BASIC_MMAP_IMPL
|
|
1273
1200
|
|
|
1274
|
-
|
|
1275
|
-
#endif // MIO_MMAP_HEADER
|
|
1201
|
+
#endif // MIO_MMAP_HEADER
|
|
1276
1202
|
/* Copyright 2017 https://github.com/mandreyel
|
|
1277
1203
|
*
|
|
1278
1204
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
@@ -1297,9 +1223,9 @@ bool operator>=(const basic_mmap<AccessMode, ByteT>& a,
|
|
|
1297
1223
|
#define MIO_PAGE_HEADER
|
|
1298
1224
|
|
|
1299
1225
|
#ifdef _WIN32
|
|
1300
|
-
#
|
|
1226
|
+
#include <windows.h>
|
|
1301
1227
|
#else
|
|
1302
|
-
#
|
|
1228
|
+
#include <unistd.h>
|
|
1303
1229
|
#endif
|
|
1304
1230
|
|
|
1305
1231
|
namespace mio {
|
|
@@ -1308,8 +1234,7 @@ namespace mio {
|
|
|
1308
1234
|
* This is used by `basic_mmap` to determine whether to create a read-only or
|
|
1309
1235
|
* a read-write memory mapping.
|
|
1310
1236
|
*/
|
|
1311
|
-
enum class access_mode
|
|
1312
|
-
{
|
|
1237
|
+
enum class access_mode {
|
|
1313
1238
|
read,
|
|
1314
1239
|
write
|
|
1315
1240
|
};
|
|
@@ -1321,10 +1246,8 @@ enum class access_mode
|
|
|
1321
1246
|
* to determine the page size, caches the value, and returns it. Any subsequent call to
|
|
1322
1247
|
* this function serves the cached value, so no further syscalls are made.
|
|
1323
1248
|
*/
|
|
1324
|
-
inline size_t page_size()
|
|
1325
|
-
{
|
|
1326
|
-
static const size_t page_size = []
|
|
1327
|
-
{
|
|
1249
|
+
inline size_t page_size() {
|
|
1250
|
+
static const size_t page_size = [] {
|
|
1328
1251
|
#ifdef _WIN32
|
|
1329
1252
|
SYSTEM_INFO SystemInfo;
|
|
1330
1253
|
GetSystemInfo(&SystemInfo);
|
|
@@ -1341,16 +1264,15 @@ inline size_t page_size()
|
|
|
1341
1264
|
* difference until the nearest page boundary before `offset`, or does nothing if
|
|
1342
1265
|
* `offset` is already page aligned.
|
|
1343
1266
|
*/
|
|
1344
|
-
inline size_t make_offset_page_aligned(size_t offset) noexcept
|
|
1345
|
-
{
|
|
1267
|
+
inline size_t make_offset_page_aligned(size_t offset) noexcept {
|
|
1346
1268
|
const size_t page_size_ = page_size();
|
|
1347
1269
|
// Use integer division to round down to the nearest page alignment.
|
|
1348
1270
|
return offset / page_size_ * page_size_;
|
|
1349
1271
|
}
|
|
1350
1272
|
|
|
1351
|
-
}
|
|
1273
|
+
} // namespace mio
|
|
1352
1274
|
|
|
1353
|
-
#endif
|
|
1275
|
+
#endif // MIO_PAGE_HEADER
|
|
1354
1276
|
/* Copyright 2017 https://github.com/mandreyel
|
|
1355
1277
|
*
|
|
1356
1278
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
@@ -1376,9 +1298,8 @@ inline size_t make_offset_page_aligned(size_t offset) noexcept
|
|
|
1376
1298
|
|
|
1377
1299
|
// #include "mio/mmap.hpp"
|
|
1378
1300
|
|
|
1379
|
-
|
|
1380
|
-
#include <system_error>
|
|
1381
|
-
#include <memory> // std::shared_ptr
|
|
1301
|
+
#include <memory> // std::shared_ptr
|
|
1302
|
+
#include <system_error> // std::error_code
|
|
1382
1303
|
|
|
1383
1304
|
namespace mio {
|
|
1384
1305
|
|
|
@@ -1389,54 +1310,50 @@ namespace mio {
|
|
|
1389
1310
|
* This is not the default behaviour of `basic_mmap` to avoid allocating on the heap if
|
|
1390
1311
|
* shared semantics are not required.
|
|
1391
1312
|
*/
|
|
1392
|
-
template<
|
|
1393
|
-
|
|
1394
|
-
typename ByteT
|
|
1395
|
-
> class basic_shared_mmap
|
|
1396
|
-
{
|
|
1313
|
+
template< access_mode AccessMode, typename ByteT >
|
|
1314
|
+
class basic_shared_mmap {
|
|
1397
1315
|
using impl_type = basic_mmap<AccessMode, ByteT>;
|
|
1398
1316
|
std::shared_ptr<impl_type> pimpl_;
|
|
1399
1317
|
|
|
1400
|
-
public:
|
|
1401
|
-
|
|
1402
|
-
using
|
|
1403
|
-
using
|
|
1404
|
-
using
|
|
1405
|
-
using
|
|
1406
|
-
using
|
|
1407
|
-
using
|
|
1408
|
-
using
|
|
1409
|
-
using
|
|
1410
|
-
using
|
|
1318
|
+
public:
|
|
1319
|
+
|
|
1320
|
+
using value_type = typename impl_type::value_type;
|
|
1321
|
+
using size_type = typename impl_type::size_type;
|
|
1322
|
+
using reference = typename impl_type::reference;
|
|
1323
|
+
using const_reference = typename impl_type::const_reference;
|
|
1324
|
+
using pointer = typename impl_type::pointer;
|
|
1325
|
+
using const_pointer = typename impl_type::const_pointer;
|
|
1326
|
+
using difference_type = typename impl_type::difference_type;
|
|
1327
|
+
using iterator = typename impl_type::iterator;
|
|
1328
|
+
using const_iterator = typename impl_type::const_iterator;
|
|
1329
|
+
using reverse_iterator = typename impl_type::reverse_iterator;
|
|
1411
1330
|
using const_reverse_iterator = typename impl_type::const_reverse_iterator;
|
|
1412
|
-
using iterator_category
|
|
1413
|
-
using handle_type
|
|
1414
|
-
using mmap_type
|
|
1331
|
+
using iterator_category = typename impl_type::iterator_category;
|
|
1332
|
+
using handle_type = typename impl_type::handle_type;
|
|
1333
|
+
using mmap_type = impl_type;
|
|
1415
1334
|
|
|
1416
|
-
basic_shared_mmap()
|
|
1417
|
-
basic_shared_mmap(const basic_shared_mmap&)
|
|
1335
|
+
basic_shared_mmap() = default;
|
|
1336
|
+
basic_shared_mmap(const basic_shared_mmap&) = default;
|
|
1418
1337
|
basic_shared_mmap& operator=(const basic_shared_mmap&) = default;
|
|
1419
|
-
basic_shared_mmap(basic_shared_mmap&&)
|
|
1420
|
-
basic_shared_mmap& operator=(basic_shared_mmap&&)
|
|
1338
|
+
basic_shared_mmap(basic_shared_mmap&&) = default;
|
|
1339
|
+
basic_shared_mmap& operator=(basic_shared_mmap&&) = default;
|
|
1421
1340
|
|
|
1422
1341
|
/** Takes ownership of an existing mmap object. */
|
|
1423
|
-
basic_shared_mmap(mmap_type&& mmap)
|
|
1424
|
-
|
|
1425
|
-
{}
|
|
1342
|
+
basic_shared_mmap(mmap_type&& mmap) : pimpl_(std::make_shared<mmap_type>(std::move(mmap))) {
|
|
1343
|
+
}
|
|
1426
1344
|
|
|
1427
1345
|
/** Takes ownership of an existing mmap object. */
|
|
1428
|
-
basic_shared_mmap& operator=(mmap_type&& mmap)
|
|
1429
|
-
{
|
|
1346
|
+
basic_shared_mmap& operator=(mmap_type&& mmap) {
|
|
1430
1347
|
pimpl_ = std::make_shared<mmap_type>(std::move(mmap));
|
|
1431
1348
|
return *this;
|
|
1432
1349
|
}
|
|
1433
1350
|
|
|
1434
1351
|
/** Initializes this object with an already established shared mmap. */
|
|
1435
|
-
basic_shared_mmap(std::shared_ptr<mmap_type> mmap) : pimpl_(std::move(mmap)) {
|
|
1352
|
+
basic_shared_mmap(std::shared_ptr<mmap_type> mmap) : pimpl_(std::move(mmap)) {
|
|
1353
|
+
}
|
|
1436
1354
|
|
|
1437
1355
|
/** Initializes this object with an already established shared mmap. */
|
|
1438
|
-
basic_shared_mmap& operator=(std::shared_ptr<mmap_type> mmap)
|
|
1439
|
-
{
|
|
1356
|
+
basic_shared_mmap& operator=(std::shared_ptr<mmap_type> mmap) {
|
|
1440
1357
|
pimpl_ = std::move(mmap);
|
|
1441
1358
|
return *this;
|
|
1442
1359
|
}
|
|
@@ -1448,11 +1365,12 @@ public:
|
|
|
1448
1365
|
* thrown.
|
|
1449
1366
|
*/
|
|
1450
1367
|
template<typename String>
|
|
1451
|
-
basic_shared_mmap(const String& path, const size_type offset = 0, const size_type length = map_entire_file)
|
|
1452
|
-
{
|
|
1368
|
+
basic_shared_mmap(const String& path, const size_type offset = 0, const size_type length = map_entire_file) {
|
|
1453
1369
|
std::error_code error;
|
|
1454
1370
|
map(path, offset, length, error);
|
|
1455
|
-
if(error) {
|
|
1371
|
+
if (error) {
|
|
1372
|
+
throw std::system_error(error);
|
|
1373
|
+
}
|
|
1456
1374
|
}
|
|
1457
1375
|
|
|
1458
1376
|
/**
|
|
@@ -1460,13 +1378,14 @@ public:
|
|
|
1460
1378
|
* while establishing the mapping is wrapped in a `std::system_error` and is
|
|
1461
1379
|
* thrown.
|
|
1462
1380
|
*/
|
|
1463
|
-
basic_shared_mmap(const handle_type handle, const size_type offset = 0, const size_type length = map_entire_file)
|
|
1464
|
-
{
|
|
1381
|
+
basic_shared_mmap(const handle_type handle, const size_type offset = 0, const size_type length = map_entire_file) {
|
|
1465
1382
|
std::error_code error;
|
|
1466
1383
|
map(handle, offset, length, error);
|
|
1467
|
-
if(error) {
|
|
1384
|
+
if (error) {
|
|
1385
|
+
throw std::system_error(error);
|
|
1386
|
+
}
|
|
1468
1387
|
}
|
|
1469
|
-
#endif
|
|
1388
|
+
#endif // __cpp_exceptions
|
|
1470
1389
|
|
|
1471
1390
|
/**
|
|
1472
1391
|
* If this is a read-write mapping and the last reference to the mapping,
|
|
@@ -1476,32 +1395,36 @@ public:
|
|
|
1476
1395
|
~basic_shared_mmap() = default;
|
|
1477
1396
|
|
|
1478
1397
|
/** Returns the underlying `std::shared_ptr` instance that holds the mmap. */
|
|
1479
|
-
std::shared_ptr<mmap_type> get_shared_ptr() {
|
|
1398
|
+
std::shared_ptr<mmap_type> get_shared_ptr() {
|
|
1399
|
+
return pimpl_;
|
|
1400
|
+
}
|
|
1480
1401
|
|
|
1481
1402
|
/**
|
|
1482
1403
|
* On UNIX systems 'file_handle' and 'mapping_handle' are the same. On Windows,
|
|
1483
1404
|
* however, a mapped region of a file gets its own handle, which is returned by
|
|
1484
1405
|
* 'mapping_handle'.
|
|
1485
1406
|
*/
|
|
1486
|
-
handle_type file_handle() const noexcept
|
|
1487
|
-
{
|
|
1407
|
+
handle_type file_handle() const noexcept {
|
|
1488
1408
|
return pimpl_ ? pimpl_->file_handle() : invalid_handle;
|
|
1489
1409
|
}
|
|
1490
1410
|
|
|
1491
|
-
handle_type mapping_handle() const noexcept
|
|
1492
|
-
{
|
|
1411
|
+
handle_type mapping_handle() const noexcept {
|
|
1493
1412
|
return pimpl_ ? pimpl_->mapping_handle() : invalid_handle;
|
|
1494
1413
|
}
|
|
1495
1414
|
|
|
1496
1415
|
/** Returns whether a valid memory mapping has been created. */
|
|
1497
|
-
bool is_open() const noexcept {
|
|
1416
|
+
bool is_open() const noexcept {
|
|
1417
|
+
return pimpl_ && pimpl_->is_open();
|
|
1418
|
+
}
|
|
1498
1419
|
|
|
1499
1420
|
/**
|
|
1500
1421
|
* Returns true if no mapping was established, that is, conceptually the
|
|
1501
1422
|
* same as though the length that was mapped was 0. This function is
|
|
1502
1423
|
* provided so that this class has Container semantics.
|
|
1503
1424
|
*/
|
|
1504
|
-
bool empty() const noexcept {
|
|
1425
|
+
bool empty() const noexcept {
|
|
1426
|
+
return !pimpl_ || pimpl_->empty();
|
|
1427
|
+
}
|
|
1505
1428
|
|
|
1506
1429
|
/**
|
|
1507
1430
|
* `size` and `length` both return the logical length, i.e. the number of bytes
|
|
@@ -1509,10 +1432,15 @@ public:
|
|
|
1509
1432
|
* bytes that were mapped which is a multiple of the underlying operating system's
|
|
1510
1433
|
* page allocation granularity.
|
|
1511
1434
|
*/
|
|
1512
|
-
size_type size() const noexcept {
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1435
|
+
size_type size() const noexcept {
|
|
1436
|
+
return pimpl_ ? pimpl_->length() : 0;
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
size_type length() const noexcept {
|
|
1440
|
+
return pimpl_ ? pimpl_->length() : 0;
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
size_type mapped_length() const noexcept {
|
|
1516
1444
|
return pimpl_ ? pimpl_->mapped_length() : 0;
|
|
1517
1445
|
}
|
|
1518
1446
|
|
|
@@ -1520,61 +1448,95 @@ public:
|
|
|
1520
1448
|
* Returns a pointer to the first requested byte, or `nullptr` if no memory mapping
|
|
1521
1449
|
* exists.
|
|
1522
1450
|
*/
|
|
1523
|
-
template<
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1451
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
1452
|
+
pointer data() noexcept {
|
|
1453
|
+
return pimpl_->data();
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
const_pointer data() const noexcept {
|
|
1457
|
+
return pimpl_ ? pimpl_->data() : nullptr;
|
|
1458
|
+
}
|
|
1528
1459
|
|
|
1529
1460
|
/**
|
|
1530
1461
|
* Returns an iterator to the first requested byte, if a valid memory mapping
|
|
1531
1462
|
* exists, otherwise this function call is undefined behaviour.
|
|
1532
1463
|
*/
|
|
1533
|
-
iterator begin() noexcept {
|
|
1534
|
-
|
|
1535
|
-
|
|
1464
|
+
iterator begin() noexcept {
|
|
1465
|
+
return pimpl_->begin();
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
const_iterator begin() const noexcept {
|
|
1469
|
+
return pimpl_->begin();
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
const_iterator cbegin() const noexcept {
|
|
1473
|
+
return pimpl_->cbegin();
|
|
1474
|
+
}
|
|
1536
1475
|
|
|
1537
1476
|
/**
|
|
1538
1477
|
* Returns an iterator one past the last requested byte, if a valid memory mapping
|
|
1539
1478
|
* exists, otherwise this function call is undefined behaviour.
|
|
1540
1479
|
*/
|
|
1541
|
-
template<
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
const_iterator
|
|
1480
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
1481
|
+
iterator end() noexcept {
|
|
1482
|
+
return pimpl_->end();
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
const_iterator end() const noexcept {
|
|
1486
|
+
return pimpl_->end();
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
const_iterator cend() const noexcept {
|
|
1490
|
+
return pimpl_->cend();
|
|
1491
|
+
}
|
|
1547
1492
|
|
|
1548
1493
|
/**
|
|
1549
1494
|
* Returns a reverse iterator to the last memory mapped byte, if a valid
|
|
1550
1495
|
* memory mapping exists, otherwise this function call is undefined
|
|
1551
1496
|
* behaviour.
|
|
1552
1497
|
*/
|
|
1553
|
-
template<
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
const_reverse_iterator
|
|
1498
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
1499
|
+
reverse_iterator rbegin() noexcept {
|
|
1500
|
+
return pimpl_->rbegin();
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
const_reverse_iterator rbegin() const noexcept {
|
|
1504
|
+
return pimpl_->rbegin();
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
const_reverse_iterator crbegin() const noexcept {
|
|
1508
|
+
return pimpl_->crbegin();
|
|
1509
|
+
}
|
|
1559
1510
|
|
|
1560
1511
|
/**
|
|
1561
1512
|
* Returns a reverse iterator past the first mapped byte, if a valid memory
|
|
1562
1513
|
* mapping exists, otherwise this function call is undefined behaviour.
|
|
1563
1514
|
*/
|
|
1564
|
-
template<
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
const_reverse_iterator
|
|
1515
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
1516
|
+
reverse_iterator rend() noexcept {
|
|
1517
|
+
return pimpl_->rend();
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
const_reverse_iterator rend() const noexcept {
|
|
1521
|
+
return pimpl_->rend();
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
const_reverse_iterator crend() const noexcept {
|
|
1525
|
+
return pimpl_->crend();
|
|
1526
|
+
}
|
|
1570
1527
|
|
|
1571
1528
|
/**
|
|
1572
1529
|
* Returns a reference to the `i`th byte from the first requested byte (as returned
|
|
1573
1530
|
* by `data`). If this is invoked when no valid memory mapping has been created
|
|
1574
1531
|
* prior to this call, undefined behaviour ensues.
|
|
1575
1532
|
*/
|
|
1576
|
-
reference operator[](const size_type i) noexcept {
|
|
1577
|
-
|
|
1533
|
+
reference operator[](const size_type i) noexcept {
|
|
1534
|
+
return (*pimpl_)[i];
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const_reference operator[](const size_type i) const noexcept {
|
|
1538
|
+
return (*pimpl_)[i];
|
|
1539
|
+
}
|
|
1578
1540
|
|
|
1579
1541
|
/**
|
|
1580
1542
|
* Establishes a memory mapping with AccessMode. If the mapping is unsuccesful, the
|
|
@@ -1597,9 +1559,7 @@ public:
|
|
|
1597
1559
|
* case a mapping of the entire file is created.
|
|
1598
1560
|
*/
|
|
1599
1561
|
template<typename String>
|
|
1600
|
-
void map(const String& path, const size_type offset,
|
|
1601
|
-
const size_type length, std::error_code& error)
|
|
1602
|
-
{
|
|
1562
|
+
void map(const String& path, const size_type offset, const size_type length, std::error_code& error) {
|
|
1603
1563
|
map_impl(path, offset, length, error);
|
|
1604
1564
|
}
|
|
1605
1565
|
|
|
@@ -1616,8 +1576,7 @@ public:
|
|
|
1616
1576
|
* The entire file is mapped.
|
|
1617
1577
|
*/
|
|
1618
1578
|
template<typename String>
|
|
1619
|
-
void map(const String& path, std::error_code& error)
|
|
1620
|
-
{
|
|
1579
|
+
void map(const String& path, std::error_code& error) {
|
|
1621
1580
|
map_impl(path, 0, map_entire_file, error);
|
|
1622
1581
|
}
|
|
1623
1582
|
|
|
@@ -1640,9 +1599,7 @@ public:
|
|
|
1640
1599
|
* `length` is the number of bytes to map. It may be `map_entire_file`, in which
|
|
1641
1600
|
* case a mapping of the entire file is created.
|
|
1642
1601
|
*/
|
|
1643
|
-
void map(const handle_type handle, const size_type offset,
|
|
1644
|
-
const size_type length, std::error_code& error)
|
|
1645
|
-
{
|
|
1602
|
+
void map(const handle_type handle, const size_type offset, const size_type length, std::error_code& error) {
|
|
1646
1603
|
map_impl(handle, offset, length, error);
|
|
1647
1604
|
}
|
|
1648
1605
|
|
|
@@ -1657,8 +1614,7 @@ public:
|
|
|
1657
1614
|
*
|
|
1658
1615
|
* The entire file is mapped.
|
|
1659
1616
|
*/
|
|
1660
|
-
void map(const handle_type handle, std::error_code& error)
|
|
1661
|
-
{
|
|
1617
|
+
void map(const handle_type handle, std::error_code& error) {
|
|
1662
1618
|
map_impl(handle, 0, map_entire_file, error);
|
|
1663
1619
|
}
|
|
1664
1620
|
|
|
@@ -1671,61 +1627,59 @@ public:
|
|
|
1671
1627
|
* mapping was created using a file path. If, on the other hand, an existing
|
|
1672
1628
|
* file handle was used to create the mapping, the file handle is not closed.
|
|
1673
1629
|
*/
|
|
1674
|
-
void unmap() {
|
|
1630
|
+
void unmap() {
|
|
1631
|
+
if (pimpl_)
|
|
1632
|
+
pimpl_->unmap();
|
|
1633
|
+
}
|
|
1675
1634
|
|
|
1676
|
-
void swap(basic_shared_mmap& other) {
|
|
1635
|
+
void swap(basic_shared_mmap& other) {
|
|
1636
|
+
pimpl_.swap(other.pimpl_);
|
|
1637
|
+
}
|
|
1677
1638
|
|
|
1678
1639
|
/** Flushes the memory mapped page to disk. Errors are reported via `error`. */
|
|
1679
|
-
template<
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1640
|
+
template< access_mode A = AccessMode, typename = typename std::enable_if<A == access_mode::write>::type >
|
|
1641
|
+
void sync(std::error_code& error) {
|
|
1642
|
+
if (pimpl_)
|
|
1643
|
+
pimpl_->sync(error);
|
|
1644
|
+
}
|
|
1683
1645
|
|
|
1684
1646
|
/** All operators compare the underlying `basic_mmap`'s addresses. */
|
|
1685
1647
|
|
|
1686
|
-
friend bool operator==(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1687
|
-
{
|
|
1648
|
+
friend bool operator==(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1688
1649
|
return a.pimpl_ == b.pimpl_;
|
|
1689
1650
|
}
|
|
1690
1651
|
|
|
1691
|
-
friend bool operator!=(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1692
|
-
{
|
|
1652
|
+
friend bool operator!=(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1693
1653
|
return !(a == b);
|
|
1694
1654
|
}
|
|
1695
1655
|
|
|
1696
|
-
friend bool operator<(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1697
|
-
{
|
|
1656
|
+
friend bool operator<(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1698
1657
|
return a.pimpl_ < b.pimpl_;
|
|
1699
1658
|
}
|
|
1700
1659
|
|
|
1701
|
-
friend bool operator<=(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1702
|
-
{
|
|
1660
|
+
friend bool operator<=(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1703
1661
|
return a.pimpl_ <= b.pimpl_;
|
|
1704
1662
|
}
|
|
1705
1663
|
|
|
1706
|
-
friend bool operator>(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1707
|
-
{
|
|
1664
|
+
friend bool operator>(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1708
1665
|
return a.pimpl_ > b.pimpl_;
|
|
1709
1666
|
}
|
|
1710
1667
|
|
|
1711
|
-
friend bool operator>=(const basic_shared_mmap& a, const basic_shared_mmap& b)
|
|
1712
|
-
{
|
|
1668
|
+
friend bool operator>=(const basic_shared_mmap& a, const basic_shared_mmap& b) {
|
|
1713
1669
|
return a.pimpl_ >= b.pimpl_;
|
|
1714
1670
|
}
|
|
1715
1671
|
|
|
1716
|
-
private:
|
|
1672
|
+
private:
|
|
1673
|
+
|
|
1717
1674
|
template<typename MappingToken>
|
|
1718
|
-
void map_impl(const MappingToken& token, const size_type offset,
|
|
1719
|
-
|
|
1720
|
-
{
|
|
1721
|
-
if(!pimpl_)
|
|
1722
|
-
{
|
|
1675
|
+
void map_impl(const MappingToken& token, const size_type offset, const size_type length, std::error_code& error) {
|
|
1676
|
+
if (!pimpl_) {
|
|
1723
1677
|
mmap_type mmap = make_mmap<mmap_type>(token, offset, length, error);
|
|
1724
|
-
if(error) {
|
|
1678
|
+
if (error) {
|
|
1679
|
+
return;
|
|
1680
|
+
}
|
|
1725
1681
|
pimpl_ = std::make_shared<mmap_type>(std::move(mmap));
|
|
1726
|
-
}
|
|
1727
|
-
else
|
|
1728
|
-
{
|
|
1682
|
+
} else {
|
|
1729
1683
|
pimpl_->map(token, offset, length, error);
|
|
1730
1684
|
}
|
|
1731
1685
|
}
|
|
@@ -1749,12 +1703,12 @@ using basic_shared_mmap_sink = basic_shared_mmap<access_mode::write, ByteT>;
|
|
|
1749
1703
|
* These aliases cover the most common use cases, both representing a raw byte stream
|
|
1750
1704
|
* (either with a char or an unsigned char/uint8_t).
|
|
1751
1705
|
*/
|
|
1752
|
-
using shared_mmap_source
|
|
1706
|
+
using shared_mmap_source = basic_shared_mmap_source<char>;
|
|
1753
1707
|
using shared_ummap_source = basic_shared_mmap_source<unsigned char>;
|
|
1754
1708
|
|
|
1755
|
-
using shared_mmap_sink
|
|
1709
|
+
using shared_mmap_sink = basic_shared_mmap_sink<char>;
|
|
1756
1710
|
using shared_ummap_sink = basic_shared_mmap_sink<unsigned char>;
|
|
1757
1711
|
|
|
1758
|
-
}
|
|
1712
|
+
} // namespace mio
|
|
1759
1713
|
|
|
1760
|
-
#endif
|
|
1714
|
+
#endif // MIO_SHARED_MMAP_HEADER
|