10#include "interval.hpp"
29#include <condition_variable>
38#pragma GCC diagnostic push
39#pragma GCC diagnostic ignored "-Wunknown-pragmas"
42#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
43#define SET_FILE_OP_TIMES 1
44#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
45#elif !defined(SET_FILE_OP_TIMES)
46#define SET_FILE_OP_TIMES 0
48#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
49#define CHECK_STREAM_STATE 0
50#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
52#define CHECK_STREAM_STATE 1
71 using fsize_t = uint64_t;
72 constexpr fsize_t fsize_max = UINT64_MAX;
74 constexpr size_t iterate_count = 0x10;
75 constexpr size_t default_block_size = 0x10000;
76 constexpr utf16_t utf16_bom = u
'\ufeff';
77 constexpr utf32_t utf32_bom = U
'\ufeff';
78 constexpr const char utf8_bom[3] = {
'\xef',
'\xbb',
'\xbf' };
88 virtual ~basic()
noexcept(
false) {}
101 virtual _Success_(
return != 0 || length == 0) size_t
read(
102 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
104 _Unreferenced_(data);
105 _Unreferenced_(length);
106 m_state = state_t::fail;
119 virtual _Success_(
return != 0) size_t
write(
120 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
122 _Unreferenced_(data);
123 _Unreferenced_(length);
124 m_state = state_t::fail;
133 m_state = state_t::ok;
141 m_state = state_t::ok;
147 virtual void skip(_In_ fsize_t amount)
151 else if (amount < iterate_count) {
152 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
154 if (!
ok()) _Unlikely_
159 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
161 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
163 amount -=
read_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
164 if (!
ok()) _Unlikely_
168 catch (
const std::bad_alloc&) { m_state = state_t::fail; }
175 state_t
state()
const {
return m_state; };
180 bool ok()
const {
return m_state == state_t::ok; };
191 std::vector<uint8_t> result;
192 size_t offset, length;
194 length = default_block_size;
195 while (offset < max_length) {
196 length = std::min(length, max_length);
197 try { result.resize(length); }
198 catch (
const std::bad_alloc&) {
199 m_state = state_t::fail;
202 auto num_read =
read_array(result.data() + offset,
sizeof(uint8_t), length - offset);
204 if (!
ok()) _Unlikely_
206 length += default_block_size;
208 result.resize(offset);
220 throw std::system_error(sys_error(), std::system_category(),
"failed to read");
229 write(&
byte,
sizeof(uint8_t));
230 else if (amount < iterate_count) {
231 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
232 write(&
byte,
sizeof(uint8_t));
233 if (!
ok()) _Unlikely_
238 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
240 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
241 memset(dummy.get(),
byte, block);
243 amount -=
write_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
244 if (!
ok()) _Unlikely_
248 catch (
const std::bad_alloc&) { m_state = state_t::fail; }
266 if (!
ok()) _Unlikely_ {
275 m_state = state_t::eof;
294 if (!
ok()) _Unlikely_
296#if BYTE_ORDER == BIG_ENDIAN
297 T data_le = HE2LE(data);
298 write(&data_le,
sizeof(T));
300 write(&data,
sizeof(T));
310 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
311 size_t readln(_Inout_ std::basic_string<T, TR, AX>& str)
322 template<
class T_from,
class T_to,
class TR = std::
char_traits<T_to>,
class AX = std::allocator<T_to>>
325 if (encoder.from_encoding() == encoder.to_encoding())
327 std::basic_string<T_from> tmp;
329 encoder.strcpy(str, tmp);
338 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
342 T chr, previous = (T)0;
345 if (!initial && !(previous ==
static_cast<T
>(
'\r') && chr ==
static_cast<T
>(
'\n')))
350 }
while (
ok() && chr !=
static_cast<T
>(
'\n'));
359 template<
class T_from,
class T_to,
class TR = std::
char_traits<T_to>,
class AX = std::allocator<T_to>>
362 if (encoder.from_encoding() == encoder.to_encoding())
364 std::basic_string<T_from> tmp;
366 encoder.strcat(str, tmp);
375 size_t read_array(_Out_writes_bytes_(size* count)
void* array, _In_
size_t size, _In_
size_t count)
377 for (
size_t to_read = mul(size, count);;) {
378 size_t num_read =
read(array, to_read);
382 if (!
ok()) _Unlikely_
383 return count - to_read / size;
384 reinterpret_cast<uint8_t*&
>(array) += num_read;
393 size_t write_array(_In_reads_bytes_opt_(size* count)
const void* array, _In_
size_t size, _In_
size_t count)
395 return write(array, mul(size, count)) / size;
406 template <
class T_from,
class T_to>
409 if (!
ok()) _Unlikely_
411 size_t num_chars = stdex::strlen(str);
412 if (encoder.from_encoding() == encoder.to_encoding())
413 return write_array(str,
sizeof(T_from), num_chars);
414 std::basic_string<T_to> tmp(encoder.convert(str, num_chars));
415 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
427 template <
class T_from,
class T_to>
430 if (!
ok()) _Unlikely_
432 num_chars = stdex::strnlen(str, num_chars);
433 if (encoder.from_encoding() == encoder.to_encoding())
434 return write_array(str,
sizeof(T_from), num_chars);
435 std::basic_string<T_to> tmp(encoder.convert(str, num_chars));
436 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
447 template<
class T_from,
class T_to,
class TR = std::
char_traits<T_from>,
class AX = std::allocator<T_from>>
450 if (!
ok()) _Unlikely_
452 if (encoder.from_encoding() == encoder.to_encoding())
453 return write_array(str.data(),
sizeof(T_from), str.size());
454 std::basic_string<T_to> tmp(encoder.convert(str));
455 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
469 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
473 if (!
ok()) _Unlikely_
477 if (!
ok()) _Unlikely_
479 data.reserve(num_chars);
482 uint32_t num_read =
static_cast<uint32_t
>(
read_array(buf,
sizeof(T), std::min<uint32_t>(num_chars, _countof(buf))));
483 data.append(buf, num_read);
484 num_chars -= num_read;
485 if (!num_chars || !
ok())
505 size_t num_chars = stdex::strlen(data);
506 if (num_chars > UINT32_MAX)
507 throw std::invalid_argument(
"string too long");
509 if (!
ok()) _Unlikely_
526 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
530 size_t num_chars = data.size();
531 if (num_chars > UINT32_MAX)
532 throw std::invalid_argument(
"string too long");
534 if (!
ok()) _Unlikely_
546 size_t write_sa(_In_ LPSAFEARRAY sa)
549 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
550 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
551 throw std::invalid_argument(
"SafeArrayGet[UL]Bound failed");
552 safearray_accessor<void> a(sa);
553 return write(a.data(),
static_cast<size_t>(ubound) - lbound + 1);
564 std::unique_ptr<uint8_t[]> data(
new uint8_t[
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
565 fsize_t num_copied = 0, to_write = amount;
566 m_state = state_t::ok;
568 size_t num_read = stream.read(data.get(),
static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
569 size_t num_written =
write(data.get(), num_read);
570 num_copied += num_written;
571 to_write -= num_written;
572 if (stream.m_state == state_t::eof) {
574 m_state = state_t::ok;
577 m_state = stream.m_state;
589 if (charset == charset_id::utf32)
591 else if (charset == charset_id::utf16)
593 else if (charset == charset_id::utf8)
602 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t
locale, ...)
616 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t
locale, ...)
630 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t
locale, _In_ va_list params)
633 tmp.reserve(default_block_size);
634 vappendf(tmp, format,
locale, params);
635 return write_array(tmp.data(),
sizeof(
char), tmp.size());
643 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t
locale, _In_ va_list params)
646 tmp.reserve(default_block_size);
647 vappendf(tmp, format,
locale, params);
648 return write_array(tmp.data(),
sizeof(
wchar_t), tmp.size());
651 basic& operator >>(_Out_ int8_t& data) {
return read_data(data); }
652 basic& operator <<(_In_
const int8_t data) {
return write_data(data); }
653 basic& operator >>(_Out_ int16_t& data) {
return read_data(data); }
654 basic& operator <<(_In_
const int16_t data) {
return write_data(data); }
655 basic& operator >>(_Out_ int32_t& data) {
return read_data(data); }
656 basic& operator <<(_In_
const int32_t data) {
return write_data(data); }
657 basic& operator >>(_Out_ int64_t& data) {
return read_data(data); }
658 basic& operator <<(_In_
const int64_t data) {
return write_data(data); }
659 basic& operator >>(_Out_ uint8_t& data) {
return read_data(data); }
660 basic& operator <<(_In_
const uint8_t data) {
return write_data(data); }
661 basic& operator >>(_Out_ uint16_t& data) {
return read_data(data); }
662 basic& operator <<(_In_
const uint16_t data) {
return write_data(data); }
663 basic& operator >>(_Out_ uint32_t& data) {
return read_data(data); }
664 basic& operator <<(_In_
const uint32_t data) {
return write_data(data); }
665 basic& operator >>(_Out_ uint64_t& data) {
return read_data(data); }
666 basic& operator <<(_In_
const uint64_t data) {
return write_data(data); }
667 basic& operator >>(_Out_
float& data) {
return read_data(data); }
668 basic& operator <<(_In_
const float data) {
return write_data(data); }
669 basic& operator >>(_Out_
double& data) {
return read_data(data); }
670 basic& operator <<(_In_
const double data) {
return write_data(data); }
671 basic& operator >>(_Out_
char& data) {
return read_data(data); }
672 basic& operator <<(_In_
const char data) {
return write_data(data); }
673#ifdef _NATIVE_WCHAR_T_DEFINED
674 basic& operator >>(_Out_
wchar_t& data) {
return read_data(data); }
675 basic& operator <<(_In_
const wchar_t data) {
return write_data(data); }
677 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
678 basic& operator >>(_Out_ std::basic_string<T, TR, AX>& data) {
return read_str(data); }
680 basic& operator <<(_In_
const T* data) {
return write_str(data); }
681 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
682 basic& operator <<(_In_
const std::basic_string<T, TR, AX>& data) {
return write_str(data); }
684 template <
class T,
class AX = std::allocator<T>>
685 basic& operator <<(_In_
const std::vector<T, AX>& data)
687 size_t num = data.size();
688 if (num > UINT32_MAX) _Unlikely_
689 throw std::invalid_argument(
"collection too big");
690 *this << static_cast<uint32_t>(num);
691 for (
auto& el : data)
696 template <
class T,
class AX = std::allocator<T>>
697 basic& operator >>(_Out_ std::vector<T, AX>& data)
702 if (!
ok()) _Unlikely_
705 for (uint32_t i = 0; i < num; ++i) {
708 if (!
ok()) _Unlikely_
710 data.push_back(std::move(el));
714 template <
class KEY,
class PR = std::less<KEY>,
class AX = std::allocator<KEY>>
715 basic& operator <<(_In_
const std::set<KEY, PR, AX>& data)
717 size_t num = data.size();
718 if (num > UINT32_MAX) _Unlikely_
719 throw std::invalid_argument(
"collection too big");
720 *this << static_cast<uint32_t>(num);
721 for (
auto& el : data)
726 template <
class KEY,
class PR = std::less<KEY>,
class AX = std::allocator<KEY>>
727 basic& operator >>(_Out_ std::set<KEY, PR, AX>& data)
732 if (!
ok()) _Unlikely_
734 for (uint32_t i = 0; i < num; ++i) {
737 if (!
ok()) _Unlikely_
739 data.insert(std::move(el));
743 template <
class KEY,
class PR = std::less<KEY>,
class AX = std::allocator<KEY>>
744 basic& operator <<(_In_
const std::multiset<KEY, PR, AX>& data)
746 size_t num = data.size();
747 if (num > UINT32_MAX) _Unlikely_
748 throw std::invalid_argument(
"collection too big");
749 *this << static_cast<uint32_t>(num);
750 for (
auto& el : data)
755 template <
class KEY,
class PR = std::less<KEY>,
class AX = std::allocator<KEY>>
756 basic& operator >>(_Out_ std::multiset<KEY, PR, AX>& data)
761 if (!
ok()) _Unlikely_
763 for (uint32_t i = 0; i < num; ++i) {
766 if (!
ok()) _Unlikely_
768 data.insert(std::move(el));
780 using fpos_t = uint64_t;
781 constexpr fpos_t fpos_max = UINT64_MAX;
782 constexpr fpos_t fpos_min = 0;
787 using foff_t = int64_t;
788 constexpr foff_t foff_max = INT64_MAX;
789 constexpr foff_t foff_min = INT64_MIN;
807 using clock = std::chrono::file_clock;
809 using clock = std::chrono::system_clock;
811 using time_point = std::chrono::time_point<clock>;
821 size_t length = std::min<size_t>(max_length,
static_cast<size_t>(
size() -
tell()));
822 std::vector<uint8_t> result;
823 try { result.resize(length); }
824 catch (
const std::bad_alloc&) {
825 m_state = state_t::fail;
828 result.resize(
read_array(result.data(),
sizeof(uint8_t), length));
837 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
846 return seek(
static_cast<foff_t
>(offset), seek_t::beg);
854 fpos_t
seekcur(_In_ foff_t offset) {
return seek(offset, seek_t::cur); }
861 fpos_t
seekend(_In_ foff_t offset) {
return seek(offset, seek_t::end); }
863 virtual void skip(_In_ fsize_t amount)
865 if (amount > foff_max)
866 throw std::invalid_argument(
"file offset too big");
867 seek(
static_cast<foff_t
>(amount), seek_t::cur);
876 virtual fpos_t
tell()
const = 0;
881 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
883 _Unreferenced_(offset);
884 _Unreferenced_(length);
885 throw std::domain_error(
"not implemented");
891 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
893 _Unreferenced_(offset);
894 _Unreferenced_(length);
895 throw std::domain_error(
"not implemented");
902 virtual fsize_t
size()
const = 0;
914 return time_point::min();
922 return time_point::min();
930 return time_point::min();
938 _Unreferenced_(date);
939 throw std::domain_error(
"not implemented");
947 _Unreferenced_(date);
948 throw std::domain_error(
"not implemented");
956 _Unreferenced_(date);
957 throw std::domain_error(
"not implemented");
964 LPSAFEARRAY read_sa()
966 _Assume_(
size() <= SIZE_MAX);
967 if (
size() > ULONG_MAX)
968 throw std::range_error(
"data too big");
969 ULONG length =
static_cast<ULONG
>(
size());
970 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, length));
972 throw std::runtime_error(
"SafeArrayCreateVector failed");
973 if (
seek(0) != 0) _Unlikely_
974 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
975 safearray_accessor<void> a(sa.get());
976 if (
read_array(a.data(), 1, length) != length)
977 throw std::system_error(sys_error(), std::system_category(),
"failed to read");
987 charset_id
read_charset(_In_ charset_id default_charset = charset_id::system)
989 if (
seek(0) != 0) _Unlikely_
990 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
993 if (
ok() && id_utf32 == utf32_bom)
994 return charset_id::utf32;
996 if (
seek(0) != 0) _Unlikely_
997 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
1000 if (
ok() && id_utf16 == utf16_bom)
1001 return charset_id::utf16;
1003 if (
seek(0) != 0) _Unlikely_
1004 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
1005 char id_utf8[3] = { 0 };
1007 if (
ok() && strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
1008 return charset_id::utf8;
1010 if (
seek(0) != 0) _Unlikely_
1011 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
1012 return default_charset;
1025#pragma warning(suppress: 26495)
1028 void init(_Inout_
basic& source)
1036 m_state = m_source->
state();
1047 basic(source.state()),
1051 virtual _Success_(
return != 0 || length == 0) size_t
read(
1052 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1054 size_t num_read = m_source->
read(data, length);
1055 m_state = m_source->
state();
1059 virtual _Success_(
return != 0) size_t
write(
1060 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1062 size_t num_written = m_source->
write(data, length);
1063 m_state = m_source->
state();
1070 m_state = m_source->
state();
1076 m_state = m_source->
state();
1091 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1094 const std::lock_guard<std::mutex> lk(_w->mutex);
1095 _w->op = worker::op_t::quit;
1097 _w->cv.notify_one();
1099 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
1108 m_workers.push_back(std::unique_ptr<worker>(
new worker(source)));
1116 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1118 if (_w->source == source) {
1120 const std::lock_guard<std::mutex> lk(_w->mutex);
1121 _w->op = worker::op_t::quit;
1123 _w->cv.notify_one();
1131 virtual _Success_(
return != 0) size_t
write(
1132 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1134 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1137 const std::lock_guard<std::mutex> lk(_w->mutex);
1138 _w->op = worker::op_t::write;
1140 _w->length = length;
1142 _w->cv.notify_one();
1144 size_t num_written = length;
1145 m_state = state_t::ok;
1146 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1148 std::unique_lock<std::mutex> lk(_w->mutex);
1149 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
1150 if (_w->num_written < num_written)
1151 num_written = _w->num_written;
1152 if (
ok() && !_w->source->ok())
1153 m_state = _w->source->state();
1160 foreach_worker(worker::op_t::close);
1165 foreach_worker(worker::op_t::flush);
1179 *
static_cast<std::thread*
>(
this) = std::thread([](_Inout_
worker& w) { w.process_op(); }, std::ref(*
this));
1186 std::unique_lock<std::mutex> lk(mutex);
1187 cv.wait(lk, [&] {
return op != op_t::noop; });
1221 std::condition_variable cv;
1224 void foreach_worker(_In_ worker::op_t op)
1226 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1229 const std::lock_guard<std::mutex> lk(_w->mutex);
1232 _w->cv.notify_one();
1234 m_state = state_t::ok;
1235 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1237 std::unique_lock<std::mutex> lk(_w->mutex);
1238 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
1240 m_state = _w->source->state();
1244 std::list<std::unique_ptr<worker>> m_workers;
1247 constexpr size_t default_async_limit = 0x100000;
1254 template <
size_t N_cap = default_async_limit>
1260 m_worker([](_Inout_
async_reader& w) { w.process(); }, std::ref(*
this))
1269#pragma warning(suppress: 6101)
1270 virtual _Success_(
return != 0 || length == 0) size_t
read(
1271 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1273 _Assume_(data || !length);
1274 for (
size_t to_read = length;;) {
1275 uint8_t* ptr;
size_t num_read;
1276 std::tie(ptr, num_read) = m_ring.front();
1277 if (!ptr) _Unlikely_ {
1278 m_state = to_read < length || !length ? state_t::ok : m_source->
state();
1279 return length - to_read;
1281 if (to_read < num_read)
1283 memcpy(data, ptr, num_read);
1284 m_ring.pop(num_read);
1285 to_read -= num_read;
1287 m_state = state_t::ok;
1290 reinterpret_cast<uint8_t*&
>(data) += num_read;
1298 uint8_t* ptr;
size_t num_write;
1299 std::tie(ptr, num_write) = m_ring.back();
1300 if (!ptr) _Unlikely_
1302 num_write = m_source->
read(ptr, num_write);
1303 m_ring.push(num_write);
1304 if (!m_source->
ok()) {
1312 ring<uint8_t, N_cap> m_ring;
1313 std::thread m_worker;
1321 template <
size_t N_cap = default_async_limit>
1327 m_worker([](_Inout_
async_writer& w) { w.process(); }, std::ref(*
this))
1336 virtual _Success_(
return != 0) size_t
write(
1337 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1339 _Assume_(data || !length);
1340 for (
size_t to_write = length;;) {
1341 uint8_t* ptr;
size_t num_write;
1342 std::tie(ptr, num_write) = m_ring.back();
1343 if (!ptr) _Unlikely_ {
1344 m_state = state_t::fail;
1345 return length - to_write;
1347 if (to_write < num_write)
1348 num_write = to_write;
1349 memcpy(ptr, data, num_write);
1350 m_ring.push(num_write);
1351 to_write -= num_write;
1353 m_state = state_t::ok;
1356 reinterpret_cast<const uint8_t*&
>(data) += num_write;
1370 uint8_t* ptr;
size_t num_read;
1371 std::tie(ptr, num_read) = m_ring.front();
1374 num_read = m_source->
write(ptr, num_read);
1375 m_ring.pop(num_read);
1376 if (!m_source->
ok()) {
1384 ring<uint8_t, N_cap> m_ring;
1385 std::thread m_worker;
1388 constexpr size_t default_buffer_size = 0x400;
1397 explicit buffer(_In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1399 m_read_buffer(read_buffer_size),
1400 m_write_buffer(write_buffer_size)
1412 buffer(_Inout_
basic& source, _In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1414 m_read_buffer(read_buffer_size),
1415 m_write_buffer(write_buffer_size)
1424 virtual _Success_(
return != 0 || length == 0) size_t
read(
1425 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1427 _Assume_(data || !length);
1428 for (
size_t to_read = length;;) {
1429 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
1430 if (to_read <= buffer_size) {
1431 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
1432 m_read_buffer.head += to_read;
1433 m_state = state_t::ok;
1437 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
1438 reinterpret_cast<uint8_t*&
>(data) += buffer_size;
1439 to_read -= buffer_size;
1441 m_read_buffer.head = 0;
1442 if (to_read > m_read_buffer.capacity) {
1444 m_read_buffer.tail = 0;
1445 to_read -= m_source->
read(data, to_read);
1446 m_state = to_read < length ? state_t::ok : m_source->
state();
1447 return length - to_read;
1449 m_read_buffer.tail = m_source->
read(m_read_buffer.data, m_read_buffer.capacity);
1450 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
1451 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
1452 m_read_buffer.head = m_read_buffer.tail;
1453 to_read -= m_read_buffer.tail;
1454 m_state = to_read < length ? state_t::ok : m_source->
state();
1455 return length - to_read;
1460 virtual _Success_(
return != 0) size_t
write(
1461 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1463 _Assume_(data || !length);
1464 if (!length) _Unlikely_ {
1467 if (!
ok()) _Unlikely_
1473 for (
size_t to_write = length;;) {
1474 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
1475 if (to_write <= available_buffer) {
1476 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
1477 m_write_buffer.tail += to_write;
1478 m_state = state_t::ok;
1481 if (available_buffer) {
1482 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
1483 reinterpret_cast<const uint8_t*&
>(data) += available_buffer;
1484 to_write -= available_buffer;
1485 m_write_buffer.tail += available_buffer;
1487 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1489 m_write_buffer.head +=
converter::write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1490 if (m_write_buffer.head == m_write_buffer.tail)
1491 m_write_buffer.head = m_write_buffer.tail = 0;
1493 return length - to_write;
1495 if (to_write > m_write_buffer.capacity) {
1498 return length - to_write;
1513 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1515 m_write_buffer.head += m_source->
write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1516 if (m_write_buffer.head == m_write_buffer.tail) {
1517 m_write_buffer.head = 0;
1518 m_write_buffer.tail = 0;
1521 m_state = m_source->
state();
1525 m_state = state_t::ok;
1530 size_t head, tail, capacity;
1532 buffer_t(_In_
size_t buffer_size) :
1535 capacity(buffer_size),
1536 data(buffer_size ?
new uint8_t[buffer_size] :
nullptr)
1544 } m_read_buffer, m_write_buffer;
1553 limiter(_Inout_
basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
1559 virtual _Success_(
return != 0 || length == 0) size_t
read(
1560 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1571 m_state = state_t::eof;
1580 virtual _Success_(
return != 0) size_t
write(
1581 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1592 m_state = state_t::fail;
1613 window(_Inout_
basic& source, _In_ fpos_t _read_offset = 0, _In_ fsize_t
read_limit = fsize_max, _In_ fpos_t _write_offset = 0, _In_ fsize_t
write_limit = fsize_max) :
1619 virtual _Success_(
return != 0 || length == 0) size_t
read(
1620 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1624 m_state = m_source->
state();
1625 if (!
ok()) _Unlikely_
1638 m_source->
skip(length);
1639 m_state = state_t::eof;
1648 virtual _Success_(
return != 0) size_t
write(
1649 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1651 size_t num_skipped, num_written;
1654 m_state = state_t::ok;
1658 reinterpret_cast<const uint8_t*&
>(data) +=
static_cast<size_t>(
write_offset);
1672 num_skipped += length;
1674 m_state = state_t::ok;
1677 num_skipped += length -
static_cast<size_t>(
write_limit);
1681 return num_skipped + num_written;
1697 basic(source.state()),
1699 m_offset(source.tell()),
1700 m_region(offset, offset + length)
1703 virtual _Success_(
return != 0 || length == 0) size_t
read(
1704 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1706 _Assume_(data || !length);
1708 size_t num_read = m_source.
read(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1709 m_state = m_source.
state();
1710 m_offset += num_read;
1713 m_state = length ? state_t::eof : state_t::ok;
1717 virtual _Success_(
return != 0) size_t
write(
1718 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1720 _Assume_(data || !length);
1722 size_t num_written = m_source.
write(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1723 m_state = m_source.
state();
1724 m_offset += num_written;
1727 m_state = state_t::fail;
1734 m_state = m_source.
state();
1740 m_state = m_source.
state();
1743 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
1745 m_offset = m_source.
seek(offset, how);
1746 m_state = m_source.
state();
1747 return ok() ? m_offset - m_region.
start : fpos_max;
1750 virtual void skip(_In_ fsize_t amount)
1752 m_source.
skip(amount);
1753 m_state = m_source.
state();
1758 fpos_t offset = m_source.
tell();
1759 return m_region.
contains(offset) ? offset - m_region.
start : fpos_max;
1762 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
1765 m_source.
lock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1766 m_state = m_source.
state();
1769 m_state = state_t::fail;
1772 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
1775 m_source.
unlock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1776 m_state = m_source.
state();
1779 m_state = state_t::fail;
1784 return m_region.
size();
1789 m_state = state_t::fail;
1798 constexpr size_t default_cache_size = 0x1000;
1807#pragma warning(suppress: 26495)
1808 explicit cache(_In_
size_t cache_size = default_cache_size) :
1809 basic(state_t::fail),
1821 m_state = m_source->state();
1822 m_offset = m_source->tell();
1823#if SET_FILE_OP_TIMES
1824 m_atime = m_source->atime();
1825 m_mtime = m_source->mtime();
1833 if (!
ok()) _Unlikely_
1834 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1835 m_source->seekbeg(m_offset);
1836#if SET_FILE_OP_TIMES
1837 m_source->set_atime(m_atime);
1838 m_source->set_mtime(m_mtime);
1846 cache(_Inout_
basic_file& source, _In_
size_t cache_size = default_cache_size) :
1847 basic(source.state()),
1849 m_cache(cache_size),
1850 m_offset(source.tell())
1851#if SET_FILE_OP_TIMES
1852 , m_atime(source.atime())
1853 , m_mtime(source.mtime())
1857 virtual ~cache()
noexcept(
false)
1861 if (!
ok()) _Unlikely_
1862 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1863 m_source->seekbeg(m_offset);
1864#if SET_FILE_OP_TIMES
1865 m_source->set_atime(m_atime);
1866 m_source->set_mtime(m_mtime);
1871 virtual _Success_(
return != 0 || length == 0) size_t
read(
1872 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1874 _Assume_(data || !length);
1875#if SET_FILE_OP_TIMES
1876 m_atime = time_point::now();
1878 for (
size_t to_read = length;;) {
1879 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1880 if (m_cache.region.contains(m_offset)) {
1881 size_t remaining_cache =
static_cast<size_t>(m_cache.region.end - m_offset);
1882 if (to_read <= remaining_cache) {
1883 memcpy(data, m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), to_read);
1884 m_offset += to_read;
1885 m_state = state_t::ok;
1888 memcpy(data, m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
1889 reinterpret_cast<uint8_t*&
>(data) += remaining_cache;
1890 to_read -= remaining_cache;
1891 m_offset += remaining_cache;
1894 if (!
ok()) _Unlikely_ {
1895 if (to_read < length)
1896 m_state = state_t::ok;
1897 return length - to_read;
1901 fpos_t end_max = m_offset + to_read;
1902 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1904 m_source->seekbeg(m_offset);
1905 if (!m_source->ok()) _Unlikely_ {
1906 m_state = to_read < length ? state_t::ok : state_t::fail;
1907 return length - to_read;
1909 size_t num_read = m_source->read(data, to_read -
static_cast<size_t>(end_max % m_cache.capacity));
1910 m_offset += num_read;
1911 to_read -= num_read;
1913 m_state = state_t::ok;
1916 reinterpret_cast<uint8_t*&
>(data) += num_read;
1917 m_state = m_source->state();
1919 if (to_read < length)
1920 m_state = state_t::ok;
1921 return length - to_read;
1925 load_cache(m_offset);
1926 if (!
ok()) _Unlikely_ {
1927 m_state = to_read < length ? state_t::ok : state_t::fail;
1928 return length - to_read;
1930 if (m_cache.region.end <= m_offset) _Unlikely_ {
1931 m_state = to_read < length ? state_t::ok : state_t::eof;
1932 return length - to_read;
1937 virtual _Success_(
return != 0) size_t
write(
1938 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1940 _Assume_(data || !length);
1941#if SET_FILE_OP_TIMES
1942 m_atime = m_mtime = time_point::now();
1944 for (
size_t to_write = length;;) {
1945 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1946 fpos_t end_max = m_cache.region.start + m_cache.capacity;
1947 if (m_cache.region.start <= m_offset && m_offset < end_max) {
1948 size_t remaining_cache =
static_cast<size_t>(end_max - m_offset);
1949 if (to_write <= remaining_cache) {
1950 memcpy(m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
1951 m_offset += to_write;
1952 m_cache.status = cache_t::cache_t::status_t::dirty;
1953 m_cache.region.end = std::max(m_cache.region.end, m_offset);
1954 m_state = state_t::ok;
1957 memcpy(m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
1958 reinterpret_cast<const uint8_t*&
>(data) += remaining_cache;
1959 to_write -= remaining_cache;
1960 m_offset += remaining_cache;
1961 m_cache.status = cache_t::cache_t::status_t::dirty;
1962 m_cache.region.end = end_max;
1965 if (!
ok()) _Unlikely_
1966 return length - to_write;
1969 fpos_t end_max = m_offset + to_write;
1970 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1972 m_source->seekbeg(m_offset);
1973 if (!
ok()) _Unlikely_
1974 return length - to_write;
1975 size_t num_written = m_source->write(data, to_write -
static_cast<size_t>(end_max % m_cache.capacity));
1976 m_offset += num_written;
1977 m_state = m_source->state();
1978 to_write -= num_written;
1979 if (!to_write || !
ok())
1980 return length - to_write;
1981 reinterpret_cast<const uint8_t*&
>(data) += num_written;
1984 load_cache(m_offset);
1985 if (!
ok()) _Unlikely_
1986 return length - to_write;
1993 if (!
ok()) _Unlikely_
1994 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1996 m_state = m_source->state();
2001#if SET_FILE_OP_TIMES
2002 m_atime = m_mtime = time_point::min();
2005 if (!
ok()) _Unlikely_
2010 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
2012 m_state = state_t::ok;
2017 offset =
static_cast<foff_t
>(m_offset) + offset;
2021 if (n == fsize_max) _Unlikely_{
2022 m_state = state_t::fail;
2025 offset =
static_cast<foff_t
>(n) + offset;
2029 throw std::invalid_argument(
"unknown seek origin");
2031 if (offset < 0) _Unlikely_
2032 throw std::invalid_argument(
"negative file offset");
2033 return m_offset =
static_cast<fpos_t
>(offset);
2041 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
2043 m_source->lock(offset, length);
2044 m_state = m_source->state();
2047 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
2049 m_source->unlock(offset, length);
2050 m_state = m_source->state();
2055 return m_cache.status != cache_t::cache_t::status_t::empty ?
2056 std::max(m_source->size(), m_cache.region.end) :
2062#if SET_FILE_OP_TIMES
2063 m_atime = m_mtime = time_point::now();
2065 m_source->seekbeg(m_offset);
2066 if (m_cache.region.end <= m_offset) {
2069 else if (m_cache.region.start <= m_offset) {
2071 m_cache.region.end = m_offset;
2075 m_cache.status = cache_t::cache_t::status_t::empty;
2077 m_source->truncate();
2078 m_state = m_source->state();
2083 return m_source->ctime();
2088#if SET_FILE_OP_TIMES
2089 return std::max(m_atime, m_source->atime());
2091 return m_source->atime();
2097#if SET_FILE_OP_TIMES
2098 return std::max(m_mtime, m_source->mtime());
2100 return m_source->mtime();
2106 m_source->set_ctime(date);
2111#if SET_FILE_OP_TIMES
2114 m_source->set_atime(date);
2119#if SET_FILE_OP_TIMES
2122 m_source->set_mtime(date);
2129 if (m_cache.status != cache_t::cache_t::status_t::dirty)
2130 m_state = state_t::ok;
2131 else if (!m_cache.region.empty()) {
2134 m_cache.status = cache_t::cache_t::status_t::loaded;
2137 m_state = state_t::ok;
2138 m_cache.status = cache_t::cache_t::status_t::loaded;
2142 void invalidate_cache()
2144 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
2146 if (!
ok()) _Unlikely_
2149 m_state = state_t::ok;
2150 m_cache.status = cache_t::cache_t::status_t::empty;
2153 void load_cache(_In_ fpos_t start)
2155 _Assume_(m_cache.status != cache_t::cache_t::status_t::dirty);
2156 start -= start % m_cache.capacity;
2157 m_source->seekbeg(m_cache.region.start = start);
2158 if (m_source->ok()) {
2159 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
2160 m_cache.status = cache_t::cache_t::status_t::loaded;
2161 m_state = state_t::ok;
2164 m_state = state_t::fail;
2169 _Assume_(m_cache.status == cache_t::cache_t::status_t::dirty);
2170 m_source->seekbeg(m_cache.region.start);
2171 m_source->write(m_cache.data,
static_cast<size_t>(m_cache.region.size()));
2172 m_state = m_source->state();
2175 basic_file* m_source;
2179 enum class status_t {
2184 interval<fpos_t> region;
2186 cache_t(_In_
size_t _capacity) :
2187 data(new uint8_t[_capacity]),
2188 capacity(_capacity),
2189 status(status_t::empty),
2199#if SET_FILE_OP_TIMES
2213 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok) :
2218 virtual _Success_(
return != 0 || length == 0) size_t
read(
2219 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2221 _Assume_(data || !length);
2227 block_size = 0x1F80000;
2228#elif defined(_WIN32)
2229 block_size = 0x3f00000;
2231 block_size = SSIZE_MAX;
2233 for (
size_t to_read = length;;) {
2238 __try { succeeded = ReadFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_read, block_size)), &num_read,
nullptr); }
2239 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
2240 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
2243 block_size = default_block_size;
2246 if (!succeeded) _Unlikely_
2248 auto num_read =
::read(m_h, data, std::min<size_t>(to_read, block_size));
2249 if (num_read < 0) _Unlikely_
2252 m_state = to_read < length ? state_t::ok : state_t::fail;
2253 return length - to_read;
2255 if (!num_read) _Unlikely_ {
2256 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2257 return length - to_read;
2259 to_read -=
static_cast<size_t>(num_read);
2261 m_state = state_t::ok;
2264 reinterpret_cast<uint8_t*&
>(data) += num_read;
2268 virtual _Success_(
return != 0) size_t
write(
2269 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2276 block_size = 0x1F80000;
2277#elif defined(_WIN32)
2278 block_size = 0x3f00000;
2280 block_size = SSIZE_MAX;
2282 for (
size_t to_write = length;;) {
2287 __try { succeeded = WriteFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_write, block_size)), &num_written,
nullptr); }
2288 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
2289 to_write -= num_written;
2291 m_state = state_t::ok;
2294 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2295 if (!succeeded) _Unlikely_ {
2296 m_state = state_t::fail;
2297 return length - to_write;
2300 auto num_written =
::write(m_h, data, std::min<size_t>(to_write, block_size));
2301 if (num_written < 0) _Unlikely_ {
2302 m_state = state_t::fail;
2303 return length - to_write;
2305 to_write -=
static_cast<size_t>(num_written);
2307 m_state = state_t::ok;
2310 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2319 m_state = state_t::ok;
2322 m_state = state_t::fail;
2329 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
2331 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
2342 buffered_sys(_In_opt_ sys_handle h = invalid_handle,
size_t read_buffer_size = default_buffer_size,
size_t write_buffer_size = default_buffer_size) :
2343 buffer(read_buffer_size, write_buffer_size),
2364 socket(_In_opt_ socket_t h = invalid_socket, _In_ state_t
state = state_t::ok) :
2374 socket(_Inout_
socket&& other) noexcept : m_h(other.m_h)
2376 other.m_h = invalid_socket;
2381 if (
this != std::addressof(other)) {
2382 if (m_h != invalid_socket)
2385 other.m_h = invalid_socket;
2397 socket(_In_
int af, _In_
int type, _In_
int protocol)
2399 m_h = ::socket(af, type, protocol);
2400 if (m_h == invalid_socket) _Unlikely_
2401 m_state = state_t::fail;
2406 if (m_h != invalid_socket)
2413 operator bool() const noexcept {
return m_h != invalid_socket; }
2418 socket_t
get() const noexcept {
return m_h; }
2420 virtual _Success_(
return != 0 || length == 0) size_t
read(
2421 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2423 _Assume_(data || !length);
2424 constexpr int block_size = 0x10000000;
2425 for (
size_t to_read = length;;) {
2426 auto num_read = recv(m_h,
reinterpret_cast<char*
>(data),
2428 static_cast<int>(std::min<size_t>(to_read, block_size)),
2430 std::min<size_t>(to_read, block_size),
2433 if (num_read < 0) _Unlikely_ {
2434 m_state = to_read < length ? state_t::ok : state_t::fail;
2435 return length - to_read;
2438 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2439 return length - to_read;
2441 to_read -=
static_cast<size_t>(num_read);
2443 m_state = state_t::ok;
2446 reinterpret_cast<uint8_t*&
>(data) += num_read;
2450 virtual _Success_(
return != 0) size_t
write(
2451 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2453 _Assume_(data || !length);
2454 constexpr int block_size = 0x10000000;
2455 for (
size_t to_write = length;;) {
2456 auto num_written = send(m_h,
reinterpret_cast<const char*
>(data),
2458 static_cast<int>(std::min<size_t>(to_write, block_size)),
2460 std::min<size_t>(to_write, block_size),
2463 if (num_written < 0) _Unlikely_ {
2464 m_state = state_t::fail;
2465 return length - to_write;
2467 to_write -=
static_cast<size_t>(num_written);
2469 m_state = state_t::ok;
2472 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2478 if (m_h != invalid_socket) {
2480 m_h = invalid_socket;
2482 m_state = state_t::ok;
2493 class sequential_stream :
public basic
2496 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
2501 virtual ~sequential_stream()
2503 m_source->Release();
2506 virtual _Success_(
return != 0 || length == 0) size_t read(
2507 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2509 _Assume_(data || !length);
2510 for (
size_t to_read = length;;) {
2513 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
2514 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2515 if (FAILED(hr)) _Unlikely_ {
2516 m_state = to_read < length ? state_t::ok : state_t::fail;
2517 return length - to_read;
2519 to_read -= num_read;
2520 if (hr == S_FALSE) _Unlikely_ {
2521 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2522 return length - to_read;
2525 m_state = state_t::ok;
2528 reinterpret_cast<uint8_t*&
>(data) += num_read;
2532 virtual _Success_(
return != 0) size_t write(
2533 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2535 _Assume_(data || !length);
2536 for (
size_t to_write = length;;) {
2538 ULONG num_written = 0;
2539 __try { hr = m_source->Write(data,
static_cast<ULONG
>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
2540 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2543 if (FAILED(hr)) _Unlikely_ {
2544 m_state = state_t::fail;
2545 return length - to_write;
2547 to_write -= num_written;
2549 m_state = state_t::ok;
2552 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2557 ISequentialStream* m_source;
2563 class asp :
public basic
2566 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
2568 m_response(response)
2571 m_request->AddRef();
2573 m_response->AddRef();
2579 m_request->Release();
2581 m_response->Release();
2584 virtual _Success_(
return != 0 || length == 0) size_t read(
2585 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2587 _Assume_(data || !length);
2588 if (!m_request) _Unlikely_ {
2589 m_state = state_t::fail;
2592 for (
size_t to_read = length;;) {
2593 VARIANT var_amount, var_data;
2594 V_VT(&var_amount) = VT_I4;
2595 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
2596 V_VT(&var_data) = VT_EMPTY;
2597 HRESULT hr = [&]() {
2598 __try {
return m_request->BinaryRead(&var_amount, &var_data); }
2599 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2601 if (FAILED(hr)) _Unlikely_ {
2602 m_state = to_read < length ? state_t::ok : state_t::fail;
2603 return length - to_read;
2605 _Assume_(V_VT(&var_amount) == VT_I4);
2606 _Assume_(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
2607 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
2608 if (!V_I4(&var_amount)) _Unlikely_ {
2609 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2610 return length - to_read;
2612 safearray_accessor<uint8_t> a(sa.get());
2613 memcpy(data, a.data(), V_I4(&var_amount));
2614 to_read -= V_I4(&var_amount);
2616 m_state = state_t::ok;
2619 reinterpret_cast<uint8_t*&
>(data) += V_I4(&var_amount);
2623 virtual _Success_(
return != 0) size_t write(
2624 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2627 m_state = state_t::fail;
2630 for (
size_t to_write = length;;) {
2631 UINT num_written =
static_cast<UINT
>(std::min<size_t>(to_write, UINT_MAX));
2632 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(
reinterpret_cast<LPCSTR
>(data), num_written));
2634 V_VT(&var_data) = VT_BSTR;
2635 V_BSTR(&var_data) = bstr_data.get();
2636 HRESULT hr = [&]() {
2637 __try {
return m_response->BinaryWrite(var_data); }
2638 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2640 if (FAILED(hr)) _Unlikely_ {
2641 m_state = state_t::fail;
2642 return length - to_write;
2644 to_write -= num_written;
2646 m_state = state_t::ok;
2649 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2653 virtual void close()
2656 __try { m_response->End(); }
2657 __except (EXCEPTION_EXECUTE_HANDLER) {}
2659 m_state = state_t::ok;
2662 virtual void flush()
2666 __try { hr = m_response->Flush(); }
2667 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2668 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
2673 IRequest* m_request;
2674 IResponse* m_response;
2683 mode_for_reading = 1 << 0,
2684 mode_for_writing = 1 << 1,
2685 mode_for_chmod = 1 << 2,
2687 mode_open_existing = 0 << 3,
2688 mode_truncate_existing = 1 << 3,
2689 mode_preserve_existing = 2 << 3,
2690 mode_create_new = 3 << 3,
2691 mode_create = 4 << 3,
2692 mode_disposition_mask = 7 << 3,
2694 mode_append = 1 << 6,
2696 mode_binary = 1 << 7,
2699 share_reading = 1 << 8,
2700 share_writing = 1 << 9,
2701 share_deleting = 1 << 10,
2702 share_all = share_reading | share_writing | share_deleting,
2704 inherit_handle = 1 << 11,
2706 hint_write_thru = 1 << 12,
2707 hint_no_buffering = 1 << 13,
2708 hint_random_access = 1 << 14,
2709 hint_sequential_access = 1 << 15,
2712#pragma warning(push)
2713#pragma warning(disable: 4250)
2728 file(_In_z_
const schar_t* filename, _In_
int mode)
2730 open(filename, mode);
2739 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
2740 file(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode) :
file(filename.c_str(), mode) {}
2748 void open(_In_z_
const schar_t* filename, _In_
int mode)
2750 if (m_h != invalid_handle)
2754 DWORD dwDesiredAccess = 0;
2755 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
2756 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
2757 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
2759 DWORD dwShareMode = 0;
2760 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
2761 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
2762 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
2764 SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES) };
2765 sa.bInheritHandle = mode & inherit_handle ? true :
false;
2767 DWORD dwCreationDisposition;
2768 switch (mode & mode_disposition_mask) {
2769 case mode_open_existing: dwCreationDisposition = OPEN_EXISTING;
break;
2770 case mode_truncate_existing: dwCreationDisposition = TRUNCATE_EXISTING;
break;
2771 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS;
break;
2772 case mode_create_new: dwCreationDisposition = CREATE_NEW;
break;
2773 case mode_create: dwCreationDisposition = CREATE_ALWAYS;
break;
2774 default:
throw std::invalid_argument(
"invalid mode");
2777 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
2778 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
2779 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
2780 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
2781 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
2783 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, NULL);
2786 switch (mode & (mode_for_reading | mode_for_writing)) {
2787 case mode_for_reading: flags |= O_RDONLY;
break;
2788 case mode_for_writing: flags |= O_WRONLY;
break;
2789 case mode_for_reading | mode_for_writing: flags |= O_RDWR;
break;
2791 switch (mode & mode_disposition_mask) {
2792 case mode_open_existing:
break;
2793 case mode_truncate_existing: flags |= O_TRUNC;
break;
2794 case mode_preserve_existing: flags |= O_CREAT;
break;
2795 case mode_create_new: flags |= O_CREAT | O_EXCL;
break;
2796 case mode_create: flags |= O_CREAT | O_TRUNC;
break;
2797 default:
throw std::invalid_argument(
"invalid mode");
2799 if (mode & hint_write_thru) flags |= O_DSYNC;
2801 if (mode & hint_no_buffering) flags |= O_RSYNC;
2804 m_h =
::open(filename, flags, DEFFILEMODE);
2806 if (m_h != invalid_handle) {
2807 m_state = state_t::ok;
2808 if (mode & mode_append)
2809 seek(0, seek_t::end);
2812 m_state = state_t::fail;
2821 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
2822 void open(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode)
2824 open(filename.c_str(), mode);
2827 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
2831 li.QuadPart = offset;
2832 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart,
static_cast<DWORD
>(how));
2833 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
2834 m_state = state_t::ok;
2838 off64_t result = lseek64(m_h, offset,
static_cast<int>(how));
2840 m_state = state_t::ok;
2841 return static_cast<fpos_t
>(result);
2844 m_state = state_t::fail;
2850 if (m_h != invalid_handle) {
2854 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
2855 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
2858 off64_t result = lseek64(m_h, 0, SEEK_CUR);
2860 return static_cast<fpos_t
>(result);
2866 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
2869 LARGE_INTEGER liOffset;
2870 LARGE_INTEGER liSize;
2871 liOffset.QuadPart = offset;
2872 liSize.QuadPart = length;
2873 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2874 m_state = state_t::ok;
2878 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2880 if (offset > std::numeric_limits<off64_t>::max())
2881 throw std::invalid_argument(
"file offset too big");
2882 if (length > std::numeric_limits<off64_t>::max())
2883 throw std::invalid_argument(
"file section length too big");
2884 m_state = lseek64(m_h,
static_cast<off64_t
>(offset), SEEK_SET) >= 0 && lockf64(m_h, F_LOCK,
static_cast<off64_t
>(length)) >= 0 ? state_t::ok : state_t::fail;
2885 lseek64(m_h, orig, SEEK_SET);
2886 m_state = state_t::ok;
2890 m_state = state_t::fail;
2893 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
2896 LARGE_INTEGER liOffset;
2897 LARGE_INTEGER liSize;
2898 liOffset.QuadPart = offset;
2899 liSize.QuadPart = length;
2900 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2901 m_state = state_t::ok;
2905 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2907 if (offset > std::numeric_limits<off64_t>::max())
2908 throw std::invalid_argument(
"file offset too big");
2909 if (length > std::numeric_limits<off64_t>::max())
2910 throw std::invalid_argument(
"file section length too big");
2911 if (lseek64(m_h,
static_cast<off64_t
>(offset), SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK,
static_cast<off64_t
>(length)) >= 0) {
2912 lseek64(m_h, orig, SEEK_SET);
2913 m_state = state_t::ok;
2916 lseek64(m_h, orig, SEEK_SET);
2919 m_state = state_t::fail;
2926 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
2927 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
2931 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2933 off64_t length = lseek64(m_h, 0, SEEK_END);
2934 lseek64(m_h, orig, SEEK_SET);
2936 return static_cast<fsize_t
>(length);
2945 if (SetEndOfFile(m_h)) {
2946 m_state = state_t::ok;
2950 off64_t length = lseek64(m_h, 0, SEEK_CUR);
2951 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
2952 m_state = state_t::ok;
2956 m_state = state_t::fail;
2960 static time_point ft2tp(_In_
const FILETIME& ft)
2963 uint64_t t = (
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
2965 uint64_t t = ((
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
2967 return time_point(time_point::duration(t));
2970 static void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
2973 uint64_t t = tp.time_since_epoch().count();
2975 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
2977 ft.dwHighDateTime =
static_cast<DWORD
>((t >> 32) & 0xffffffff);
2978 ft.dwLowDateTime =
static_cast<DWORD
>(t & 0xffffffff);
2986 if (GetFileTime(m_h, &ft,
nullptr,
nullptr))
2989 return time_point::min();
2996 if (GetFileTime(m_h,
nullptr, &ft,
nullptr))
3000 if (fstat(m_h, &buf) >= 0)
3001 return clock::from_time_t(buf.st_atime);
3003 return time_point::min();
3010 if (GetFileTime(m_h,
nullptr,
nullptr, &ft))
3014 if (fstat(m_h, &buf) >= 0)
3015 return clock::from_time_t(buf.st_mtime);
3017 return time_point::min();
3022 _Assume_(m_h != invalid_handle);
3026 if (SetFileTime(m_h, &ft,
nullptr,
nullptr))
3028 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
3030 _Unreferenced_(date);
3031 throw std::runtime_error(
"not supported");
3037 _Assume_(m_h != invalid_handle);
3041 if (SetFileTime(m_h,
nullptr, &ft,
nullptr))
3043 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
3045 struct timespec ts[2] = {
3046 { date.time_since_epoch().count(), 0 },
3049 if (futimens(m_h, ts) >= 0)
3051 throw std::system_error(errno, std::system_category(),
"futimens failed");
3060 if (SetFileTime(m_h,
nullptr,
nullptr, &ft))
3062 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
3064 struct timespec ts[2] = {
3066 { date.time_since_epoch().count(), 0 },
3068 if (futimens(m_h, ts) >= 0)
3070 throw std::system_error(errno, std::system_category(),
"futimens failed");
3079 static bool exists(_In_z_
const stdex::schar_t* filename)
3082 return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
3085 return stat(filename, &s) == 0;
3094 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3095 static bool exists(_In_
const std::basic_string<TR, AX>& filename)
3097 return exists(filename.c_str());
3107 static bool readonly(_In_z_
const stdex::schar_t* filename)
3110 DWORD dwAttr = GetFileAttributes(filename);
3111 return dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_READONLY) != 0;
3114 return stat(filename, &s) == 0 && (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0;
3125 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3126 static bool readonly(_In_
const std::basic_string<TR, AX>& filename)
3139 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok, _In_
size_t cache_size = default_cache_size) :
3153 cached_file(_In_z_
const schar_t* filename, _In_
int mode, _In_
size_t cache_size = default_cache_size) :
3155 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
3167 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3168 cached_file(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode, _In_
size_t cache_size = default_cache_size) :
cached_file(filename.c_str(), mode, cache_size) {}
3181 void open(_In_z_
const schar_t* filename, _In_
int mode)
3184 if (!
ok()) _Unlikely_{
3185 m_state = state_t::fail;
3188 m_source.
open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
3189 if (m_source.
ok()) {
3193 m_state = state_t::fail;
3202 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3203 void open(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode)
3205 open(filename.c_str(), mode);
3211 operator bool() const noexcept {
return m_source; }
3231#if SET_FILE_OP_TIMES
3232 m_ctime = m_atime = m_mtime = time_point::now();
3244 m_data(reinterpret_cast<uint8_t*>(malloc(
size))),
3251 m_state = state_t::fail;
3252 throw std::bad_alloc();
3254#if SET_FILE_OP_TIMES
3255 m_ctime = m_atime = m_mtime = time_point::now();
3277 _Assume_(reserved >=
size);
3278#if SET_FILE_OP_TIMES
3279 m_ctime = m_atime = m_mtime = time_point::now();
3303 load(filename, mode);
3312 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3322 m_data(reinterpret_cast<uint8_t*>(malloc(other.
m_size))),
3327#if SET_FILE_OP_TIMES
3328 , m_ctime(other.m_ctime)
3329 , m_atime(other.m_atime)
3330 , m_mtime(other.m_mtime)
3334 m_state = state_t::fail;
3335 throw std::bad_alloc();
3337 memcpy(
m_data, other.m_data, other.m_size);
3347 if (
this != std::addressof(other)) {
3351 m_data =
reinterpret_cast<uint8_t*
>(malloc(other.m_size));
3353 m_state = state_t::fail;
3354 throw std::bad_alloc();
3356 memcpy(
m_data, other.m_data, other.m_size);
3361#if SET_FILE_OP_TIMES
3362 m_ctime = other.m_ctime;
3363 m_atime = other.m_atime;
3364 m_mtime = other.m_mtime;
3382#if SET_FILE_OP_TIMES
3383 , m_ctime(other.m_ctime)
3384 , m_atime(other.m_atime)
3385 , m_mtime(other.m_mtime)
3388 other.m_state = state_t::ok;
3389 other.m_data =
nullptr;
3392 other.m_reserved = 0;
3393 other.m_manage =
true;
3394#if SET_FILE_OP_TIMES
3395 other.m_ctime = other.m_atime = other.m_mtime = time_point::now();
3406 if (
this != std::addressof(other)) {
3407 *
static_cast<basic_file*
>(
this) = std::move(other);
3411 other.m_data =
nullptr;
3417 other.m_reserved = 0;
3419 other.m_manage =
true;
3420#if SET_FILE_OP_TIMES
3421 m_ctime = other.m_ctime;
3422 m_atime = other.m_atime;
3423 m_mtime = other.m_mtime;
3424 other.m_ctime = other.m_atime = other.m_mtime = time_point::now();
3442 void reserve(_In_
size_t required, _In_
bool tight =
false) noexcept
3445 m_state = state_t::ok;
3449 m_state = state_t::fail;
3452 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
3453 auto data =
reinterpret_cast<uint8_t*
>(realloc(
m_data, reserved));
3454 if (!
data && reserved) _Unlikely_ {
3455 m_state = state_t::fail;
3462 m_state = state_t::ok;
3471 void load(_In_z_
const schar_t* filename, _In_
int mode)
3473 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
3475 m_state = state_t::fail;
3479 if (
size > SIZE_MAX) {
3480 m_state = state_t::fail;
3484 if (!
ok()) _Unlikely_ {
3491#if SET_FILE_OP_TIMES
3492 m_ctime = f.
ctime();
3493 m_atime = f.
atime();
3494 m_mtime = f.
mtime();
3504 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3505 void load(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode)
3507 load(filename.c_str(), mode);
3516 void save(_In_z_
const schar_t* filename, _In_
int mode)
3518 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
3520 m_state = state_t::fail;
3525 m_state = state_t::fail;
3529#if SET_FILE_OP_TIMES
3542 template <
class TR = std::
char_traits<s
char_t>,
class AX = std::allocator<s
char_t>>
3543 void save(_In_
const std::basic_string<TR, AX>& filename, _In_
int mode)
3545 save(filename.c_str(), mode);
3553 virtual _Success_(
return != 0 || length == 0) size_t
read(
3554 _Out_writes_bytes_to_opt_(length, return)
void*
data, _In_
size_t length)
3556 _Assume_(
data || !length);
3557#if SET_FILE_OP_TIMES
3558 m_atime = time_point::now();
3561 if (length <= available) {
3564 m_state = state_t::ok;
3567 if (length && !available) {
3568 m_state = state_t::eof;
3573 m_state = state_t::ok;
3594#if SET_FILE_OP_TIMES
3595 m_atime = time_point::now();
3597 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
3601 size_t end_offset =
m_offset +
sizeof(T);
3602 if (end_offset <=
m_size) {
3605#if !CHECK_STREAM_STATE
3606 m_state = state_t::ok;
3612 m_state = state_t::eof;
3631 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3634#if SET_FILE_OP_TIMES
3635 m_atime = time_point::now();
3637 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
3641 size_t end_offset =
m_offset +
sizeof(uint32_t);
3642 if (end_offset <=
m_size) {
3643 uint32_t num_chars = LE2HE(*
reinterpret_cast<uint32_t*
>(
m_data +
m_offset));
3645 end_offset = stdex::add(
m_offset, stdex::mul(num_chars,
sizeof(T)));
3647 if (end_offset <=
m_size) {
3648 data.assign(start, start + num_chars);
3650#if !CHECK_STREAM_STATE
3651 m_state = state_t::ok;
3655 if (end_offset <=
m_size)
3659 m_state = state_t::eof;
3663 virtual _Success_(
return != 0) size_t
write(
3664 _In_reads_bytes_opt_(length) const
void*
data, _In_
size_t length)
3666 _Assume_(
data || !length);
3667#if SET_FILE_OP_TIMES
3668 m_atime = m_mtime = time_point::now();
3670 size_t end_offset =
m_offset + length;
3673 if (!
ok()) _Unlikely_
3680 m_state = state_t::ok;
3689#if SET_FILE_OP_TIMES
3690 m_atime = m_mtime = time_point::now();
3692 size_t end_offset =
m_offset + amount;
3695 if (!
ok()) _Unlikely_
3702 m_state = state_t::ok;
3722#if SET_FILE_OP_TIMES
3723 m_atime = m_mtime = time_point::now();
3725 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3727 size_t end_offset =
m_offset +
sizeof(T);
3730 if (!
ok()) _Unlikely_
3737#if !CHECK_STREAM_STATE
3738 m_state = state_t::ok;
3760#if SET_FILE_OP_TIMES
3761 m_atime = m_mtime = time_point::now();
3763 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3765 size_t num_chars = stdex::strlen(
data);
3766 if (num_chars > UINT32_MAX)
3767 throw std::invalid_argument(
"string too long");
3768 size_t size_chars = num_chars *
sizeof(T);
3769 size_t size =
sizeof(uint32_t) + size_chars;
3773 if (!
ok()) _Unlikely_
3777 *
reinterpret_cast<uint32_t*
>(p) = HE2LE((uint32_t)num_chars);
3778 memcpy(p +
sizeof(uint32_t),
data, size_chars);
3782#if !CHECK_STREAM_STATE
3783 m_state = state_t::ok;
3802 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3805#if SET_FILE_OP_TIMES
3806 m_atime = m_mtime = time_point::now();
3808 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3810 size_t num_chars =
data.size();
3811 if (num_chars > UINT32_MAX)
3812 throw std::invalid_argument(
"string too long");
3813 size_t size_chars = num_chars *
sizeof(T);
3814 size_t size =
sizeof(uint32_t) + size_chars;
3818 if (!
ok()) _Unlikely_
3822 *
reinterpret_cast<uint32_t*
>(p) = HE2LE((uint32_t)num_chars);
3823 memcpy(p +
sizeof(uint32_t),
data.data(), size_chars);
3827#if !CHECK_STREAM_STATE
3828 m_state = state_t::ok;
3840#if SET_FILE_OP_TIMES
3841 m_atime = m_mtime = time_point::now();
3844 size_t num_copied = 0, to_write = amount;
3845 m_state = state_t::ok;
3846 if (amount != SIZE_MAX) {
3847 dst_size = stdex::add(dst_size, amount);
3849 if (!
ok()) _Unlikely_
3852 num_read = stream.read(
m_data + dst_offset, to_write);
3853 dst_offset += num_read;
3854 num_copied += num_read;
3855 to_write -= num_read;
3857 if (stream.state() != state_t::eof)
3858 m_state = state_t::fail;
3866 block_size = std::min(to_write, default_block_size);
3867 dst_size = stdex::add(dst_size, block_size);
3869 if (!
ok()) _Unlikely_
3871 num_read = stream.read(
m_data + dst_offset, block_size);
3872 dst_size = dst_offset += num_read;
3873 num_copied += num_read;
3874 to_write -= num_read;
3876 if (stream.state() != state_t::eof)
3877 m_state = state_t::fail;
3896#if SET_FILE_OP_TIMES
3897 m_ctime = m_atime = m_mtime = time_point::min();
3899 m_state = state_t::ok;
3902 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
3905 case seek_t::beg:
break;
3906 case seek_t::cur: offset =
static_cast<foff_t
>(
m_offset) + offset;
break;
3907 case seek_t::end: offset =
static_cast<foff_t
>(
m_size) + offset;
break;
3908 default:
throw std::invalid_argument(
"unknown seek origin");
3910 if (offset < 0) _Unlikely_
3911 throw std::invalid_argument(
"negative file offset");
3912 if (
static_cast<fpos_t
>(offset) > SIZE_MAX) _Unlikely_
3913 throw std::invalid_argument(
"file offset too big");
3914 m_state = state_t::ok;
3915 return m_offset =
static_cast<size_t>(offset);
3930#if SET_FILE_OP_TIMES
3931 m_atime = m_mtime = time_point::now();
3937#if SET_FILE_OP_TIMES
3938 virtual time_point
ctime()
const
3943 virtual time_point
atime()
const
3948 virtual time_point
mtime()
const
3980#if SET_FILE_OP_TIMES
3981 m_atime = m_mtime = time_point::now();
3983 _Assume_(offset +
sizeof(T) <
m_size);
3984 (*
reinterpret_cast<T*
>(
m_data + offset)) = HE2LE(
data);
3988 void set(_In_ fpos_t offset, _In_
const int8_t
data) { set<int8_t>(offset,
data); }
3989 void set(_In_ fpos_t offset, _In_
const int16_t
data) { set<int16_t>(offset,
data); }
3990 void set(_In_ fpos_t offset, _In_
const int32_t
data) { set<int32_t>(offset,
data); }
3991 void set(_In_ fpos_t offset, _In_
const int64_t
data) { set<int64_t>(offset,
data); }
3992 void set(_In_ fpos_t offset, _In_
const uint8_t
data) { set<uint8_t>(offset,
data); }
3993 void set(_In_ fpos_t offset, _In_
const uint16_t
data) { set<uint16_t>(offset,
data); }
3994 void set(_In_ fpos_t offset, _In_
const uint32_t
data) { set<uint32_t>(offset,
data); }
3995 void set(_In_ fpos_t offset, _In_
const uint64_t
data) { set<uint64_t>(offset,
data); }
3996 void set(_In_ fpos_t offset, _In_
const float data) { set<float>(offset,
data); }
3997 void set(_In_ fpos_t offset, _In_
const double data) { set<double>(offset,
data); }
3998 void set(_In_ fpos_t offset, _In_
const char data) { set<char>(offset,
data); }
3999#ifdef _NATIVE_WCHAR_T_DEFINED
4000 void set(_In_ fpos_t offset, _In_
const wchar_t data) { set<wchar_t>(offset,
data); }
4014 _Assume_(offset +
sizeof(T) <
m_size);
4016#if SET_FILE_OP_TIMES
4017 m_atime = time_point::now();
4022 void get(_In_ fpos_t offset, _Out_ int8_t &
data) { get<int8_t>(offset,
data); }
4023 void get(_In_ fpos_t offset, _Out_ int16_t &
data) { get<int16_t>(offset,
data); }
4024 void get(_In_ fpos_t offset, _Out_ int32_t &
data) { get<int32_t>(offset,
data); }
4025 void get(_In_ fpos_t offset, _Out_ int64_t &
data) { get<int64_t>(offset,
data); }
4026 void get(_In_ fpos_t offset, _Out_ uint8_t &
data) { get<uint8_t>(offset,
data); }
4027 void get(_In_ fpos_t offset, _Out_ uint16_t &
data) { get<uint16_t>(offset,
data); }
4028 void get(_In_ fpos_t offset, _Out_ uint32_t &
data) { get<uint32_t>(offset,
data); }
4029 void get(_In_ fpos_t offset, _Out_ uint64_t &
data) { get<uint64_t>(offset,
data); }
4030 void get(_In_ fpos_t offset, _Out_
float&
data) { get<float>(offset,
data); }
4031 void get(_In_ fpos_t offset, _Out_
double&
data) { get<double>(offset,
data); }
4032 void get(_In_ fpos_t offset, _Out_
char&
data) { get<char>(offset,
data); }
4033#ifdef _NATIVE_WCHAR_T_DEFINED
4034 void get(_In_ fpos_t offset, _Out_
wchar_t&
data) { get<wchar_t>(offset,
data); }
4059#ifdef _NATIVE_WCHAR_T_DEFINED
4063 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
4064 memory_file& operator >>(_Out_ std::basic_string<T, TR, AX>&
data) {
return read_str(
data); }
4067 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
4068 memory_file& operator <<(_In_
const std::basic_string<T, TR, AX>&
data) {
return write_str(
data); }
4076#if SET_FILE_OP_TIMES
4105#pragma warning(suppress: 6101)
4106 virtual _Success_(
return != 0 || length == 0) size_t
read(
4107 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
4109 _Assume_(data || !length);
4110 for (
size_t to_read = length;;) {
4111 if (!m_head) _Unlikely_ {
4112 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
4113 return length - to_read;
4115 size_t remaining = m_head->size - m_offset;
4116 if (remaining > to_read) {
4117 memcpy(data, m_head->data + m_offset, to_read);
4118 m_offset += to_read;
4120 m_state = state_t::ok;
4123 memcpy(data, m_head->data + m_offset, remaining);
4125 m_size -= remaining;
4126 reinterpret_cast<uint8_t*&
>(data) += remaining;
4127 to_read -= remaining;
4134 virtual _Success_(
return != 0) size_t
write(
4135 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
4137 _Assume_(data || !length);
4139 std::unique_ptr<node_t> n(
reinterpret_cast<node_t*
>(
new uint8_t[
sizeof(
node_t) + length]));
4142 memcpy(n->data, data, length);
4145 m_tail = m_tail->next = n.release();
4147 m_head = m_tail = n.release();
4148 m_state = state_t::ok;
4151 catch (
const std::bad_alloc&) {
4152 m_state = state_t::fail;
4159 m_size = m_offset = 0;
4165 m_state = state_t::ok;
4171 size_t size()
const {
return m_size; };
4174 size_t m_offset, m_size;
4178#pragma warning(suppress:4200)
4180 } *m_head, * m_tail;
4189 basic(num_files ? files[0]->
state() : state_t::fail),
4190 m_files(files, files + num_files)
4193 virtual _Success_(
return != 0 || length == 0) size_t
read(
4194 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
4196 _Assume_(data || !length);
4197 if (m_files.empty()) {
4198 m_state = state_t::fail;
4201 size_t result = m_files[0]->read(data, length);
4202 _Assume_(result <= length);
4203 m_state = m_files[0]->state();
4204 if (length > m_tmp.size())
4205 m_tmp.resize(length);
4206 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4207 if (m_files[i]->
read(m_tmp.data(), length) != result ||
4208 memcmp(m_tmp.data(), data, result))
4209 throw std::runtime_error(
"read mismatch");
4210 if (m_files[i]->
state() != m_state)
4211 throw std::runtime_error(
"state mismatch");
4216 virtual _Success_(
return != 0) size_t
write(
4217 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
4219 if (m_files.empty()) {
4220 m_state = state_t::fail;
4223 size_t result = m_files[0]->write(data, length);
4224 m_state = m_files[0]->state();
4225 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4226 if (m_files[i]->
write(data, length) != result)
4227 throw std::runtime_error(
"write mismatch");
4228 if (m_files[i]->
state() != m_state)
4229 throw std::runtime_error(
"state mismatch");
4236 if (m_files.empty()) {
4237 m_state = state_t::ok;
4240 m_files[0]->flush();
4241 m_state = m_files[0]->state();
4242 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4243 m_files[i]->flush();
4244 if (m_files[i]->
state() != m_state)
4245 throw std::runtime_error(
"state mismatch");
4251 if (m_files.empty()) {
4252 m_state = state_t::ok;
4255 m_files[0]->close();
4256 m_state = m_files[0]->state();
4257 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4258 m_files[i]->close();
4259 if (m_files[i]->
state() != m_state)
4260 throw std::runtime_error(
"state mismatch");
4263 m_tmp.shrink_to_fit();
4266 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
4268 if (m_files.empty()) {
4269 m_state = state_t::fail;
4272 fpos_t result = m_files[0]->seek(offset, how);
4273 m_state = m_files[0]->state();
4274 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4275 if (m_files[i]->
seek(offset, how) != result)
4276 throw std::runtime_error(
"seek mismatch");
4277 if (m_files[i]->
state() != m_state)
4278 throw std::runtime_error(
"state mismatch");
4285 if (m_files.empty())
4287 fpos_t result = m_files[0]->tell();
4288 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4289 if (m_files[i]->
tell() != result)
4290 throw std::runtime_error(
"tell mismatch");
4295 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
4297 if (m_files.empty())
4298 m_state = state_t::fail;
4299 m_files[0]->lock(offset, length);
4300 m_state = m_files[0]->state();
4301 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4302 m_files[i]->lock(offset, length);
4303 if (m_files[i]->
state() != m_state)
4304 throw std::runtime_error(
"state mismatch");
4308 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
4310 if (m_files.empty())
4311 m_state = state_t::fail;
4312 m_files[0]->unlock(offset, length);
4313 m_state = m_files[0]->state();
4314 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4315 m_files[i]->unlock(offset, length);
4316 if (m_files[i]->
state() != m_state)
4317 throw std::runtime_error(
"state mismatch");
4323 if (m_files.empty())
4325 fsize_t result = m_files[0]->size();
4326 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4327 if (m_files[i]->
size() != result)
4328 throw std::runtime_error(
"size mismatch");
4335 if (m_files.empty())
4336 m_state = state_t::fail;
4337 m_files[0]->truncate();
4338 m_state = m_files[0]->state();
4339 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4340 m_files[i]->truncate();
4341 if (m_files[i]->
state() != m_state)
4342 throw std::runtime_error(
"state mismatch");
4347 std::vector<basic_file*> m_files;
4348 std::vector<uint8_t> m_tmp;
4353#if defined(__GNUC__)
4354#pragma GCC diagnostic pop
Encoding converter context.
Definition unicode.hpp:138
locale_t helper class to free_locale when going out of scope.
Definition locale.hpp:74
Provides read-ahead stream capability.
Definition stream.hpp:1256
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1270
Provides write-back stream capability.
Definition stream.hpp:1323
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1336
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1360
Basic seekable stream operations.
Definition stream.hpp:817
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:863
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:912
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:881
virtual void truncate()=0
Sets file size - truncates the remainder of file content from the current file position to the end of...
virtual fsize_t size() const =0
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
charset_id read_charset(charset_id default_charset=charset_id::system)
Attempts to detect textfile charset based on UTF-32, UTF-16 or UTF-8 BOM.
Definition stream.hpp:987
fpos_t seekbeg(fpos_t offset)
Seeks to absolute file position.
Definition stream.hpp:844
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:819
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:954
fpos_t seekcur(foff_t offset)
Seeks to relative from current file position.
Definition stream.hpp:854
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:920
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:936
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:891
virtual fpos_t tell() const =0
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:928
fpos_t seekend(foff_t offset)
Seeks to relative from end file position.
Definition stream.hpp:861
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:945
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)=0
Seeks to specified relative file position.
OS data stream (file, pipe, socket...)
Definition stream.hpp:2211
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:2268
virtual void flush()
Persists volatile element data.
Definition stream.hpp:2326
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:2218
virtual void close()
Closes the stream.
Definition stream.hpp:2315
UTF-8 byte-order-mark
Definition stream.hpp:84
size_t write_array(const T_from *str, charset_encoder< T_from, T_to > &encoder)
Writes array of characters to the stream.
Definition stream.hpp:407
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:180
size_t readln_and_attach(std::basic_string< T, TR, AX > &str)
Reads stream to the end-of-line or end-of-file and append to str.
Definition stream.hpp:339
size_t write_vsprintf(_Printf_format_string_params_(2) const char *format, locale_t locale, va_list params)
Writes formatted string to the stream.
Definition stream.hpp:630
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:175
size_t write_sprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale,...)
Writes formatted string to the stream.
Definition stream.hpp:616
size_t write_vsprintf(_Printf_format_string_params_(2) const wchar_t *format, locale_t locale, va_list params)
Writes formatted string to the stream.
Definition stream.hpp:643
virtual void flush()
Persists volatile element data.
Definition stream.hpp:131
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:147
virtual void close()
Closes the stream.
Definition stream.hpp:139
uint8_t read_byte()
Reads one byte of data.
Definition stream.hpp:215
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:189
size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
Writes formatted string to the stream.
Definition stream.hpp:602
size_t readln(std::basic_string< T_to, TR, AX > &str, charset_encoder< T_from, T_to > &encoder)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:323
size_t read_array(_Out_writes_bytes_(size *count) void *array, size_t size, size_t count)
Reads an array of data from the stream.
Definition stream.hpp:375
size_t readln(std::basic_string< T, TR, AX > &str)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:311
basic & read_str(std::basic_string< T, TR, AX > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:470
basic & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:502
size_t readln_and_attach(std::basic_string< T_to, TR, AX > &str, charset_encoder< T_from, T_to > &encoder)
Reads stream to the end-of-line or end-of-file and append to str.
Definition stream.hpp:360
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:101
void write_charset(charset_id charset)
Writes UTF8, UTF-16 or UTF-32 byte-order-mark.
Definition stream.hpp:587
basic & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:292
fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
Writes content of another stream.
Definition stream.hpp:562
size_t write_array(const std::basic_string< T_from, TR, AX > &str, charset_encoder< T_from, T_to > &encoder)
Writes array of characters to the stream.
Definition stream.hpp:448
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:119
basic & write_str(const std::basic_string< T, TR, AX > &data)
Writes string to the stream length-prefixed.
Definition stream.hpp:527
size_t write_array(_In_reads_or_z_opt_(num_chars) const T_from *str, size_t num_chars, charset_encoder< T_from, T_to > &encoder)
Writes array of characters to the stream.
Definition stream.hpp:428
size_t write_array(_In_reads_bytes_opt_(size *count) const void *array, size_t size, size_t count)
Writes an array of data to the stream.
Definition stream.hpp:393
void write_byte(uint8_t byte, fsize_t amount=1)
Writes a byte of data.
Definition stream.hpp:226
basic & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:264
Buffered read/write stream.
Definition stream.hpp:1394
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1503
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1424
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1460
Buffered OS data stream (file, pipe, socket...)
Definition stream.hpp:2340
Cached file.
Definition stream.hpp:1804
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2081
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2060
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1871
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2086
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2047
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2095
virtual void close()
Closes the stream.
Definition stream.hpp:1990
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:2117
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2041
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1999
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1937
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:2053
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2104
virtual fpos_t tell() const
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
Definition stream.hpp:2036
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2109
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2010
Cached file-system file.
Definition stream.hpp:3137
void open(const std::basic_string< TR, AX > &filename, int mode)
Opens file.
Definition stream.hpp:3203
void open(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:3181
cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:3153
cached_file(const std::basic_string< TR, AX > &filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:3168
Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
Definition stream.hpp:1022
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1073
virtual void close()
Closes the stream.
Definition stream.hpp:1067
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1051
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1059
Compares multiple files to perform the same.
Definition stream.hpp:4186
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:4333
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:4216
virtual void close()
Closes the stream.
Definition stream.hpp:4249
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:4321
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:4295
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:4308
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:4266
virtual fpos_t tell() const
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
Definition stream.hpp:4283
virtual void flush()
Persists volatile element data.
Definition stream.hpp:4234
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:4193
In-memory FIFO queue.
Definition stream.hpp:4087
virtual void close()
Closes the stream.
Definition stream.hpp:4157
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:4134
size_t size() const
Returns total size of pending data in the queue.
Definition stream.hpp:4171
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:4106
Limits file reading/writing to a predefined window.
Definition stream.hpp:1694
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1787
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1737
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:1750
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1743
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1717
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1762
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1703
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1772
virtual fpos_t tell() const
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
Definition stream.hpp:1756
virtual void close()
Closes the stream.
Definition stream.hpp:1731
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:1782
File-system file.
Definition stream.hpp:2718
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:2922
static bool readonly(const std::basic_string< TR, AX > &filename)
Checks if file/folder/symlink is read-only.
Definition stream.hpp:3126
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:3006
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2893
file(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:2728
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:3020
static bool readonly(const stdex::schar_t *filename)
Checks if file/folder/symlink is read-only.
Definition stream.hpp:3107
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2992
static bool exists(const std::basic_string< TR, AX > &filename)
Checks if file/folder/symlink likely exists.
Definition stream.hpp:3095
void open(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:2748
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:3055
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:3035
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2866
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2942
void open(const std::basic_string< TR, AX > &filename, int mode)
Opens file.
Definition stream.hpp:2822
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2982
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2827
virtual fpos_t tell() const
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
Definition stream.hpp:2848
file(const std::basic_string< TR, AX > &filename, int mode)
Opens file.
Definition stream.hpp:2740
static bool exists(const stdex::schar_t *filename)
Checks if file/folder/symlink likely exists.
Definition stream.hpp:3079
Limits reading from/writing to stream to a predefined number of bytes.
Definition stream.hpp:1551
fsize_t read_limit
Number of bytes left that may be read from the stream.
Definition stream.hpp:1603
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1559
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1580
fsize_t write_limit
Number of bytes left, that can be written to the stream.
Definition stream.hpp:1604
In-memory file.
Definition stream.hpp:3221
void save(const std::basic_string< TR, AX > &filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:3543
memory_file & operator=(memory_file &&other) noexcept
Moves content from another file.
Definition stream.hpp:3404
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:3923
memory_file(const schar_t *filename, int mode)
Loads content from file-system file.
Definition stream.hpp:3301
memory_file & read_str(std::basic_string< T, TR, AX > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:3632
memory_file(const memory_file &other)
Copies content from another file.
Definition stream.hpp:3320
memory_file & write_str(const std::basic_string< T, TR, AX > &data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3803
void load(const std::basic_string< TR, AX > &filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:3505
size_t m_size
file size
Definition stream.hpp:4074
void get(fpos_t offset, T &data)
Reads data from specified file location This does not move file pointer. It checks for data size Assu...
Definition stream.hpp:4012
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3838
uint8_t * m_data
file data
Definition stream.hpp:4071
memory_file & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:3592
virtual void close()
Closes the stream.
Definition stream.hpp:3888
memory_file(const std::basic_string< TR, AX > &filename, int mode)
Loads content from file-system file.
Definition stream.hpp:3313
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:3553
virtual fpos_t tell() const
Returns absolute file position in file or fpos_max if fails. This method does not update stream state...
Definition stream.hpp:3918
size_t m_reserved
reserved file size
Definition stream.hpp:4075
memory_file(size_t size, state_t state=state_t::ok)
Creates an empty file of reserved size.
Definition stream.hpp:3242
void reserve(size_t required, bool tight=false) noexcept
Reallocates memory.
Definition stream.hpp:3442
memory_file(memory_file &&other) noexcept
Moves content from another file.
Definition stream.hpp:3375
void write_byte(uint8_t byte, size_t amount=1)
Writes a byte of data.
Definition stream.hpp:3687
memory_file & operator=(const memory_file &other)
Copies content from another file.
Definition stream.hpp:3345
void set(fpos_t offset, const T data)
Writes data to specified file location This does not move file pointer nor update file size....
Definition stream.hpp:3978
size_t m_offset
file pointer
Definition stream.hpp:4073
void save(const schar_t *filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:3516
void load(const schar_t *filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:3471
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3902
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3928
memory_file & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:3720
memory_file & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3758
bool m_manage
may reallocate m_data?
Definition stream.hpp:4072
memory_file(void *data, size_t size, bool manage=false, state_t state=state_t::ok)
Creates a file based on available data.
Definition stream.hpp:3291
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:3663
memory_file(void *data, size_t size, size_t reserved, bool manage=false, state_t state=state_t::ok)
Creates a file based on available data.
Definition stream.hpp:3268
const void * data() const
Returns pointer to data.
Definition stream.hpp:3551
Definition stream.hpp:1170
enum stdex::stream::replicator::worker::op_t op
Operation to perform.
size_t num_written
Number of bytes written.
Definition stream.hpp:1219
size_t length
Byte limit of data to write.
Definition stream.hpp:1218
const void * data
Data to write.
Definition stream.hpp:1217
Replicates writing of the same data to multiple streams.
Definition stream.hpp:1087
void push_back(basic *source)
Adds stream on the list.
Definition stream.hpp:1106
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1163
void remove(basic *source)
Removes stream from the list.
Definition stream.hpp:1114
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1131
virtual void close()
Closes the stream.
Definition stream.hpp:1158
Socket stream.
Definition stream.hpp:2362
socket_t get() const noexcept
Returns socket handle.
Definition stream.hpp:2418
virtual void close()
Closes the stream.
Definition stream.hpp:2476
socket(int af, int type, int protocol)
Creates a socket.
Definition stream.hpp:2397
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:2420
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:2450
Limits reading from/writing to stream to a predefined window.
Definition stream.hpp:1611
fpos_t write_offset
Number of bytes to discard on write.
Definition stream.hpp:1687
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:1648
virtual size_t read(_Out_writes_bytes_to_opt_(length, return) void *data, size_t length)
Reads block of data from the stream.
Definition stream.hpp:1619
fpos_t read_offset
Number of bytes to skip on read.
Definition stream.hpp:1686
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:99
virtual void close()
Closes object.
Definition system.hpp:140
Numerical interval.
Definition interval.hpp:18
bool contains(T x) const
Is value in interval?
Definition interval.hpp:79
T size() const
Returns interval size.
Definition interval.hpp:47
T end
interval end
Definition interval.hpp:20
T start
interval start
Definition interval.hpp:19
Definition stream.hpp:1528
Definition stream.hpp:4175