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"
9#ifdef MSTL_PLATFORM_WINDOWS__
11#include "MSTL/core/config/undef_cmacro.hpp"
13#ifdef MSTL_PLATFORM_LINUX__
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__)
29 using difference_type = ::off_t;
30 using file_handle = int;
31 using time_type = ::time_t;
32 using aiocb_type = ::aiocb;
36 difference_type offset;
38 size_type chunk_index;
42 void* address =
nullptr;
45 FILE_ACCESS access = FILE_ACCESS::READ;
46 bool is_mapped =
false;
49 struct binary_diff_entry {
50 difference_type offset = 0;
54 bool is_size_diff =
false;
57 struct async_context {
59 string* buffer =
nullptr;
60 aiocb_type* cb =
nullptr;
63 explicit async_context(
string &&d);
64 explicit async_context(
string* buf);
69 bool completed =
false;
70 size_t bytes_transferred = 0;
72 aiocb_type* cb =
nullptr;
73 async_context* user_context =
nullptr;
77 MSTL_ALWAYS_INLINE
static const file_handle& INVALID_HANDLE() noexcept {
78 static const auto INVALID_HANDLE =
79#ifdef MSTL_PLATFORM_WINDOWS__
81#elif defined(MSTL_PLATFORM_LINUX__)
84 return INVALID_HANDLE;
87 file_handle handle_ = INVALID_HANDLE();
90 bool append_mode_ =
false;
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;
98 mutable mutex map_mutex_;
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;
106#ifdef MSTL_PLATFORM_WINDOWS__
107 ::HANDLE mapping_handle_ = INVALID_HANDLE_VALUE;
110 mutable mutex async_mutex_;
111 mutable vector<aiocb_type*> async_operations_;
112 mutable unordered_map<aiocb_type*, async_context*> async_contexts_;
114 mutable string last_error_msg_;
115 mutable int last_error_code_ = 0;
117 size_type buffer_size_ = FILE_BUFFER_SIZE;
120 bool complete_async_result(async_result& result, size_type bytes_transferred);
121 bool check_async_completion(async_result& result);
123 bool flush_write_buffer() const noexcept;
124 bool fill_read_buffer() const noexcept;
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();
130 void set_last_error() const;
132 void adjust_buffer_size();
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);
147 file(
const file&) =
delete;
148 file& operator =(
const file&) =
delete;
150 file(file&& other)
noexcept;
151 file& operator =(file&& other)
noexcept;
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);
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);
167 void close() noexcept;
168 bool flush() noexcept;
170 MSTL_NODISCARD file_handle native_handle() const noexcept {
return handle_; }
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);
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;
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;
186 bool read_line(
string& line)
const;
187 MSTL_NODISCARD
string read_line()
const;
188 MSTL_NODISCARD vector<string> read_lines()
const;
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;
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);
197 void cancel_async(async_result& result);
199 MSTL_NODISCARD size_type
size()
const;
200 bool size(size_type& out_size)
const;
201 MSTL_NODISCARD
uint64_t size64()
const;
203 MSTL_NODISCARD
const _MSTL path& path() const noexcept {
return path_; }
205 MSTL_NODISCARD
bool is_opened() const noexcept {
return opened_; }
206 MSTL_NODISCARD
bool is_append() const noexcept {
return append_mode_; }
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_; }
211 void clear_error() noexcept;
213 MSTL_NODISCARD file_line_iterator begin_lines()
const {
return file_line_iterator(
this); }
214 MSTL_NODISCARD file_line_iterator end_lines()
const {
return {}; }
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);
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);
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);
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;
232 bool prefetch(size_type hint_size = 0) const noexcept;
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;
238 bool try_lock(difference_type offset, difference_type length, FILE_LOCK mode) const noexcept;
240 MSTL_NODISCARD
bool is_locked(
241 difference_type offset,
242 difference_type length,
243 FILE_LOCK* out_type) const noexcept;
245 bool lock_whole(FILE_LOCK mode) const noexcept;
246 bool unlock_whole() const noexcept;
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);
255 bool lock_mapped_pages(
bool lock_in_memory) const noexcept;
256 MSTL_NODISCARD map_info map_infos() const noexcept;
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; }
264 MSTL_NODISCARD FILE_ATTRI attributes() const noexcept;
265 bool set_attributes(FILE_ATTRI attr) noexcept;
267#ifdef MSTL_PLATFORM_WINDOWS__
268 MSTL_NODISCARD datetime creation_time() const noexcept;
270 MSTL_NODISCARD datetime last_access_time() const noexcept;
271 MSTL_NODISCARD datetime last_write_time() const noexcept;
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;
279#ifdef MSTL_PLATFORM_WINDOWS__
280 bool set_creation_time(
const datetime& dt)
noexcept;
282 bool set_last_access_time(
const datetime& dt)
noexcept;
283 bool set_last_write_time(
const datetime& dt)
noexcept;
285 MSTL_NODISCARD
static size_type
size(
const _MSTL path& p);
288 static bool create_and_write(
const _MSTL path& p,
const string& content,
bool append =
false);
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);
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);
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);
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);
308class MSTL_API file_lock_guard {
310 using difference_type = file::difference_type;
314 difference_type offset_;
315 difference_type length_;
319 file_lock_guard(file& f, difference_type offset, difference_type length, FILE_LOCK mode);
322 file_lock_guard(
const file_lock_guard&) =
delete;
323 file_lock_guard& operator =(
const file_lock_guard&) =
delete;
325 MSTL_NODISCARD
bool is_locked()
const {
return locked_; }
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
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()))
获取容器的底层数据指针