10#include "interval.hpp"
29#include <condition_variable>
37#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
38#define SET_FILE_OP_TIMES 1
39#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
40#elif !defined(SET_FILE_OP_TIMES)
41#define SET_FILE_OP_TIMES 0
43#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
44#define CHECK_STREAM_STATE 0
45#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
47#define CHECK_STREAM_STATE 1
66 using fsize_t = uint64_t;
67 constexpr fsize_t fsize_max = UINT64_MAX;
69 constexpr size_t iterate_count = 0x10;
70 constexpr size_t default_block_size = 0x10000;
71 constexpr char16_t utf16_bom = u
'\ufeff';
72 constexpr char32_t utf32_bom = U
'\ufeff';
73 constexpr const char utf8_bom[3] = {
'\xef',
'\xbb',
'\xbf' };
83 virtual ~basic()
noexcept(
false) {}
96 virtual _Success_(
return != 0 || length == 0) size_t
read(
97 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
100 _Unreferenced_(length);
101 m_state = state_t::fail;
114 virtual _Success_(
return != 0) size_t
write(
115 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
117 _Unreferenced_(data);
118 _Unreferenced_(length);
119 m_state = state_t::fail;
128 m_state = state_t::ok;
136 m_state = state_t::ok;
142 virtual void skip(_In_ fsize_t amount)
146 else if (amount < iterate_count) {
147 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
149 if (!
ok()) _Unlikely_
154 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
156 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
158 amount -=
read_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
159 if (!
ok()) _Unlikely_
163 catch (
const std::bad_alloc&) { m_state = state_t::fail; }
170 inline state_t
state()
const {
return m_state; };
175 inline bool ok()
const {
return m_state == state_t::ok; };
186 std::vector<uint8_t> result;
187 size_t offset, length;
189 length = default_block_size;
190 while (offset < max_length) {
191 length = std::min(length, max_length);
192 try { result.resize(length); }
193 catch (
const std::bad_alloc&) {
194 m_state = state_t::fail;
197 auto num_read =
read_array(result.data() + offset,
sizeof(uint8_t), length - offset);
199 if (!
ok()) _Unlikely_
201 length += default_block_size;
203 result.resize(offset);
215 throw std::system_error(sys_error(), std::system_category(),
"failed to read");
224 write(&
byte,
sizeof(uint8_t));
225 else if (amount < iterate_count) {
226 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
227 write(&
byte,
sizeof(uint8_t));
228 if (!
ok()) _Unlikely_
233 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
235 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
236 memset(dummy.get(),
byte, block);
238 amount -=
write_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
239 if (!
ok()) _Unlikely_
243 catch (
const std::bad_alloc&) { m_state = state_t::fail; }
261 if (!
ok()) _Unlikely_ {
270 m_state = state_t::eof;
289 if (!
ok()) _Unlikely_
291#if BYTE_ORDER == BIG_ENDIAN
292 T data_le = HE2LE(data);
293 write(&data_le,
sizeof(T));
295 write(&data,
sizeof(T));
305 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
306 inline size_t readln(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
317 template<
class T_from,
class T_to,
class _Traits = std::
char_traits<T_to>,
class _Ax = std::allocator<T_to>>
320 if (encoder.from_encoding() == encoder.to_encoding())
322 std::basic_string<T_from> tmp;
324 encoder.strcpy(str, tmp);
333 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
337 _Elem chr, previous = (_Elem)0;
340 if (!initial && !(previous ==
static_cast<_Elem
>(
'\r') && chr ==
static_cast<_Elem
>(
'\n')))
345 }
while (
ok() && chr !=
static_cast<_Elem
>(
'\n'));
354 template<
class T_from,
class T_to,
class _Traits = std::
char_traits<T_to>,
class _Ax = std::allocator<T_to>>
357 if (encoder.from_encoding() == encoder.to_encoding())
359 std::basic_string<T_from> tmp;
361 encoder.strcat(str, tmp);
370 size_t read_array(_Out_writes_bytes_(size* count)
void* array, _In_
size_t size, _In_
size_t count)
372 for (
size_t to_read = mul(size, count);;) {
373 size_t num_read =
read(array, to_read);
377 if (!
ok()) _Unlikely_
378 return count - to_read / size;
379 reinterpret_cast<uint8_t*&
>(array) += num_read;
388 inline size_t write_array(_In_reads_bytes_opt_(size* count)
const void* array, _In_
size_t size, _In_
size_t count)
390 return write(array, mul(size, count)) / size;
401 template <
class T_from,
class T_to>
404 if (!
ok()) _Unlikely_
406 size_t num_chars = stdex::strlen(str);
407 if (encoder.from_encoding() == encoder.to_encoding())
408 return write_array(str,
sizeof(T_from), num_chars);
409 std::basic_string<T_to> tmp(encoder.convert(str, num_chars));
410 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
422 template <
class T_from,
class T_to>
425 if (!
ok()) _Unlikely_
427 num_chars = stdex::strnlen(str, num_chars);
428 if (encoder.from_encoding() == encoder.to_encoding())
429 return write_array(str,
sizeof(T_from), num_chars);
430 std::basic_string<T_to> tmp(encoder.convert(str, num_chars));
431 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
442 template<
class T_from,
class T_to,
class _Traits = std::
char_traits<T_from>,
class _Ax = std::allocator<T_from>>
445 if (!
ok()) _Unlikely_
447 if (encoder.from_encoding() == encoder.to_encoding())
448 return write_array(str.data(),
sizeof(T_from), str.size());
449 std::basic_string<T_to> tmp(encoder.convert(str));
450 return write_array(tmp.data(),
sizeof(T_to), tmp.size());
464 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
468 if (!
ok()) _Unlikely_
472 if (!
ok()) _Unlikely_
474 data.reserve(num_chars);
477 uint32_t num_read =
static_cast<uint32_t
>(
read_array(buf,
sizeof(_Elem), std::min<uint32_t>(num_chars, _countof(buf))));
478 data.append(buf, buf + num_read);
479 num_chars -= num_read;
480 if (!num_chars || !
ok())
500 size_t num_chars = stdex::strlen(data);
501 if (num_chars > UINT32_MAX)
502 throw std::invalid_argument(
"string too long");
504 if (!
ok()) _Unlikely_
521 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
525 size_t num_chars = data.size();
526 if (num_chars > UINT32_MAX)
527 throw std::invalid_argument(
"string too long");
529 if (!
ok()) _Unlikely_
531 write_array(data.data(),
sizeof(_Elem), num_chars);
541 size_t write_sa(_In_ LPSAFEARRAY sa)
543 safearray_accessor<void> a(sa);
545 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
546 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
547 throw std::invalid_argument(
"SafeArrayGet[UL]Bound failed");
548 return write(a.data(),
static_cast<size_t>(ubound) - lbound + 1);
559 std::unique_ptr<uint8_t[]> data(
new uint8_t[
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
560 fsize_t num_copied = 0, to_write = amount;
561 m_state = state_t::ok;
563 size_t num_read = stream.read(data.get(),
static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
564 size_t num_written =
write(data.get(), num_read);
565 num_copied += num_written;
566 to_write -= num_written;
567 if (stream.m_state == state_t::eof) {
569 m_state = state_t::ok;
572 m_state = stream.m_state;
584 if (charset == charset_id::utf32)
586 else if (charset == charset_id::utf16)
588 else if (charset == charset_id::utf8)
597 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t locale, ...)
600 va_start(params, locale);
611 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t locale, ...)
614 va_start(params, locale);
625 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t locale, _In_ va_list params)
628 tmp.reserve(default_block_size);
629 vappendf(tmp, format, locale, params);
630 return write_array(tmp.data(),
sizeof(
char), tmp.size());
638 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
641 tmp.reserve(default_block_size);
642 vappendf(tmp, format, locale, params);
643 return write_array(tmp.data(),
sizeof(
wchar_t), tmp.size());
646 inline basic& operator >>(_Out_ int8_t& data) {
return read_data(data); }
647 inline basic& operator <<(_In_
const int8_t data) {
return write_data(data); }
648 inline basic& operator >>(_Out_ int16_t& data) {
return read_data(data); }
649 inline basic& operator <<(_In_
const int16_t data) {
return write_data(data); }
650 inline basic& operator >>(_Out_ int32_t& data) {
return read_data(data); }
651 inline basic& operator <<(_In_
const int32_t data) {
return write_data(data); }
652 inline basic& operator >>(_Out_ int64_t& data) {
return read_data(data); }
653 inline basic& operator <<(_In_
const int64_t data) {
return write_data(data); }
654 inline basic& operator >>(_Out_ uint8_t& data) {
return read_data(data); }
655 inline basic& operator <<(_In_
const uint8_t data) {
return write_data(data); }
656 inline basic& operator >>(_Out_ uint16_t& data) {
return read_data(data); }
657 inline basic& operator <<(_In_
const uint16_t data) {
return write_data(data); }
658 inline basic& operator >>(_Out_ uint32_t& data) {
return read_data(data); }
659 inline basic& operator <<(_In_
const uint32_t data) {
return write_data(data); }
660 inline basic& operator >>(_Out_ uint64_t& data) {
return read_data(data); }
661 inline basic& operator <<(_In_
const uint64_t data) {
return write_data(data); }
662 inline basic& operator >>(_Out_
float& data) {
return read_data(data); }
663 inline basic& operator <<(_In_
const float data) {
return write_data(data); }
664 inline basic& operator >>(_Out_
double& data) {
return read_data(data); }
665 inline basic& operator <<(_In_
const double data) {
return write_data(data); }
666 inline basic& operator >>(_Out_
char& data) {
return read_data(data); }
667 inline basic& operator <<(_In_
const char data) {
return write_data(data); }
668#ifdef _NATIVE_WCHAR_T_DEFINED
669 inline basic& operator >>(_Out_
wchar_t& data) {
return read_data(data); }
670 inline basic& operator <<(_In_
const wchar_t data) {
return write_data(data); }
672 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
673 inline basic& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>& data) {
return read_str(data); }
675 inline basic& operator <<(_In_
const T* data) {
return write_str(data); }
676 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
677 inline basic& operator <<(_In_
const std::basic_string<_Elem, _Traits, _Ax>& data) {
return write_str(data); }
679 template <
class _Ty,
class _Alloc = std::allocator<_Ty>>
680 basic& operator <<(_In_
const std::vector<_Ty, _Alloc>& data)
682 size_t num = data.size();
683 if (num > UINT32_MAX) _Unlikely_
684 throw std::invalid_argument(
"collection too big");
685 *this << static_cast<uint32_t>(num);
686 for (
auto& el : data)
691 template <
class _Ty,
class _Alloc = std::allocator<_Ty>>
692 basic& operator >>(_Out_ std::vector<_Ty, _Alloc>& data)
697 if (!
ok()) _Unlikely_
700 for (uint32_t i = 0; i < num; ++i) {
703 if (!
ok()) _Unlikely_
705 data.push_back(std::move(el));
709 template <
class _Kty,
class _Pr = std::less<_Kty>,
class _Alloc = std::allocator<_Kty>>
710 basic& operator <<(_In_
const std::set<_Kty, _Pr, _Alloc>& data)
712 size_t num = data.size();
713 if (num > UINT32_MAX) _Unlikely_
714 throw std::invalid_argument(
"collection too big");
715 *this << static_cast<uint32_t>(num);
716 for (
auto& el : data)
721 template <
class _Kty,
class _Pr = std::less<_Kty>,
class _Alloc = std::allocator<_Kty>>
722 basic& operator >>(_Out_ std::set<_Kty, _Pr, _Alloc>& data)
727 if (!
ok()) _Unlikely_
729 for (uint32_t i = 0; i < num; ++i) {
732 if (!
ok()) _Unlikely_
734 data.insert(std::move(el));
738 template <
class _Kty,
class _Pr = std::less<_Kty>,
class _Alloc = std::allocator<_Kty>>
739 basic& operator <<(_In_
const std::multiset<_Kty, _Pr, _Alloc>& data)
741 size_t num = data.size();
742 if (num > UINT32_MAX) _Unlikely_
743 throw std::invalid_argument(
"collection too big");
744 *this << static_cast<uint32_t>(num);
745 for (
auto& el : data)
750 template <
class _Kty,
class _Pr = std::less<_Kty>,
class _Alloc = std::allocator<_Kty>>
751 basic& operator >>(_Out_ std::multiset<_Kty, _Pr, _Alloc>& data)
756 if (!
ok()) _Unlikely_
758 for (uint32_t i = 0; i < num; ++i) {
761 if (!
ok()) _Unlikely_
763 data.insert(std::move(el));
775 using fpos_t = uint64_t;
776 constexpr fpos_t fpos_max = UINT64_MAX;
777 constexpr fpos_t fpos_min = 0;
782 using foff_t = int64_t;
783 constexpr foff_t foff_max = INT64_MAX;
784 constexpr foff_t foff_min = INT64_MIN;
802 using clock = std::chrono::file_clock;
804 using clock = std::chrono::system_clock;
806 using time_point = std::chrono::time_point<clock>;
816 size_t length = std::min<size_t>(max_length,
static_cast<size_t>(
size() -
tell()));
817 std::vector<uint8_t> result;
818 try { result.resize(length); }
819 catch (
const std::bad_alloc&) {
820 m_state = state_t::fail;
823 result.resize(
read_array(result.data(),
sizeof(uint8_t), length));
832 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
839 inline fpos_t
seekbeg(_In_ fpos_t offset) {
return seek(offset, seek_t::beg); }
846 inline fpos_t
seekcur(_In_ foff_t offset) {
return seek(offset, seek_t::cur); }
853 inline fpos_t
seekend(_In_ foff_t offset) {
return seek(offset, seek_t::end); }
855 virtual void skip(_In_ fsize_t amount)
857 seek(amount, seek_t::cur);
866 virtual fpos_t
tell()
const = 0;
871 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
873 _Unreferenced_(offset);
874 _Unreferenced_(length);
875 throw std::domain_error(
"not implemented");
881 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
883 _Unreferenced_(offset);
884 _Unreferenced_(length);
885 throw std::domain_error(
"not implemented");
892 virtual fsize_t
size()
const = 0;
904 return time_point::min();
912 return time_point::min();
920 return time_point::min();
928 _Unreferenced_(date);
929 throw std::domain_error(
"not implemented");
937 _Unreferenced_(date);
938 throw std::domain_error(
"not implemented");
946 _Unreferenced_(date);
947 throw std::domain_error(
"not implemented");
954 LPSAFEARRAY read_sa()
956 _Assume_(
size() <= SIZE_MAX);
957 size_t length =
static_cast<size_t>(
size());
958 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
960 throw std::runtime_error(
"SafeArrayCreateVector failed");
961 safearray_accessor<void> a(sa.get());
962 if (
seek(0) != 0) _Unlikely_
963 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
964 if (
read_array(a.data(), 1, length) != length)
965 throw std::system_error(sys_error(), std::system_category(),
"failed to read");
975 charset_id
read_charset(_In_ charset_id default_charset = charset_id::system)
977 if (
seek(0) != 0) _Unlikely_
978 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
981 if (
ok() && id_utf32 == utf32_bom)
982 return charset_id::utf32;
984 if (
seek(0) != 0) _Unlikely_
985 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
988 if (
ok() && id_utf16 == utf16_bom)
989 return charset_id::utf16;
991 if (
seek(0) != 0) _Unlikely_
992 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
993 char id_utf8[3] = { 0 };
995 if (
ok() && strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
996 return charset_id::utf8;
998 if (
seek(0) != 0) _Unlikely_
999 throw std::system_error(sys_error(), std::system_category(),
"failed to seek");
1000 return default_charset;
1013#pragma warning(suppress: 26495)
1016 void init(_Inout_
basic& source)
1024 m_state = m_source->
state();
1035 basic(source.state()),
1039 virtual _Success_(
return != 0 || length == 0) size_t
read(
1040 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1042 size_t num_read = m_source->
read(data, length);
1043 m_state = m_source->
state();
1047 virtual _Success_(
return != 0) size_t
write(
1048 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1050 size_t num_written = m_source->
write(data, length);
1051 m_state = m_source->
state();
1058 m_state = m_source->
state();
1064 m_state = m_source->
state();
1079 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1082 const std::lock_guard<std::mutex> lk(_w->mutex);
1083 _w->op = worker::op_t::quit;
1085 _w->cv.notify_one();
1087 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
1096 m_workers.push_back(std::unique_ptr<worker>(
new worker(source)));
1104 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1106 if (_w->source == source) {
1108 const std::lock_guard<std::mutex> lk(_w->mutex);
1109 _w->op = worker::op_t::quit;
1111 _w->cv.notify_one();
1119 virtual _Success_(
return != 0) size_t
write(
1120 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1122 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1125 const std::lock_guard<std::mutex> lk(_w->mutex);
1126 _w->op = worker::op_t::write;
1128 _w->length = length;
1130 _w->cv.notify_one();
1132 size_t num_written = length;
1133 m_state = state_t::ok;
1134 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1136 std::unique_lock<std::mutex> lk(_w->mutex);
1137 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
1138 if (_w->num_written < num_written)
1139 num_written = _w->num_written;
1140 if (
ok() && !_w->source->ok())
1141 m_state = _w->source->state();
1148 foreach_worker(worker::op_t::close);
1153 foreach_worker(worker::op_t::flush);
1167 *
static_cast<std::thread*
>(
this) = std::thread([](_Inout_
worker& w) { w.process_op(); }, std::ref(*
this));
1174 std::unique_lock<std::mutex> lk(mutex);
1175 cv.wait(lk, [&] {
return op != op_t::noop; });
1209 std::condition_variable cv;
1212 void foreach_worker(_In_ worker::op_t op)
1214 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1217 const std::lock_guard<std::mutex> lk(_w->mutex);
1220 _w->cv.notify_one();
1222 m_state = state_t::ok;
1223 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1225 std::unique_lock<std::mutex> lk(_w->mutex);
1226 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
1228 m_state = _w->source->state();
1232 std::list<std::unique_ptr<worker>> m_workers;
1235 constexpr size_t default_async_limit = 0x100000;
1242 template <
size_t CAPACITY = default_async_limit>
1248 m_worker([](_Inout_
async_reader& w) { w.process(); }, std::ref(*
this))
1257#pragma warning(suppress: 6101)
1258 virtual _Success_(
return != 0 || length == 0) size_t
read(
1259 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1261 _Assume_(data || !length);
1262 for (
size_t to_read = length;;) {
1263 uint8_t* ptr;
size_t num_read;
1264 std::tie(ptr, num_read) = m_ring.front();
1265 if (!ptr) _Unlikely_ {
1266 m_state = to_read < length || !length ? state_t::ok : m_source->
state();
1267 return length - to_read;
1269 if (to_read < num_read)
1271 memcpy(data, ptr, num_read);
1272 m_ring.pop(num_read);
1273 to_read -= num_read;
1275 m_state = state_t::ok;
1278 reinterpret_cast<uint8_t*&
>(data) += num_read;
1286 uint8_t* ptr;
size_t num_write;
1287 std::tie(ptr, num_write) = m_ring.back();
1288 if (!ptr) _Unlikely_
1290 num_write = m_source->
read(ptr, num_write);
1291 m_ring.push(num_write);
1292 if (!m_source->
ok()) {
1300 ring<uint8_t, CAPACITY> m_ring;
1301 std::thread m_worker;
1309 template <
size_t CAPACITY = default_async_limit>
1315 m_worker([](_Inout_
async_writer& w) { w.process(); }, std::ref(*
this))
1324 virtual _Success_(
return != 0) size_t
write(
1325 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1327 _Assume_(data || !length);
1328 for (
size_t to_write = length;;) {
1329 uint8_t* ptr;
size_t num_write;
1330 std::tie(ptr, num_write) = m_ring.back();
1331 if (!ptr) _Unlikely_ {
1332 m_state = state_t::fail;
1333 return length - to_write;
1335 if (to_write < num_write)
1336 num_write = to_write;
1337 memcpy(ptr, data, num_write);
1338 m_ring.push(num_write);
1339 to_write -= num_write;
1341 m_state = state_t::ok;
1344 reinterpret_cast<const uint8_t*&
>(data) += num_write;
1358 uint8_t* ptr;
size_t num_read;
1359 std::tie(ptr, num_read) = m_ring.front();
1362 num_read = m_source->
write(ptr, num_read);
1363 m_ring.pop(num_read);
1364 if (!m_source->
ok()) {
1372 ring<uint8_t, CAPACITY> m_ring;
1373 std::thread m_worker;
1376 constexpr size_t default_buffer_size = 0x400;
1385 explicit buffer(_In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1387 m_read_buffer(read_buffer_size),
1388 m_write_buffer(write_buffer_size)
1400 buffer(_Inout_
basic& source, _In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1402 m_read_buffer(read_buffer_size),
1403 m_write_buffer(write_buffer_size)
1412 virtual _Success_(
return != 0 || length == 0) size_t
read(
1413 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1415 _Assume_(data || !length);
1416 for (
size_t to_read = length;;) {
1417 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
1418 if (to_read <= buffer_size) {
1419 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
1420 m_read_buffer.head += to_read;
1421 m_state = state_t::ok;
1425 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
1426 reinterpret_cast<uint8_t*&
>(data) += buffer_size;
1427 to_read -= buffer_size;
1429 m_read_buffer.head = 0;
1430 if (to_read > m_read_buffer.capacity) {
1432 m_read_buffer.tail = 0;
1433 to_read -= m_source->
read(data, to_read);
1434 m_state = to_read < length ? state_t::ok : m_source->
state();
1435 return length - to_read;
1437 m_read_buffer.tail = m_source->
read(m_read_buffer.data, m_read_buffer.capacity);
1438 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
1439 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
1440 m_read_buffer.head = m_read_buffer.tail;
1441 to_read -= m_read_buffer.tail;
1442 m_state = to_read < length ? state_t::ok : m_source->
state();
1443 return length - to_read;
1448 virtual _Success_(
return != 0) size_t
write(
1449 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1451 _Assume_(data || !length);
1452 if (!length) _Unlikely_ {
1455 if (!
ok()) _Unlikely_
1461 for (
size_t to_write = length;;) {
1462 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
1463 if (to_write <= available_buffer) {
1464 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
1465 m_write_buffer.tail += to_write;
1466 m_state = state_t::ok;
1469 if (available_buffer) {
1470 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
1471 reinterpret_cast<const uint8_t*&
>(data) += available_buffer;
1472 to_write -= available_buffer;
1473 m_write_buffer.tail += available_buffer;
1475 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1477 m_write_buffer.head +=
converter::write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1478 if (m_write_buffer.head == m_write_buffer.tail)
1479 m_write_buffer.head = m_write_buffer.tail = 0;
1481 return length - to_write;
1483 if (to_write > m_write_buffer.capacity) {
1486 return length - to_write;
1501 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1503 m_write_buffer.head += m_source->
write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1504 if (m_write_buffer.head == m_write_buffer.tail) {
1505 m_write_buffer.head = 0;
1506 m_write_buffer.tail = 0;
1509 m_state = m_source->
state();
1513 m_state = state_t::ok;
1518 size_t head, tail, capacity;
1520 buffer_t(_In_
size_t buffer_size) :
1523 capacity(buffer_size),
1524 data(buffer_size ?
new uint8_t[buffer_size] :
nullptr)
1532 } m_read_buffer, m_write_buffer;
1541 limiter(_Inout_
basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
1547 virtual _Success_(
return != 0 || length == 0) size_t
read(
1548 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1559 m_state = state_t::eof;
1568 virtual _Success_(
return != 0) size_t
write(
1569 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1580 m_state = state_t::fail;
1601 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) :
1607 virtual _Success_(
return != 0 || length == 0) size_t
read(
1608 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1612 m_state = m_source->
state();
1613 if (!
ok()) _Unlikely_
1626 m_source->
skip(length);
1627 m_state = state_t::eof;
1636 virtual _Success_(
return != 0) size_t
write(
1637 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1639 size_t num_skipped, num_written;
1642 m_state = state_t::ok;
1646 reinterpret_cast<const uint8_t*&
>(data) +=
static_cast<size_t>(
write_offset);
1660 num_skipped += length;
1662 m_state = state_t::ok;
1665 num_skipped += length -
static_cast<size_t>(
write_limit);
1669 return num_skipped + num_written;
1685 basic(source.state()),
1687 m_offset(source.tell()),
1688 m_region(offset, offset + length)
1691 virtual _Success_(
return != 0 || length == 0) size_t
read(
1692 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1694 _Assume_(data || !length);
1696 size_t num_read = m_source.
read(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1697 m_state = m_source.
state();
1698 m_offset += num_read;
1701 m_state = length ? state_t::eof : state_t::ok;
1705 virtual _Success_(
return != 0) size_t
write(
1706 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1708 _Assume_(data || !length);
1710 size_t num_written = m_source.
write(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1711 m_state = m_source.
state();
1712 m_offset += num_written;
1715 m_state = state_t::fail;
1722 m_state = m_source.
state();
1728 m_state = m_source.
state();
1731 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
1733 m_offset = m_source.
seek(offset, how);
1734 m_state = m_source.
state();
1735 return ok() ? m_offset - m_region.
start : fpos_max;
1738 virtual void skip(_In_ fsize_t amount)
1740 m_source.
skip(amount);
1741 m_state = m_source.
state();
1746 fpos_t offset = m_source.
tell();
1747 return m_region.
contains(offset) ? offset - m_region.
start : fpos_max;
1750 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
1753 m_source.
lock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1754 m_state = m_source.
state();
1757 m_state = state_t::fail;
1760 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
1763 m_source.
unlock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1764 m_state = m_source.
state();
1767 m_state = state_t::fail;
1772 return m_region.
size();
1777 m_state = state_t::fail;
1786 constexpr size_t default_cache_size = 0x1000;
1795#pragma warning(suppress: 26495)
1796 explicit cache(_In_
size_t cache_size = default_cache_size) :
1797 basic(state_t::fail),
1809 m_state = m_source->state();
1810 m_offset = m_source->tell();
1811#if SET_FILE_OP_TIMES
1812 m_atime = m_source->atime();
1813 m_mtime = m_source->mtime();
1821 if (!
ok()) _Unlikely_
1822 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1823 m_source->seek(m_offset);
1824#if SET_FILE_OP_TIMES
1825 m_source->set_atime(m_atime);
1826 m_source->set_mtime(m_mtime);
1834 cache(_Inout_
basic_file& source, _In_
size_t cache_size = default_cache_size) :
1835 basic(source.state()),
1837 m_cache(cache_size),
1838 m_offset(source.tell())
1839#if SET_FILE_OP_TIMES
1840 , m_atime(source.atime())
1841 , m_mtime(source.mtime())
1845 virtual ~cache()
noexcept(
false)
1849 if (!
ok()) _Unlikely_
1850 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1851 m_source->seek(m_offset);
1852#if SET_FILE_OP_TIMES
1853 m_source->set_atime(m_atime);
1854 m_source->set_mtime(m_mtime);
1859 virtual _Success_(
return != 0 || length == 0) size_t
read(
1860 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1862 _Assume_(data || !length);
1863#if SET_FILE_OP_TIMES
1864 m_atime = time_point::now();
1866 for (
size_t to_read = length;;) {
1867 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1868 if (m_cache.region.contains(m_offset)) {
1869 size_t remaining_cache =
static_cast<size_t>(m_cache.region.end - m_offset);
1870 if (to_read <= remaining_cache) {
1871 memcpy(data, m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), to_read);
1872 m_offset += to_read;
1873 m_state = state_t::ok;
1876 memcpy(data, m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
1877 reinterpret_cast<uint8_t*&
>(data) += remaining_cache;
1878 to_read -= remaining_cache;
1879 m_offset += remaining_cache;
1882 if (!
ok()) _Unlikely_ {
1883 if (to_read < length)
1884 m_state = state_t::ok;
1885 return length - to_read;
1889 fpos_t end_max = m_offset + to_read;
1890 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1892 m_source->seek(m_offset);
1893 if (!m_source->ok()) _Unlikely_ {
1894 m_state = to_read < length ? state_t::ok : state_t::fail;
1895 return length - to_read;
1897 size_t num_read = m_source->read(data, to_read -
static_cast<size_t>(end_max % m_cache.capacity));
1898 m_offset += num_read;
1899 to_read -= num_read;
1901 m_state = state_t::ok;
1904 reinterpret_cast<uint8_t*&
>(data) += num_read;
1905 m_state = m_source->state();
1907 if (to_read < length)
1908 m_state = state_t::ok;
1909 return length - to_read;
1913 load_cache(m_offset);
1914 if (!
ok() || m_cache.region.end <= m_offset) _Unlikely_ {
1915 m_state = to_read < length ? state_t::ok : state_t::fail;
1916 return length - to_read;
1921 virtual _Success_(
return != 0) size_t
write(
1922 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1924 _Assume_(data || !length);
1925#if SET_FILE_OP_TIMES
1926 m_atime = m_mtime = time_point::now();
1928 for (
size_t to_write = length;;) {
1929 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1930 fpos_t end_max = m_cache.region.start + m_cache.capacity;
1931 if (m_cache.region.start <= m_offset && m_offset < end_max) {
1932 size_t remaining_cache =
static_cast<size_t>(end_max - m_offset);
1933 if (to_write <= remaining_cache) {
1934 memcpy(m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
1935 m_offset += to_write;
1936 m_cache.status = cache_t::cache_t::status_t::dirty;
1937 m_cache.region.end = std::max(m_cache.region.end, m_offset);
1938 m_state = state_t::ok;
1941 memcpy(m_cache.data +
static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
1942 reinterpret_cast<const uint8_t*&
>(data) += remaining_cache;
1943 to_write -= remaining_cache;
1944 m_offset += remaining_cache;
1945 m_cache.status = cache_t::cache_t::status_t::dirty;
1946 m_cache.region.end = end_max;
1949 if (!
ok()) _Unlikely_
1950 return length - to_write;
1953 fpos_t end_max = m_offset + to_write;
1954 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1956 m_source->seek(m_offset);
1957 if (!
ok()) _Unlikely_
1958 return length - to_write;
1959 size_t num_written = m_source->write(data, to_write -
static_cast<size_t>(end_max % m_cache.capacity));
1960 m_offset += num_written;
1961 m_state = m_source->state();
1962 to_write -= num_written;
1963 if (!to_write || !
ok())
1964 return length - to_write;
1965 reinterpret_cast<const uint8_t*&
>(data) += num_written;
1968 load_cache(m_offset);
1969 if (!
ok()) _Unlikely_
1970 return length - to_write;
1977 if (!
ok()) _Unlikely_
1978 throw std::system_error(sys_error(), std::system_category(),
"failed to flush cache");
1980 m_state = m_source->state();
1985#if SET_FILE_OP_TIMES
1986 m_atime = m_mtime = time_point::min();
1989 if (!
ok()) _Unlikely_
1994 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
1996 m_state = state_t::ok;
1999 return m_offset = offset;
2001 return m_offset += offset;
2004 if (n == fsize_max) _Unlikely_{
2005 m_state = state_t::fail;
2008 return m_offset = n + offset;
2011 throw std::invalid_argument(
"unknown seek origin");
2020 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
2022 m_source->lock(offset, length);
2023 m_state = m_source->state();
2026 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
2028 m_source->unlock(offset, length);
2029 m_state = m_source->state();
2034 return m_cache.status != cache_t::cache_t::status_t::empty ?
2035 std::max(m_source->size(), m_cache.region.end) :
2041#if SET_FILE_OP_TIMES
2042 m_atime = m_mtime = time_point::now();
2044 m_source->seek(m_offset);
2045 if (m_cache.region.end <= m_offset) {
2048 else if (m_cache.region.start <= m_offset) {
2050 m_cache.region.end = m_offset;
2054 m_cache.status = cache_t::cache_t::status_t::empty;
2056 m_source->truncate();
2057 m_state = m_source->state();
2062 return m_source->ctime();
2067#if SET_FILE_OP_TIMES
2068 return std::max(m_atime, m_source->atime());
2070 return m_source->atime();
2076#if SET_FILE_OP_TIMES
2077 return std::max(m_mtime, m_source->mtime());
2079 return m_source->mtime();
2085 m_source->set_ctime(date);
2090#if SET_FILE_OP_TIMES
2093 m_source->set_atime(date);
2098#if SET_FILE_OP_TIMES
2101 m_source->set_mtime(date);
2108 if (m_cache.status != cache_t::cache_t::status_t::dirty)
2109 m_state = state_t::ok;
2110 else if (!m_cache.region.empty()) {
2113 m_cache.status = cache_t::cache_t::status_t::loaded;
2116 m_state = state_t::ok;
2117 m_cache.status = cache_t::cache_t::status_t::loaded;
2121 void invalidate_cache()
2123 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
2125 if (!
ok()) _Unlikely_
2128 m_state = state_t::ok;
2129 m_cache.status = cache_t::cache_t::status_t::empty;
2132 void load_cache(_In_ fpos_t start)
2134 _Assume_(m_cache.status != cache_t::cache_t::status_t::dirty);
2135 start -= start % m_cache.capacity;
2136 m_source->seek(m_cache.region.start = start);
2137 if (m_source->ok()) {
2138 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
2139 m_cache.status = cache_t::cache_t::status_t::loaded;
2140 m_state = state_t::ok;
2143 m_state = state_t::fail;
2148 _Assume_(m_cache.status == cache_t::cache_t::status_t::dirty);
2149 m_source->seek(m_cache.region.start);
2150 m_source->write(m_cache.data,
static_cast<size_t>(m_cache.region.size()));
2151 m_state = m_source->state();
2154 basic_file* m_source;
2158 enum class status_t {
2163 interval<fpos_t> region;
2165 cache_t(_In_
size_t _capacity) :
2166 data(new uint8_t[_capacity]),
2167 capacity(_capacity),
2168 status(status_t::empty),
2178#if SET_FILE_OP_TIMES
2192 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok) :
2197 virtual _Success_(
return != 0 || length == 0) size_t
read(
2198 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2200 _Assume_(data || !length);
2206 block_size = 0x1F80000;
2207#elif defined(_WIN32)
2208 block_size = 0x3f00000;
2210 block_size = SSIZE_MAX;
2212 for (
size_t to_read = length;;) {
2217 __try { succeeded = ReadFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_read, block_size)), &num_read,
nullptr); }
2218 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
2219 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
2222 block_size = default_block_size;
2225 if (!succeeded) _Unlikely_
2227 ssize_t num_read =
::read(m_h, data,
static_cast<ssize_t
>(std::min<size_t>(to_read, block_size)));
2228 if (num_read < 0) _Unlikely_
2231 m_state = to_read < length ? state_t::ok : state_t::fail;
2232 return length - to_read;
2234 if (!num_read) _Unlikely_ {
2235 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2236 return length - to_read;
2238 to_read -= num_read;
2240 m_state = state_t::ok;
2243 reinterpret_cast<uint8_t*&
>(data) += num_read;
2247 virtual _Success_(
return != 0) size_t
write(
2248 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2255 block_size = 0x1F80000;
2256#elif defined(_WIN32)
2257 block_size = 0x3f00000;
2259 block_size = SSIZE_MAX;
2261 for (
size_t to_write = length;;) {
2266 __try { succeeded = WriteFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_write, block_size)), &num_written,
nullptr); }
2267 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
2268 to_write -= num_written;
2270 m_state = state_t::ok;
2273 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2274 if (!succeeded) _Unlikely_ {
2275 m_state = state_t::fail;
2276 return length - to_write;
2279 ssize_t num_written =
::write(m_h, data,
static_cast<ssize_t
>(std::min<size_t>(to_write, block_size)));
2280 if (num_written < 0) _Unlikely_ {
2281 m_state = state_t::fail;
2282 return length - to_write;
2284 to_write -= num_written;
2286 m_state = state_t::ok;
2289 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2298 m_state = state_t::ok;
2301 m_state = state_t::fail;
2308 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
2310 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
2321 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) :
2322 buffer(read_buffer_size, write_buffer_size),
2343 socket(_In_opt_ socket_t h = invalid_socket, _In_ state_t
state = state_t::ok) :
2353 socket(_Inout_
socket&& other) noexcept : m_h(other.m_h)
2355 other.m_h = invalid_socket;
2360 if (
this != std::addressof(other)) {
2361 if (m_h != invalid_socket)
2364 other.m_h = invalid_socket;
2376 socket(_In_
int af, _In_
int type, _In_
int protocol)
2378 m_h = ::socket(af, type, protocol);
2379 if (m_h == invalid_socket) _Unlikely_
2380 m_state = state_t::fail;
2385 if (m_h != invalid_socket)
2392 inline operator bool() const noexcept {
return m_h != invalid_socket; }
2397 inline socket_t
get() const noexcept {
return m_h; }
2399 virtual _Success_(
return != 0 || length == 0) size_t
read(
2400 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2402 _Assume_(data || !length);
2403 constexpr int block_size = 0x10000000;
2404 for (
size_t to_read = length;;) {
2405 int num_read = recv(m_h,
reinterpret_cast<char*
>(data),
static_cast<int>(std::min<size_t>(to_read, block_size)), 0);
2406 if (num_read == SOCKET_ERROR) _Unlikely_ {
2407 m_state = to_read < length ? state_t::ok : state_t::fail;
2408 return length - to_read;
2411 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2412 return length - to_read;
2414 to_read -= num_read;
2416 m_state = state_t::ok;
2419 reinterpret_cast<uint8_t*&
>(data) += num_read;
2423 virtual _Success_(
return != 0) size_t
write(
2424 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2426 _Assume_(data || !length);
2427 constexpr int block_size = 0x10000000;
2428 for (
size_t to_write = length;;) {
2429 int num_written = send(m_h,
reinterpret_cast<const char*
>(data),
static_cast<int>(std::min<size_t>(to_write, block_size)), 0);
2430 if (num_written == SOCKET_ERROR) _Unlikely_ {
2431 m_state = state_t::fail;
2432 return length - to_write;
2434 to_write -= num_written;
2436 m_state = state_t::ok;
2439 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2445 if (m_h != invalid_socket) {
2447 m_h = invalid_socket;
2449 m_state = state_t::ok;
2460 class sequential_stream :
public basic
2463 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
2468 virtual ~sequential_stream()
2470 m_source->Release();
2473 virtual _Success_(
return != 0 || length == 0) size_t read(
2474 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2476 _Assume_(data || !length);
2477 for (
size_t to_read = length;;) {
2480 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
2481 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2482 if (FAILED(hr)) _Unlikely_ {
2483 m_state = to_read < length ? state_t::ok : state_t::fail;
2484 return length - to_read;
2486 to_read -= num_read;
2487 if (hr == S_FALSE) _Unlikely_ {
2488 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2489 return length - to_read;
2492 m_state = state_t::ok;
2495 reinterpret_cast<uint8_t*&
>(data) += num_read;
2499 virtual _Success_(
return != 0) size_t write(
2500 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2502 _Assume_(data || !length);
2503 for (
size_t to_write = length;;) {
2505 ULONG num_written = 0;
2506 __try { hr = m_source->Write(data,
static_cast<ULONG
>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
2507 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2510 if (FAILED(hr)) _Unlikely_ {
2511 m_state = state_t::fail;
2512 return length - to_write;
2514 to_write -= num_written;
2516 m_state = state_t::ok;
2519 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2524 ISequentialStream* m_source;
2530 class asp :
public basic
2533 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
2535 m_response(response)
2538 m_request->AddRef();
2540 m_response->AddRef();
2546 m_request->Release();
2548 m_response->Release();
2551 virtual _Success_(
return != 0 || length == 0) size_t read(
2552 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2554 _Assume_(data || !length);
2555 if (!m_request) _Unlikely_ {
2556 m_state = state_t::fail;
2559 for (
size_t to_read = length;;) {
2560 VARIANT var_amount, var_data;
2561 V_VT(&var_amount) = VT_I4;
2562 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
2563 V_VT(&var_data) = VT_EMPTY;
2564 HRESULT hr = [&]() {
2565 __try {
return m_request->BinaryRead(&var_amount, &var_data); }
2566 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2568 if (FAILED(hr)) _Unlikely_ {
2569 m_state = to_read < length ? state_t::ok : state_t::fail;
2570 return length - to_read;
2572 _Assume_(V_VT(&var_amount) == VT_I4);
2573 _Assume_(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
2574 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
2575 if (!V_I4(&var_amount)) _Unlikely_ {
2576 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2577 return length - to_read;
2579 safearray_accessor<uint8_t> a(sa.get());
2580 memcpy(data, a.data(), V_I4(&var_amount));
2581 to_read -= V_I4(&var_amount);
2583 m_state = state_t::ok;
2586 reinterpret_cast<uint8_t*&
>(data) += V_I4(&var_amount);
2590 virtual _Success_(
return != 0) size_t write(
2591 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2594 m_state = state_t::fail;
2597 for (
size_t to_write = length;;) {
2598 UINT num_written =
static_cast<UINT
>(std::min<size_t>(to_write, UINT_MAX));
2599 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(
reinterpret_cast<LPCSTR
>(data), num_written));
2601 V_VT(&var_data) = VT_BSTR;
2602 V_BSTR(&var_data) = bstr_data.get();
2603 HRESULT hr = [&]() {
2604 __try {
return m_response->BinaryWrite(var_data); }
2605 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2607 if (FAILED(hr)) _Unlikely_ {
2608 m_state = state_t::fail;
2609 return length - to_write;
2611 to_write -= num_written;
2613 m_state = state_t::ok;
2616 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2620 virtual void close()
2623 __try { m_response->End(); }
2624 __except (EXCEPTION_EXECUTE_HANDLER) {}
2626 m_state = state_t::ok;
2629 virtual void flush()
2633 __try { hr = m_response->Flush(); }
2634 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2635 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
2640 IRequest* m_request;
2641 IResponse* m_response;
2650 mode_for_reading = 1 << 0,
2651 mode_for_writing = 1 << 1,
2652 mode_for_chmod = 1 << 2,
2654 mode_open_existing = 0 << 3,
2655 mode_truncate_existing = 1 << 3,
2656 mode_preserve_existing = 2 << 3,
2657 mode_create_new = 3 << 3,
2658 mode_create = 4 << 3,
2659 mode_disposition_mask = 7 << 3,
2661 mode_append = 1 << 6,
2663 mode_binary = 1 << 7,
2666 share_reading = 1 << 8,
2667 share_writing = 1 << 9,
2668 share_deleting = 1 << 10,
2669 share_all = share_reading | share_writing | share_deleting,
2671 inherit_handle = 1 << 11,
2673 hint_write_thru = 1 << 12,
2674 hint_no_buffering = 1 << 13,
2675 hint_random_access = 1 << 14,
2676 hint_sequential_access = 1 << 15,
2679#pragma warning(push)
2680#pragma warning(disable: 4250)
2695 file(_In_z_
const schar_t* filename, _In_
int mode)
2697 open(filename, mode);
2706 inline file(_In_
const stdex::sstring& filename, _In_
int mode) :
file(filename.c_str(), mode) {}
2714 void open(_In_z_
const schar_t* filename, _In_
int mode)
2716 if (m_h != invalid_handle)
2720 DWORD dwDesiredAccess = 0;
2721 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
2722 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
2723 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
2725 DWORD dwShareMode = 0;
2726 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
2727 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
2728 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
2730 SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES) };
2731 sa.bInheritHandle = mode & inherit_handle ? true :
false;
2733 DWORD dwCreationDisposition;
2734 switch (mode & mode_disposition_mask) {
2735 case mode_open_existing: dwCreationDisposition = OPEN_EXISTING;
break;
2736 case mode_truncate_existing: dwCreationDisposition = TRUNCATE_EXISTING;
break;
2737 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS;
break;
2738 case mode_create_new: dwCreationDisposition = CREATE_NEW;
break;
2739 case mode_create: dwCreationDisposition = CREATE_ALWAYS;
break;
2740 default:
throw std::invalid_argument(
"invalid mode");
2743 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
2744 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
2745 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
2746 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
2747 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
2749 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, NULL);
2752 switch (mode & (mode_for_reading | mode_for_writing)) {
2753 case mode_for_reading: flags |= O_RDONLY;
break;
2754 case mode_for_writing: flags |= O_WRONLY;
break;
2755 case mode_for_reading | mode_for_writing: flags |= O_RDWR;
break;
2757 switch (mode & mode_disposition_mask) {
2758 case mode_open_existing:
break;
2759 case mode_truncate_existing: flags |= O_TRUNC;
break;
2760 case mode_preserve_existing: flags |= O_CREAT;
break;
2761 case mode_create_new: flags |= O_CREAT | O_EXCL;
break;
2762 case mode_create: flags |= O_CREAT | O_TRUNC;
break;
2763 default:
throw std::invalid_argument(
"invalid mode");
2765 if (mode & hint_write_thru) flags |= O_DSYNC;
2767 if (mode & hint_no_buffering) flags |= O_RSYNC;
2770 m_h =
::open(filename, flags, DEFFILEMODE);
2772 if (m_h != invalid_handle) {
2773 m_state = state_t::ok;
2774 if (mode & mode_append)
2775 seek(0, seek_t::end);
2778 m_state = state_t::fail;
2787 inline void open(_In_
const stdex::sstring& filename, _In_
int mode)
2789 open(filename.c_str(), mode);
2792 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
2796 li.QuadPart = offset;
2797 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart,
static_cast<DWORD
>(how));
2798 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
2799 m_state = state_t::ok;
2803 off64_t result = lseek64(m_h, offset,
static_cast<int>(how));
2805 m_state = state_t::ok;
2809 m_state = state_t::fail;
2815 if (m_h != invalid_handle) {
2819 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
2820 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
2823 off64_t result = lseek64(m_h, 0, SEEK_CUR);
2831 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
2834 LARGE_INTEGER liOffset;
2835 LARGE_INTEGER liSize;
2836 liOffset.QuadPart = offset;
2837 liSize.QuadPart = length;
2838 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2839 m_state = state_t::ok;
2843 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2845 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
2846 lseek64(m_h, orig, SEEK_SET);
2847 m_state = state_t::ok;
2851 m_state = state_t::fail;
2854 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
2857 LARGE_INTEGER liOffset;
2858 LARGE_INTEGER liSize;
2859 liOffset.QuadPart = offset;
2860 liSize.QuadPart = length;
2861 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2862 m_state = state_t::ok;
2866 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2868 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
2869 lseek64(m_h, orig, SEEK_SET);
2870 m_state = state_t::ok;
2873 lseek64(m_h, orig, SEEK_SET);
2876 m_state = state_t::fail;
2883 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
2884 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
2888 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
2890 length = lseek64(m_h, 0, SEEK_END);
2891 lseek64(m_h, orig, SEEK_SET);
2900 if (SetEndOfFile(m_h)) {
2901 m_state = state_t::ok;
2905 off64_t length = lseek64(m_h, 0, SEEK_CUR);
2906 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
2907 m_state = state_t::ok;
2911 m_state = state_t::fail;
2915 static inline time_point ft2tp(_In_
const FILETIME& ft)
2918 uint64_t t = (
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
2920 uint64_t t = ((
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
2922 return time_point(time_point::duration(t));
2925 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
2928 uint64_t t = tp.time_since_epoch().count();
2930 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
2932 ft.dwHighDateTime =
static_cast<DWORD
>((t >> 32) & 0xffffffff);
2933 ft.dwLowDateTime =
static_cast<DWORD
>(t & 0xffffffff);
2941 if (GetFileTime(m_h, &ft,
nullptr,
nullptr))
2944 return time_point::min();
2951 if (GetFileTime(m_h,
nullptr, &ft,
nullptr))
2955 if (fstat(m_h, &buf) >= 0)
2956 return clock::from_time_t(buf.st_atime);
2958 return time_point::min();
2965 if (GetFileTime(m_h,
nullptr,
nullptr, &ft))
2969 if (fstat(m_h, &buf) >= 0)
2970 return clock::from_time_t(buf.st_mtime);
2972 return time_point::min();
2977 _Assume_(m_h != invalid_handle);
2981 if (SetFileTime(m_h, &ft,
nullptr,
nullptr))
2983 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
2985 throw std::runtime_error(
"not supported");
2991 _Assume_(m_h != invalid_handle);
2995 if (SetFileTime(m_h,
nullptr, &ft,
nullptr))
2997 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
2999 struct timespec ts[2] = {
3000 { date.time_since_epoch().count(), 0 },
3003 if (futimens(m_h, ts) >= 0)
3005 throw std::system_error(errno, std::system_category(),
"futimens failed");
3014 if (SetFileTime(m_h,
nullptr,
nullptr, &ft))
3016 throw std::system_error(GetLastError(), std::system_category(),
"SetFileTime failed");
3018 struct timespec ts[2] = {
3020 { date.time_since_epoch().count(), 0 },
3022 if (futimens(m_h, ts) >= 0)
3024 throw std::system_error(errno, std::system_category(),
"futimens failed");
3033 static bool exists(_In_z_
const stdex::schar_t* filename)
3036 return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
3039 return stat(filename, &s) == 0;
3048 static inline bool exists(_In_
const stdex::sstring& filename)
3050 return exists(filename.c_str());
3060 static bool readonly(_In_z_
const stdex::schar_t* filename)
3063 DWORD dwAttr = GetFileAttributes(filename);
3064 return dwAttr != INVALID_FILE_ATTRIBUTES && (dwAttr & FILE_ATTRIBUTE_READONLY) != 0;
3067 return stat(filename, &s) == 0 && (s.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0;
3078 static inline bool readonly(_In_
const stdex::sstring& filename)
3091 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok, _In_
size_t cache_size = default_cache_size) :
3105 cached_file(_In_z_
const schar_t* filename, _In_
int mode, _In_
size_t cache_size = default_cache_size) :
3107 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
3119 inline cached_file(_In_
const stdex::sstring& filename, _In_
int mode, _In_
size_t cache_size = default_cache_size) :
cached_file(filename.c_str(), mode, cache_size) {}
3132 void open(_In_z_
const schar_t* filename, _In_
int mode)
3135 if (!
ok()) _Unlikely_{
3136 m_state = state_t::fail;
3139 m_source.
open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
3140 if (m_source.
ok()) {
3144 m_state = state_t::fail;
3153 inline void open(_In_
const stdex::sstring& filename, _In_
int mode)
3155 open(filename.c_str(), mode);
3161 inline operator bool() const noexcept {
return m_source; }
3181#if SET_FILE_OP_TIMES
3182 m_ctime = m_atime = m_mtime = time_point::now();
3194 m_data(reinterpret_cast<uint8_t*>(malloc(
size))),
3201 m_state = state_t::fail;
3202 throw std::bad_alloc();
3204#if SET_FILE_OP_TIMES
3205 m_ctime = m_atime = m_mtime = time_point::now();
3227 _Assume_(reserved >=
size);
3228#if SET_FILE_OP_TIMES
3229 m_ctime = m_atime = m_mtime = time_point::now();
3253 load(filename, mode);
3271 m_data(reinterpret_cast<uint8_t*>(malloc(other.
m_size))),
3276#if SET_FILE_OP_TIMES
3277 , m_ctime(other.m_ctime)
3278 , m_atime(other.m_atime)
3279 , m_mtime(other.m_mtime)
3283 m_state = state_t::fail;
3284 throw std::bad_alloc();
3286 memcpy(
m_data, other.m_data, other.m_size);
3296 if (
this != std::addressof(other)) {
3300 m_data =
reinterpret_cast<uint8_t*
>(malloc(other.m_size));
3302 m_state = state_t::fail;
3303 throw std::bad_alloc();
3305 memcpy(
m_data, other.m_data, other.m_size);
3310#if SET_FILE_OP_TIMES
3311 m_ctime = other.m_ctime;
3312 m_atime = other.m_atime;
3313 m_mtime = other.m_mtime;
3331#if SET_FILE_OP_TIMES
3332 , m_ctime(other.m_ctime)
3333 , m_atime(other.m_atime)
3334 , m_mtime(other.m_mtime)
3337 other.m_state = state_t::ok;
3338 other.m_data =
nullptr;
3341 other.m_reserved = 0;
3342 other.m_manage =
true;
3343#if SET_FILE_OP_TIMES
3344 other.m_ctime = other.m_atime = other.m_mtime = time_point::now();
3355 if (
this != std::addressof(other)) {
3356 *
static_cast<basic_file*
>(
this) = std::move(other);
3360 other.m_data =
nullptr;
3366 other.m_reserved = 0;
3368 other.m_manage =
true;
3369#if SET_FILE_OP_TIMES
3370 m_ctime = other.m_ctime;
3371 m_atime = other.m_atime;
3372 m_mtime = other.m_mtime;
3373 other.m_ctime = other.m_atime = other.m_mtime = time_point::now();
3391 void reserve(_In_
size_t required, _In_
bool tight =
false) noexcept
3394 m_state = state_t::ok;
3398 m_state = state_t::fail;
3401 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
3402 auto data =
reinterpret_cast<uint8_t*
>(realloc(
m_data, reserved));
3403 if (!
data && reserved) _Unlikely_ {
3404 m_state = state_t::fail;
3411 m_state = state_t::ok;
3420 void load(_In_z_
const schar_t* filename, _In_
int mode)
3422 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
3424 m_state = state_t::fail;
3428 if (
size > SIZE_MAX) {
3429 m_state = state_t::fail;
3433 if (!
ok()) _Unlikely_ {
3440#if SET_FILE_OP_TIMES
3441 m_ctime = f.
ctime();
3442 m_atime = f.
atime();
3443 m_mtime = f.
mtime();
3453 inline void load(_In_
const stdex::sstring& filename, _In_
int mode)
3455 load(filename.c_str(), mode);
3464 void save(_In_z_
const schar_t* filename, _In_
int mode)
3466 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
3468 m_state = state_t::fail;
3473 m_state = state_t::fail;
3477#if SET_FILE_OP_TIMES
3490 inline void save(_In_
const stdex::sstring& filename, _In_
int mode)
3492 save(filename.c_str(), mode);
3500 virtual _Success_(
return != 0 || length == 0) size_t
read(
3501 _Out_writes_bytes_to_opt_(length, return)
void*
data, _In_
size_t length)
3503 _Assume_(
data || !length);
3504#if SET_FILE_OP_TIMES
3505 m_atime = time_point::now();
3508 if (length <= available) {
3511 m_state = state_t::ok;
3514 if (length && !available) {
3515 m_state = state_t::eof;
3520 m_state = state_t::ok;
3541#if SET_FILE_OP_TIMES
3542 m_atime = time_point::now();
3544 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
3548 size_t end_offset =
m_offset +
sizeof(T);
3549 if (end_offset <=
m_size) {
3552#if !CHECK_STREAM_STATE
3553 m_state = state_t::ok;
3559 m_state = state_t::eof;
3578 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
3581#if SET_FILE_OP_TIMES
3582 m_atime = time_point::now();
3584 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
3588 size_t end_offset =
m_offset +
sizeof(uint32_t);
3589 if (end_offset <=
m_size) {
3590 uint32_t num_chars = LE2HE(*
reinterpret_cast<uint32_t*
>(
m_data +
m_offset));
3592 end_offset = stdex::add(
m_offset, stdex::mul(num_chars,
sizeof(_Elem)));
3594 if (end_offset <=
m_size) {
3595 data.assign(start, start + num_chars);
3597#if !CHECK_STREAM_STATE
3598 m_state = state_t::ok;
3602 if (end_offset <=
m_size)
3606 m_state = state_t::eof;
3610 virtual _Success_(
return != 0) size_t
write(
3611 _In_reads_bytes_opt_(length) const
void*
data, _In_
size_t length)
3613 _Assume_(
data || !length);
3614#if SET_FILE_OP_TIMES
3615 m_atime = m_mtime = time_point::now();
3617 size_t end_offset =
m_offset + length;
3620 if (!
ok()) _Unlikely_
3627 m_state = state_t::ok;
3636#if SET_FILE_OP_TIMES
3637 m_atime = m_mtime = time_point::now();
3639 size_t end_offset =
m_offset + amount;
3642 if (!
ok()) _Unlikely_
3649 m_state = state_t::ok;
3669#if SET_FILE_OP_TIMES
3670 m_atime = m_mtime = time_point::now();
3672 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3674 size_t end_offset =
m_offset +
sizeof(T);
3677 if (!
ok()) _Unlikely_
3684#if !CHECK_STREAM_STATE
3685 m_state = state_t::ok;
3707#if SET_FILE_OP_TIMES
3708 m_atime = m_mtime = time_point::now();
3710 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3712 size_t num_chars = stdex::strlen(
data);
3713 if (num_chars > UINT32_MAX)
3714 throw std::invalid_argument(
"string too long");
3715 size_t size_chars = num_chars *
sizeof(T);
3716 size_t size =
sizeof(uint32_t) + size_chars;
3720 if (!
ok()) _Unlikely_
3724 *
reinterpret_cast<uint32_t*
>(p) = HE2LE((uint32_t)num_chars);
3725 memcpy(p +
sizeof(uint32_t),
data, size_chars);
3729#if !CHECK_STREAM_STATE
3730 m_state = state_t::ok;
3749 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
3752#if SET_FILE_OP_TIMES
3753 m_atime = m_mtime = time_point::now();
3755 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3757 size_t num_chars =
data.size();
3758 if (num_chars > UINT32_MAX)
3759 throw std::invalid_argument(
"string too long");
3760 size_t size_chars = num_chars *
sizeof(_Elem);
3761 size_t size =
sizeof(uint32_t) + size_chars;
3765 if (!
ok()) _Unlikely_
3769 *
reinterpret_cast<uint32_t*
>(p) = HE2LE((uint32_t)num_chars);
3770 memcpy(p +
sizeof(uint32_t),
data.data(), size_chars);
3774#if !CHECK_STREAM_STATE
3775 m_state = state_t::ok;
3787#if SET_FILE_OP_TIMES
3788 m_atime = m_mtime = time_point::now();
3791 size_t num_copied = 0, to_write = amount;
3792 m_state = state_t::ok;
3793 if (amount != SIZE_MAX) {
3794 dst_size = stdex::add(dst_size, amount);
3796 if (!
ok()) _Unlikely_
3799 num_read = stream.read(
m_data + dst_offset, to_write);
3800 dst_size = dst_offset += num_read;
3801 num_copied += num_read;
3802 to_write -= num_read;
3804 if (stream.state() != state_t::eof)
3805 m_state = state_t::fail;
3813 block_size = std::min(to_write, default_block_size);
3814 dst_size = stdex::add(dst_size, block_size);
3816 if (!
ok()) _Unlikely_
3818 num_read = stream.read(
m_data + dst_offset, block_size);
3819 dst_size = dst_offset += num_read;
3820 num_copied += num_read;
3821 to_write -= num_read;
3823 if (stream.state() != state_t::eof)
3824 m_state = state_t::fail;
3843#if SET_FILE_OP_TIMES
3844 m_ctime = m_atime = m_mtime = time_point::min();
3846 m_state = state_t::ok;
3849 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
3853 case seek_t::beg: target = offset;
break;
3854 case seek_t::cur: target =
static_cast<fpos_t
>(
m_offset) + offset;
break;
3855 case seek_t::end: target =
static_cast<fpos_t
>(
m_size) + offset;
break;
3856 default:
throw std::invalid_argument(
"unknown seek origin");
3858 if (target <= SIZE_MAX) {
3859 m_state = state_t::ok;
3860 return m_offset =
static_cast<size_t>(target);
3862 m_state = state_t::fail;
3878#if SET_FILE_OP_TIMES
3879 m_atime = m_mtime = time_point::now();
3885#if SET_FILE_OP_TIMES
3886 virtual time_point
ctime()
const
3891 virtual time_point
atime()
const
3896 virtual time_point
mtime()
const
3926 inline void set(_In_ fpos_t offset, _In_
const T
data)
3928#if SET_FILE_OP_TIMES
3929 m_atime = m_mtime = time_point::now();
3931 _Assume_(offset +
sizeof(T) <
m_size);
3932 (*
reinterpret_cast<T*
>(
m_data + offset)) = HE2LE(
data);
3936 inline void set(_In_ fpos_t offset, _In_
const int8_t
data) { set<int8_t>(offset,
data); }
3937 inline void set(_In_ fpos_t offset, _In_
const int16_t
data) { set<int16_t>(offset,
data); }
3938 inline void set(_In_ fpos_t offset, _In_
const int32_t
data) { set<int32_t>(offset,
data); }
3939 inline void set(_In_ fpos_t offset, _In_
const int64_t
data) { set<int64_t>(offset,
data); }
3940 inline void set(_In_ fpos_t offset, _In_
const uint8_t
data) { set<uint8_t>(offset,
data); }
3941 inline void set(_In_ fpos_t offset, _In_
const uint16_t
data) { set<uint16_t>(offset,
data); }
3942 inline void set(_In_ fpos_t offset, _In_
const uint32_t
data) { set<uint32_t>(offset,
data); }
3943 inline void set(_In_ fpos_t offset, _In_
const uint64_t
data) { set<uint64_t>(offset,
data); }
3944 inline void set(_In_ fpos_t offset, _In_
const float data) { set<float>(offset,
data); }
3945 inline void set(_In_ fpos_t offset, _In_
const double data) { set<double>(offset,
data); }
3946 inline void set(_In_ fpos_t offset, _In_
const char data) { set<char>(offset,
data); }
3947#ifdef _NATIVE_WCHAR_T_DEFINED
3948 inline void set(_In_ fpos_t offset, _In_
const wchar_t data) { set<wchar_t>(offset,
data); }
3960 inline void get(_In_ fpos_t offset, _Out_ T &
data)
3962 _Assume_(offset +
sizeof(T) <
m_size);
3964#if SET_FILE_OP_TIMES
3965 m_atime = time_point::now();
3970 inline void get(_In_ fpos_t offset, _Out_ int8_t &
data) { get<int8_t>(offset,
data); }
3971 inline void get(_In_ fpos_t offset, _Out_ int16_t &
data) { get<int16_t>(offset,
data); }
3972 inline void get(_In_ fpos_t offset, _Out_ int32_t &
data) { get<int32_t>(offset,
data); }
3973 inline void get(_In_ fpos_t offset, _Out_ int64_t &
data) { get<int64_t>(offset,
data); }
3974 inline void get(_In_ fpos_t offset, _Out_ uint8_t &
data) { get<uint8_t>(offset,
data); }
3975 inline void get(_In_ fpos_t offset, _Out_ uint16_t &
data) { get<uint16_t>(offset,
data); }
3976 inline void get(_In_ fpos_t offset, _Out_ uint32_t &
data) { get<uint32_t>(offset,
data); }
3977 inline void get(_In_ fpos_t offset, _Out_ uint64_t &
data) { get<uint64_t>(offset,
data); }
3978 inline void get(_In_ fpos_t offset, _Out_
float&
data) { get<float>(offset,
data); }
3979 inline void get(_In_ fpos_t offset, _Out_
double&
data) { get<double>(offset,
data); }
3980 inline void get(_In_ fpos_t offset, _Out_
char&
data) { get<char>(offset,
data); }
3981#ifdef _NATIVE_WCHAR_T_DEFINED
3982 inline void get(_In_ fpos_t offset, _Out_
wchar_t&
data) { get<wchar_t>(offset,
data); }
3986 inline memory_file& operator >>(_Out_ int8_t &
data) {
return read_data(
data); }
3987 inline memory_file& operator <<(_In_
const int16_t
data) {
return write_data(
data); }
3988 inline memory_file& operator >>(_Out_ int16_t &
data) {
return read_data(
data); }
3989 inline memory_file& operator <<(_In_
const int32_t
data) {
return write_data(
data); }
3990 inline memory_file& operator >>(_Out_ int32_t &
data) {
return read_data(
data); }
3991 inline memory_file& operator <<(_In_
const int64_t
data) {
return write_data(
data); }
3992 inline memory_file& operator >>(_Out_ int64_t &
data) {
return read_data(
data); }
3993 inline memory_file& operator <<(_In_
const uint8_t
data) {
return write_data(
data); }
3994 inline memory_file& operator >>(_Out_ uint8_t &
data) {
return read_data(
data); }
3995 inline memory_file& operator <<(_In_
const uint16_t
data) {
return write_data(
data); }
3996 inline memory_file& operator >>(_Out_ uint16_t &
data) {
return read_data(
data); }
3997 inline memory_file& operator <<(_In_
const uint32_t
data) {
return write_data(
data); }
3998 inline memory_file& operator >>(_Out_ uint32_t &
data) {
return read_data(
data); }
3999 inline memory_file& operator <<(_In_
const uint64_t
data) {
return write_data(
data); }
4000 inline memory_file& operator >>(_Out_ uint64_t &
data) {
return read_data(
data); }
4007#ifdef _NATIVE_WCHAR_T_DEFINED
4008 inline memory_file& operator <<(_In_
const wchar_t data) {
return write_data(
data); }
4009 inline memory_file& operator >>(_Out_
wchar_t&
data) {
return read_data(
data); }
4011 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
4012 inline memory_file& operator >>(_Out_ std::basic_string<_Elem, _Traits, _Ax>&
data) {
return read_str(
data); }
4014 inline memory_file& operator <<(_In_
const T *
data) {
return write_str(
data); }
4015 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
4016 inline memory_file& operator <<(_In_
const std::basic_string<_Elem, _Traits, _Ax>&
data) {
return write_str(
data); }
4024#if SET_FILE_OP_TIMES
4053#pragma warning(suppress: 6101)
4054 virtual _Success_(
return != 0 || length == 0) size_t
read(
4055 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
4057 _Assume_(data || !length);
4058 for (
size_t to_read = length;;) {
4059 if (!m_head) _Unlikely_ {
4060 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
4061 return length - to_read;
4063 size_t remaining = m_head->size - m_offset;
4064 if (remaining > to_read) {
4065 memcpy(data, m_head->data + m_offset, to_read);
4066 m_offset += to_read;
4068 m_state = state_t::ok;
4071 memcpy(data, m_head->data + m_offset, remaining);
4073 m_size -= remaining;
4074 reinterpret_cast<uint8_t*&
>(data) += remaining;
4075 to_read -= remaining;
4082 virtual _Success_(
return != 0) size_t
write(
4083 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
4085 _Assume_(data || !length);
4087 std::unique_ptr<node_t> n(
reinterpret_cast<node_t*
>(
new uint8_t[
sizeof(
node_t) + length]));
4090 memcpy(n->data, data, length);
4093 m_tail = m_tail->next = n.release();
4095 m_head = m_tail = n.release();
4096 m_state = state_t::ok;
4099 catch (
const std::bad_alloc&) {
4100 m_state = state_t::fail;
4107 m_size = m_offset = 0;
4113 m_state = state_t::ok;
4119 inline size_t size()
const {
return m_size; };
4122 size_t m_offset, m_size;
4126#pragma warning(suppress:4200)
4128 } *m_head, * m_tail;
4137 basic(num_files ? files[0]->
state() : state_t::fail),
4138 m_files(files, files + num_files)
4141 virtual _Success_(
return != 0 || length == 0) size_t
read(
4142 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
4144 _Assume_(data || !length);
4145 if (m_files.empty()) {
4146 m_state = state_t::fail;
4149 size_t result = m_files[0]->read(data, length);
4150 _Assume_(result <= length);
4151 m_state = m_files[0]->state();
4152 if (length > m_tmp.size())
4153 m_tmp.resize(length);
4154 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4155 if (m_files[i]->
read(m_tmp.data(), length) != result ||
4156 memcmp(m_tmp.data(), data, result))
4157 throw std::runtime_error(
"read mismatch");
4158 if (m_files[i]->
state() != m_state)
4159 throw std::runtime_error(
"state mismatch");
4164 virtual _Success_(
return != 0) size_t
write(
4165 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
4167 if (m_files.empty()) {
4168 m_state = state_t::fail;
4171 size_t result = m_files[0]->write(data, length);
4172 m_state = m_files[0]->state();
4173 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4174 if (m_files[i]->
write(data, length) != result)
4175 throw std::runtime_error(
"write mismatch");
4176 if (m_files[i]->
state() != m_state)
4177 throw std::runtime_error(
"state mismatch");
4184 if (m_files.empty()) {
4185 m_state = state_t::ok;
4188 m_files[0]->flush();
4189 m_state = m_files[0]->state();
4190 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4191 m_files[i]->flush();
4192 if (m_files[i]->
state() != m_state)
4193 throw std::runtime_error(
"state mismatch");
4199 if (m_files.empty()) {
4200 m_state = state_t::ok;
4203 m_files[0]->close();
4204 m_state = m_files[0]->state();
4205 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4206 m_files[i]->close();
4207 if (m_files[i]->
state() != m_state)
4208 throw std::runtime_error(
"state mismatch");
4211 m_tmp.shrink_to_fit();
4214 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
4216 if (m_files.empty()) {
4217 m_state = state_t::fail;
4220 fpos_t result = m_files[0]->seek(offset, how);
4221 m_state = m_files[0]->state();
4222 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4223 if (m_files[i]->
seek(offset, how) != result)
4224 throw std::runtime_error(
"seek mismatch");
4225 if (m_files[i]->
state() != m_state)
4226 throw std::runtime_error(
"state mismatch");
4233 if (m_files.empty())
4235 fpos_t result = m_files[0]->tell();
4236 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4237 if (m_files[i]->
tell() != result)
4238 throw std::runtime_error(
"tell mismatch");
4243 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
4245 if (m_files.empty())
4246 m_state = state_t::fail;
4247 m_files[0]->lock(offset, length);
4248 m_state = m_files[0]->state();
4249 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4250 m_files[i]->lock(offset, length);
4251 if (m_files[i]->
state() != m_state)
4252 throw std::runtime_error(
"state mismatch");
4256 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
4258 if (m_files.empty())
4259 m_state = state_t::fail;
4260 m_files[0]->unlock(offset, length);
4261 m_state = m_files[0]->state();
4262 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4263 m_files[i]->unlock(offset, length);
4264 if (m_files[i]->
state() != m_state)
4265 throw std::runtime_error(
"state mismatch");
4271 if (m_files.empty())
4273 fsize_t result = m_files[0]->size();
4274 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4275 if (m_files[i]->
size() != result)
4276 throw std::runtime_error(
"size mismatch");
4283 if (m_files.empty())
4284 m_state = state_t::fail;
4285 m_files[0]->truncate();
4286 m_state = m_files[0]->state();
4287 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
4288 m_files[i]->truncate();
4289 if (m_files[i]->
state() != m_state)
4290 throw std::runtime_error(
"state mismatch");
4295 std::vector<basic_file*> m_files;
4296 std::vector<uint8_t> m_tmp;
Encoding converter context.
Definition unicode.hpp:133
Provides read-ahead stream capability.
Definition stream.hpp:1244
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:1258
Provides write-back stream capability.
Definition stream.hpp:1311
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1348
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:1324
Basic seekable stream operations.
Definition stream.hpp:812
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:855
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:902
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:871
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:975
fpos_t seekbeg(fpos_t offset)
Seeks to absolute file position.
Definition stream.hpp:839
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:814
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:944
fpos_t seekcur(foff_t offset)
Seeks to relative from current file position.
Definition stream.hpp:846
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:910
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:926
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:881
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:918
fpos_t seekend(foff_t offset)
Seeks to relative from end file position.
Definition stream.hpp:853
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:935
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:2190
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:2247
virtual void flush()
Persists volatile element data.
Definition stream.hpp:2305
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:2197
virtual void close()
Closes the stream.
Definition stream.hpp:2294
UTF-8 byte-order-mark
Definition stream.hpp:79
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:402
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:175
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:625
size_t readln(std::basic_string< _Elem, _Traits, _Ax > &str)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:306
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:170
basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:465
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:611
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:638
virtual void flush()
Persists volatile element data.
Definition stream.hpp:126
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:142
virtual void close()
Closes the stream.
Definition stream.hpp:134
size_t readln(std::basic_string< T_to, _Traits, _Ax > &str, charset_encoder< T_from, T_to > &encoder)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:318
size_t readln_and_attach(std::basic_string< T_to, _Traits, _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:355
uint8_t read_byte()
Reads one byte of data.
Definition stream.hpp:210
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:184
size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
Writes formatted string to the stream.
Definition stream.hpp:597
size_t readln_and_attach(std::basic_string< _Elem, _Traits, _Ax > &str)
Reads stream to the end-of-line or end-of-file and append to str.
Definition stream.hpp:334
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:370
basic & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:497
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:96
void write_charset(charset_id charset)
Writes UTF8, UTF-16 or UTF-32 byte-order-mark.
Definition stream.hpp:582
size_t write_array(const std::basic_string< T_from, _Traits, _Ax > &str, charset_encoder< T_from, T_to > &encoder)
Writes array of characters to the stream.
Definition stream.hpp:443
basic & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
Writes string to the stream length-prefixed.
Definition stream.hpp:522
basic & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:287
fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
Writes content of another stream.
Definition stream.hpp:557
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:114
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:423
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:388
void write_byte(uint8_t byte, fsize_t amount=1)
Writes a byte of data.
Definition stream.hpp:221
basic & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:259
Buffered read/write stream.
Definition stream.hpp:1382
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1491
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:1412
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:1448
Buffered OS data stream (file, pipe, socket...)
Definition stream.hpp:2319
Cached file.
Definition stream.hpp:1792
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2060
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2039
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:1859
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2065
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2026
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2074
virtual void close()
Closes the stream.
Definition stream.hpp:1974
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:2096
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2020
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1983
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:1921
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:2032
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2083
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:2015
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2088
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1994
Cached file-system file.
Definition stream.hpp:3089
cached_file(const stdex::sstring &filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:3119
void open(const stdex::sstring &filename, int mode)
Opens file.
Definition stream.hpp:3153
void open(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:3132
cached_file(const schar_t *filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:3105
Modifies data on the fly when reading from/writing to a source stream. Could also be used to modify r...
Definition stream.hpp:1010
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1061
virtual void close()
Closes the stream.
Definition stream.hpp:1055
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:1039
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:1047
Compares multiple files to perform the same.
Definition stream.hpp:4134
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:4281
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:4164
virtual void close()
Closes the stream.
Definition stream.hpp:4197
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:4269
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:4243
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:4256
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:4214
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:4231
virtual void flush()
Persists volatile element data.
Definition stream.hpp:4182
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:4141
In-memory FIFO queue.
Definition stream.hpp:4035
virtual void close()
Closes the stream.
Definition stream.hpp:4105
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:4082
size_t size() const
Returns total size of pending data in the queue.
Definition stream.hpp:4119
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:4054
Limits file reading/writing to a predefined window.
Definition stream.hpp:1682
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1775
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1725
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:1738
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1731
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:1705
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1750
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:1691
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1760
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:1744
virtual void close()
Closes the stream.
Definition stream.hpp:1719
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:1770
File-system file.
Definition stream.hpp:2685
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:2879
file(const stdex::sstring &filename, int mode)
Opens file.
Definition stream.hpp:2706
static bool readonly(const stdex::sstring &filename)
Checks if file/folder/symlink is read-only.
Definition stream.hpp:3078
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2961
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2854
file(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:2695
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2975
static bool readonly(const stdex::schar_t *filename)
Checks if file/folder/symlink is read-only.
Definition stream.hpp:3060
static bool exists(const stdex::sstring &filename)
Checks if file/folder/symlink likely exists.
Definition stream.hpp:3048
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2947
void open(const schar_t *filename, int mode)
Opens file.
Definition stream.hpp:2714
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:3009
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2989
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2831
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2897
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2937
void open(const stdex::sstring &filename, int mode)
Opens file.
Definition stream.hpp:2787
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2792
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:2813
static bool exists(const stdex::schar_t *filename)
Checks if file/folder/symlink likely exists.
Definition stream.hpp:3033
Limits reading from/writing to stream to a predefined number of bytes.
Definition stream.hpp:1539
fsize_t read_limit
Number of bytes left that may be read from the stream.
Definition stream.hpp:1591
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:1547
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:1568
fsize_t write_limit
Number of bytes left, that can be written to the stream.
Definition stream.hpp:1592
In-memory file.
Definition stream.hpp:3171
memory_file & operator=(memory_file &&other) noexcept
Moves content from another file.
Definition stream.hpp:3353
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:3871
memory_file(const schar_t *filename, int mode)
Loads content from file-system file.
Definition stream.hpp:3251
memory_file & write_str(const std::basic_string< _Elem, _Traits, _Ax > &data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3750
memory_file(const memory_file &other)
Copies content from another file.
Definition stream.hpp:3269
size_t m_size
file size
Definition stream.hpp:4022
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:3960
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3785
uint8_t * m_data
file data
Definition stream.hpp:4019
memory_file & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:3539
virtual void close()
Closes the stream.
Definition stream.hpp:3835
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:3500
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:3866
size_t m_reserved
reserved file size
Definition stream.hpp:4023
memory_file(size_t size, state_t state=state_t::ok)
Creates an empty file of reserved size.
Definition stream.hpp:3192
void reserve(size_t required, bool tight=false) noexcept
Reallocates memory.
Definition stream.hpp:3391
memory_file(const stdex::sstring &filename, int mode)
Loads content from file-system file.
Definition stream.hpp:3262
memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:3579
memory_file(memory_file &&other) noexcept
Moves content from another file.
Definition stream.hpp:3324
void write_byte(uint8_t byte, size_t amount=1)
Writes a byte of data.
Definition stream.hpp:3634
memory_file & operator=(const memory_file &other)
Copies content from another file.
Definition stream.hpp:3294
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:3926
void load(const stdex::sstring &filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:3453
size_t m_offset
file pointer
Definition stream.hpp:4021
void save(const schar_t *filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:3464
void load(const schar_t *filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:3420
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3849
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3876
memory_file & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:3667
memory_file & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3705
void save(const stdex::sstring &filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:3490
bool m_manage
may reallocate m_data?
Definition stream.hpp:4020
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:3241
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:3610
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:3218
const void * data() const
Returns pointer to data.
Definition stream.hpp:3498
Definition stream.hpp:1158
enum stdex::stream::replicator::worker::op_t op
Operation to perform.
size_t num_written
Number of bytes written.
Definition stream.hpp:1207
size_t length
Byte limit of data to write.
Definition stream.hpp:1206
const void * data
Data to write.
Definition stream.hpp:1205
Replicates writing of the same data to multiple streams.
Definition stream.hpp:1075
void push_back(basic *source)
Adds stream on the list.
Definition stream.hpp:1094
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1151
void remove(basic *source)
Removes stream from the list.
Definition stream.hpp:1102
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:1119
virtual void close()
Closes the stream.
Definition stream.hpp:1146
Socket stream.
Definition stream.hpp:2341
socket_t get() const noexcept
Returns socket handle.
Definition stream.hpp:2397
virtual void close()
Closes the stream.
Definition stream.hpp:2443
socket(int af, int type, int protocol)
Creates a socket.
Definition stream.hpp:2376
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:2399
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:2423
Limits reading from/writing to stream to a predefined window.
Definition stream.hpp:1599
fpos_t write_offset
Number of bytes to discard on write.
Definition stream.hpp:1675
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:1636
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:1607
fpos_t read_offset
Number of bytes to skip on read.
Definition stream.hpp:1674
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:93
virtual void close()
Closes object.
Definition system.hpp:134
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:1516
Definition stream.hpp:4123