19#if defined(_WIN32) && !defined(WIN32_LEAN_AND_MEAN)
23#include <condition_variable>
30#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
31#define SET_FILE_OP_TIMES 1
32#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
33#elif !defined(SET_FILE_OP_TIMES)
34#define SET_FILE_OP_TIMES 0
36#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
37#define CHECK_STREAM_STATE 0
38#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
40#define CHECK_STREAM_STATE 1
59 using fsize_t = uint64_t;
60 constexpr fsize_t fsize_max = UINT64_MAX;
62 constexpr size_t iterate_count = 0x10;
63 constexpr size_t default_block_size = 0x10000;
64 constexpr wchar_t utf16_bom = L
'\ufeff';
65 constexpr const char utf8_bom[3] = {
'\xef',
'\xbb',
'\xbf' };
86 virtual _Success_(
return != 0 || length == 0) size_t
read(
87 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
89 UNREFERENCED_PARAMETER(data);
90 UNREFERENCED_PARAMETER(length);
91 m_state = state_t::fail;
104 virtual _Success_(
return != 0) size_t
write(
105 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
107 UNREFERENCED_PARAMETER(data);
108 UNREFERENCED_PARAMETER(length);
109 m_state = state_t::fail;
118 m_state = state_t::ok;
126 m_state = state_t::ok;
132 virtual void skip(_In_ fsize_t amount)
136 else if (amount < iterate_count) {
137 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
139 if (!
ok()) _Unlikely_
144 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
146 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
148 amount -=
read_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
149 if (!
ok()) _Unlikely_
153 catch (std::bad_alloc) { m_state = state_t::fail; }
160 inline state_t
state()
const {
return m_state; };
165 inline bool ok()
const {
return m_state == state_t::ok; };
176 std::vector<uint8_t> result;
177 size_t offset, length;
179 length = default_block_size;
180 while (offset < max_length) {
181 length = std::min(length, max_length);
182 try { result.resize(length); }
183 catch (std::bad_alloc) {
184 m_state = state_t::fail;
187 auto num_read =
read_array(result.data() + offset,
sizeof(uint8_t), length - offset);
189 if (!
ok()) _Unlikely_
191 length += default_block_size;
193 result.resize(offset);
205 throw std::runtime_error(
"failed to read");
214 write(&
byte,
sizeof(uint8_t));
215 else if (amount < iterate_count) {
216 for (
size_t i = 0; i < static_cast<size_t>(amount); i++) {
217 write(&
byte,
sizeof(uint8_t));
218 if (!
ok()) _Unlikely_
223 size_t block =
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
225 std::unique_ptr<uint8_t[]> dummy(
new uint8_t[block]);
226 memset(dummy.get(),
byte, block);
228 amount -=
write_array(dummy.get(),
sizeof(uint8_t),
static_cast<size_t>(std::min<fsize_t>(amount, block)));
229 if (!
ok()) _Unlikely_
233 catch (std::bad_alloc) { m_state = state_t::fail; }
251 if (!
ok()) _Unlikely_ {
260 m_state = state_t::eof;
279 if (!
ok()) _Unlikely_
282 T data_le = HE2LE(data);
283 write(&data_le,
sizeof(T));
285 write(&data,
sizeof(T));
295 template<
class _Traits = std::
char_traits<
char>,
class _Ax = std::allocator<
char>>
296 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
307 template<
class _Traits = std::
char_traits<
wchar_t>,
class _Ax = std::allocator<
wchar_t>>
308 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
319 template<
class _Traits = std::
char_traits<
wchar_t>,
class _Ax = std::allocator<
wchar_t>>
320 size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
322 if (charset == charset_id::utf16)
327 str2wstr(wstr, str, charset);
336 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
340 _Elem chr, previous = (_Elem)0;
343 if (!initial && !(previous ==
static_cast<_Elem
>(
'\r') && chr ==
static_cast<_Elem
>(
'\n')))
348 }
while (
ok() && chr !=
static_cast<_Elem
>(
'\n'));
357 template<
class _Traits = std::
char_traits<
wchar_t>,
class _Ax = std::allocator<
wchar_t>>
358 size_t readln_and_attach(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
360 if (charset == charset_id::utf16)
364 str2wstr(wstr, str, charset);
373 size_t read_array(_Out_writes_bytes_(size* count)
void* array, _In_
size_t size, _In_
size_t count)
375 for (
size_t to_read = mul(size, count);;) {
376 size_t num_read =
read(array, to_read);
380 if (!
ok()) _Unlikely_
381 return count - to_read / size;
382 reinterpret_cast<uint8_t*&
>(array) += num_read;
391 inline size_t write_array(_In_reads_bytes_opt_(size* count)
const void* array, _In_
size_t size, _In_
size_t count)
393 return write(array, mul(size, count)) / size;
405 size_t write_array(_In_reads_or_z_opt_(num_chars)
const wchar_t* wstr, _In_
size_t num_chars, _In_ charset_id charset)
407 if (!
ok()) _Unlikely_
409 num_chars = stdex::strnlen(wstr, num_chars);
410 if (charset != charset_id::utf16) {
411 std::string str(wstr2str(wstr, num_chars, charset));
412 return write_array(str.data(),
sizeof(
char), str.size());
414 return write_array(wstr,
sizeof(
wchar_t), num_chars);
428 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
429 inline basic&
read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data)
433 if (!
ok()) _Unlikely_ {
437 data.resize(num_chars);
438 data.resize(
read_array(data.data(),
sizeof(_Elem), num_chars));
457 size_t num_chars = stdex::strlen(data);
458 if (num_chars > UINT32_MAX)
459 throw std::invalid_argument(
"string too long");
461 if (!
ok()) _Unlikely_
473 size_t write_sa(_In_ LPSAFEARRAY sa)
475 safearray_accessor<void> a(sa);
477 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
478 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
479 throw std::invalid_argument(
"SafeArrayGet[UL]Bound failed");
480 return write(a.data(),
static_cast<size_t>(ubound) - lbound + 1);
491 std::unique_ptr<uint8_t[]> data(
new uint8_t[
static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
492 fsize_t num_copied = 0, to_write = amount;
493 m_state = state_t::ok;
495 size_t num_read = stream.read(data.get(),
static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
496 size_t num_written =
write(data.get(), num_read);
497 num_copied += num_written;
498 to_write -= num_written;
499 if (stream.m_state == state_t::eof) {
501 m_state = state_t::ok;
504 m_state = stream.m_state;
516 if (charset == charset_id::utf16)
518 else if (charset == charset_id::utf8)
527 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t locale, ...)
530 va_start(params, locale);
541 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t locale, ...)
544 va_start(params, locale);
555 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t locale, _In_ va_list params)
558 str.reserve(default_block_size);
559 vappendf(str, format, locale, params);
560 return write_array(str.data(),
sizeof(
char), str.size());
568 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
571 str.reserve(default_block_size);
572 vappendf(str, format, locale, params);
573 return write_array(str.data(),
sizeof(
wchar_t), str.size());
576 inline basic& operator >>(_Out_ int8_t& data) {
return read_data(data); }
577 inline basic& operator <<(_In_
const int8_t data) {
return write_data(data); }
578 inline basic& operator >>(_Out_ int16_t& data) {
return read_data(data); }
579 inline basic& operator <<(_In_
const int16_t data) {
return write_data(data); }
580 inline basic& operator >>(_Out_ int32_t& data) {
return read_data(data); }
581 inline basic& operator <<(_In_
const int32_t data) {
return write_data(data); }
582 inline basic& operator >>(_Out_ int64_t& data) {
return read_data(data); }
583 inline basic& operator <<(_In_
const int64_t data) {
return write_data(data); }
584 inline basic& operator >>(_Out_ uint8_t& data) {
return read_data(data); }
585 inline basic& operator <<(_In_
const uint8_t data) {
return write_data(data); }
586 inline basic& operator >>(_Out_ uint16_t& data) {
return read_data(data); }
587 inline basic& operator <<(_In_
const uint16_t data) {
return write_data(data); }
588 inline basic& operator >>(_Out_ uint32_t& data) {
return read_data(data); }
589 inline basic& operator <<(_In_
const uint32_t data) {
return write_data(data); }
590 inline basic& operator >>(_Out_ uint64_t& data) {
return read_data(data); }
591 inline basic& operator <<(_In_
const uint64_t data) {
return write_data(data); }
592#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
593 inline basic& operator >>(_Out_
size_t& data) {
return read_data(data); }
594 inline basic& operator <<(_In_
const size_t data) {
return write_data(data); }
596 inline basic& operator >>(_Out_
float& data) {
return read_data(data); }
597 inline basic& operator <<(_In_
const float data) {
return write_data(data); }
598 inline basic& operator >>(_Out_
double& data) {
return read_data(data); }
599 inline basic& operator <<(_In_
const double data) {
return write_data(data); }
600 inline basic& operator >>(_Out_
char& data) {
return read_data(data); }
601 inline basic& operator <<(_In_
const char data) {
return write_data(data); }
602#ifdef _NATIVE_WCHAR_T_DEFINED
603 inline basic& operator >>(_Out_
wchar_t& data) {
return read_data(data); }
604 inline basic& operator <<(_In_
const wchar_t data) {
return write_data(data); }
606 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
607 inline basic& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data) {
return read_str(data); }
609 inline basic& operator <<(_In_
const T* data) {
return write_str(data); }
618 using fpos_t = uint64_t;
619 constexpr fpos_t fpos_max = UINT64_MAX;
620 constexpr fpos_t fpos_min = 0;
625 using foff_t = int64_t;
626 constexpr foff_t foff_max = INT64_MAX;
627 constexpr foff_t foff_min = INT64_MIN;
645 using time_point = std::chrono::time_point<std::chrono::file_clock>;
647 using time_point = std::chrono::time_point<std::chrono::system_clock>;
658 size_t length = std::min<size_t>(max_length,
static_cast<size_t>(
size() -
tell()));
659 std::vector<uint8_t> result;
660 try { result.resize(length); }
661 catch (std::bad_alloc) {
662 m_state = state_t::fail;
665 result.resize(
read_array(result.data(),
sizeof(uint8_t), length));
674 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
681 inline fpos_t
seekbeg(_In_ fpos_t offset) {
return seek(offset, seek_t::beg); }
688 inline fpos_t
seekcur(_In_ foff_t offset) {
return seek(offset, seek_t::cur); }
695 inline fpos_t
seekend(_In_ foff_t offset) {
return seek(offset, seek_t::end); }
697 virtual void skip(_In_ fsize_t amount)
699 seek(amount, seek_t::cur);
708 virtual fpos_t
tell()
const = 0;
713 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
715 UNREFERENCED_PARAMETER(offset);
716 UNREFERENCED_PARAMETER(length);
717 throw std::exception(
"not implemented");
723 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
725 UNREFERENCED_PARAMETER(offset);
726 UNREFERENCED_PARAMETER(length);
727 throw std::exception(
"not implemented");
746 return time_point::min();
754 return time_point::min();
762 return time_point::min();
770 UNREFERENCED_PARAMETER(date);
771 throw std::exception(
"not implemented");
779 UNREFERENCED_PARAMETER(date);
780 throw std::exception(
"not implemented");
788 UNREFERENCED_PARAMETER(date);
789 throw std::exception(
"not implemented");
796 LPSAFEARRAY read_sa()
798 assert(
size() <= SIZE_MAX);
799 size_t length =
static_cast<size_t>(
size());
800 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
802 throw std::runtime_error(
"SafeArrayCreateVector failed");
803 safearray_accessor<void> a(sa.get());
805 throw std::runtime_error(
"failed to seek");
806 if (
read_array(a.data(), 1, length) != length)
807 throw std::runtime_error(
"failed to read");
817 charset_id
read_charset(_In_ charset_id default_charset = charset_id::default)
820 throw std::runtime_error(
"failed to seek");
823 if (!
ok()) _Unlikely_
824 return default_charset;
825 if (id_utf16 == utf16_bom)
826 return charset_id::utf16;
829 throw std::runtime_error(
"failed to seek");
830 char id_utf8[3] = { 0 };
832 if (!
ok()) _Unlikely_
833 return default_charset;
834 if (strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
835 return charset_id::utf8;
838 throw std::runtime_error(
"failed to seek");
839 return default_charset;
850 basic(state_t::fail),
854 void init(_Inout_
basic& source)
856 m_state = source.state();
862 basic(source.state()),
866 virtual _Success_(
return != 0 || length == 0) size_t
read(
867 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
869 size_t num_read = m_source->
read(data, length);
870 m_state = m_source->
state();
874 virtual _Success_(
return != 0) size_t
write(
875 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
877 size_t num_written = m_source->
write(data, length);
878 m_state = m_source->
state();
885 m_state = m_source->
state();
891 m_state = m_source->
state();
906 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
909 const std::lock_guard<std::mutex> lk(_w->mutex);
910 _w->op = worker::op_t::quit;
914 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
915 w->get()->thread.join();
923 m_workers.push_back(std::unique_ptr<worker>(
new worker(source)));
931 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
933 if (_w->source == source) {
935 const std::lock_guard<std::mutex> lk(_w->mutex);
936 _w->op = worker::op_t::quit;
946 virtual _Success_(
return != 0) size_t
write(
947 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
949 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
952 const std::lock_guard<std::mutex> lk(_w->mutex);
953 _w->op = worker::op_t::write;
959 size_t num_written = length;
960 m_state = state_t::ok;
961 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
963 std::unique_lock<std::mutex> lk(_w->mutex);
964 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
965 if (_w->num_written < num_written)
966 num_written = _w->num_written;
967 if (
ok() && !_w->source->ok())
968 m_state = _w->source->state();
975 foreach_worker(worker::op_t::close);
980 foreach_worker(worker::op_t::flush);
993 thread(process_op, std::ref(*
this))
997 static void process_op(_Inout_
worker& w)
1000 std::unique_lock<std::mutex> lk(w.mutex);
1001 w.cv.wait(lk, [&] {
return w.op != op_t::noop; });
1006 w.num_written = w.source->write(w.data, w.length);
1034 std::condition_variable cv;
1038 void foreach_worker(_In_ worker::op_t op)
1040 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1043 const std::lock_guard<std::mutex> lk(_w->mutex);
1046 _w->cv.notify_one();
1048 m_state = state_t::ok;
1049 for (
auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
1051 std::unique_lock<std::mutex> lk(_w->mutex);
1052 _w->cv.wait(lk, [&] {
return _w->op == worker::op_t::noop; });
1054 m_state = _w->source->state();
1058 std::list<std::unique_ptr<worker>> m_workers;
1061 constexpr size_t default_async_limit = 0x100000;
1068 template <
size_t CAPACITY = default_async_limit>
1074 m_worker(process, std::ref(*
this))
1083#pragma warning(suppress: 6101)
1084 virtual _Success_(
return != 0 || length == 0) size_t
read(
1085 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1087 assert(data || !length);
1088 for (
size_t to_read = length;;) {
1089 uint8_t* ptr;
size_t num_read;
1090 std::tie(ptr, num_read) = m_ring.front();
1091 if (!ptr) _Unlikely_ {
1093 m_state = to_read < length || !length ? state_t::ok : m_source->
state();
1094 return length - to_read;
1096 if (to_read < num_read)
1098 memcpy(data, ptr, num_read);
1099 m_ring.pop(num_read);
1100 to_read -= num_read;
1102 m_state = state_t::ok;
1105 reinterpret_cast<uint8_t*&
>(data) += num_read;
1113 uint8_t* ptr;
size_t num_write;
1114 std::tie(ptr, num_write) = w.m_ring.back();
1115 if (!ptr) _Unlikely_
1117 num_write = w.m_source->read(ptr, num_write);
1118 w.m_ring.push(num_write);
1119 if (!w.m_source->ok()) {
1127 ring<uint8_t, CAPACITY> m_ring;
1128 std::thread m_worker;
1136 template <
size_t CAPACITY = default_async_limit>
1142 m_worker(process, std::ref(*
this))
1151 virtual _Success_(
return != 0) size_t
write(
1152 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1154 assert(data || !length);
1155 for (
size_t to_write = length;;) {
1156 uint8_t* ptr;
size_t num_write;
1157 std::tie(ptr, num_write) = m_ring.back();
1158 if (!ptr) _Unlikely_ {
1159 m_state = state_t::fail;
1160 return length - to_write;
1162 if (to_write < num_write)
1163 num_write = to_write;
1164 memcpy(ptr, data, num_write);
1165 m_ring.push(num_write);
1166 to_write -= num_write;
1168 m_state = state_t::ok;
1171 reinterpret_cast<const uint8_t*&
>(data) += num_write;
1185 uint8_t* ptr;
size_t num_read;
1186 std::tie(ptr, num_read) = w.m_ring.front();
1189 num_read = w.m_source->write(ptr, num_read);
1190 w.m_ring.pop(num_read);
1191 if (!w.m_source->ok()) {
1199 ring<uint8_t, CAPACITY> m_ring;
1200 std::thread m_worker;
1203 constexpr size_t default_buffer_size = 0x400;
1211 explicit buffer(_In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1213 m_read_buffer(read_buffer_size),
1214 m_write_buffer(write_buffer_size)
1218 buffer(_Inout_
basic& source, _In_
size_t read_buffer_size = default_buffer_size, _In_
size_t write_buffer_size = default_buffer_size) :
1220 m_read_buffer(read_buffer_size),
1221 m_write_buffer(write_buffer_size)
1230 virtual _Success_(
return != 0 || length == 0) size_t
read(
1231 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1233 assert(data || !length);
1234 for (
size_t to_read = length;;) {
1235 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
1236 if (to_read <= buffer_size) {
1237 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
1238 m_read_buffer.head += to_read;
1239 m_state = state_t::ok;
1243 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
1244 reinterpret_cast<uint8_t*&
>(data) += buffer_size;
1245 to_read -= buffer_size;
1247 m_read_buffer.head = 0;
1248 if (to_read > m_read_buffer.capacity) {
1250 m_read_buffer.tail = 0;
1251 to_read -= m_source->
read(data, to_read);
1252 m_state = to_read < length ? state_t::ok : m_source->
state();
1253 return length - to_read;
1255 m_read_buffer.tail = m_source->
read(m_read_buffer.data, m_read_buffer.capacity);
1256 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
1257 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
1258 m_read_buffer.head = m_read_buffer.tail;
1259 to_read -= m_read_buffer.tail;
1260 m_state = to_read < length ? state_t::ok : m_source->
state();
1261 return length - to_read;
1266 virtual _Success_(
return != 0) size_t
write(
1267 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1269 assert(data || !length);
1270 if (!length) _Unlikely_ {
1273 if (!
ok()) _Unlikely_
1275 m_source->
write(
nullptr, 0);
1276 m_state = m_source->
state();
1280 for (
size_t to_write = length;;) {
1281 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
1282 if (to_write <= available_buffer) {
1283 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
1284 m_write_buffer.tail += to_write;
1285 m_state = state_t::ok;
1288 if (available_buffer) {
1289 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
1290 reinterpret_cast<const uint8_t*&
>(data) += available_buffer;
1291 to_write -= available_buffer;
1292 m_write_buffer.tail += available_buffer;
1294 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1296 m_write_buffer.head += m_source->
write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1297 m_state = m_source->
state();
1298 if (m_write_buffer.head == m_write_buffer.tail)
1299 m_write_buffer.head = m_write_buffer.tail = 0;
1301 return length - to_write;
1303 if (to_write > m_write_buffer.capacity) {
1305 to_write -= m_source->
write(data, to_write);
1306 m_state = m_source->
state();
1307 return length - to_write;
1322 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
1324 m_write_buffer.head += m_source->
write(m_write_buffer.data + m_write_buffer.head, buffer_size);
1325 if (m_write_buffer.head == m_write_buffer.tail) {
1326 m_write_buffer.head = 0;
1327 m_write_buffer.tail = 0;
1330 m_state = m_source->
state();
1334 m_state = state_t::ok;
1339 size_t head, tail, capacity;
1341 buffer_t(_In_
size_t buffer_size) :
1344 capacity(buffer_size),
1345 data(buffer_size ?
new uint8_t[buffer_size] :
nullptr)
1353 } m_read_buffer, m_write_buffer;
1362 limiter(_Inout_
basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
1368 virtual _Success_(
return != 0 || length == 0) size_t
read(
1369 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1373 num_read = m_source->
read(data, length);
1374 m_state = m_source->
state();
1377 num_read = m_source->
read(data, length);
1378 m_state = m_source->
state();
1383 m_state = state_t::eof;
1386 num_read = m_source->
read(data,
static_cast<size_t>(
read_limit));
1387 m_state = m_source->
state();
1393 virtual _Success_(
return != 0) size_t
write(
1394 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1398 num_written = m_source->
write(data, length);
1399 m_state = m_source->
state();
1402 num_written = m_source->
write(data, length);
1403 m_state = m_source->
state();
1408 m_state = state_t::fail;
1412 m_state = m_source->
state();
1430 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) :
1436 virtual _Success_(
return != 0 || length == 0) size_t
read(
1437 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1441 m_state = m_source->
state();
1442 if (!
ok()) _Unlikely_
1448 num_read = m_source->
read(data, length);
1449 m_state = m_source->
state();
1452 num_read = m_source->
read(data, length);
1453 m_state = m_source->
state();
1458 m_source->
skip(length);
1459 m_state = state_t::eof;
1462 num_read = m_source->
read(data,
static_cast<size_t>(
read_limit));
1463 m_state = m_source->
state();
1469 virtual _Success_(
return != 0) size_t
write(
1470 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1472 size_t num_skipped, num_written;
1475 m_state = state_t::ok;
1479 reinterpret_cast<const uint8_t*&
>(data) +=
static_cast<size_t>(
write_offset);
1487 num_written = m_source->
write(data, length);
1488 m_state = m_source->
state();
1491 num_written = m_source->
write(data, length);
1492 m_state = m_source->
state();
1496 num_skipped += length;
1498 m_state = state_t::ok;
1501 num_skipped += length -
static_cast<size_t>(
write_limit);
1503 m_state = m_source->
state();
1506 return num_skipped + num_written;
1522 basic(source.state()),
1524 m_offset(source.tell()),
1525 m_region(offset, offset + length)
1528 virtual _Success_(
return != 0 || length == 0) size_t
read(
1529 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1531 assert(data || !length);
1533 size_t num_read = m_source.
read(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1534 m_state = m_source.
state();
1535 m_offset += num_read;
1538 m_state = length ? state_t::eof : state_t::ok;
1542 virtual _Success_(
return != 0) size_t
write(
1543 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1545 assert(data || !length);
1547 size_t num_written = m_source.
write(data,
static_cast<size_t>(std::min<fpos_t>(length, m_region.
end - m_offset)));
1548 m_state = m_source.
state();
1549 m_offset += num_written;
1552 m_state = state_t::fail;
1559 m_state = m_source.
state();
1565 m_state = m_source.
state();
1568 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
1570 m_offset = m_source.
seek(offset, how);
1571 m_state = m_source.
state();
1572 return ok() ? m_offset - m_region.
start : fpos_max;
1575 virtual void skip(_In_ fsize_t amount)
1577 m_source.
skip(amount);
1578 m_state = m_source.
state();
1583 fpos_t offset = m_source.
tell();
1584 return m_region.
contains(offset) ? offset - m_region.
start : fpos_max;
1587 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
1590 m_source.
lock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1591 m_state = m_source.
state();
1594 m_state = state_t::fail;
1597 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
1600 m_source.
unlock(m_region.
start + offset, std::min<fsize_t>(length, m_region.
end - offset));
1601 m_state = m_source.
state();
1604 m_state = state_t::fail;
1609 return m_region.
size();
1614 m_state = state_t::fail;
1623 constexpr size_t default_cache_size = 0x1000;
1631 explicit cache(_In_
size_t cache_size = default_cache_size) :
1632 basic(state_t::fail),
1634 m_cache(cache_size),
1636#if SET_FILE_OP_TIMES
1637 , m_atime(time_point::min()),
1638 m_mtime(time_point::min())
1644 m_state = source.state();
1650 cache(_Inout_
basic_file& source, _In_
size_t cache_size = default_cache_size) :
1651 basic(source.state()),
1653 m_cache(cache_size),
1655#if SET_FILE_OP_TIMES
1656 , m_atime(time_point::min()),
1657 m_mtime(time_point::min())
1669 virtual _Success_(
return != 0 || length == 0) size_t
read(
1670 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1672 assert(data || !length);
1673#if SET_FILE_OP_TIMES
1674 m_atime = time_point::now();
1676 for (
size_t to_read = length;;) {
1677 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1680 if (to_read <= remaining_cache) {
1681 memcpy(data, m_cache.data +
static_cast<size_t>(
m_offset - m_cache.
region.
start), to_read);
1683 m_state = state_t::ok;
1686 memcpy(data, m_cache.data +
static_cast<size_t>(
m_offset - m_cache.
region.
start), remaining_cache);
1687 reinterpret_cast<uint8_t*&
>(data) += remaining_cache;
1688 to_read -= remaining_cache;
1692 if (!
ok()) _Unlikely_ {
1693 if (to_read < length)
1694 m_state = state_t::ok;
1695 return length - to_read;
1699 fpos_t end_max =
m_offset + to_read;
1700 if (
m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1703 if (!m_source->
ok()) _Unlikely_ {
1704 m_state = to_read < length ? state_t::ok : state_t::fail;
1705 return length - to_read;
1707 size_t num_read = m_source->
read(data, to_read -
static_cast<size_t>(end_max % m_cache.capacity));
1709 to_read -= num_read;
1711 m_state = state_t::ok;
1714 reinterpret_cast<uint8_t*&
>(data) += num_read;
1715 m_state = m_source->
state();
1717 if (to_read < length)
1718 m_state = state_t::ok;
1719 return length - to_read;
1725 m_state = to_read < length ? state_t::ok : state_t::fail;
1726 return length - to_read;
1731 virtual _Success_(
return != 0) size_t
write(
1732 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
1734 assert(data || !length);
1735#if SET_FILE_OP_TIMES
1736 m_atime = m_mtime = time_point::now();
1738 for (
size_t to_write = length;;) {
1739 if (m_cache.status != cache_t::cache_t::status_t::empty) {
1740 fpos_t end_max = m_cache.
region.
start + m_cache.capacity;
1742 size_t remaining_cache =
static_cast<size_t>(end_max -
m_offset);
1743 if (to_write <= remaining_cache) {
1744 memcpy(m_cache.data +
static_cast<size_t>(
m_offset - m_cache.
region.
start), data, to_write);
1746 m_cache.status = cache_t::cache_t::status_t::dirty;
1748 m_state = state_t::ok;
1751 memcpy(m_cache.data +
static_cast<size_t>(
m_offset - m_cache.
region.
start), data, remaining_cache);
1752 reinterpret_cast<const uint8_t*&
>(data) += remaining_cache;
1753 to_write -= remaining_cache;
1755 m_cache.status = cache_t::cache_t::status_t::dirty;
1759 if (!
ok()) _Unlikely_
1760 return length - to_write;
1763 fpos_t end_max =
m_offset + to_write;
1764 if (
m_offset / m_cache.capacity < end_max / m_cache.capacity) {
1767 if (!
ok()) _Unlikely_
1768 return length - to_write;
1769 size_t num_written = m_source->
write(data, to_write -
static_cast<size_t>(end_max % m_cache.capacity));
1770 reinterpret_cast<const uint8_t*&
>(data) += num_written;
1771 to_write -= num_written;
1773 m_state = m_source->
state();
1774 if (!to_write || !
ok())
1775 return length - to_write;
1779 if (!
ok()) _Unlikely_
1780 return length - to_write;
1788 m_state = m_source->
state();
1793#if SET_FILE_OP_TIMES
1794 m_atime = m_mtime = time_point::min();
1797 if (!
ok()) _Unlikely_
1802 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
1804 m_state = state_t::ok;
1813 throw std::invalid_argument(
"unknown seek origin");
1822 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
1824 m_source->
lock(offset, length);
1825 m_state = m_source->
state();
1828 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
1830 m_source->
unlock(offset, length);
1831 m_state = m_source->
state();
1836 return m_cache.data ? std::max(m_source->
size(), m_cache.
region.
end) : m_source->
size();
1841#if SET_FILE_OP_TIMES
1842 m_atime = m_mtime = time_point::now();
1855 m_cache.status = cache_t::cache_t::status_t::empty;
1858 m_state = m_source->
state();
1863 return m_source->
ctime();
1868#if SET_FILE_OP_TIMES
1869 return std::max(m_atime, m_source->
atime());
1871 return m_source->
atime();
1877#if SET_FILE_OP_TIMES
1878 return std::max(m_mtime, m_source->
mtime());
1880 return m_source->
mtime();
1891#if SET_FILE_OP_TIMES
1899#if SET_FILE_OP_TIMES
1908 if (m_cache.status != cache_t::cache_t::status_t::dirty) {
1909 m_state = state_t::ok;
1913 m_source->
write(m_cache.data,
static_cast<size_t>(m_cache.
region.
size()));
1914 m_state = m_source->
state();
1916 m_cache.status = cache_t::cache_t::status_t::loaded;
1919 m_state = state_t::ok;
1920 m_cache.status = cache_t::cache_t::status_t::loaded;
1924 void invalidate_cache()
1929 m_cache.status = cache_t::cache_t::status_t::empty;
1933 void load_cache(_In_ fpos_t start)
1935 assert(m_cache.status != cache_t::cache_t::status_t::dirty);
1936 start -= start % m_cache.capacity;
1938 if (m_source->
ok()) {
1939 m_cache.
region.
end = start + m_source->
read(m_cache.data, m_cache.capacity);
1940 m_cache.status = cache_t::cache_t::status_t::loaded;
1941 m_state = state_t::ok;
1944 m_state = state_t::fail;
1947 basic_file* m_source;
1951 enum class status_t {
1958 cache_t(_In_
size_t _capacity) :
1959 data(new uint8_t[_capacity]),
1960 capacity(_capacity),
1961 status(status_t::empty),
1971#if SET_FILE_OP_TIMES
1984 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok) :
1989 virtual _Success_(
return != 0 || length == 0) size_t
read(
1990 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
1992 assert(data || !length);
1998 block_size = 0x1F80000;
1999#elif defined(_WIN32)
2000 block_size = 0x3f00000;
2002 block_size = SSIZE_MAX;
2004 for (
size_t to_read = length;;) {
2009 __try { succeeded = ReadFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_read, block_size)), &num_read,
nullptr); }
2010 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
2011 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
2014 block_size = default_block_size;
2017 if (!succeeded) _Unlikely_
2019 ssize_t num_read =
static_cast<ssize_t
>(std::min<size_t>(to_read, block_size));
2020 num_read =
read(m_h, data, num_read);
2021 if (num_read < 0) _Unlikely_
2024 m_state = to_read < length ? state_t::ok : state_t::fail;
2025 return length - to_read;
2027 if (!num_read) _Unlikely_ {
2028 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2029 return length - to_read;
2031 to_read -= num_read;
2033 m_state = state_t::ok;
2036 reinterpret_cast<uint8_t*&
>(data) += num_read;
2040 virtual _Success_(
return != 0) size_t
write(
2041 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2048 block_size = 0x1F80000;
2049#elif defined(_WIN32)
2050 block_size = 0x3f00000;
2052 block_size = SSIZE_MAX;
2054 for (
size_t to_write = length;;) {
2059 __try { succeeded = WriteFile(m_h, data,
static_cast<DWORD
>(std::min<size_t>(to_write, block_size)), &num_written,
nullptr); }
2060 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
2061 to_write -= num_written;
2063 m_state = state_t::ok;
2066 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2067 if (!succeeded) _Unlikely_ {
2068 m_state = state_t::fail;
2069 return length - to_write;
2072 ssize_t num_written =
write(m_h, data,
static_cast<ssize_t
>(std::min<size_t>(to_write, block_size)));
2073 if (num_written < 0) _Unlikely_ {
2074 m_state = state_t::fail;
2075 return length - to_write;
2077 to_write -= num_written;
2079 m_state = state_t::ok;
2082 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2091 m_state = state_t::ok;
2093 catch (std::exception) {
2094 m_state = state_t::fail;
2101 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
2103 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
2114 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) :
2115 buffer(read_buffer_size, write_buffer_size),
2129 class ISequentialStream :
public basic
2132 ISequentialStream(_In_::ISequentialStream* source) : m_source(source)
2137 virtual ~ISequentialStream()
2139 m_source->Release();
2142 virtual _Success_(
return != 0 || length == 0) size_t read(
2143 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2145 assert(data || !length);
2146 for (
size_t to_read = length;;) {
2149 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
2150 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2151 if (FAILED(hr)) _Unlikely_ {
2152 m_state = to_read < length ? state_t::ok : state_t::fail;
2153 return length - to_read;
2155 to_read -= num_read;
2156 if (hr == S_FALSE) _Unlikely_ {
2157 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2158 return length - to_read;
2161 m_state = state_t::ok;
2164 reinterpret_cast<uint8_t*&
>(data) += num_read;
2168 virtual _Success_(
return != 0) size_t write(
2169 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2171 assert(data || !length);
2172 for (
size_t to_write = length;;) {
2174 ULONG num_written = 0;
2175 __try { hr = m_source->Write(data,
static_cast<ULONG
>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
2176 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2179 if (FAILED(hr)) _Unlikely_ {
2180 m_state = state_t::fail;
2181 return length - to_write;
2183 to_write -= num_written;
2185 m_state = state_t::ok;
2188 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2193 ::ISequentialStream* m_source;
2196#ifndef WIN32_LEAN_AND_MEAN
2200 class asp :
public basic
2203 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
2205 m_response(response)
2208 m_request->AddRef();
2210 m_response->AddRef();
2216 m_request->Release();
2218 m_response->Release();
2221 virtual _Success_(
return != 0 || length == 0) size_t read(
2222 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
2224 assert(data || !length);
2225 if (!m_request) _Unlikely_ {
2226 m_state = state_t::fail;
2229 for (
size_t to_read = length;;) {
2230 VARIANT var_amount, var_data;
2231 V_VT(&var_amount) = VT_I4;
2232 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
2233 V_VT(&var_data) = VT_EMPTY;
2234 HRESULT hr = [&]() {
2235 __try {
return m_request->BinaryRead(&var_amount, &var_data); }
2236 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2238 if (FAILED(hr)) _Unlikely_ {
2239 m_state = to_read < length ? state_t::ok : state_t::fail;
2240 return length - to_read;
2242 assert(V_VT(&var_amount) == VT_I4);
2243 assert(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
2244 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
2245 if (!V_I4(&var_amount)) _Unlikely_ {
2246 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
2247 return length - to_read;
2249 safearray_accessor<uint8_t> a(sa.get());
2250 memcpy(data, a.data(), V_I4(&var_amount));
2251 to_read -= V_I4(&var_amount);
2253 m_state = state_t::ok;
2256 reinterpret_cast<uint8_t*&
>(data) += V_I4(&var_amount);
2260 virtual _Success_(
return != 0) size_t write(
2261 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
2264 m_state = state_t::fail;
2267 for (
size_t to_write = length;;) {
2268 UINT num_written =
static_cast<UINT
>(std::min<size_t>(to_write, UINT_MAX));
2269 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(
reinterpret_cast<LPCSTR
>(data), num_written));
2271 V_VT(&var_data) = VT_BSTR;
2272 V_BSTR(&var_data) = bstr_data.get();
2273 HRESULT hr = [&]() {
2274 __try {
return m_response->BinaryWrite(var_data); }
2275 __except (EXCEPTION_EXECUTE_HANDLER) {
return E_FAIL; }
2277 if (FAILED(hr)) _Unlikely_ {
2278 m_state = state_t::fail;
2279 return length - to_write;
2281 to_write -= num_written;
2283 m_state = state_t::ok;
2286 reinterpret_cast<const uint8_t*&
>(data) += num_written;
2290 virtual void close()
2293 __try { m_response->End(); }
2294 __except (EXCEPTION_EXECUTE_HANDLER) {}
2296 m_state = state_t::ok;
2299 virtual void flush()
2303 __try { hr = m_response->Flush(); }
2304 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
2305 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
2310 IRequest* m_request;
2311 IResponse* m_response;
2321 mode_for_reading = 1 << 0,
2322 mode_for_writing = 1 << 1,
2323 mode_for_chmod = 1 << 2,
2324 mode_create = 1 << 3,
2325 mode_preserve_existing = mode_create | (1 << 4),
2326 mode_append = 1 << 5,
2328 mode_binary = 1 << 6,
2331 share_reading = 1 << 7,
2332 share_writing = 1 << 8,
2333 share_deleting = 1 << 9,
2334 share_all = share_reading | share_writing | share_deleting,
2336 inherit_handle = 1 << 10,
2338 hint_write_thru = 1 << 11,
2339 hint_no_buffering = 1 << 12,
2340 hint_random_access = 1 << 13,
2341 hint_sequential_access = 1 << 14,
2344#pragma warning(push)
2345#pragma warning(disable: 4250)
2360 file(_In_z_
const sys_char* filename, _In_
int mode)
2362 open(filename, mode);
2371 void open(_In_z_
const sys_char* filename, _In_
int mode)
2373 if (m_h != invalid_handle)
2377 DWORD dwDesiredAccess = 0;
2378 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
2379 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
2380 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
2382 DWORD dwShareMode = 0;
2383 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
2384 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
2385 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
2387 SECURITY_ATTRIBUTES sa = {
sizeof(SECURITY_ATTRIBUTES) };
2388 sa.bInheritHandle = mode & inherit_handle ? true :
false;
2390 DWORD dwCreationDisposition;
2391 switch (mode & mode_preserve_existing) {
2392 case mode_create: dwCreationDisposition = CREATE_ALWAYS;
break;
2393 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS;
break;
2394 case 0: dwCreationDisposition = OPEN_EXISTING;
break;
2395 default:
throw std::invalid_argument(
"invalid mode");
2398 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
2399 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
2400 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
2401 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
2402 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
2404 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes,
nullptr);
2407 if (mode & mode_for_reading) flags |= O_RDONLY;
2408 if (mode & mode_for_writing) flags |= O_WRONLY;
2409 if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
2410 if (mode & hint_write_thru) flags |= O_DSYNC;
2411 if (mode & hint_no_buffering) flags |= O_RSYNC;
2413 m_h =
open(filename, flags, DEFFILEMODE);
2415 if (m_h != invalid_handle) {
2416 m_state = state_t::ok;
2417 if (mode & mode_append)
2418 seek(0, seek_t::end);
2421 m_state = state_t::fail;
2424 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
2428 li.QuadPart = offset;
2429 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart,
static_cast<DWORD
>(how));
2430 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
2431 m_state = state_t::ok;
2435 off64_t result = lseek64(m_h, offset, how);
2437 m_state = state_t::ok;
2441 m_state = state_t::fail;
2447 if (m_h != invalid_handle) {
2451 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
2452 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
2455 off64_t result = lseek64(m_h, 0, SEEK_CUR);
2463 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
2466 LARGE_INTEGER liOffset;
2467 LARGE_INTEGER liSize;
2468 liOffset.QuadPart = offset;
2469 liSize.QuadPart = length;
2470 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2471 m_state = state_t::ok;
2475 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2477 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
2478 lseek64(m_h, orig, SEEK_SET);
2479 m_state = state_t::ok;
2483 m_state = state_t::fail;
2486 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
2489 LARGE_INTEGER liOffset;
2490 LARGE_INTEGER liSize;
2491 liOffset.QuadPart = offset;
2492 liSize.QuadPart = length;
2493 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
2494 m_state = state_t::ok;
2498 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
2500 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
2501 lseek64(m_h, orig, SEEK_SET);
2502 m_state = state_t::ok;
2505 lseek64(m_h, orig, SEEK_SET);
2508 m_state = state_t::fail;
2515 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
2516 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
2520 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
2522 length = lseek64(m_h, 0, SEEK_END);
2523 lseek64(m_h, orig, SEEK_SET);
2532 if (SetEndOfFile(m_h)) {
2533 m_state = state_t::ok;
2537 off64_t length = lseek64(m_h, 0, SEEK_CUR);
2538 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
2539 m_state = state_t::ok;
2543 m_state = state_t::fail;
2547 static inline time_point ft2tp(_In_
const FILETIME& ft)
2550 uint64_t t = (
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
2552 uint64_t t = ((
static_cast<int64_t
>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
2554 return time_point(time_point::duration(t));
2557 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
2560 uint64_t t = tp.time_since_epoch().count();
2562 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
2564 ft.dwHighDateTime =
static_cast<DWORD
>((t >> 32) & 0xffffffff);
2565 ft.dwLowDateTime =
static_cast<DWORD
>(t & 0xffffffff);
2573 if (GetFileTime(m_h, &ft,
nullptr,
nullptr))
2576 return time_point::min();
2583 if (GetFileTime(m_h,
nullptr, &ft,
nullptr))
2587 if (fstat(m_h, &buf) >= 0);
2588 return time_point::from_time_t(buf.st_atim);
2590 return time_point::min();
2597 if (GetFileTime(m_h,
nullptr,
nullptr, &ft))
2601 if (fstat(m_h, &buf) >= 0)
2602 return time_point::from_time_t(buf.st_mtim);
2604 return time_point::min();
2609 assert(m_h != invalid_handle);
2613 if (SetFileTime(m_h, &ft,
nullptr,
nullptr))
2616 throw std::runtime_error(
"failed to set file ctime");
2621 assert(m_h != invalid_handle);
2625 if (SetFileTime(m_h,
nullptr, &ft,
nullptr))
2628 struct timespec ts[2];
2629 ts[0].tv_sec = date;
2630 ts[1].tv_nsec = UTIME_OMIT;
2631 if (futimens(m_h, ts) >= 0)
2634 throw std::runtime_error(
"failed to set file atime");
2642 if (SetFileTime(m_h,
nullptr,
nullptr, &ft))
2645 struct timespec ts[2];
2646 ts[0].tv_nsec = UTIME_OMIT;
2647 ts[1].tv_sec = date;
2648 if (futimens(m_h, ts) >= 0)
2651 throw std::runtime_error(
"failed to set file mtime");
2662 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t
state = state_t::ok, _In_
size_t cache_size = default_cache_size) :
2676 cached_file(_In_z_
const sys_char* filename, _In_
int mode, _In_
size_t cache_size = default_cache_size) :
2678 m_source(filename, mode& mode_for_writing ? mode | mode_for_reading : mode)
2690 void open(_In_z_
const sys_char* filename, _In_
int mode)
2692 if (mode & mode_for_writing) mode |= mode_for_reading;
2693 m_source.
open(filename, mode);
2694 if (m_source.
ok()) {
2695#if SET_FILE_OP_TIMES
2696 m_atime = m_mtime = time_point::min();
2699 m_state = state_t::ok;
2702 m_state = state_t::fail;
2723#if SET_FILE_OP_TIMES
2724 m_ctime = m_atime = m_mtime = time_point::now();
2736 m_data(reinterpret_cast<uint8_t*>(malloc(
size))),
2743 throw std::bad_alloc();
2744#if SET_FILE_OP_TIMES
2745 m_ctime = m_atime = m_mtime = time_point::now();
2767 assert(reserved >=
size);
2768#if SET_FILE_OP_TIMES
2769 m_ctime = m_atime = m_mtime = time_point::now();
2793 load(filename, mode);
2808 void reserve(_In_
size_t required, _In_
bool tight =
false) noexcept
2811 m_state = state_t::ok;
2815 m_state = state_t::fail;
2818 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
2819 auto data =
reinterpret_cast<uint8_t*
>(realloc(
m_data, reserved));
2820 if (!
data && reserved) _Unlikely_ {
2821 m_state = state_t::fail;
2828 m_state = state_t::ok;
2837 void load(_In_z_
const sys_char* filename, _In_
int mode)
2839 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
2841 m_state = state_t::fail;
2845 if (
size > SIZE_MAX) {
2846 m_state = state_t::fail;
2850 if (!
ok()) _Unlikely_ {
2857#if SET_FILE_OP_TIMES
2858 m_ctime = f.
ctime();
2859 m_atime = f.
atime();
2860 m_mtime = f.
mtime();
2870 void save(_In_z_
const sys_char* filename, _In_
int mode)
2872 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
2874 m_state = state_t::fail;
2879 m_state = state_t::fail;
2883#if SET_FILE_OP_TIMES
2895 virtual _Success_(
return != 0 || length == 0) size_t
read(
2896 _Out_writes_bytes_to_opt_(length, return)
void*
data, _In_
size_t length)
2898 assert(
data || !length);
2899#if SET_FILE_OP_TIMES
2900 m_atime = time_point::now();
2903 if (length <= available) {
2906 m_state = state_t::ok;
2909 if (length && !available) {
2910 m_state = state_t::eof;
2915 m_state = state_t::ok;
2936#if SET_FILE_OP_TIMES
2937 m_atime = time_point::now();
2939 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
2943 size_t end_offset =
m_offset +
sizeof(T);
2944 if (end_offset <=
m_size) {
2947#if !CHECK_STREAM_STATE
2948 m_state = state_t::ok;
2954 m_state = state_t::eof;
2973 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2976#if SET_FILE_OP_TIMES
2977 m_atime = time_point::now();
2979 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_ {
2983 size_t end_offset =
m_offset +
sizeof(uint32_t);
2984 if (end_offset <=
m_size) {
2985 uint32_t num_chars = LE2HE(*
reinterpret_cast<uint32_t*
>(
m_data +
m_offset));
2987 end_offset = stdex::add(
m_offset + stdex::mul(num_chars,
sizeof(_Elem)));
2989 if (end_offset <=
m_size) {
2990 data.assign(start, start + num_chars);
2992#if !CHECK_STREAM_STATE
2993 m_state = state_t::ok;
2997 if (end_offset <=
m_size)
3001 m_state = state_t::eof;
3005 virtual _Success_(
return != 0) size_t
write(
3006 _In_reads_bytes_opt_(length) const
void*
data, _In_
size_t length)
3008 assert(
data || !length);
3009#if SET_FILE_OP_TIMES
3010 m_atime = m_mtime = time_point::now();
3012 size_t end_offset =
m_offset + length;
3015 if (!
ok()) _Unlikely_
3022 m_state = state_t::ok;
3031#if SET_FILE_OP_TIMES
3032 m_atime = m_mtime = time_point::now();
3034 size_t end_offset =
m_offset + amount;
3037 if (!
ok()) _Unlikely_
3044 m_state = state_t::ok;
3064#if SET_FILE_OP_TIMES
3065 m_atime = m_mtime = time_point::now();
3067 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3069 size_t end_offset =
m_offset +
sizeof(T);
3072 if (!
ok()) _Unlikely_
3079#if !CHECK_STREAM_STATE
3080 m_state = state_t::ok;
3102#if SET_FILE_OP_TIMES
3103 m_atime = m_mtime = time_point::now();
3105 if (CHECK_STREAM_STATE && !
ok()) _Unlikely_
3107 size_t num_chars = stdex::strlen(
data);
3108 if (num_chars > UINT32_MAX)
3109 throw std::invalid_argument(
"string too long");
3110 size_t size_chars = num_chars *
sizeof(T);
3111 size_t size =
sizeof(uint32_t) + size_chars;
3115 if (!
ok()) _Unlikely_
3119 *
reinterpret_cast<uint32_t*
>(p) = HE2LE((uint32_t)num_chars);
3120 memcpy(p +
sizeof(uint32_t),
data, size_chars);
3124#if !CHECK_STREAM_STATE
3125 m_state = state_t::ok;
3137#if SET_FILE_OP_TIMES
3138 m_atime = m_mtime = time_point::now();
3141 size_t num_copied = 0, to_write = amount;
3142 m_state = state_t::ok;
3143 if (amount != SIZE_MAX) {
3144 dst_size = stdex::add(dst_size, amount);
3146 if (!
ok()) _Unlikely_
3149 num_read = stream.read(
m_data + dst_offset, to_write);
3150 dst_size = dst_offset += num_read;
3151 num_copied += num_read;
3152 to_write -= num_read;
3154 if (stream.state() != state_t::eof)
3155 m_state = state_t::fail;
3163 block_size = std::min(to_write, default_block_size);
3164 dst_size = stdex::add(dst_size, block_size);
3166 if (!
ok()) _Unlikely_
3168 num_read = stream.read(
m_data + dst_offset, block_size);
3169 dst_size = dst_offset += num_read;
3170 num_copied += num_read;
3171 to_write -= num_read;
3173 if (stream.state() != state_t::eof)
3174 m_state = state_t::fail;
3193#if SET_FILE_OP_TIMES
3194 m_ctime = m_atime = m_mtime = time_point::min();
3196 m_state = state_t::ok;
3199 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
3203 case seek_t::beg: target = offset;
break;
3204 case seek_t::cur: target =
static_cast<fpos_t
>(
m_offset) + offset;
break;
3205 case seek_t::end: target =
static_cast<fpos_t
>(
m_size) + offset;
break;
3206 default:
throw std::invalid_argument(
"unknown seek origin");
3208 if (target <= SIZE_MAX) {
3209 m_state = state_t::ok;
3210 return m_offset =
static_cast<size_t>(target);
3212 m_state = state_t::fail;
3228#if SET_FILE_OP_TIMES
3229 m_atime = m_mtime = time_point::now();
3235#if SET_FILE_OP_TIMES
3236 virtual time_point
ctime()
const
3241 virtual time_point
atime()
const
3246 virtual time_point
mtime()
const
3276 inline void set(_In_ fpos_t offset, _In_
const T
data)
3278#if SET_FILE_OP_TIMES
3279 m_atime = m_mtime = time_point::now();
3281 assert(offset +
sizeof(T) <
m_size);
3282 (*
reinterpret_cast<T*
>(
m_data + offset)) = HE2LE(
data);
3286 inline void set(_In_ fpos_t offset, _In_
const int8_t
data) { set<int8_t>(offset,
data); }
3287 inline void set(_In_ fpos_t offset, _In_
const int16_t
data) { set<int16_t>(offset,
data); }
3288 inline void set(_In_ fpos_t offset, _In_
const int32_t
data) { set<int32_t>(offset,
data); }
3289 inline void set(_In_ fpos_t offset, _In_
const int64_t
data) { set<int64_t>(offset,
data); }
3290 inline void set(_In_ fpos_t offset, _In_
const uint8_t
data) { set<uint8_t>(offset,
data); }
3291 inline void set(_In_ fpos_t offset, _In_
const uint16_t
data) { set<uint16_t>(offset,
data); }
3292 inline void set(_In_ fpos_t offset, _In_
const uint32_t
data) { set<uint32_t>(offset,
data); }
3293 inline void set(_In_ fpos_t offset, _In_
const uint64_t
data) { set<uint64_t>(offset,
data); }
3294#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
3295 inline void set(_In_ fpos_t offset, _In_
const size_t data) { set<size_t>(offset,
data); }
3297 inline void set(_In_ fpos_t offset, _In_
const float data) { set<float>(offset,
data); }
3298 inline void set(_In_ fpos_t offset, _In_
const double data) { set<double>(offset,
data); }
3299 inline void set(_In_ fpos_t offset, _In_
const char data) { set<char>(offset,
data); }
3300#ifdef _NATIVE_WCHAR_T_DEFINED
3301 inline void set(_In_ fpos_t offset, _In_
const wchar_t data) { set<wchar_t>(offset,
data); }
3313 inline void get(_In_ fpos_t offset, _Out_ T &
data)
3315 assert(offset +
sizeof(T) <
m_size);
3317#if SET_FILE_OP_TIMES
3318 m_atime = time_point::now();
3323 inline void get(_In_ fpos_t offset, _Out_ int8_t &
data) { get<int8_t>(offset,
data); }
3324 inline void get(_In_ fpos_t offset, _Out_ int16_t &
data) { get<int16_t>(offset,
data); }
3325 inline void get(_In_ fpos_t offset, _Out_ int32_t &
data) { get<int32_t>(offset,
data); }
3326 inline void get(_In_ fpos_t offset, _Out_ int64_t &
data) { get<int64_t>(offset,
data); }
3327 inline void get(_In_ fpos_t offset, _Out_ uint8_t &
data) { get<uint8_t>(offset,
data); }
3328 inline void get(_In_ fpos_t offset, _Out_ uint16_t &
data) { get<uint16_t>(offset,
data); }
3329 inline void get(_In_ fpos_t offset, _Out_ uint32_t &
data) { get<uint32_t>(offset,
data); }
3330 inline void get(_In_ fpos_t offset, _Out_ uint64_t &
data) { get<uint64_t>(offset,
data); }
3331#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
3332 inline void get(_In_ fpos_t offset, _Out_
size_t &
data) { get<size_t>(offset,
data); }
3334 inline void get(_In_ fpos_t offset, _Out_
float&
data) { get<float>(offset,
data); }
3335 inline void get(_In_ fpos_t offset, _Out_
double&
data) { get<double>(offset,
data); }
3336 inline void get(_In_ fpos_t offset, _Out_
char&
data) { get<char>(offset,
data); }
3337#ifdef _NATIVE_WCHAR_T_DEFINED
3338 inline void get(_In_ fpos_t offset, _Out_
wchar_t&
data) { get<wchar_t>(offset,
data); }
3342 inline memory_file& operator >>(_Out_ int8_t &
data) {
return read_data(
data); }
3343 inline memory_file& operator <<(_In_
const int16_t
data) {
return write_data(
data); }
3344 inline memory_file& operator >>(_Out_ int16_t &
data) {
return read_data(
data); }
3345 inline memory_file& operator <<(_In_
const int32_t
data) {
return write_data(
data); }
3346 inline memory_file& operator >>(_Out_ int32_t &
data) {
return read_data(
data); }
3347 inline memory_file& operator <<(_In_
const int64_t
data) {
return write_data(
data); }
3348 inline memory_file& operator >>(_Out_ int64_t &
data) {
return read_data(
data); }
3349 inline memory_file& operator <<(_In_
const uint8_t
data) {
return write_data(
data); }
3350 inline memory_file& operator >>(_Out_ uint8_t &
data) {
return read_data(
data); }
3351 inline memory_file& operator <<(_In_
const uint16_t
data) {
return write_data(
data); }
3352 inline memory_file& operator >>(_Out_ uint16_t &
data) {
return read_data(
data); }
3353 inline memory_file& operator <<(_In_
const uint32_t
data) {
return write_data(
data); }
3354 inline memory_file& operator >>(_Out_ uint32_t &
data) {
return read_data(
data); }
3355 inline memory_file& operator <<(_In_
const uint64_t
data) {
return write_data(
data); }
3356 inline memory_file& operator >>(_Out_ uint64_t &
data) {
return read_data(
data); }
3357#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
3359 inline memory_file& operator >>(_Out_
size_t &
data) {
return read_data(
data); }
3367#ifdef _NATIVE_WCHAR_T_DEFINED
3368 inline memory_file& operator <<(_In_
const wchar_t data) {
return write_data(
data); }
3369 inline memory_file& operator >>(_Out_
wchar_t&
data) {
return read_data(
data); }
3372 inline memory_file& operator <<(_In_
const T *
data) {
return write_str(
data); }
3373 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
3374 inline memory_file& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&
data) {
return read_str(
data); }
3382#if SET_FILE_OP_TIMES
3411#pragma warning(suppress: 6101)
3412 virtual _Success_(
return != 0 || length == 0) size_t
read(
3413 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
3415 assert(data || !length);
3416 for (
size_t to_read = length;;) {
3417 if (!m_head) _Unlikely_ {
3419 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
3420 return length - to_read;
3422 size_t remaining = m_head->size - m_offset;
3423 if (remaining > to_read) {
3424 memcpy(data, m_head->data + m_offset, to_read);
3425 m_offset += to_read;
3427 m_state = state_t::ok;
3430 memcpy(data, m_head->data + m_offset, remaining);
3432 m_size -= remaining;
3433 reinterpret_cast<uint8_t*&
>(data) += remaining;
3434 to_read -= remaining;
3441 virtual _Success_(
return != 0) size_t
write(
3442 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
3444 assert(data || !length);
3446 std::unique_ptr<node_t> n(
reinterpret_cast<node_t*
>(
new uint8_t[
sizeof(
node_t) + length]));
3449 memcpy(n->data, data, length);
3452 m_tail = m_tail->next = n.release();
3454 m_head = m_tail = n.release();
3455 m_state = state_t::ok;
3458 catch (std::bad_alloc) {
3459 m_state = state_t::fail;
3466 m_size = m_offset = 0;
3472 m_state = state_t::ok;
3478 inline size_t size()
const {
return m_size; };
3481 size_t m_offset, m_size;
3485#pragma warning(suppress:4200)
3487 } *m_head, * m_tail;
3496 basic(num_files ? files[0]->
state() : state_t::fail),
3497 m_files(files, files + num_files)
3501 virtual _Success_(
return != 0 || length == 0) size_t
read(
3502 _Out_writes_bytes_to_opt_(length, return)
void* data, _In_
size_t length)
3504 assert(data || !length);
3505 if (m_files.empty()) {
3506 m_state = state_t::fail;
3509 size_t result = m_files[0]->read(data, length);
3510 _Analysis_assume_(result <= length);
3511 m_state = m_files[0]->state();
3512 if (length > m_tmp.size())
3513 m_tmp.resize(length);
3514 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3515 if (m_files[i]->
read(m_tmp.data(), length) != result ||
3516 memcmp(m_tmp.data(), data, result))
3517 throw std::runtime_error(
"read mismatch");
3518 if (m_files[i]->
state() != m_state)
3519 throw std::runtime_error(
"state mismatch");
3524 virtual _Success_(
return != 0) size_t
write(
3525 _In_reads_bytes_opt_(length) const
void* data, _In_
size_t length)
3527 if (m_files.empty()) {
3528 m_state = state_t::fail;
3531 size_t result = m_files[0]->write(data, length);
3532 m_state = m_files[0]->state();
3533 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3534 if (m_files[i]->
write(data, length) != result)
3535 throw std::runtime_error(
"write mismatch");
3536 if (m_files[i]->
state() != m_state)
3537 throw std::runtime_error(
"state mismatch");
3544 if (m_files.empty()) {
3545 m_state = state_t::ok;
3548 m_files[0]->flush();
3549 m_state = m_files[0]->state();
3550 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3551 m_files[i]->flush();
3552 if (m_files[i]->
state() != m_state)
3553 throw std::runtime_error(
"state mismatch");
3559 if (m_files.empty()) {
3560 m_state = state_t::ok;
3563 m_files[0]->close();
3564 m_state = m_files[0]->state();
3565 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3566 m_files[i]->close();
3567 if (m_files[i]->
state() != m_state)
3568 throw std::runtime_error(
"state mismatch");
3571 m_tmp.shrink_to_fit();
3574 virtual fpos_t
seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
3576 if (m_files.empty()) {
3577 m_state = state_t::fail;
3580 fpos_t result = m_files[0]->seek(offset, how);
3581 m_state = m_files[0]->state();
3582 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3583 if (m_files[i]->
seek(offset, how) != result)
3584 throw std::runtime_error(
"seek mismatch");
3585 if (m_files[i]->
state() != m_state)
3586 throw std::runtime_error(
"state mismatch");
3593 if (m_files.empty())
3595 fpos_t result = m_files[0]->tell();
3596 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3597 if (m_files[i]->
tell() != result)
3598 throw std::runtime_error(
"tell mismatch");
3603 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
3605 if (m_files.empty())
3606 m_state = state_t::fail;
3607 m_files[0]->lock(offset, length);
3608 m_state = m_files[0]->state();
3609 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3610 m_files[i]->lock(offset, length);
3611 if (m_files[i]->
state() != m_state)
3612 throw std::runtime_error(
"state mismatch");
3616 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
3618 if (m_files.empty())
3619 m_state = state_t::fail;
3620 m_files[0]->unlock(offset, length);
3621 m_state = m_files[0]->state();
3622 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3623 m_files[i]->unlock(offset, length);
3624 if (m_files[i]->
state() != m_state)
3625 throw std::runtime_error(
"state mismatch");
3631 if (m_files.empty()) {
3632 m_state = state_t::fail;
3635 fsize_t result = m_files[0]->size();
3636 m_state = m_files[0]->state();
3637 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3638 if (m_files[i]->
size() != result)
3639 throw std::runtime_error(
"size mismatch");
3640 if (m_files[i]->
state() != m_state)
3641 throw std::runtime_error(
"state mismatch");
3648 if (m_files.empty())
3649 m_state = state_t::fail;
3650 m_files[0]->truncate();
3651 m_state = m_files[0]->state();
3652 for (
size_t i = 1, n = m_files.size(); i < n; ++i) {
3653 m_files[i]->truncate();
3654 if (m_files[i]->
state() != m_state)
3655 throw std::runtime_error(
"state mismatch");
3660 std::vector<basic_file*> m_files;
3661 std::vector<uint8_t> m_tmp;
Provides read-ahead stream capability.
Definition stream.hpp:1070
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:1084
Provides write-back stream capability.
Definition stream.hpp:1138
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1175
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:1151
Basic seekable stream operations.
Definition stream.hpp:654
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:697
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:744
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:713
virtual void truncate()=0
Sets file size - truncates the remainder of file content from the current file position to the end of...
charset_id read_charset(charset_id default_charset=charset_id::default)
Attempts to detect textfile charset based on UTF16 or UTF8 BOM.
Definition stream.hpp:817
fpos_t seekbeg(fpos_t offset)
Seeks to absolute file position.
Definition stream.hpp:681
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:656
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:786
fpos_t seekcur(foff_t offset)
Seeks to relative from current file position.
Definition stream.hpp:688
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:752
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:768
virtual fsize_t size()=0
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:723
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:760
fpos_t seekend(foff_t offset)
Seeks to relative from end file position.
Definition stream.hpp:695
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:777
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:1982
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:2040
virtual void flush()
Persists volatile element data.
Definition stream.hpp:2098
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:1989
virtual void close()
Closes the stream.
Definition stream.hpp:2087
UTF-8 byte-order-mark
Definition stream.hpp:71
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:165
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:555
size_t write_array(_In_reads_or_z_opt_(num_chars) const wchar_t *wstr, size_t num_chars, charset_id charset)
Writes array of characters to the stream.
Definition stream.hpp:405
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:160
basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:429
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:541
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:568
virtual void flush()
Persists volatile element data.
Definition stream.hpp:116
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:132
virtual void close()
Closes the stream.
Definition stream.hpp:124
uint8_t read_byte()
Reads one byte of data.
Definition stream.hpp:200
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:174
size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
Writes formatted string to the stream.
Definition stream.hpp:527
size_t readln_and_attach(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
Reads stream to the end-of-line or end-of-file and append to str.
Definition stream.hpp:358
size_t readln(std::basic_string< char, _Traits, _Ax > &str)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:296
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:337
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:373
basic & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:454
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:86
size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:308
void write_charset(charset_id charset)
Writes UTF8 or UTF-16 byte-order-mark.
Definition stream.hpp:514
size_t readln(std::basic_string< wchar_t, _Traits, _Ax > &wstr, charset_id charset)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:320
basic & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:277
fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
Writes content of another stream.
Definition stream.hpp:489
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:104
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:391
void write_byte(uint8_t byte, fsize_t amount=1)
Writes a byte of data.
Definition stream.hpp:211
basic & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:249
Buffered read/write stream.
Definition stream.hpp:1209
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1312
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:1230
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:1266
Buffered OS data stream (file, pipe, socket...)
Definition stream.hpp:2112
Cached file.
Definition stream.hpp:1629
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:1861
fpos_t m_offset
Logical absolute file position.
Definition stream.hpp:1970
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1839
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:1669
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:1866
virtual fsize_t size()
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:1834
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1828
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:1875
virtual void close()
Closes the stream.
Definition stream.hpp:1784
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:1897
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1822
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1791
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:1731
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:1884
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:1817
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:1889
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1802
Cached file-system file.
Definition stream.hpp:2660
cached_file(const sys_char *filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:2676
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2690
Modifies data on the fly when reading from/writing to a source stream.
Definition stream.hpp:847
virtual void flush()
Persists volatile element data.
Definition stream.hpp:888
virtual void close()
Closes the stream.
Definition stream.hpp:882
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:866
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:874
Compares multiple files to perform the same.
Definition stream.hpp:3493
virtual fsize_t size()
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:3629
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3646
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:3524
virtual void close()
Closes the stream.
Definition stream.hpp:3557
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:3603
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:3616
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3574
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:3591
virtual void flush()
Persists volatile element data.
Definition stream.hpp:3542
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:3501
In-memory FIFO queue.
Definition stream.hpp:3393
virtual void close()
Closes the stream.
Definition stream.hpp:3464
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:3441
size_t size() const
Returns total size of pending data in the queue.
Definition stream.hpp:3478
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:3412
Limits file reading/writing to a predefined window.
Definition stream.hpp:1519
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1612
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1562
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:1575
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1568
virtual fsize_t size()
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:1607
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:1542
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1587
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:1528
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1597
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:1581
virtual void close()
Closes the stream.
Definition stream.hpp:1556
File-system file.
Definition stream.hpp:2350
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2593
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2486
file(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2360
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2607
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2579
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:2637
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2619
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2371
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2463
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2529
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2569
virtual fsize_t size()
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:2511
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2424
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:2445
Limits reading from/writing to stream to a predefined number of bytes.
Definition stream.hpp:1360
fsize_t read_limit
Number of bytes left that may be read from the stream.
Definition stream.hpp:1420
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:1368
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:1393
fsize_t write_limit
Number of bytes left, that can be written to the stream.
Definition stream.hpp:1421
In-memory file.
Definition stream.hpp:2713
void load(const sys_char *filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:2837
size_t m_size
file size
Definition stream.hpp:3380
void get(fpos_t offset, T &data)
Reads data from specified file location This does not move file pointer. It checks for data size asse...
Definition stream.hpp:3313
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3135
uint8_t * m_data
file data
Definition stream.hpp:3377
memory_file & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:2934
virtual void close()
Closes the stream.
Definition stream.hpp:3185
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:2895
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:3216
size_t m_reserved
reserved file size
Definition stream.hpp:3381
memory_file(size_t size, state_t state=state_t::ok)
Creates an empty file of reserved size.
Definition stream.hpp:2734
void reserve(size_t required, bool tight=false) noexcept
Reallocates memory.
Definition stream.hpp:2808
memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:2974
void write_byte(uint8_t byte, size_t amount=1)
Writes a byte of data.
Definition stream.hpp:3029
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:3276
size_t m_offset
file pointer
Definition stream.hpp:3379
memory_file(const sys_char *filename, int mode)
Loads content from file-system file.
Definition stream.hpp:2791
virtual fsize_t size()
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:3221
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3199
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3226
memory_file & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:3062
memory_file & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3100
bool m_manage
may reallocate m_data?
Definition stream.hpp:3378
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:2781
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:3005
void save(const sys_char *filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:2870
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:2758
const void * data() const
Returns pointer to data.
Definition stream.hpp:2893
Definition stream.hpp:985
enum stdex::stream::replicator::worker::op_t op
Operation to perform.
size_t num_written
Number of bytes written.
Definition stream.hpp:1032
size_t length
Byte limit of data to write.
Definition stream.hpp:1031
const void * data
Data to write.
Definition stream.hpp:1030
Replicates writing of the same data to multiple streams.
Definition stream.hpp:902
void push_back(basic *source)
Adds stream on the list.
Definition stream.hpp:921
virtual void flush()
Persists volatile element data.
Definition stream.hpp:978
void remove(basic *source)
Removes stream from the list.
Definition stream.hpp:929
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:946
virtual void close()
Closes the stream.
Definition stream.hpp:973
Limits reading from/writing to stream to a predefined window.
Definition stream.hpp:1428
fpos_t write_offset
Number of bytes to discard on write.
Definition stream.hpp:1512
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:1469
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:1436
fpos_t read_offset
Number of bytes to skip on read.
Definition stream.hpp:1511
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:57
virtual void close()
Closes object.
Definition system.hpp:98
Numerical interval.
Definition interval.hpp:18
bool contains(T x) const
Is value in interval?
Definition interval.hpp:88
bool empty() const
Is interval empty?
Definition interval.hpp:54
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:1337
Definition stream.hpp:1948
interval< fpos_t > region
valid data region
Definition stream.hpp:1956
Definition stream.hpp:3482