MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
file.hpp
1#ifndef MSTL_CORE_FILE_FILE_HPP__
2#define MSTL_CORE_FILE_FILE_HPP__
3#include "MSTL/core/container/vector.hpp"
4#include "MSTL/core/container/unordered_map.hpp"
5#include "MSTL/core/time/datetime.hpp"
6#include "MSTL/core/iterator/file_line_iterator.hpp"
8#include "path.hpp"
9#ifdef MSTL_PLATFORM_WINDOWS__
10#include <Windows.h>
11#include "MSTL/core/config/undef_cmacro.hpp"
12#endif
13#ifdef MSTL_PLATFORM_LINUX__
14#include <sys/stat.h>
15#include <aio.h>
16#endif
18
19class MSTL_API file {
20public:
21#ifdef MSTL_PLATFORM_WINDOWS__
22 using size_type = ::DWORD;
23 using difference_type = ::LONGLONG;
24 using file_handle = ::HANDLE;
25 using time_type = ::FILETIME;
26 using aiocb_type = ::OVERLAPPED;
27#elif defined(MSTL_PLATFORM_LINUX__)
28 using size_type = size_t;
29 using difference_type = ::off_t;
30 using file_handle = int;
31 using time_type = ::time_t;
32 using aiocb_type = ::aiocb;
33#endif
34
35 struct chunk_info {
36 difference_type offset;
37 size_type size;
38 size_type chunk_index;
39 };
40
41 struct map_info {
42 void* address = nullptr;
43 size_type size = 0;
44 size_type offset = 0;
45 FILE_ACCESS access = FILE_ACCESS::READ;
46 bool is_mapped = false;
47 };
48
49 struct binary_diff_entry {
50 difference_type offset = 0;
51 byte_t byte1 = 0;
52 byte_t byte2 = 0;
53 int64_t size_diff = 0;
54 bool is_size_diff = false;
55 };
56
57 struct async_context {
58 string data{};
59 string* buffer = nullptr;
60 aiocb_type* cb = nullptr;
61 bool is_write;
62
63 explicit async_context(string &&d);
64 explicit async_context(string* buf);
65 ~async_context();
66 };
67
68 struct async_result {
69 bool completed = false;
70 size_t bytes_transferred = 0;
71 int error_code = 0;
72 aiocb_type* cb = nullptr;
73 async_context* user_context = nullptr;
74 };
75
76private:
77 MSTL_ALWAYS_INLINE static const file_handle& INVALID_HANDLE() noexcept {
78 static const auto INVALID_HANDLE =
79#ifdef MSTL_PLATFORM_WINDOWS__
80 INVALID_HANDLE_VALUE;
81#elif defined(MSTL_PLATFORM_LINUX__)
82 -1;
83#endif
84 return INVALID_HANDLE;
85 }
86
87 file_handle handle_ = INVALID_HANDLE();
88 _MSTL path path_{};
89 bool opened_ = false;
90 bool append_mode_ = false;
91
92 mutable vector<byte_t> read_buffer_{};
93 mutable size_type read_buffer_pos_ = 0;
94 mutable size_type read_buffer_size_ = 0;
95 mutable vector<byte_t> write_buffer_{};
96 mutable size_type write_buffer_pos_ = 0;
97
98 mutable mutex map_mutex_;
99
100 void* mapped_ptr_ = nullptr;
101 size_type mapped_size_ = 0;
102 size_type mapped_offset_ = 0;
103 FILE_ACCESS mapped_access_ = FILE_ACCESS::READ;
104 size_type is_mapped_ = false;
105
106#ifdef MSTL_PLATFORM_WINDOWS__
107 ::HANDLE mapping_handle_ = INVALID_HANDLE_VALUE;
108#endif
109
110 mutable mutex async_mutex_;
111 mutable vector<aiocb_type*> async_operations_;
112 mutable unordered_map<aiocb_type*, async_context*> async_contexts_;
113
114 mutable string last_error_msg_;
115 mutable int last_error_code_ = 0;
116
117 size_type buffer_size_ = FILE_BUFFER_SIZE;
118
119private:
120 bool complete_async_result(async_result& result, size_type bytes_transferred);
121 bool check_async_completion(async_result& result);
122
123 bool flush_write_buffer() const noexcept;
124 bool fill_read_buffer() const noexcept;
125
126 static datetime filetime_to_datetime(const time_type& ft) noexcept;
127 static time_type datetime_to_filetime(const datetime& dt) noexcept;
128 static string get_last_error_msg();
129
130 void set_last_error() const;
131
132 void adjust_buffer_size();
133
134public:
135 file() = default;
136
137 explicit file(
138 _MSTL path p,
139 FILE_ACCESS access = FILE_ACCESS::READ_WRITE,
140 FILE_SHARED share_mode = FILE_SHARED::SHARE_READ,
141 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
142 FILE_ATTRI attributes = FILE_ATTRI::NORMAL,
143 bool append = false) : path_(_MSTL move(p)) {
144 this->open(path_, append, access, share_mode, creation, attributes);
145 }
146
147 file(const file&) = delete;
148 file& operator =(const file&) = delete;
149
150 file(file&& other) noexcept;
151 file& operator =(file&& other) noexcept;
152
153 ~file();
154
155 bool open(_MSTL path p, bool append = false,
156 FILE_ACCESS access = FILE_ACCESS::READ_WRITE,
157 FILE_SHARED share_mode = FILE_SHARED::SHARE_READ_WRITE,
158 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
159 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
160
161 bool open(bool append = false,
162 FILE_ACCESS access = FILE_ACCESS::READ_WRITE,
163 FILE_SHARED share_mode = FILE_SHARED::SHARE_READ_WRITE,
164 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
165 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
166
167 void close() noexcept;
168 bool flush() noexcept;
169
170 MSTL_NODISCARD file_handle native_handle() const noexcept { return handle_; }
171
172 size_type write(const string& data, size_type size);
173 size_type write(const string& data);
174 size_type write(const void* data, size_type size);
175
176 size_type read(void* buffer, size_type size) const;
177 size_type read(string& str, size_type size) const;
178 size_type read(string& str) const;
179 MSTL_NODISCARD string read() const;
180
181 size_type read_binary(void* buffer, size_type size) const;
182 size_type read_binary(string& str, size_type size) const;
183 size_type read_binary(string& str) const;
184 MSTL_NODISCARD string read_binary() const;
185
186 bool read_line(string& line) const;
187 MSTL_NODISCARD string read_line() const;
188 MSTL_NODISCARD vector<string> read_lines() const;
189
190 vector<string> read_chunks(size_type chunk_size = FILE_BUFFER_SIZE * 16) const;
191 bool write_chunks(const vector<string>& chunks);
192 MSTL_NODISCARD vector<chunk_info> chunks_info(size_type chunk_size) const;
193
194 async_result async_read(string& buffer, size_type size, difference_type offset = -1) const;
195 async_result async_write(string data, size_type size, difference_type offset = -1);
196 bool wait_async(async_result& result, uint32_t timeout_ms = numeric_traits<uint32_t>::max());
197 void cancel_async(async_result& result);
198
199 MSTL_NODISCARD size_type size() const;
200 bool size(size_type& out_size) const;
201 MSTL_NODISCARD uint64_t size64() const;
202
203 MSTL_NODISCARD const _MSTL path& path() const noexcept { return path_; }
204
205 MSTL_NODISCARD bool is_opened() const noexcept { return opened_; }
206 MSTL_NODISCARD bool is_append() const noexcept { return append_mode_; }
207
208 MSTL_NODISCARD string last_error() const noexcept { return last_error_msg_; }
209 MSTL_NODISCARD int last_error_code() const noexcept { return last_error_code_; }
210
211 void clear_error() noexcept;
212
213 MSTL_NODISCARD file_line_iterator begin_lines() const { return file_line_iterator(this); }
214 MSTL_NODISCARD file_line_iterator end_lines() const { return {}; }
215
216 MSTL_NODISCARD static bool compare(const _MSTL path& file1, const _MSTL path& file2, bool binary = true);
217 MSTL_NODISCARD static bool compare_binary(const _MSTL path& file1, const _MSTL path& file2);
218
219 MSTL_NODISCARD static bool compare_text(
220 const _MSTL path& file1, const _MSTL path& file2,
221 bool ignore_case = false, bool ignore_whitespace = false);
222
223 MSTL_NODISCARD static vector<binary_diff_entry> binary_diff(
224 const _MSTL path& file1,
225 const _MSTL path& file2,
226 size_type max_diffs = 100);
227
228 bool seek(difference_type distance, FILE_POINTER method = FILE_POINTER::END) const noexcept;
229 difference_type tell() const noexcept;
230 difference_type system_tell() const noexcept;
231
232 bool prefetch(size_type hint_size = 0) const noexcept;
233 bool truncate(difference_type size) const noexcept;
234
235 bool lock(difference_type offset, difference_type length, FILE_LOCK mode = FILE_LOCK::EXCLUSIVE) const noexcept;
236 bool unlock(difference_type offset, difference_type length) const noexcept;
237
238 bool try_lock(difference_type offset, difference_type length, FILE_LOCK mode) const noexcept;
239
240 MSTL_NODISCARD bool is_locked(
241 difference_type offset,
242 difference_type length,
243 FILE_LOCK* out_type) const noexcept;
244
245 bool lock_whole(FILE_LOCK mode) const noexcept;
246 bool unlock_whole() const noexcept;
247
248 bool map(size_type offset = 0, size_type size = 0,
249 FILE_ACCESS access = FILE_ACCESS::READ,
250 FILE_MAP_HINT hint = FILE_MAP_HINT::SEQUENTIAL);
251 void unmap() noexcept;
252 bool remap(size_type new_offset, size_type new_size);
253 bool flush_mapped(bool async = false);
254
255 bool lock_mapped_pages(bool lock_in_memory) const noexcept;
256 MSTL_NODISCARD map_info map_infos() const noexcept;
257
258 MSTL_NODISCARD void* mapped_data() const noexcept { return mapped_ptr_; }
259 MSTL_NODISCARD size_type mapped_size() const noexcept { return mapped_size_; }
260 MSTL_NODISCARD size_type mapped_offset() const noexcept { return mapped_offset_; }
261 MSTL_NODISCARD FILE_ACCESS mapped_access() const noexcept { return mapped_access_; }
262 MSTL_NODISCARD bool is_mapped() const noexcept { return mapped_ptr_ != nullptr; }
263
264 MSTL_NODISCARD FILE_ATTRI attributes() const noexcept;
265 bool set_attributes(FILE_ATTRI attr) noexcept;
266
267#ifdef MSTL_PLATFORM_WINDOWS__
268 MSTL_NODISCARD datetime creation_time() const noexcept;
269#endif
270 MSTL_NODISCARD datetime last_access_time() const noexcept;
271 MSTL_NODISCARD datetime last_write_time() const noexcept;
272
273#ifdef MSTL_PLATFORM_WINDOWS__
274 bool set_all_times(const datetime& create, const datetime& access, const datetime& write) noexcept;
275#elif defined(MSTL_PLATFORM_LINUX__)
276 bool set_all_times(const datetime& access, const datetime& write) noexcept;
277#endif
278
279#ifdef MSTL_PLATFORM_WINDOWS__
280 bool set_creation_time(const datetime& dt) noexcept;
281#endif
282 bool set_last_access_time(const datetime& dt) noexcept;
283 bool set_last_write_time(const datetime& dt) noexcept;
284
285 MSTL_NODISCARD static size_type size(const _MSTL path& p);
286 static bool size(const _MSTL path& p, size_type& size);
287
288 static bool create_and_write(const _MSTL path& p, const string& content, bool append = false);
289
290 static bool read(const _MSTL path& p, string& content,
291 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
292 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
293
294 MSTL_NODISCARD static string read(const _MSTL path& p,
295 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
296 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
297
298 static bool read_binary(const _MSTL path& p, string& content,
299 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
300 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
301
302 MSTL_NODISCARD static string read_binary(const _MSTL path& p,
303 FILE_CREATION creation = FILE_CREATION::OPEN_EXIST,
304 FILE_ATTRI attributes = FILE_ATTRI::NORMAL);
305};
306
307
308class MSTL_API file_lock_guard {
309public:
310 using difference_type = file::difference_type;
311
312private:
313 file& file_;
314 difference_type offset_;
315 difference_type length_;
316 bool locked_;
317
318public:
319 file_lock_guard(file& f, difference_type offset, difference_type length, FILE_LOCK mode);
320 ~file_lock_guard();
321
322 file_lock_guard(const file_lock_guard&) = delete;
323 file_lock_guard& operator =(const file_lock_guard&) = delete;
324
325 MSTL_NODISCARD bool is_locked() const { return locked_; }
326
327 bool unlock();
328};
329
331#endif // MSTL_CORE_FILE_FILE_HPP__
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
MSTL_NODISCARD future< async_result_t< Func, Args... > > async(launch policy, Func &&function, Args &&... args)
异步执行函数(指定策略)
unsigned char byte_t
字节类型,定义为无符号字符
unsigned int uint32_t
32位无符号整数类型
long long int64_t
64位有符号整数类型
unsigned long long uint64_t
64位无符号整数类型
constexpr iter_difference_t< Iterator > distance(Iterator first, Iterator last)
计算两个迭代器之间的距离
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 decimal_t truncate(const decimal_t x, const int bit) noexcept
截断
MSTL_INLINE17 constexpr try_lock_tag try_lock
尝试锁定标签实例
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
uint64_t size_t
无符号大小类型
constexpr Iterator2 move(Iterator1 first, Iterator1 last, Iterator2 result)
移动范围元素
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) size(const Container &cont) noexcept(noexcept(cont.size()))
获取容器的大小
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) data(Container &cont) noexcept(noexcept(cont.data()))
获取容器的底层数据指针
MSTL互斥锁