From f4ff5fb02d860d75d0625c4293763684bfc9684b Mon Sep 17 00:00:00 2001 From: rozmansi Date: Tue, 22 Aug 2023 15:16:49 +0000 Subject: [PATCH] deploy: fe47a47e4e86264c5f94f225afbed2ab632d3db3 --- annotated.html | 2 +- base64_8hpp_source.html | 2 +- chrono_8hpp_source.html | 579 +- classes.html | 2 +- classstdex_1_1base64__dec-members.html | 2 +- classstdex_1_1base64__dec.html | 2 +- classstdex_1_1base64__enc-members.html | 2 +- classstdex_1_1base64__enc.html | 2 +- classstdex_1_1errno__error-members.html | 2 +- classstdex_1_1errno__error.html | 2 +- classstdex_1_1global__progress-members.html | 2 +- classstdex_1_1global__progress.html | 2 +- classstdex_1_1hex__dec-members.html | 2 +- classstdex_1_1hex__dec.html | 2 +- classstdex_1_1hex__enc-members.html | 2 +- classstdex_1_1hex__enc.html | 2 +- classstdex_1_1idrec_1_1record-members.html | 2 +- classstdex_1_1idrec_1_1record.html | 2 +- classstdex_1_1lazy__progress-members.html | 2 +- classstdex_1_1lazy__progress.html | 2 +- ...dex_1_1parser_1_1basic__angle-members.html | 2 +- classstdex_1_1parser_1_1basic__angle.html | 2 +- ...x_1_1parser_1_1basic__any__cu-members.html | 2 +- classstdex_1_1parser_1_1basic__any__cu.html | 2 +- ...stdex_1_1parser_1_1basic__bol-members.html | 2 +- classstdex_1_1parser_1_1basic__bol.html | 2 +- ...ex_1_1parser_1_1basic__branch-members.html | 2 +- classstdex_1_1parser_1_1basic__branch.html | 2 +- ...r_1_1basic__chemical__formula-members.html | 2 +- ...1_1parser_1_1basic__chemical__formula.html | 2 +- ...sstdex_1_1parser_1_1basic__cu-members.html | 2 +- classstdex_1_1parser_1_1basic__cu.html | 2 +- ...x_1_1parser_1_1basic__cu__set-members.html | 2 +- classstdex_1_1parser_1_1basic__cu__set.html | 2 +- ...tdex_1_1parser_1_1basic__date-members.html | 2 +- classstdex_1_1parser_1_1basic__date.html | 2 +- ...r_1_1basic__dns__domain__char-members.html | 2 +- ...1_1parser_1_1basic__dns__domain__char.html | 2 +- ...1_1parser_1_1basic__dns__name-members.html | 2 +- classstdex_1_1parser_1_1basic__dns__name.html | 2 +- ...rser_1_1basic__email__address-members.html | 2 +- ...ex_1_1parser_1_1basic__email__address.html | 2 +- ..._1_1parser_1_1basic__emoticon-members.html | 2 +- classstdex_1_1parser_1_1basic__emoticon.html | 2 +- ...stdex_1_1parser_1_1basic__eol-members.html | 2 +- classstdex_1_1parser_1_1basic__eol.html | 2 +- ..._1_1parser_1_1basic__fraction-members.html | 2 +- classstdex_1_1parser_1_1basic__fraction.html | 2 +- ...x_1_1parser_1_1basic__integer-members.html | 2 +- classstdex_1_1parser_1_1basic__integer.html | 2 +- ...1_1parser_1_1basic__integer10-members.html | 2 +- classstdex_1_1parser_1_1basic__integer10.html | 2 +- ...1parser_1_1basic__integer10ts-members.html | 2 +- ...stdex_1_1parser_1_1basic__integer10ts.html | 2 +- ...1_1parser_1_1basic__integer16-members.html | 2 +- classstdex_1_1parser_1_1basic__integer16.html | 2 +- ...arser_1_1basic__ipv4__address-members.html | 2 +- ...dex_1_1parser_1_1basic__ipv4__address.html | 2 +- ...arser_1_1basic__ipv6__address-members.html | 2 +- ...dex_1_1parser_1_1basic__ipv6__address.html | 2 +- ...1basic__ipv6__scope__id__char-members.html | 2 +- ...arser_1_1basic__ipv6__scope__id__char.html | 2 +- ..._1parser_1_1basic__iterations-members.html | 2 +- ...sstdex_1_1parser_1_1basic__iterations.html | 2 +- ...parser_1_1basic__json__string-members.html | 2 +- ...tdex_1_1parser_1_1basic__json__string.html | 2 +- ...rser_1_1basic__mixed__numeral-members.html | 2 +- ...ex_1_1parser_1_1basic__mixed__numeral.html | 2 +- ...r_1_1basic__monetary__numeral-members.html | 2 +- ...1_1parser_1_1basic__monetary__numeral.html | 2 +- ...tdex_1_1parser_1_1basic__noop-members.html | 2 +- classstdex_1_1parser_1_1basic__noop.html | 2 +- ...ex_1_1parser_1_1basic__parser-members.html | 2 +- classstdex_1_1parser_1_1basic__parser.html | 2 +- ...1parser_1_1basic__permutation-members.html | 2 +- ...stdex_1_1parser_1_1basic__permutation.html | 2 +- ...arser_1_1basic__phone__number-members.html | 2 +- ...dex_1_1parser_1_1basic__phone__number.html | 2 +- ...1_1parser_1_1basic__punct__cu-members.html | 2 +- classstdex_1_1parser_1_1basic__punct__cu.html | 2 +- ...rser_1_1basic__roman__numeral-members.html | 2 +- ...ex_1_1parser_1_1basic__roman__numeral.html | 2 +- ...1_1basic__scientific__numeral-members.html | 2 +- ...1parser_1_1basic__scientific__numeral.html | 2 +- ...dex_1_1parser_1_1basic__score-members.html | 2 +- classstdex_1_1parser_1_1basic__score.html | 2 +- ..._1_1parser_1_1basic__sequence-members.html | 2 +- classstdex_1_1parser_1_1basic__sequence.html | 2 +- ...stdex_1_1parser_1_1basic__set-members.html | 2 +- classstdex_1_1parser_1_1basic__set.html | 2 +- ...ser_1_1basic__signed__numeral-members.html | 2 +- ...x_1_1parser_1_1basic__signed__numeral.html | 2 +- ...1_1parser_1_1basic__space__cu-members.html | 2 +- classstdex_1_1parser_1_1basic__space__cu.html | 2 +- ..._1basic__space__or__punct__cu-members.html | 2 +- ...parser_1_1basic__space__or__punct__cu.html | 2 +- ...ex_1_1parser_1_1basic__string-members.html | 2 +- classstdex_1_1parser_1_1basic__string.html | 2 +- ...rser_1_1basic__string__branch-members.html | 2 +- ...ex_1_1parser_1_1basic__string__branch.html | 2 +- ...tdex_1_1parser_1_1basic__time-members.html | 2 +- classstdex_1_1parser_1_1basic__time.html | 2 +- ...stdex_1_1parser_1_1basic__url-members.html | 2 +- classstdex_1_1parser_1_1basic__url.html | 2 +- ...1_1basic__url__password__char-members.html | 2 +- ...1parser_1_1basic__url__password__char.html | 2 +- ...1_1parser_1_1basic__url__path-members.html | 2 +- classstdex_1_1parser_1_1basic__url__path.html | 2 +- ...ser_1_1basic__url__path__char-members.html | 2 +- ...x_1_1parser_1_1basic__url__path__char.html | 2 +- ...1_1basic__url__username__char-members.html | 2 +- ...1parser_1_1basic__url__username__char.html | 2 +- ...tdex_1_1parser_1_1http__agent-members.html | 2 +- classstdex_1_1parser_1_1http__agent.html | 2 +- ..._1_1parser_1_1http__any__type-members.html | 2 +- classstdex_1_1parser_1_1http__any__type.html | 2 +- ...x_1_1parser_1_1http__asterisk-members.html | 2 +- classstdex_1_1parser_1_1http__asterisk.html | 2 +- ...dex_1_1parser_1_1http__cookie-members.html | 2 +- classstdex_1_1parser_1_1http__cookie.html | 2 +- ...er_1_1http__cookie__parameter-members.html | 2 +- ..._1_1parser_1_1http__cookie__parameter.html | 2 +- ...dex_1_1parser_1_1http__header-members.html | 2 +- classstdex_1_1parser_1_1http__header.html | 2 +- ...x_1_1parser_1_1http__language-members.html | 2 +- classstdex_1_1parser_1_1http__language.html | 2 +- ..._1parser_1_1http__line__break-members.html | 2 +- ...sstdex_1_1parser_1_1http__line__break.html | 2 +- ...1parser_1_1http__media__range-members.html | 2 +- ...stdex_1_1parser_1_1http__media__range.html | 2 +- ..._1parser_1_1http__media__type-members.html | 2 +- ...sstdex_1_1parser_1_1http__media__type.html | 2 +- ..._1_1parser_1_1http__parameter-members.html | 2 +- classstdex_1_1parser_1_1http__parameter.html | 2 +- ...x_1_1parser_1_1http__protocol-members.html | 2 +- classstdex_1_1parser_1_1http__protocol.html | 2 +- ...arser_1_1http__quoted__string-members.html | 2 +- ...dex_1_1parser_1_1http__quoted__string.html | 2 +- ...ex_1_1parser_1_1http__request-members.html | 2 +- classstdex_1_1parser_1_1http__request.html | 2 +- ...tdex_1_1parser_1_1http__space-members.html | 2 +- classstdex_1_1parser_1_1http__space.html | 2 +- ...1_1parser_1_1http__text__char-members.html | 2 +- classstdex_1_1parser_1_1http__text__char.html | 2 +- ...tdex_1_1parser_1_1http__token-members.html | 2 +- classstdex_1_1parser_1_1http__token.html | 2 +- ...sstdex_1_1parser_1_1http__url-members.html | 2 +- classstdex_1_1parser_1_1http__url.html | 2 +- ...arser_1_1http__url__parameter-members.html | 2 +- ...dex_1_1parser_1_1http__url__parameter.html | 2 +- ..._1_1parser_1_1http__url__path-members.html | 2 +- classstdex_1_1parser_1_1http__url__path.html | 2 +- ...r_1_1http__url__path__segment-members.html | 2 +- ...1_1parser_1_1http__url__path__segment.html | 2 +- ..._1_1parser_1_1http__url__port-members.html | 2 +- classstdex_1_1parser_1_1http__url__port.html | 2 +- ..._1parser_1_1http__url__server-members.html | 2 +- ...sstdex_1_1parser_1_1http__url__server.html | 2 +- ...tdex_1_1parser_1_1http__value-members.html | 2 +- classstdex_1_1parser_1_1http__value.html | 2 +- ...er_1_1http__value__collection-members.html | 2 +- ..._1_1parser_1_1http__value__collection.html | 2 +- ...dex_1_1parser_1_1http__weight-members.html | 2 +- classstdex_1_1parser_1_1http__weight.html | 2 +- ...rser_1_1http__weighted__value-members.html | 2 +- ...ex_1_1parser_1_1http__weighted__value.html | 2 +- ...1parser_1_1parser__collection-members.html | 2 +- ...stdex_1_1parser_1_1parser__collection.html | 2 +- ...ex_1_1parser_1_1sgml__any__cp-members.html | 2 +- classstdex_1_1parser_1_1sgml__any__cp.html | 2 +- classstdex_1_1parser_1_1sgml__cp-members.html | 2 +- classstdex_1_1parser_1_1sgml__cp.html | 2 +- ...ex_1_1parser_1_1sgml__cp__set-members.html | 2 +- classstdex_1_1parser_1_1sgml__cp__set.html | 2 +- ...er_1_1sgml__dns__domain__char-members.html | 2 +- ..._1_1parser_1_1sgml__dns__domain__char.html | 2 +- ..._1sgml__ipv6__scope__id__char-members.html | 2 +- ...parser_1_1sgml__ipv6__scope__id__char.html | 2 +- ..._1_1parser_1_1sgml__punct__cp-members.html | 2 +- classstdex_1_1parser_1_1sgml__punct__cp.html | 2 +- ..._1_1parser_1_1sgml__space__cp-members.html | 2 +- classstdex_1_1parser_1_1sgml__space__cp.html | 2 +- ...1_1sgml__space__or__punct__cp-members.html | 2 +- ...1parser_1_1sgml__space__or__punct__cp.html | 2 +- ...dex_1_1parser_1_1sgml__string-members.html | 2 +- classstdex_1_1parser_1_1sgml__string.html | 2 +- ..._1_1sgml__url__password__char-members.html | 2 +- ..._1parser_1_1sgml__url__password__char.html | 2 +- ...rser_1_1sgml__url__path__char-members.html | 2 +- ...ex_1_1parser_1_1sgml__url__path__char.html | 2 +- ..._1_1sgml__url__username__char-members.html | 2 +- ..._1parser_1_1sgml__url__username__char.html | 2 +- classstdex_1_1progress-members.html | 2 +- classstdex_1_1progress.html | 2 +- classstdex_1_1progress__switcher-members.html | 2 +- classstdex_1_1progress__switcher.html | 2 +- classstdex_1_1ring-members.html | 2 +- classstdex_1_1ring.html | 2 +- ...ex_1_1stream_1_1async__reader-members.html | 2 +- classstdex_1_1stream_1_1async__reader.html | 2 +- ...ex_1_1stream_1_1async__writer-members.html | 2 +- classstdex_1_1stream_1_1async__writer.html | 2 +- classstdex_1_1stream_1_1basic-members.html | 2 +- classstdex_1_1stream_1_1basic.html | 2 +- ...tdex_1_1stream_1_1basic__file-members.html | 2 +- classstdex_1_1stream_1_1basic__file.html | 2 +- ...stdex_1_1stream_1_1basic__sys-members.html | 2 +- classstdex_1_1stream_1_1basic__sys.html | 2 +- classstdex_1_1stream_1_1buffer-members.html | 2 +- classstdex_1_1stream_1_1buffer.html | 2 +- ...ex_1_1stream_1_1buffered__sys-members.html | 2 +- classstdex_1_1stream_1_1buffered__sys.html | 2 +- classstdex_1_1stream_1_1cache-members.html | 2 +- classstdex_1_1stream_1_1cache.html | 2 +- ...dex_1_1stream_1_1cached__file-members.html | 2 +- classstdex_1_1stream_1_1cached__file.html | 2 +- ...sstdex_1_1stream_1_1converter-members.html | 2 +- classstdex_1_1stream_1_1converter.html | 2 +- ...stdex_1_1stream_1_1diag__file-members.html | 2 +- classstdex_1_1stream_1_1diag__file.html | 2 +- classstdex_1_1stream_1_1fifo-members.html | 2 +- classstdex_1_1stream_1_1fifo.html | 2 +- classstdex_1_1stream_1_1file-members.html | 2 +- classstdex_1_1stream_1_1file.html | 2 +- ...dex_1_1stream_1_1file__window-members.html | 2 +- classstdex_1_1stream_1_1file__window.html | 2 +- classstdex_1_1stream_1_1limiter-members.html | 2 +- classstdex_1_1stream_1_1limiter.html | 2 +- ...dex_1_1stream_1_1memory__file-members.html | 2 +- classstdex_1_1stream_1_1memory__file.html | 2 +- ...stdex_1_1stream_1_1replicator-members.html | 2 +- classstdex_1_1stream_1_1replicator.html | 2 +- ...tream_1_1replicator_1_1worker-members.html | 2 +- ...dex_1_1stream_1_1replicator_1_1worker.html | 2 +- classstdex_1_1stream_1_1window-members.html | 2 +- classstdex_1_1stream_1_1window.html | 2 +- classstdex_1_1sys__object-members.html | 2 +- classstdex_1_1sys__object.html | 2 +- classstdex_1_1user__cancelled-members.html | 2 +- classstdex_1_1user__cancelled.html | 2 +- classstdex_1_1vector__queue-members.html | 2 +- classstdex_1_1vector__queue.html | 2 +- dir_4be4f7b278e009bf0f1906cf31fb73bd.html | 2 +- dir_d44c64559bbebec7f509842c48db8b23.html | 2 +- dir_fca3c47b2ea228727bd6729832f89576.html | 2 +- endian_8hpp_source.html | 2 +- errno_8hpp_source.html | 2 +- exception_8hpp_source.html | 2 +- files.html | 2 +- functions.html | 2 +- functions_b.html | 2 +- functions_c.html | 2 +- functions_d.html | 2 +- functions_e.html | 2 +- functions_f.html | 2 +- functions_func.html | 2 +- functions_func_b.html | 2 +- functions_func_c.html | 2 +- functions_func_d.html | 2 +- functions_func_e.html | 2 +- functions_func_f.html | 2 +- functions_func_g.html | 2 +- functions_func_h.html | 2 +- functions_func_i.html | 2 +- functions_func_l.html | 2 +- functions_func_m.html | 2 +- functions_func_n.html | 2 +- functions_func_o.html | 2 +- functions_func_p.html | 2 +- functions_func_q.html | 2 +- functions_func_r.html | 2 +- functions_func_s.html | 2 +- functions_func_t.html | 2 +- functions_func_u.html | 2 +- functions_func_v.html | 2 +- functions_func_w.html | 2 +- functions_func_~.html | 2 +- functions_g.html | 2 +- functions_h.html | 2 +- functions_i.html | 2 +- functions_l.html | 2 +- functions_m.html | 2 +- functions_n.html | 2 +- functions_o.html | 2 +- functions_p.html | 2 +- functions_q.html | 2 +- functions_r.html | 2 +- functions_s.html | 2 +- functions_t.html | 2 +- functions_type.html | 2 +- functions_u.html | 2 +- functions_v.html | 2 +- functions_vars.html | 2 +- functions_w.html | 2 +- functions_~.html | 2 +- hex_8hpp_source.html | 2 +- hierarchy.html | 2 +- idrec_8hpp_source.html | 2 +- index.html | 2 +- interval_8hpp_source.html | 2 +- mapping_8hpp_source.html | 2 +- math_8hpp_source.html | 2 +- memory_8hpp_source.html | 2 +- parser_8hpp_source.html | 54 +- pch_8h_source.html | 2 +- progress_8hpp_source.html | 2 +- ring_8hpp_source.html | 2 +- sal_8hpp_source.html | 2 +- sgml_8hpp_source.html | 798 +- sgml__unicode_8hpp_source.html | 2 +- stream_8hpp_source.html | 6739 +++++++++-------- string_8hpp_source.html | 1416 ++-- ...stdex_1_1chrono_1_1aosn__date-members.html | 2 +- structstdex_1_1chrono_1_1aosn__date.html | 2 +- ..._1_1chrono_1_1aosn__timestamp-members.html | 6 +- structstdex_1_1chrono_1_1aosn__timestamp.html | 17 +- structstdex_1_1interval-members.html | 2 +- structstdex_1_1interval.html | 2 +- structstdex_1_1mapping-members.html | 2 +- structstdex_1_1mapping.html | 2 +- structstdex_1_1no__delete-members.html | 2 +- structstdex_1_1no__delete.html | 2 +- ..._1_1no__delete_3_01_t_0f_0e_4-members.html | 2 +- structstdex_1_1no__delete_3_01_t_0f_0e_4.html | 2 +- ...1parser_1_1http__factor__more-members.html | 2 +- ...stdex_1_1parser_1_1http__factor__more.html | 2 +- ...stream_1_1buffer_1_1buffer__t-members.html | 2 +- ...tdex_1_1stream_1_1buffer_1_1buffer__t.html | 2 +- ..._1stream_1_1cache_1_1cache__t-members.html | 2 +- ...tstdex_1_1stream_1_1cache_1_1cache__t.html | 2 +- ..._1_1stream_1_1fifo_1_1node__t-members.html | 2 +- structstdex_1_1stream_1_1fifo_1_1node__t.html | 2 +- system_8hpp_source.html | 331 +- unicode_8hpp_source.html | 2 +- vector__queue_8hpp_source.html | 2 +- 335 files changed, 5465 insertions(+), 5129 deletions(-) diff --git a/annotated.html b/annotated.html index 18cbdea11..c7f1b040f 100644 --- a/annotated.html +++ b/annotated.html @@ -217,7 +217,7 @@ $(function() { diff --git a/base64_8hpp_source.html b/base64_8hpp_source.html index 54bf0f719..1b0e0ffd4 100644 --- a/base64_8hpp_source.html +++ b/base64_8hpp_source.html @@ -318,7 +318,7 @@ $(function() { diff --git a/chrono_8hpp_source.html b/chrono_8hpp_source.html index 46917155f..9e2b2bb9d 100644 --- a/chrono_8hpp_source.html +++ b/chrono_8hpp_source.html @@ -86,253 +86,344 @@ $(function() {
7
8#include "sal.hpp"
9#include "system.hpp"
-
10#include <stdint.h>
-
11#include <chrono>
-
12#include <stdexcept>
-
13
-
14namespace stdex {
-
15 namespace chrono
-
16 {
-
20 struct aosn_date
-
21 {
-
22 using rep = int32_t;
-
23 using period = std::ratio<86400>; // 1 day
-
24 using duration = std::chrono::duration<rep, period>;
-
25 using time_point = std::chrono::time_point<aosn_date>;
-
26 static constexpr bool is_steady = false;
-
27
-
31 static time_point now() noexcept
-
32 {
-
33#ifdef _WIN32
-
34 FILETIME t;
-
35 GetSystemTimeAsFileTime(&t);
-
36 return from_system(t);
-
37#else
-
38 time_t t;
-
39 time(&t);
-
40 return from_time_t(t);
-
41#endif
-
42 }
-
43
-
47 static __time64_t to_time_t(_In_ const time_point tp) noexcept
-
48 {
-
49 return static_cast<__time64_t>(tp.time_since_epoch().count()) * 86400 - 210866803200;
-
50 }
-
51
-
55 static time_point from_time_t(_In_ __time64_t t) noexcept
-
56 {
-
57 return time_point(duration(static_cast<rep>((t + 210866803200) / 86400)));
-
58 }
-
59
-
60#ifdef _WIN32
-
64 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
-
65 {
-
66 return from_dmy(static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear));
-
67 }
-
68
-
72 static time_point from_system(_In_ const FILETIME& t) noexcept
-
73 {
-
74 uint64_t x = ((static_cast<uint64_t>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
-
75 return time_point(duration(static_cast<rep>(x / 86400000 + 2305814))); // Convert from 100 ns to 1-day interval and adjust epoch
-
76 }
-
77
-
81 static time_point from_system(_In_ DATE t)
-
82 {
-
83 SYSTEMTIME st;
-
84 if (!VariantTimeToSystemTime(t, &st))
-
85 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
-
86 return from_system(st);
-
87 }
-
88#else
-
92 static time_point from_system(_In_ const struct timespec& t) noexcept
-
93 {
-
94 return from_time_t(t.tv_sec);
-
95 }
-
96#endif
-
97
-
101 static time_point from_dmy(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year) noexcept
-
102 {
-
103 int32_t mtmp, ytmp;
-
104 if (month > 2) {
-
105 mtmp = month - 3;
-
106 ytmp = year;
-
107 }
-
108 else {
-
109 mtmp = month + 9;
-
110 ytmp = year - 1;
-
111 }
-
112 int32_t ctmp = (ytmp / 100);
-
113 int32_t dtmp = ytmp - (100 * ctmp);
-
114 int32_t result1 = 146097L * ctmp / 4;
-
115 int32_t result2 = (1461 * dtmp) / 4;
-
116 int32_t result3 = (153 * mtmp + 2) / 5;
-
117 return time_point(duration(static_cast<int32_t>(result1) + day + result2 + 1721119L + result3));
-
118 }
-
119
-
123 static void to_dmy(_In_ const time_point tp, _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year) noexcept
-
124 {
-
125 int32_t mtmp = tp.time_since_epoch().count() - 1721119L;
-
126 int32_t yr = (4 * mtmp - 1) / 146097L;
-
127 mtmp = 4 * mtmp - 1 - 146097L * yr;
-
128 int32_t da = mtmp / 4;
-
129 mtmp = (4 * da + 3) / 1461;
-
130 da = 4 * da + 3 - 1461 * mtmp;
-
131 da = (da + 4) / 4;
-
132 int32_t mo = (5 * da - 3) / 153;
-
133 da = 5 * da - 3 - 153 * mo;
-
134 da = (da + 5) / 5;
-
135 yr = 100 * yr + mtmp;
-
136 if (mo < 10)
-
137 mo += 3;
-
138 else {
-
139 mo -= 9;
-
140 yr++;
-
141 }
-
142 if (day) *day = static_cast<uint8_t>(da);
-
143 if (month) *month = static_cast<uint8_t>(mo);
-
144 if (year) *year = yr;
-
145 }
-
146
-
150 static uint8_t day_of_week(_In_ const time_point tp)
-
151 {
-
152 return static_cast<uint8_t>(tp.time_since_epoch().count() % 7);
-
153 }
-
154
-
158 static uint8_t day_of_week(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year)
-
159 {
-
160 return static_cast<uint8_t>(from_dmy(day, month, year).time_since_epoch().count() % 7);
-
161 }
-
162 };
-
163
-
167 struct aosn_timestamp
-
168 {
-
169 using rep = int64_t;
-
170 using period = std::ratio<1, 1'000'000>; // 1 microsecond
-
171 using duration = std::chrono::duration<rep, period>;
-
172 using time_point = std::chrono::time_point<aosn_timestamp>;
-
173 static constexpr bool is_steady = false;
-
174
-
175 static constexpr rep f_second = 1000; // number of milliseconds per second
-
176 static constexpr rep f_minute = 60; // number of seconds per minute
-
177 static constexpr rep f_hour = 60; // number of minutes per hour
-
178 static constexpr rep f_day = 24; // number of hours per day
-
179 static constexpr rep f_week = 7; // number of days per week
-
180
-
181 static constexpr rep p_second = f_second; // number of milliseconds per second
-
182 static constexpr rep p_minute = f_minute * p_second; // number of milliseconds per minute
-
183 static constexpr rep p_hour = f_hour * p_minute; // number of milliseconds per hour
-
184 static constexpr rep p_day = f_day * p_hour; // number of milliseconds per day
-
185 static constexpr rep p_week = f_week * p_day; // number of milliseconds per week
-
186
-
190 static time_point now() noexcept
-
191 {
-
192#ifdef _WIN32
-
193 FILETIME t;
-
194 GetSystemTimeAsFileTime(&t);
-
195 return from_system(t);
-
196#else
-
197 time_t t;
-
198 time(&t);
-
199 return from_time_t(t);
-
200#endif
-
201 }
-
202
-
206 static __time64_t to_time_t(_In_ const time_point tp) noexcept
-
207 {
-
208 return tp.time_since_epoch().count() / p_second - 210866803200;
-
209 }
-
210
-
214 static time_point from_time_t(_In_ __time64_t t) noexcept
-
215 {
-
216 return time_point(duration((static_cast<rep>(t) + 210866803200) * p_second));
-
217 }
-
218
-
219#ifdef _WIN32
-
223 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
-
224 {
-
225 return from_dmy(
-
226 static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear),
-
227 static_cast<uint8_t>(t.wHour), static_cast<uint8_t>(t.wMinute), static_cast<uint8_t>(t.wSecond), static_cast<uint16_t>(t.wMilliseconds));
-
228 }
-
229
-
233 static time_point from_system(_In_ const FILETIME& t) noexcept
-
234 {
-
235 rep x = ((static_cast<rep>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
-
236 return time_point(duration(x / 10000 + 199222329600000)); // Convert from 100 ns to 1 ms interval and adjust epoch
-
237 }
-
238
-
242 static time_point from_system(_In_ DATE t)
-
243 {
-
244 SYSTEMTIME st;
-
245 if (!VariantTimeToSystemTime(t, &st))
-
246 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
-
247 return from_system(st);
-
248 }
-
249#else
-
253 static time_point from_system(_In_ const struct timespec& t) noexcept
-
254 {
-
255 return from_time_t(t.tv_sec) + t.tv_nsec / 1000;
-
256 }
-
257#endif
-
258
-
262 static aosn_date::time_point to_date(_In_ time_point tp) noexcept
-
263 {
-
264 return aosn_date::time_point(aosn_date::duration(static_cast<aosn_date::rep>(tp.time_since_epoch().count() / p_day)));
-
265 }
-
266
-
270 static time_point from_date(_In_ aosn_date::time_point date) noexcept
-
271 {
-
272 return time_point(duration(static_cast<rep>(date.time_since_epoch().count()) * p_day));
-
273 }
-
274
-
278 static time_point from_dmy(
-
279 _In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year,
-
280 _In_ uint8_t hour, _In_ uint8_t minute, _In_ uint8_t second, _In_ uint16_t millisecond) noexcept
-
281 {
-
282 return time_point(duration(
-
283 (static_cast<rep>(aosn_date::from_dmy(day, month, year).time_since_epoch().count()) * p_day) +
-
284 (static_cast<rep>(hour) * p_hour + static_cast<rep>(minute) * p_minute + static_cast<rep>(second) * p_second + millisecond)));
-
285 }
-
286
-
290 static void to_dmy(_In_ const time_point tp,
-
291 _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year,
-
292 _Out_opt_ uint8_t* hour, _Out_opt_ uint8_t* minute, _Out_opt_ uint8_t* second, _Out_opt_ uint16_t* millisecond) noexcept
-
293 {
-
294 aosn_date::to_dmy(to_date(tp), day, month, year);
-
295 int32_t u = static_cast<int32_t>(tp.time_since_epoch().count() % p_day);
-
296 if (millisecond) *millisecond = static_cast<uint16_t>(u % f_second);
-
297 u = u / f_second;
-
298 if (second) *second = static_cast<uint8_t>(u % f_minute);
-
299 u = u / f_minute;
-
300 if (minute) *minute = static_cast<uint8_t>(u % f_hour);
-
301 u = u / f_hour;
-
302 if (hour) *hour = static_cast<uint8_t>(u);
-
303 }
-
304 };
-
305 }
-
306}
-
AOsn date.
Definition chrono.hpp:21
-
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year) noexcept
Returns time point from calendar day, month and year.
Definition chrono.hpp:101
-
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year) noexcept
Returns calendar day, month and year from time point.
Definition chrono.hpp:123
-
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:47
-
static uint8_t day_of_week(const time_point tp)
Returns day-of-week from time point (0 = Mon, 1 = Tue...)
Definition chrono.hpp:150
-
static uint8_t day_of_week(uint8_t day, uint8_t month, int32_t year)
Returns day-of-week from calendar day, month and year (0 = Mon, 1 = Tue...)
Definition chrono.hpp:158
-
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:55
-
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:92
-
static time_point now() noexcept
Gets current date.
Definition chrono.hpp:31
-
AOsn timestamp.
Definition chrono.hpp:168
-
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:206
-
static time_point from_date(aosn_date::time_point date) noexcept
Returns time point from aosn_date::time_point.
Definition chrono.hpp:270
-
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond) noexcept
Returns time point from calendar day, month, year and time.
Definition chrono.hpp:278
-
static aosn_date::time_point to_date(time_point tp) noexcept
Returns aosn_date::time_point from time point.
Definition chrono.hpp:262
-
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:253
-
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:214
-
static time_point now() noexcept
Gets current timestamp.
Definition chrono.hpp:190
-
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year, uint8_t *hour, uint8_t *minute, uint8_t *second, uint16_t *millisecond) noexcept
Returns calendar day, month, year and time from time point.
Definition chrono.hpp:290
+
10#include "string.hpp"
+
11#include <stdint.h>
+
12#include <chrono>
+
13#include <memory>
+
14#include <stdexcept>
+
15
+
16namespace stdex {
+
17 namespace chrono
+
18 {
+
22 struct aosn_date
+
23 {
+
24 using rep = int32_t;
+
25 using period = std::ratio<86400>; // 1 day
+
26 using duration = std::chrono::duration<rep, period>;
+
27 using time_point = std::chrono::time_point<aosn_date>;
+
28 static constexpr bool is_steady = false;
+
29
+
33 static time_point now() noexcept
+
34 {
+
35#ifdef _WIN32
+
36 FILETIME t;
+
37 GetSystemTimeAsFileTime(&t);
+
38 return from_system(t);
+
39#else
+
40 time_t t;
+
41 time(&t);
+
42 return from_time_t(t);
+
43#endif
+
44 }
+
45
+
49 static __time64_t to_time_t(_In_ const time_point tp) noexcept
+
50 {
+
51 return static_cast<__time64_t>(tp.time_since_epoch().count()) * 86400 - 210866803200;
+
52 }
+
53
+
57 static time_point from_time_t(_In_ __time64_t t) noexcept
+
58 {
+
59 return time_point(duration(static_cast<rep>((t + 210866803200) / 86400)));
+
60 }
+
61
+
62#ifdef _WIN32
+
66 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
+
67 {
+
68 return from_dmy(static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear));
+
69 }
+
70
+
74 static time_point from_system(_In_ const FILETIME& t) noexcept
+
75 {
+
76 uint64_t x = ((static_cast<uint64_t>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
+
77 return time_point(duration(static_cast<rep>(x / 86400000 + 2305814))); // Convert from 100 ns to 1-day interval and adjust epoch
+
78 }
+
79
+
83 static time_point from_system(_In_ DATE t)
+
84 {
+
85 SYSTEMTIME st;
+
86 if (!VariantTimeToSystemTime(t, &st))
+
87 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
+
88 return from_system(st);
+
89 }
+
90#else
+
94 static time_point from_system(_In_ const struct timespec& t) noexcept
+
95 {
+
96 return from_time_t(t.tv_sec);
+
97 }
+
98#endif
+
99
+
103 static time_point from_dmy(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year) noexcept
+
104 {
+
105 int32_t mtmp, ytmp;
+
106 if (month > 2) {
+
107 mtmp = month - 3;
+
108 ytmp = year;
+
109 }
+
110 else {
+
111 mtmp = month + 9;
+
112 ytmp = year - 1;
+
113 }
+
114 int32_t ctmp = (ytmp / 100);
+
115 int32_t dtmp = ytmp - (100 * ctmp);
+
116 int32_t result1 = 146097L * ctmp / 4;
+
117 int32_t result2 = (1461 * dtmp) / 4;
+
118 int32_t result3 = (153 * mtmp + 2) / 5;
+
119 return time_point(duration(static_cast<int32_t>(result1) + day + result2 + 1721119L + result3));
+
120 }
+
121
+
125 static void to_dmy(_In_ const time_point tp, _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year) noexcept
+
126 {
+
127 int32_t mtmp = tp.time_since_epoch().count() - 1721119L;
+
128 int32_t yr = (4 * mtmp - 1) / 146097L;
+
129 mtmp = 4 * mtmp - 1 - 146097L * yr;
+
130 int32_t da = mtmp / 4;
+
131 mtmp = (4 * da + 3) / 1461;
+
132 da = 4 * da + 3 - 1461 * mtmp;
+
133 da = (da + 4) / 4;
+
134 int32_t mo = (5 * da - 3) / 153;
+
135 da = 5 * da - 3 - 153 * mo;
+
136 da = (da + 5) / 5;
+
137 yr = 100 * yr + mtmp;
+
138 if (mo < 10)
+
139 mo += 3;
+
140 else {
+
141 mo -= 9;
+
142 yr++;
+
143 }
+
144 if (day) *day = static_cast<uint8_t>(da);
+
145 if (month) *month = static_cast<uint8_t>(mo);
+
146 if (year) *year = yr;
+
147 }
+
148
+
152 static uint8_t day_of_week(_In_ const time_point tp)
+
153 {
+
154 return static_cast<uint8_t>(tp.time_since_epoch().count() % 7);
+
155 }
+
156
+
160 static uint8_t day_of_week(_In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year)
+
161 {
+
162 return static_cast<uint8_t>(from_dmy(day, month, year).time_since_epoch().count() % 7);
+
163 }
+
164 };
+
165
+
169 struct aosn_timestamp
+
170 {
+
171 using rep = int64_t;
+
172 using period = std::ratio<1, 1'000'000>; // 1 microsecond
+
173 using duration = std::chrono::duration<rep, period>;
+
174 using time_point = std::chrono::time_point<aosn_timestamp>;
+
175 static constexpr bool is_steady = false;
+
176
+
177 static constexpr rep f_second = 1000; // number of milliseconds per second
+
178 static constexpr rep f_minute = 60; // number of seconds per minute
+
179 static constexpr rep f_hour = 60; // number of minutes per hour
+
180 static constexpr rep f_day = 24; // number of hours per day
+
181 static constexpr rep f_week = 7; // number of days per week
+
182
+
183 static constexpr rep p_second = f_second; // number of milliseconds per second
+
184 static constexpr rep p_minute = f_minute * p_second; // number of milliseconds per minute
+
185 static constexpr rep p_hour = f_hour * p_minute; // number of milliseconds per hour
+
186 static constexpr rep p_day = f_day * p_hour; // number of milliseconds per day
+
187 static constexpr rep p_week = f_week * p_day; // number of milliseconds per week
+
188
+
192 static time_point now() noexcept
+
193 {
+
194#ifdef _WIN32
+
195 FILETIME t;
+
196 GetSystemTimeAsFileTime(&t);
+
197 return from_system(t);
+
198#else
+
199 time_t t;
+
200 time(&t);
+
201 return from_time_t(t);
+
202#endif
+
203 }
+
204
+
208 static __time64_t to_time_t(_In_ const time_point tp) noexcept
+
209 {
+
210 return tp.time_since_epoch().count() / p_second - 210866803200;
+
211 }
+
212
+
216 static time_point from_time_t(_In_ __time64_t t) noexcept
+
217 {
+
218 return time_point(duration((static_cast<rep>(t) + 210866803200) * p_second));
+
219 }
+
220
+
221#ifdef _WIN32
+
225 static time_point from_system(_In_ const SYSTEMTIME& t) noexcept
+
226 {
+
227 return from_dmy(
+
228 static_cast<uint8_t>(t.wDay), static_cast<uint8_t>(t.wMonth), static_cast<int32_t>(t.wYear),
+
229 static_cast<uint8_t>(t.wHour), static_cast<uint8_t>(t.wMinute), static_cast<uint8_t>(t.wSecond), static_cast<uint16_t>(t.wMilliseconds));
+
230 }
+
231
+
235 static time_point from_system(_In_ const FILETIME& t) noexcept
+
236 {
+
237 rep x = ((static_cast<rep>(t.dwHighDateTime)) << 32) | t.dwLowDateTime;
+
238 return time_point(duration(x / 10000 + 199222329600000)); // Convert from 100 ns to 1 ms interval and adjust epoch
+
239 }
+
240
+
244 static time_point from_system(_In_ DATE t)
+
245 {
+
246 SYSTEMTIME st;
+
247 if (!VariantTimeToSystemTime(t, &st))
+
248 throw std::invalid_argument("failed to convert date from VARIANT_DATE");
+
249 return from_system(st);
+
250 }
+
251#else
+
255 static time_point from_system(_In_ const struct timespec& t) noexcept
+
256 {
+
257 return from_time_t(t.tv_sec) + t.tv_nsec / 1000;
+
258 }
+
259#endif
+
260
+
261 static void to_system(_In_ time_point tp, _Out_ struct tm& date) noexcept
+
262 {
+
263 uint8_t day, month, hour, minute, second;
+
264 uint16_t millisecond;
+
265 int32_t year;
+
266 to_dmy(tp, &day, &month, &year, &hour, &minute, &second, &millisecond);
+
267 date.tm_sec = second;
+
268 date.tm_min = minute;
+
269 date.tm_hour = hour;
+
270 date.tm_mday = day;
+
271 date.tm_mon = month - 1;
+
272 date.tm_year = year - 1900;
+
273 date.tm_wday = (static_cast<int>(aosn_date::day_of_week(to_date(tp))) + 1) % 7;
+
274 date.tm_yday = 0;
+
275 date.tm_isdst = 0;
+
276 }
+
277
+
281 static aosn_date::time_point to_date(_In_ time_point tp) noexcept
+
282 {
+
283 return aosn_date::time_point(aosn_date::duration(static_cast<aosn_date::rep>(tp.time_since_epoch().count() / p_day)));
+
284 }
+
285
+
289 static time_point from_date(_In_ aosn_date::time_point date) noexcept
+
290 {
+
291 return time_point(duration(static_cast<rep>(date.time_since_epoch().count()) * p_day));
+
292 }
+
293
+
297 static time_point from_dmy(
+
298 _In_ uint8_t day, _In_ uint8_t month, _In_ int32_t year,
+
299 _In_ uint8_t hour, _In_ uint8_t minute, _In_ uint8_t second, _In_ uint16_t millisecond) noexcept
+
300 {
+
301 return time_point(duration(
+
302 (static_cast<rep>(aosn_date::from_dmy(day, month, year).time_since_epoch().count()) * p_day) +
+
303 (static_cast<rep>(hour) * p_hour + static_cast<rep>(minute) * p_minute + static_cast<rep>(second) * p_second + millisecond)));
+
304 }
+
305
+
309 static void to_dmy(_In_ const time_point tp,
+
310 _Out_opt_ uint8_t* day, _Out_opt_ uint8_t* month, _Out_opt_ int32_t* year,
+
311 _Out_opt_ uint8_t* hour, _Out_opt_ uint8_t* minute, _Out_opt_ uint8_t* second, _Out_opt_ uint16_t* millisecond) noexcept
+
312 {
+
313 aosn_date::to_dmy(to_date(tp), day, month, year);
+
314 int32_t u = static_cast<int32_t>(tp.time_since_epoch().count() % p_day);
+
315 if (millisecond) *millisecond = static_cast<uint16_t>(u % f_second);
+
316 u = u / f_second;
+
317 if (second) *second = static_cast<uint8_t>(u % f_minute);
+
318 u = u / f_minute;
+
319 if (minute) *minute = static_cast<uint8_t>(u % f_hour);
+
320 u = u / f_hour;
+
321 if (hour) *hour = static_cast<uint8_t>(u);
+
322 }
+
323
+
324 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
+
325 static std::basic_string<char, _Traits, _Ax> to_str(_In_ const time_point tp, _In_z_ const char* format, _In_opt_ locale_t locale)
+
326 {
+
327 struct tm date;
+
328 to_system(tp, date);
+
329 std::basic_string<char, _Traits, _Ax> str;
+
330 char stack_buffer[1024 / sizeof(char)];
+
331 size_t n;
+
332#if _WIN32
+
333 n = _strftime_l(stack_buffer, _countof(stack_buffer), format, &date, locale);
+
334#else
+
335 n = strftime_l(stack_buffer, _countof(stack_buffer), format, &date, locale);
+
336#endif
+
337 if (n) {
+
338 str.assign(stack_buffer, stack_buffer + n);
+
339 return str;
+
340 }
+
341 size_t num_chars = stdex::mul(_countof(stack_buffer), 2);
+
342 for (;;) {
+
343 std::unique_ptr<char> buf(new char[num_chars]);
+
344#if _WIN32
+
345 n = _strftime_l(buf.get(), num_chars, format, &date, locale);
+
346#else
+
347 n = strftime_l(buf.get(), num_chars, format, &date, locale);
+
348#endif
+
349 if (n) {
+
350 str.assign(buf.get(), buf.get() + n);
+
351 return str;
+
352 }
+
353 num_chars = stdex::mul(num_chars, 2);
+
354 }
+
355 }
+
356
+
357 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
+
358 static std::basic_string<wchar_t, _Traits, _Ax> to_str(_In_ const time_point tp, _In_z_ const wchar_t* format, _In_opt_ locale_t locale)
+
359 {
+
360 struct tm date;
+
361 to_system(tp, date);
+
362 std::basic_string<wchar_t, _Traits, _Ax> str;
+
363 wchar_t stack_buffer[1024 / sizeof(wchar_t)];
+
364 size_t n;
+
365#if _WIN32
+
366 n = _wcsftime_l(stack_buffer, _countof(stack_buffer), format, &date, locale);
+
367#else
+
368 n = wcsftime_l(stack_buffer, _countof(stack_buffer), format, &date, locale);
+
369#endif
+
370 if (n) {
+
371 str.assign(stack_buffer, stack_buffer + n);
+
372 return str;
+
373 }
+
374 size_t num_chars = stdex::mul(_countof(stack_buffer), 2);
+
375 for (;;) {
+
376 std::unique_ptr<wchar_t> buf(new wchar_t[num_chars]);
+
377#if _WIN32
+
378 n = _wcsftime_l(buf.get(), num_chars, format, &date, locale);
+
379#else
+
380 n = wcsftime_l(buf.get(), num_chars, format, &date, locale);
+
381#endif
+
382 if (n) {
+
383 str.assign(buf.get(), buf.get() + n);
+
384 return str;
+
385 }
+
386 num_chars = stdex::mul(num_chars, 2);
+
387 }
+
388 }
+
389
+
390 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
+
391 static std::basic_string<char, _Traits, _Ax> to_rfc822(_In_ const time_point tp)
+
392 {
+
393 return to_str(tp, "%a, %d %b %Y %H:%M:%S GMT", locale_C.get());
+
394 }
+
395 };
+
396 }
+
397}
+
AOsn date.
Definition chrono.hpp:23
+
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year) noexcept
Returns time point from calendar day, month and year.
Definition chrono.hpp:103
+
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year) noexcept
Returns calendar day, month and year from time point.
Definition chrono.hpp:125
+
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:49
+
static uint8_t day_of_week(const time_point tp)
Returns day-of-week from time point (0 = Mon, 1 = Tue...)
Definition chrono.hpp:152
+
static uint8_t day_of_week(uint8_t day, uint8_t month, int32_t year)
Returns day-of-week from calendar day, month and year (0 = Mon, 1 = Tue...)
Definition chrono.hpp:160
+
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:57
+
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:94
+
static time_point now() noexcept
Gets current date.
Definition chrono.hpp:33
+
AOsn timestamp.
Definition chrono.hpp:170
+
static __time64_t to_time_t(const time_point tp) noexcept
Returns time_t from time point.
Definition chrono.hpp:208
+
static time_point from_date(aosn_date::time_point date) noexcept
Returns time point from aosn_date::time_point.
Definition chrono.hpp:289
+
static time_point from_dmy(uint8_t day, uint8_t month, int32_t year, uint8_t hour, uint8_t minute, uint8_t second, uint16_t millisecond) noexcept
Returns time point from calendar day, month, year and time.
Definition chrono.hpp:297
+
static aosn_date::time_point to_date(time_point tp) noexcept
Returns aosn_date::time_point from time point.
Definition chrono.hpp:281
+
static time_point from_system(const struct timespec &t) noexcept
Returns time point from struct timespec.
Definition chrono.hpp:255
+
static time_point from_time_t(__time64_t t) noexcept
Returns time point from time_t.
Definition chrono.hpp:216
+
static time_point now() noexcept
Gets current timestamp.
Definition chrono.hpp:192
+
static void to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year, uint8_t *hour, uint8_t *minute, uint8_t *second, uint16_t *millisecond) noexcept
Returns calendar day, month, year and time from time point.
Definition chrono.hpp:309
diff --git a/classes.html b/classes.html index c07c981f2..3c4dc0952 100644 --- a/classes.html +++ b/classes.html @@ -133,7 +133,7 @@ $(function() { diff --git a/classstdex_1_1base64__dec-members.html b/classstdex_1_1base64__dec-members.html index ae35d43ef..d825feb6c 100644 --- a/classstdex_1_1base64__dec-members.html +++ b/classstdex_1_1base64__dec-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1base64__dec.html b/classstdex_1_1base64__dec.html index 037cf9462..1f8be3d77 100644 --- a/classstdex_1_1base64__dec.html +++ b/classstdex_1_1base64__dec.html @@ -230,7 +230,7 @@ template<class _Ty , class _Ax , class _Tchr > diff --git a/classstdex_1_1base64__enc-members.html b/classstdex_1_1base64__enc-members.html index e604d3f9c..34b6ea607 100644 --- a/classstdex_1_1base64__enc-members.html +++ b/classstdex_1_1base64__enc-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1base64__enc.html b/classstdex_1_1base64__enc.html index bb5a9100b..6a492f59f 100644 --- a/classstdex_1_1base64__enc.html +++ b/classstdex_1_1base64__enc.html @@ -235,7 +235,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1errno__error-members.html b/classstdex_1_1errno__error-members.html index 363865112..d2374c686 100644 --- a/classstdex_1_1errno__error-members.html +++ b/classstdex_1_1errno__error-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1errno__error.html b/classstdex_1_1errno__error.html index 3fa951f4f..c96af1981 100644 --- a/classstdex_1_1errno__error.html +++ b/classstdex_1_1errno__error.html @@ -286,7 +286,7 @@ errno_t m_num diff --git a/classstdex_1_1global__progress-members.html b/classstdex_1_1global__progress-members.html index f3f62a5c8..1328f420a 100644 --- a/classstdex_1_1global__progress-members.html +++ b/classstdex_1_1global__progress-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1global__progress.html b/classstdex_1_1global__progress.html index db670c156..7e17413f1 100644 --- a/classstdex_1_1global__progress.html +++ b/classstdex_1_1global__progress.html @@ -562,7 +562,7 @@ template<class T > diff --git a/classstdex_1_1hex__dec-members.html b/classstdex_1_1hex__dec-members.html index 8361866bb..a8c494c6a 100644 --- a/classstdex_1_1hex__dec-members.html +++ b/classstdex_1_1hex__dec-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1hex__dec.html b/classstdex_1_1hex__dec.html index 8a90b657e..65f46b46a 100644 --- a/classstdex_1_1hex__dec.html +++ b/classstdex_1_1hex__dec.html @@ -221,7 +221,7 @@ template<class _Ty , class _Ax , class _Tchr > diff --git a/classstdex_1_1hex__enc-members.html b/classstdex_1_1hex__enc-members.html index c714858d3..6ec0b80a2 100644 --- a/classstdex_1_1hex__enc-members.html +++ b/classstdex_1_1hex__enc-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1hex__enc.html b/classstdex_1_1hex__enc.html index 7a9502b7a..fc7a96439 100644 --- a/classstdex_1_1hex__enc.html +++ b/classstdex_1_1hex__enc.html @@ -198,7 +198,7 @@ template<class _Elem , class _Traits , class _Ax > diff --git a/classstdex_1_1idrec_1_1record-members.html b/classstdex_1_1idrec_1_1record-members.html index 8ca2ac1f4..0af46fb8b 100644 --- a/classstdex_1_1idrec_1_1record-members.html +++ b/classstdex_1_1idrec_1_1record-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1idrec_1_1record.html b/classstdex_1_1idrec_1_1record.html index 583697640..6a442cee6 100644 --- a/classstdex_1_1idrec_1_1record.html +++ b/classstdex_1_1idrec_1_1record.html @@ -380,7 +380,7 @@ template<class T , class T_ID , const T_ID ID, class T_SIZE , unsigned int AL diff --git a/classstdex_1_1lazy__progress-members.html b/classstdex_1_1lazy__progress-members.html index 429fdeb99..6e60ad3f6 100644 --- a/classstdex_1_1lazy__progress-members.html +++ b/classstdex_1_1lazy__progress-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1lazy__progress.html b/classstdex_1_1lazy__progress.html index 428791584..cbd5718df 100644 --- a/classstdex_1_1lazy__progress.html +++ b/classstdex_1_1lazy__progress.html @@ -285,7 +285,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__angle-members.html b/classstdex_1_1parser_1_1basic__angle-members.html index 1d1132927..81bed67e9 100644 --- a/classstdex_1_1parser_1_1basic__angle-members.html +++ b/classstdex_1_1parser_1_1basic__angle-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__angle.html b/classstdex_1_1parser_1_1basic__angle.html index 57a4b6fa1..8aa20b181 100644 --- a/classstdex_1_1parser_1_1basic__angle.html +++ b/classstdex_1_1parser_1_1basic__angle.html @@ -250,7 +250,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__any__cu-members.html b/classstdex_1_1parser_1_1basic__any__cu-members.html index b19ea1a83..e90af95e5 100644 --- a/classstdex_1_1parser_1_1basic__any__cu-members.html +++ b/classstdex_1_1parser_1_1basic__any__cu-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__any__cu.html b/classstdex_1_1parser_1_1basic__any__cu.html index 6386e4ab9..69f821d75 100644 --- a/classstdex_1_1parser_1_1basic__any__cu.html +++ b/classstdex_1_1parser_1_1basic__any__cu.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__bol-members.html b/classstdex_1_1parser_1_1basic__bol-members.html index 64001def0..d42a27a16 100644 --- a/classstdex_1_1parser_1_1basic__bol-members.html +++ b/classstdex_1_1parser_1_1basic__bol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__bol.html b/classstdex_1_1parser_1_1basic__bol.html index d355058b3..db0d6e082 100644 --- a/classstdex_1_1parser_1_1basic__bol.html +++ b/classstdex_1_1parser_1_1basic__bol.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__branch-members.html b/classstdex_1_1parser_1_1basic__branch-members.html index ca7ab778c..74b493bde 100644 --- a/classstdex_1_1parser_1_1basic__branch-members.html +++ b/classstdex_1_1parser_1_1basic__branch-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__branch.html b/classstdex_1_1parser_1_1basic__branch.html index da0037b45..71d9614be 100644 --- a/classstdex_1_1parser_1_1basic__branch.html +++ b/classstdex_1_1parser_1_1basic__branch.html @@ -261,7 +261,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__chemical__formula-members.html b/classstdex_1_1parser_1_1basic__chemical__formula-members.html index d81cd9b47..e1282d3f2 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula-members.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__chemical__formula.html b/classstdex_1_1parser_1_1basic__chemical__formula.html index 6adacfa3b..beaa653da 100644 --- a/classstdex_1_1parser_1_1basic__chemical__formula.html +++ b/classstdex_1_1parser_1_1basic__chemical__formula.html @@ -245,7 +245,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__cu-members.html b/classstdex_1_1parser_1_1basic__cu-members.html index d9a77afb8..758a7d4fa 100644 --- a/classstdex_1_1parser_1_1basic__cu-members.html +++ b/classstdex_1_1parser_1_1basic__cu-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu.html b/classstdex_1_1parser_1_1basic__cu.html index efded5b80..c3d7ca894 100644 --- a/classstdex_1_1parser_1_1basic__cu.html +++ b/classstdex_1_1parser_1_1basic__cu.html @@ -204,7 +204,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__cu__set-members.html b/classstdex_1_1parser_1_1basic__cu__set-members.html index 42bb57f9f..542352328 100644 --- a/classstdex_1_1parser_1_1basic__cu__set-members.html +++ b/classstdex_1_1parser_1_1basic__cu__set-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__cu__set.html b/classstdex_1_1parser_1_1basic__cu__set.html index fd6cf8b5a..eec18945d 100644 --- a/classstdex_1_1parser_1_1basic__cu__set.html +++ b/classstdex_1_1parser_1_1basic__cu__set.html @@ -218,7 +218,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__date-members.html b/classstdex_1_1parser_1_1basic__date-members.html index 1b18519a6..323243b7e 100644 --- a/classstdex_1_1parser_1_1basic__date-members.html +++ b/classstdex_1_1parser_1_1basic__date-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__date.html b/classstdex_1_1parser_1_1basic__date.html index 67918cb69..da3ed4526 100644 --- a/classstdex_1_1parser_1_1basic__date.html +++ b/classstdex_1_1parser_1_1basic__date.html @@ -258,7 +258,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html index 23e257fc5..09fe71388 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__domain__char.html b/classstdex_1_1parser_1_1basic__dns__domain__char.html index caabb3b71..9aacb1853 100644 --- a/classstdex_1_1parser_1_1basic__dns__domain__char.html +++ b/classstdex_1_1parser_1_1basic__dns__domain__char.html @@ -206,7 +206,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__dns__name-members.html b/classstdex_1_1parser_1_1basic__dns__name-members.html index 881d9b001..aea9a5be2 100644 --- a/classstdex_1_1parser_1_1basic__dns__name-members.html +++ b/classstdex_1_1parser_1_1basic__dns__name-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__dns__name.html b/classstdex_1_1parser_1_1basic__dns__name.html index f419ab142..8ff2d2f78 100644 --- a/classstdex_1_1parser_1_1basic__dns__name.html +++ b/classstdex_1_1parser_1_1basic__dns__name.html @@ -208,7 +208,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__email__address-members.html b/classstdex_1_1parser_1_1basic__email__address-members.html index 50954a6f1..942a274b3 100644 --- a/classstdex_1_1parser_1_1basic__email__address-members.html +++ b/classstdex_1_1parser_1_1basic__email__address-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__email__address.html b/classstdex_1_1parser_1_1basic__email__address.html index efff23241..febdd9889 100644 --- a/classstdex_1_1parser_1_1basic__email__address.html +++ b/classstdex_1_1parser_1_1basic__email__address.html @@ -251,7 +251,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__emoticon-members.html b/classstdex_1_1parser_1_1basic__emoticon-members.html index e29738dda..c2debd913 100644 --- a/classstdex_1_1parser_1_1basic__emoticon-members.html +++ b/classstdex_1_1parser_1_1basic__emoticon-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__emoticon.html b/classstdex_1_1parser_1_1basic__emoticon.html index d9beb1b79..e1c41b70b 100644 --- a/classstdex_1_1parser_1_1basic__emoticon.html +++ b/classstdex_1_1parser_1_1basic__emoticon.html @@ -249,7 +249,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__eol-members.html b/classstdex_1_1parser_1_1basic__eol-members.html index 03d56ee4f..21712619d 100644 --- a/classstdex_1_1parser_1_1basic__eol-members.html +++ b/classstdex_1_1parser_1_1basic__eol-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__eol.html b/classstdex_1_1parser_1_1basic__eol.html index 8ed0d8ae5..a78e02764 100644 --- a/classstdex_1_1parser_1_1basic__eol.html +++ b/classstdex_1_1parser_1_1basic__eol.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__fraction-members.html b/classstdex_1_1parser_1_1basic__fraction-members.html index 818ff42ce..b45dd8d1e 100644 --- a/classstdex_1_1parser_1_1basic__fraction-members.html +++ b/classstdex_1_1parser_1_1basic__fraction-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__fraction.html b/classstdex_1_1parser_1_1basic__fraction.html index 780304ec2..d3605c9e0 100644 --- a/classstdex_1_1parser_1_1basic__fraction.html +++ b/classstdex_1_1parser_1_1basic__fraction.html @@ -238,7 +238,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer-members.html b/classstdex_1_1parser_1_1basic__integer-members.html index 61d1a471e..5f0e7be5b 100644 --- a/classstdex_1_1parser_1_1basic__integer-members.html +++ b/classstdex_1_1parser_1_1basic__integer-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer.html b/classstdex_1_1parser_1_1basic__integer.html index 975ea06d1..bebd9eedb 100644 --- a/classstdex_1_1parser_1_1basic__integer.html +++ b/classstdex_1_1parser_1_1basic__integer.html @@ -183,7 +183,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer10-members.html b/classstdex_1_1parser_1_1basic__integer10-members.html index cf90c27fd..99bea9428 100644 --- a/classstdex_1_1parser_1_1basic__integer10-members.html +++ b/classstdex_1_1parser_1_1basic__integer10-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10.html b/classstdex_1_1parser_1_1basic__integer10.html index 76caf8b74..ee7598029 100644 --- a/classstdex_1_1parser_1_1basic__integer10.html +++ b/classstdex_1_1parser_1_1basic__integer10.html @@ -240,7 +240,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer10ts-members.html b/classstdex_1_1parser_1_1basic__integer10ts-members.html index caef16111..f028215ef 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts-members.html +++ b/classstdex_1_1parser_1_1basic__integer10ts-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer10ts.html b/classstdex_1_1parser_1_1basic__integer10ts.html index d55ea58f0..3497fe51d 100644 --- a/classstdex_1_1parser_1_1basic__integer10ts.html +++ b/classstdex_1_1parser_1_1basic__integer10ts.html @@ -256,7 +256,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__integer16-members.html b/classstdex_1_1parser_1_1basic__integer16-members.html index 6b887ca96..0adaf3c44 100644 --- a/classstdex_1_1parser_1_1basic__integer16-members.html +++ b/classstdex_1_1parser_1_1basic__integer16-members.html @@ -110,7 +110,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__integer16.html b/classstdex_1_1parser_1_1basic__integer16.html index a148b4828..2df5eea15 100644 --- a/classstdex_1_1parser_1_1basic__integer16.html +++ b/classstdex_1_1parser_1_1basic__integer16.html @@ -258,7 +258,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv4__address-members.html b/classstdex_1_1parser_1_1basic__ipv4__address-members.html index f317e0cfb..302b09040 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address-members.html @@ -105,7 +105,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv4__address.html b/classstdex_1_1parser_1_1basic__ipv4__address.html index 02596c9e3..4e9811a2b 100644 --- a/classstdex_1_1parser_1_1basic__ipv4__address.html +++ b/classstdex_1_1parser_1_1basic__ipv4__address.html @@ -271,7 +271,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv6__address-members.html b/classstdex_1_1parser_1_1basic__ipv6__address-members.html index a9ea8bbcc..ffa1e5d5e 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address-members.html @@ -113,7 +113,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__address.html b/classstdex_1_1parser_1_1basic__ipv6__address.html index 75578fcc9..5fa580c77 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__address.html +++ b/classstdex_1_1parser_1_1basic__ipv6__address.html @@ -296,7 +296,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html index 1301bb065..56be99247 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html index 9f7f82e40..690d048d6 100644 --- a/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1basic__ipv6__scope__id__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__iterations-members.html b/classstdex_1_1parser_1_1basic__iterations-members.html index 4d3eebe52..affc29226 100644 --- a/classstdex_1_1parser_1_1basic__iterations-members.html +++ b/classstdex_1_1parser_1_1basic__iterations-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__iterations.html b/classstdex_1_1parser_1_1basic__iterations.html index 2050c8d46..458f0f58a 100644 --- a/classstdex_1_1parser_1_1basic__iterations.html +++ b/classstdex_1_1parser_1_1basic__iterations.html @@ -214,7 +214,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__json__string-members.html b/classstdex_1_1parser_1_1basic__json__string-members.html index fa8276827..3bd6574ef 100644 --- a/classstdex_1_1parser_1_1basic__json__string-members.html +++ b/classstdex_1_1parser_1_1basic__json__string-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__json__string.html b/classstdex_1_1parser_1_1basic__json__string.html index 4a703f05d..4c2b24fbe 100644 --- a/classstdex_1_1parser_1_1basic__json__string.html +++ b/classstdex_1_1parser_1_1basic__json__string.html @@ -266,7 +266,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html index 7f635d3bf..8db33cb3b 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__mixed__numeral.html b/classstdex_1_1parser_1_1basic__mixed__numeral.html index b5092c694..4c43e8bbb 100644 --- a/classstdex_1_1parser_1_1basic__mixed__numeral.html +++ b/classstdex_1_1parser_1_1basic__mixed__numeral.html @@ -253,7 +253,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html index f3bffecba..ba081cf51 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__monetary__numeral.html b/classstdex_1_1parser_1_1basic__monetary__numeral.html index 16497dac9..7ba36f4a3 100644 --- a/classstdex_1_1parser_1_1basic__monetary__numeral.html +++ b/classstdex_1_1parser_1_1basic__monetary__numeral.html @@ -257,7 +257,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__noop-members.html b/classstdex_1_1parser_1_1basic__noop-members.html index 5c3526545..68751cb80 100644 --- a/classstdex_1_1parser_1_1basic__noop-members.html +++ b/classstdex_1_1parser_1_1basic__noop-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__noop.html b/classstdex_1_1parser_1_1basic__noop.html index f9fc6d875..6b5a54be2 100644 --- a/classstdex_1_1parser_1_1basic__noop.html +++ b/classstdex_1_1parser_1_1basic__noop.html @@ -191,7 +191,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__parser-members.html b/classstdex_1_1parser_1_1basic__parser-members.html index 777ca4f14..76d02fff5 100644 --- a/classstdex_1_1parser_1_1basic__parser-members.html +++ b/classstdex_1_1parser_1_1basic__parser-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__parser.html b/classstdex_1_1parser_1_1basic__parser.html index e6d18c3c0..503aaea91 100644 --- a/classstdex_1_1parser_1_1basic__parser.html +++ b/classstdex_1_1parser_1_1basic__parser.html @@ -183,7 +183,7 @@ class stdex::parser::basic_parser< T >

Base template for all parse

diff --git a/classstdex_1_1parser_1_1basic__permutation-members.html b/classstdex_1_1parser_1_1basic__permutation-members.html index 7f43ed337..b2f7b2718 100644 --- a/classstdex_1_1parser_1_1basic__permutation-members.html +++ b/classstdex_1_1parser_1_1basic__permutation-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__permutation.html b/classstdex_1_1parser_1_1basic__permutation.html index 92d22a171..961620c9b 100644 --- a/classstdex_1_1parser_1_1basic__permutation.html +++ b/classstdex_1_1parser_1_1basic__permutation.html @@ -222,7 +222,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__phone__number-members.html b/classstdex_1_1parser_1_1basic__phone__number-members.html index 65cd32a6a..7f70eb401 100644 --- a/classstdex_1_1parser_1_1basic__phone__number-members.html +++ b/classstdex_1_1parser_1_1basic__phone__number-members.html @@ -99,7 +99,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__phone__number.html b/classstdex_1_1parser_1_1basic__phone__number.html index f80bebedd..174344faa 100644 --- a/classstdex_1_1parser_1_1basic__phone__number.html +++ b/classstdex_1_1parser_1_1basic__phone__number.html @@ -252,7 +252,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__punct__cu-members.html b/classstdex_1_1parser_1_1basic__punct__cu-members.html index 38833c495..c3bdf6619 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__punct__cu.html b/classstdex_1_1parser_1_1basic__punct__cu.html index 3b89aa9d0..1dac91fff 100644 --- a/classstdex_1_1parser_1_1basic__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__punct__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__roman__numeral-members.html b/classstdex_1_1parser_1_1basic__roman__numeral-members.html index db5180903..5fb847c53 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__roman__numeral.html b/classstdex_1_1parser_1_1basic__roman__numeral.html index 5014257fa..9f0ad2833 100644 --- a/classstdex_1_1parser_1_1basic__roman__numeral.html +++ b/classstdex_1_1parser_1_1basic__roman__numeral.html @@ -237,7 +237,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html index cffd8c93d..d8e35bf15 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral-members.html @@ -103,7 +103,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__scientific__numeral.html b/classstdex_1_1parser_1_1basic__scientific__numeral.html index d213ba9c2..756258ddd 100644 --- a/classstdex_1_1parser_1_1basic__scientific__numeral.html +++ b/classstdex_1_1parser_1_1basic__scientific__numeral.html @@ -273,7 +273,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__score-members.html b/classstdex_1_1parser_1_1basic__score-members.html index f17b8355c..c19149b8e 100644 --- a/classstdex_1_1parser_1_1basic__score-members.html +++ b/classstdex_1_1parser_1_1basic__score-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__score.html b/classstdex_1_1parser_1_1basic__score.html index 01d3ac79d..e31305a04 100644 --- a/classstdex_1_1parser_1_1basic__score.html +++ b/classstdex_1_1parser_1_1basic__score.html @@ -242,7 +242,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__sequence-members.html b/classstdex_1_1parser_1_1basic__sequence-members.html index 2310d28e9..e9e8684a8 100644 --- a/classstdex_1_1parser_1_1basic__sequence-members.html +++ b/classstdex_1_1parser_1_1basic__sequence-members.html @@ -97,7 +97,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__sequence.html b/classstdex_1_1parser_1_1basic__sequence.html index 5df536ba7..dec97b710 100644 --- a/classstdex_1_1parser_1_1basic__sequence.html +++ b/classstdex_1_1parser_1_1basic__sequence.html @@ -215,7 +215,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__set-members.html b/classstdex_1_1parser_1_1basic__set-members.html index 812fc830e..bf3fffc46 100644 --- a/classstdex_1_1parser_1_1basic__set-members.html +++ b/classstdex_1_1parser_1_1basic__set-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__set.html b/classstdex_1_1parser_1_1basic__set.html index 69e8400d8..a483df59d 100644 --- a/classstdex_1_1parser_1_1basic__set.html +++ b/classstdex_1_1parser_1_1basic__set.html @@ -229,7 +229,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__signed__numeral-members.html b/classstdex_1_1parser_1_1basic__signed__numeral-members.html index 51f2fbeeb..e5e5a73dc 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral-members.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__signed__numeral.html b/classstdex_1_1parser_1_1basic__signed__numeral.html index 9caf00666..03ea25e34 100644 --- a/classstdex_1_1parser_1_1basic__signed__numeral.html +++ b/classstdex_1_1parser_1_1basic__signed__numeral.html @@ -245,7 +245,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__space__cu-members.html b/classstdex_1_1parser_1_1basic__space__cu-members.html index 7f4ef5aa6..83eee4e3b 100644 --- a/classstdex_1_1parser_1_1basic__space__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__cu.html b/classstdex_1_1parser_1_1basic__space__cu.html index d1c9a5526..3990d2f7e 100644 --- a/classstdex_1_1parser_1_1basic__space__cu.html +++ b/classstdex_1_1parser_1_1basic__space__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html b/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html index 691bc5a1d..fc85afde8 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html index 7b35cdd4d..11481c223 100644 --- a/classstdex_1_1parser_1_1basic__space__or__punct__cu.html +++ b/classstdex_1_1parser_1_1basic__space__or__punct__cu.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__string-members.html b/classstdex_1_1parser_1_1basic__string-members.html index f80547d97..da8568db5 100644 --- a/classstdex_1_1parser_1_1basic__string-members.html +++ b/classstdex_1_1parser_1_1basic__string-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string.html b/classstdex_1_1parser_1_1basic__string.html index 8dead2810..000d5aa70 100644 --- a/classstdex_1_1parser_1_1basic__string.html +++ b/classstdex_1_1parser_1_1basic__string.html @@ -201,7 +201,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__string__branch-members.html b/classstdex_1_1parser_1_1basic__string__branch-members.html index b3045c84e..aef089d2a 100644 --- a/classstdex_1_1parser_1_1basic__string__branch-members.html +++ b/classstdex_1_1parser_1_1basic__string__branch-members.html @@ -104,7 +104,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__string__branch.html b/classstdex_1_1parser_1_1basic__string__branch.html index ac81ffda3..fbe7c3fe3 100644 --- a/classstdex_1_1parser_1_1basic__string__branch.html +++ b/classstdex_1_1parser_1_1basic__string__branch.html @@ -193,7 +193,7 @@ class stdex::parser::basic_string_branch< T, T_parser >

Test for a

diff --git a/classstdex_1_1parser_1_1basic__time-members.html b/classstdex_1_1parser_1_1basic__time-members.html index 4cb99461d..437e08e00 100644 --- a/classstdex_1_1parser_1_1basic__time-members.html +++ b/classstdex_1_1parser_1_1basic__time-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__time.html b/classstdex_1_1parser_1_1basic__time.html index 2532dbc88..c6dcbc5af 100644 --- a/classstdex_1_1parser_1_1basic__time.html +++ b/classstdex_1_1parser_1_1basic__time.html @@ -248,7 +248,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url-members.html b/classstdex_1_1parser_1_1basic__url-members.html index c176e6462..fe49028f3 100644 --- a/classstdex_1_1parser_1_1basic__url-members.html +++ b/classstdex_1_1parser_1_1basic__url-members.html @@ -108,7 +108,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url.html b/classstdex_1_1parser_1_1basic__url.html index 300e21acd..d2bddba38 100644 --- a/classstdex_1_1parser_1_1basic__url.html +++ b/classstdex_1_1parser_1_1basic__url.html @@ -278,7 +278,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__password__char-members.html b/classstdex_1_1parser_1_1basic__url__password__char-members.html index 137c72dc5..d86bd78da 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__password__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__password__char.html b/classstdex_1_1parser_1_1basic__url__password__char.html index f6f662844..171d20cb6 100644 --- a/classstdex_1_1parser_1_1basic__url__password__char.html +++ b/classstdex_1_1parser_1_1basic__url__password__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__path-members.html b/classstdex_1_1parser_1_1basic__url__path-members.html index 6e4b6626c..82f8adc51 100644 --- a/classstdex_1_1parser_1_1basic__url__path-members.html +++ b/classstdex_1_1parser_1_1basic__url__path-members.html @@ -98,7 +98,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path.html b/classstdex_1_1parser_1_1basic__url__path.html index 7b4520779..4da94a41a 100644 --- a/classstdex_1_1parser_1_1basic__url__path.html +++ b/classstdex_1_1parser_1_1basic__url__path.html @@ -248,7 +248,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__path__char-members.html b/classstdex_1_1parser_1_1basic__url__path__char-members.html index f8f34d865..a5709d16c 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__path__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__path__char.html b/classstdex_1_1parser_1_1basic__url__path__char.html index 15a1aee54..a502b8e4d 100644 --- a/classstdex_1_1parser_1_1basic__url__path__char.html +++ b/classstdex_1_1parser_1_1basic__url__path__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1basic__url__username__char-members.html b/classstdex_1_1parser_1_1basic__url__username__char-members.html index 6c28f877d..e71975e06 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char-members.html +++ b/classstdex_1_1parser_1_1basic__url__username__char-members.html @@ -92,7 +92,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1basic__url__username__char.html b/classstdex_1_1parser_1_1basic__url__username__char.html index ab53fb0f2..a535808d0 100644 --- a/classstdex_1_1parser_1_1basic__url__username__char.html +++ b/classstdex_1_1parser_1_1basic__url__username__char.html @@ -194,7 +194,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1http__agent-members.html b/classstdex_1_1parser_1_1http__agent-members.html index 0903baf4a..6714231bb 100644 --- a/classstdex_1_1parser_1_1http__agent-members.html +++ b/classstdex_1_1parser_1_1http__agent-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__agent.html b/classstdex_1_1parser_1_1http__agent.html index d6758b956..52f99ee5f 100644 --- a/classstdex_1_1parser_1_1http__agent.html +++ b/classstdex_1_1parser_1_1http__agent.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__any__type-members.html b/classstdex_1_1parser_1_1http__any__type-members.html index f410e4392..3da4bc14c 100644 --- a/classstdex_1_1parser_1_1http__any__type-members.html +++ b/classstdex_1_1parser_1_1http__any__type-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__any__type.html b/classstdex_1_1parser_1_1http__any__type.html index e603f1f8f..ac1130342 100644 --- a/classstdex_1_1parser_1_1http__any__type.html +++ b/classstdex_1_1parser_1_1http__any__type.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__asterisk-members.html b/classstdex_1_1parser_1_1http__asterisk-members.html index 8018cfce7..626a17e64 100644 --- a/classstdex_1_1parser_1_1http__asterisk-members.html +++ b/classstdex_1_1parser_1_1http__asterisk-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__asterisk.html b/classstdex_1_1parser_1_1http__asterisk.html index 516f3ea14..d2db0a88f 100644 --- a/classstdex_1_1parser_1_1http__asterisk.html +++ b/classstdex_1_1parser_1_1http__asterisk.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie-members.html b/classstdex_1_1parser_1_1http__cookie-members.html index 1f4ebdeda..7572d0e9f 100644 --- a/classstdex_1_1parser_1_1http__cookie-members.html +++ b/classstdex_1_1parser_1_1http__cookie-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie.html b/classstdex_1_1parser_1_1http__cookie.html index 0f448f415..be4d0faf6 100644 --- a/classstdex_1_1parser_1_1http__cookie.html +++ b/classstdex_1_1parser_1_1http__cookie.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__cookie__parameter-members.html b/classstdex_1_1parser_1_1http__cookie__parameter-members.html index 2edb38f75..38ef95c84 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter-members.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__cookie__parameter.html b/classstdex_1_1parser_1_1http__cookie__parameter.html index 364f9ca43..d299a669a 100644 --- a/classstdex_1_1parser_1_1http__cookie__parameter.html +++ b/classstdex_1_1parser_1_1http__cookie__parameter.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__header-members.html b/classstdex_1_1parser_1_1http__header-members.html index 9f02299be..091fc386a 100644 --- a/classstdex_1_1parser_1_1http__header-members.html +++ b/classstdex_1_1parser_1_1http__header-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__header.html b/classstdex_1_1parser_1_1http__header.html index 13093f43d..675e806fb 100644 --- a/classstdex_1_1parser_1_1http__header.html +++ b/classstdex_1_1parser_1_1http__header.html @@ -230,7 +230,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__language-members.html b/classstdex_1_1parser_1_1http__language-members.html index ba625a746..12ae3c3c1 100644 --- a/classstdex_1_1parser_1_1http__language-members.html +++ b/classstdex_1_1parser_1_1http__language-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__language.html b/classstdex_1_1parser_1_1http__language.html index d5f9c0fc7..46c92b398 100644 --- a/classstdex_1_1parser_1_1http__language.html +++ b/classstdex_1_1parser_1_1http__language.html @@ -223,7 +223,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__line__break-members.html b/classstdex_1_1parser_1_1http__line__break-members.html index e91fe7492..565744131 100644 --- a/classstdex_1_1parser_1_1http__line__break-members.html +++ b/classstdex_1_1parser_1_1http__line__break-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__line__break.html b/classstdex_1_1parser_1_1http__line__break.html index 50571ef3c..16e781050 100644 --- a/classstdex_1_1parser_1_1http__line__break.html +++ b/classstdex_1_1parser_1_1http__line__break.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__range-members.html b/classstdex_1_1parser_1_1http__media__range-members.html index a4ed99d1c..3cb564fe6 100644 --- a/classstdex_1_1parser_1_1http__media__range-members.html +++ b/classstdex_1_1parser_1_1http__media__range-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__range.html b/classstdex_1_1parser_1_1http__media__range.html index dc717b271..8c689d46e 100644 --- a/classstdex_1_1parser_1_1http__media__range.html +++ b/classstdex_1_1parser_1_1http__media__range.html @@ -231,7 +231,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__media__type-members.html b/classstdex_1_1parser_1_1http__media__type-members.html index bbbd6d79a..703cd1d55 100644 --- a/classstdex_1_1parser_1_1http__media__type-members.html +++ b/classstdex_1_1parser_1_1http__media__type-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__media__type.html b/classstdex_1_1parser_1_1http__media__type.html index 42d760a39..2bbfda7ad 100644 --- a/classstdex_1_1parser_1_1http__media__type.html +++ b/classstdex_1_1parser_1_1http__media__type.html @@ -239,7 +239,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__parameter-members.html b/classstdex_1_1parser_1_1http__parameter-members.html index 4c32b82dd..0498587f2 100644 --- a/classstdex_1_1parser_1_1http__parameter-members.html +++ b/classstdex_1_1parser_1_1http__parameter-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__parameter.html b/classstdex_1_1parser_1_1http__parameter.html index 518573634..645a77145 100644 --- a/classstdex_1_1parser_1_1http__parameter.html +++ b/classstdex_1_1parser_1_1http__parameter.html @@ -232,7 +232,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__protocol-members.html b/classstdex_1_1parser_1_1http__protocol-members.html index 2f2fc706e..b1541eb37 100644 --- a/classstdex_1_1parser_1_1http__protocol-members.html +++ b/classstdex_1_1parser_1_1http__protocol-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__protocol.html b/classstdex_1_1parser_1_1http__protocol.html index 5f3a3d8a8..33aa81818 100644 --- a/classstdex_1_1parser_1_1http__protocol.html +++ b/classstdex_1_1parser_1_1http__protocol.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__quoted__string-members.html b/classstdex_1_1parser_1_1http__quoted__string-members.html index ead0e8c41..471e34ef1 100644 --- a/classstdex_1_1parser_1_1http__quoted__string-members.html +++ b/classstdex_1_1parser_1_1http__quoted__string-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__quoted__string.html b/classstdex_1_1parser_1_1http__quoted__string.html index 90b88afce..20a2afb24 100644 --- a/classstdex_1_1parser_1_1http__quoted__string.html +++ b/classstdex_1_1parser_1_1http__quoted__string.html @@ -228,7 +228,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__request-members.html b/classstdex_1_1parser_1_1http__request-members.html index 7eb06b4d3..e533cc17a 100644 --- a/classstdex_1_1parser_1_1http__request-members.html +++ b/classstdex_1_1parser_1_1http__request-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__request.html b/classstdex_1_1parser_1_1http__request.html index abc13f6b5..3b200e99a 100644 --- a/classstdex_1_1parser_1_1http__request.html +++ b/classstdex_1_1parser_1_1http__request.html @@ -236,7 +236,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__space-members.html b/classstdex_1_1parser_1_1http__space-members.html index 65a870265..2734a0126 100644 --- a/classstdex_1_1parser_1_1http__space-members.html +++ b/classstdex_1_1parser_1_1http__space-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__space.html b/classstdex_1_1parser_1_1http__space.html index c15a168cc..edcef2ea4 100644 --- a/classstdex_1_1parser_1_1http__space.html +++ b/classstdex_1_1parser_1_1http__space.html @@ -194,7 +194,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1http__text__char-members.html b/classstdex_1_1parser_1_1http__text__char-members.html index 723ebe1c4..bf6d90d2e 100644 --- a/classstdex_1_1parser_1_1http__text__char-members.html +++ b/classstdex_1_1parser_1_1http__text__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__text__char.html b/classstdex_1_1parser_1_1http__text__char.html index 77d47b7cf..e5cc1cc71 100644 --- a/classstdex_1_1parser_1_1http__text__char.html +++ b/classstdex_1_1parser_1_1http__text__char.html @@ -194,7 +194,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1http__token-members.html b/classstdex_1_1parser_1_1http__token-members.html index 2a80956e7..5a725ff4d 100644 --- a/classstdex_1_1parser_1_1http__token-members.html +++ b/classstdex_1_1parser_1_1http__token-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__token.html b/classstdex_1_1parser_1_1http__token.html index 6b3e8146f..5bf94fdc4 100644 --- a/classstdex_1_1parser_1_1http__token.html +++ b/classstdex_1_1parser_1_1http__token.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url-members.html b/classstdex_1_1parser_1_1http__url-members.html index ad2cf1910..93143602b 100644 --- a/classstdex_1_1parser_1_1http__url-members.html +++ b/classstdex_1_1parser_1_1http__url-members.html @@ -91,7 +91,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url.html b/classstdex_1_1parser_1_1http__url.html index 4770ccaa8..346128571 100644 --- a/classstdex_1_1parser_1_1http__url.html +++ b/classstdex_1_1parser_1_1http__url.html @@ -235,7 +235,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__parameter-members.html b/classstdex_1_1parser_1_1http__url__parameter-members.html index 59ea1bdfb..e6151b7ef 100644 --- a/classstdex_1_1parser_1_1http__url__parameter-members.html +++ b/classstdex_1_1parser_1_1http__url__parameter-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__parameter.html b/classstdex_1_1parser_1_1http__url__parameter.html index bc2b647f5..c309cebcd 100644 --- a/classstdex_1_1parser_1_1http__url__parameter.html +++ b/classstdex_1_1parser_1_1http__url__parameter.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path-members.html b/classstdex_1_1parser_1_1http__url__path-members.html index 3d5a70411..ce0bfef6f 100644 --- a/classstdex_1_1parser_1_1http__url__path-members.html +++ b/classstdex_1_1parser_1_1http__url__path-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path.html b/classstdex_1_1parser_1_1http__url__path.html index 19289dca7..ab42efb24 100644 --- a/classstdex_1_1parser_1_1http__url__path.html +++ b/classstdex_1_1parser_1_1http__url__path.html @@ -224,7 +224,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__path__segment-members.html b/classstdex_1_1parser_1_1http__url__path__segment-members.html index 12db0b2e3..b4c94fedb 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment-members.html +++ b/classstdex_1_1parser_1_1http__url__path__segment-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__path__segment.html b/classstdex_1_1parser_1_1http__url__path__segment.html index a677e95b0..3766d54c2 100644 --- a/classstdex_1_1parser_1_1http__url__path__segment.html +++ b/classstdex_1_1parser_1_1http__url__path__segment.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__port-members.html b/classstdex_1_1parser_1_1http__url__port-members.html index 202aed561..34b821f41 100644 --- a/classstdex_1_1parser_1_1http__url__port-members.html +++ b/classstdex_1_1parser_1_1http__url__port-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__port.html b/classstdex_1_1parser_1_1http__url__port.html index 4e3880071..3541e7d78 100644 --- a/classstdex_1_1parser_1_1http__url__port.html +++ b/classstdex_1_1parser_1_1http__url__port.html @@ -226,7 +226,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__url__server-members.html b/classstdex_1_1parser_1_1http__url__server-members.html index d85f31466..41377d7ca 100644 --- a/classstdex_1_1parser_1_1http__url__server-members.html +++ b/classstdex_1_1parser_1_1http__url__server-members.html @@ -85,7 +85,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__url__server.html b/classstdex_1_1parser_1_1http__url__server.html index 04b42595f..61057d4e8 100644 --- a/classstdex_1_1parser_1_1http__url__server.html +++ b/classstdex_1_1parser_1_1http__url__server.html @@ -187,7 +187,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value-members.html b/classstdex_1_1parser_1_1http__value-members.html index 7874beaab..1dbdf9f89 100644 --- a/classstdex_1_1parser_1_1http__value-members.html +++ b/classstdex_1_1parser_1_1http__value-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__value.html b/classstdex_1_1parser_1_1http__value.html index 6dd63967b..4533132ff 100644 --- a/classstdex_1_1parser_1_1http__value.html +++ b/classstdex_1_1parser_1_1http__value.html @@ -228,7 +228,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__value__collection-members.html b/classstdex_1_1parser_1_1http__value__collection-members.html index c09c42831..6db22e662 100644 --- a/classstdex_1_1parser_1_1http__value__collection-members.html +++ b/classstdex_1_1parser_1_1http__value__collection-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__value__collection.html b/classstdex_1_1parser_1_1http__value__collection.html index b7156fac4..9cb0300a5 100644 --- a/classstdex_1_1parser_1_1http__value__collection.html +++ b/classstdex_1_1parser_1_1http__value__collection.html @@ -107,7 +107,7 @@ class stdex::parser::http_value_collection< T >

Collection of HTTP

diff --git a/classstdex_1_1parser_1_1http__weight-members.html b/classstdex_1_1parser_1_1http__weight-members.html index 779d1cdec..d1fd8a56b 100644 --- a/classstdex_1_1parser_1_1http__weight-members.html +++ b/classstdex_1_1parser_1_1http__weight-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__weight.html b/classstdex_1_1parser_1_1http__weight.html index 108cf6c4f..8ccfdaceb 100644 --- a/classstdex_1_1parser_1_1http__weight.html +++ b/classstdex_1_1parser_1_1http__weight.html @@ -227,7 +227,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1http__weighted__value-members.html b/classstdex_1_1parser_1_1http__weighted__value-members.html index d2b509973..79719233a 100644 --- a/classstdex_1_1parser_1_1http__weighted__value-members.html +++ b/classstdex_1_1parser_1_1http__weighted__value-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1http__weighted__value.html b/classstdex_1_1parser_1_1http__weighted__value.html index 5b848448d..65351ff53 100644 --- a/classstdex_1_1parser_1_1http__weighted__value.html +++ b/classstdex_1_1parser_1_1http__weighted__value.html @@ -237,7 +237,7 @@ template<class T , class T_asterisk = http_asterisk> diff --git a/classstdex_1_1parser_1_1parser__collection-members.html b/classstdex_1_1parser_1_1parser__collection-members.html index 2dde88412..3f16fe0af 100644 --- a/classstdex_1_1parser_1_1parser__collection-members.html +++ b/classstdex_1_1parser_1_1parser__collection-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1parser__collection.html b/classstdex_1_1parser_1_1parser__collection.html index 6591bea0f..b91bd32bb 100644 --- a/classstdex_1_1parser_1_1parser__collection.html +++ b/classstdex_1_1parser_1_1parser__collection.html @@ -192,7 +192,7 @@ template<class T > diff --git a/classstdex_1_1parser_1_1sgml__any__cp-members.html b/classstdex_1_1parser_1_1sgml__any__cp-members.html index 4ff557484..a2f91444e 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__any__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__any__cp.html b/classstdex_1_1parser_1_1sgml__any__cp.html index 5f01864d1..337926be9 100644 --- a/classstdex_1_1parser_1_1sgml__any__cp.html +++ b/classstdex_1_1parser_1_1sgml__any__cp.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__cp-members.html b/classstdex_1_1parser_1_1sgml__cp-members.html index b51330317..fa0fd2120 100644 --- a/classstdex_1_1parser_1_1sgml__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__cp-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp.html b/classstdex_1_1parser_1_1sgml__cp.html index 6c3197cc5..d53d71ece 100644 --- a/classstdex_1_1parser_1_1sgml__cp.html +++ b/classstdex_1_1parser_1_1sgml__cp.html @@ -200,7 +200,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1sgml__cp__set-members.html b/classstdex_1_1parser_1_1sgml__cp__set-members.html index d566fba6b..3e8563f94 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set-members.html +++ b/classstdex_1_1parser_1_1sgml__cp__set-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__cp__set.html b/classstdex_1_1parser_1_1sgml__cp__set.html index 8adbd3b4f..59446ed6b 100644 --- a/classstdex_1_1parser_1_1sgml__cp__set.html +++ b/classstdex_1_1parser_1_1sgml__cp__set.html @@ -216,7 +216,7 @@ size_t hit_offset diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html index 1f11267f0..dacf1409d 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__dns__domain__char.html b/classstdex_1_1parser_1_1sgml__dns__domain__char.html index e13803322..9483af8d9 100644 --- a/classstdex_1_1parser_1_1sgml__dns__domain__char.html +++ b/classstdex_1_1parser_1_1sgml__dns__domain__char.html @@ -208,7 +208,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html index 65a076c64..a9cb83ebc 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html index d941a1e65..0e2d1fb93 100644 --- a/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html +++ b/classstdex_1_1parser_1_1sgml__ipv6__scope__id__char.html @@ -190,7 +190,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__punct__cp-members.html b/classstdex_1_1parser_1_1sgml__punct__cp-members.html index 0ee70af92..99a6feeec 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__punct__cp.html b/classstdex_1_1parser_1_1sgml__punct__cp.html index 137361202..9f1336fd6 100644 --- a/classstdex_1_1parser_1_1sgml__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__punct__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__space__cp-members.html b/classstdex_1_1parser_1_1sgml__space__cp-members.html index b0f56fca1..e097000a7 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__cp.html b/classstdex_1_1parser_1_1sgml__space__cp.html index ad2a5afe8..4ff66c3af 100644 --- a/classstdex_1_1parser_1_1sgml__space__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html b/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html index b5158b894..efa774d72 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html index 95d60dc69..d1c24a7b2 100644 --- a/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html +++ b/classstdex_1_1parser_1_1sgml__space__or__punct__cp.html @@ -203,7 +203,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__string-members.html b/classstdex_1_1parser_1_1sgml__string-members.html index d5563affb..841790485 100644 --- a/classstdex_1_1parser_1_1sgml__string-members.html +++ b/classstdex_1_1parser_1_1sgml__string-members.html @@ -87,7 +87,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__string.html b/classstdex_1_1parser_1_1sgml__string.html index f7c7b63f9..5cc57b713 100644 --- a/classstdex_1_1parser_1_1sgml__string.html +++ b/classstdex_1_1parser_1_1sgml__string.html @@ -197,7 +197,7 @@ Additional Inherited Members diff --git a/classstdex_1_1parser_1_1sgml__url__password__char-members.html b/classstdex_1_1parser_1_1sgml__url__password__char-members.html index ee50ee761..ea79b21dc 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__password__char.html b/classstdex_1_1parser_1_1sgml__url__password__char.html index 8efbca94e..4bc97af32 100644 --- a/classstdex_1_1parser_1_1sgml__url__password__char.html +++ b/classstdex_1_1parser_1_1sgml__url__password__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__url__path__char-members.html b/classstdex_1_1parser_1_1sgml__url__path__char-members.html index b49a5e861..d88f68d0c 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__path__char.html b/classstdex_1_1parser_1_1sgml__url__path__char.html index 033377ccc..d7884d2c7 100644 --- a/classstdex_1_1parser_1_1sgml__url__path__char.html +++ b/classstdex_1_1parser_1_1sgml__url__path__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1parser_1_1sgml__url__username__char-members.html b/classstdex_1_1parser_1_1sgml__url__username__char-members.html index af64bd388..ae1099004 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char-members.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char-members.html @@ -93,7 +93,7 @@ $(function() { diff --git a/classstdex_1_1parser_1_1sgml__url__username__char.html b/classstdex_1_1parser_1_1sgml__url__username__char.html index 77d396125..a603e28d3 100644 --- a/classstdex_1_1parser_1_1sgml__url__username__char.html +++ b/classstdex_1_1parser_1_1sgml__url__username__char.html @@ -199,7 +199,7 @@ std::locale m_locale diff --git a/classstdex_1_1progress-members.html b/classstdex_1_1progress-members.html index 4eb41c20d..2345f4ccb 100644 --- a/classstdex_1_1progress-members.html +++ b/classstdex_1_1progress-members.html @@ -88,7 +88,7 @@ $(function() { diff --git a/classstdex_1_1progress.html b/classstdex_1_1progress.html index 226a4534f..ef3073d41 100644 --- a/classstdex_1_1progress.html +++ b/classstdex_1_1progress.html @@ -319,7 +319,7 @@ template<class T > diff --git a/classstdex_1_1progress__switcher-members.html b/classstdex_1_1progress__switcher-members.html index f7072f2fc..115c230d5 100644 --- a/classstdex_1_1progress__switcher-members.html +++ b/classstdex_1_1progress__switcher-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1progress__switcher.html b/classstdex_1_1progress__switcher.html index f9e267ebe..719fae43b 100644 --- a/classstdex_1_1progress__switcher.html +++ b/classstdex_1_1progress__switcher.html @@ -178,7 +178,7 @@ class stdex::progress_switcher< T >

Progress indicator switcher. <

diff --git a/classstdex_1_1ring-members.html b/classstdex_1_1ring-members.html index d259d4ba3..feec1d802 100644 --- a/classstdex_1_1ring-members.html +++ b/classstdex_1_1ring-members.html @@ -100,7 +100,7 @@ $(function() { diff --git a/classstdex_1_1ring.html b/classstdex_1_1ring.html index dff90979d..5293ee73d 100644 --- a/classstdex_1_1ring.html +++ b/classstdex_1_1ring.html @@ -296,7 +296,7 @@ template<class T , size_t CAPACITY> diff --git a/classstdex_1_1stream_1_1async__reader-members.html b/classstdex_1_1stream_1_1async__reader-members.html index bb4cf9c04..4bc9dac69 100644 --- a/classstdex_1_1stream_1_1async__reader-members.html +++ b/classstdex_1_1stream_1_1async__reader-members.html @@ -146,7 +146,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__reader.html b/classstdex_1_1stream_1_1async__reader.html index 033fe41a6..24759c855 100644 --- a/classstdex_1_1stream_1_1async__reader.html +++ b/classstdex_1_1stream_1_1async__reader.html @@ -395,7 +395,7 @@ template<size_t CAPACITY = default_async_limit> diff --git a/classstdex_1_1stream_1_1async__writer-members.html b/classstdex_1_1stream_1_1async__writer-members.html index dbf06c792..88602e966 100644 --- a/classstdex_1_1stream_1_1async__writer-members.html +++ b/classstdex_1_1stream_1_1async__writer-members.html @@ -146,7 +146,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1async__writer.html b/classstdex_1_1stream_1_1async__writer.html index 058e4a71e..f0fd30b4e 100644 --- a/classstdex_1_1stream_1_1async__writer.html +++ b/classstdex_1_1stream_1_1async__writer.html @@ -429,7 +429,7 @@ template<size_t CAPACITY = default_async_limit> diff --git a/classstdex_1_1stream_1_1basic-members.html b/classstdex_1_1stream_1_1basic-members.html index 90d62d21a..9766d0014 100644 --- a/classstdex_1_1stream_1_1basic-members.html +++ b/classstdex_1_1stream_1_1basic-members.html @@ -137,7 +137,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic.html b/classstdex_1_1stream_1_1basic.html index d76869326..e0fee1185 100644 --- a/classstdex_1_1stream_1_1basic.html +++ b/classstdex_1_1stream_1_1basic.html @@ -1219,7 +1219,7 @@ template<class T > diff --git a/classstdex_1_1stream_1_1basic__file-members.html b/classstdex_1_1stream_1_1basic__file-members.html index 48ca1dc0e..77a7cd65d 100644 --- a/classstdex_1_1stream_1_1basic__file-members.html +++ b/classstdex_1_1stream_1_1basic__file-members.html @@ -153,7 +153,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic__file.html b/classstdex_1_1stream_1_1basic__file.html index 9da93cad0..96ef14657 100644 --- a/classstdex_1_1stream_1_1basic__file.html +++ b/classstdex_1_1stream_1_1basic__file.html @@ -926,7 +926,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1basic__sys-members.html b/classstdex_1_1stream_1_1basic__sys-members.html index 70745abf5..96bc51ab1 100644 --- a/classstdex_1_1stream_1_1basic__sys-members.html +++ b/classstdex_1_1stream_1_1basic__sys-members.html @@ -149,7 +149,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1basic__sys.html b/classstdex_1_1stream_1_1basic__sys.html index b42a94319..0db19cb16 100644 --- a/classstdex_1_1stream_1_1basic__sys.html +++ b/classstdex_1_1stream_1_1basic__sys.html @@ -501,7 +501,7 @@ sys_handle m_h diff --git a/classstdex_1_1stream_1_1buffer-members.html b/classstdex_1_1stream_1_1buffer-members.html index f22c7f823..74a0c6163 100644 --- a/classstdex_1_1stream_1_1buffer-members.html +++ b/classstdex_1_1stream_1_1buffer-members.html @@ -147,7 +147,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1buffer.html b/classstdex_1_1stream_1_1buffer.html index b2391010b..8590ac355 100644 --- a/classstdex_1_1stream_1_1buffer.html +++ b/classstdex_1_1stream_1_1buffer.html @@ -476,7 +476,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1buffered__sys-members.html b/classstdex_1_1stream_1_1buffered__sys-members.html index 3a1cb3e87..adae9c55b 100644 --- a/classstdex_1_1stream_1_1buffered__sys-members.html +++ b/classstdex_1_1stream_1_1buffered__sys-members.html @@ -148,7 +148,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1buffered__sys.html b/classstdex_1_1stream_1_1buffered__sys.html index daf8f60f9..421665e81 100644 --- a/classstdex_1_1stream_1_1buffered__sys.html +++ b/classstdex_1_1stream_1_1buffered__sys.html @@ -352,7 +352,7 @@ void init ( diff --git a/classstdex_1_1stream_1_1cache-members.html b/classstdex_1_1stream_1_1cache-members.html index 339a4578c..ed3923b03 100644 --- a/classstdex_1_1stream_1_1cache-members.html +++ b/classstdex_1_1stream_1_1cache-members.html @@ -164,7 +164,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cache.html b/classstdex_1_1stream_1_1cache.html index c19670fef..692da85ea 100644 --- a/classstdex_1_1stream_1_1cache.html +++ b/classstdex_1_1stream_1_1cache.html @@ -977,7 +977,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1cached__file-members.html b/classstdex_1_1stream_1_1cached__file-members.html index 38bfb8a09..6ead72458 100644 --- a/classstdex_1_1stream_1_1cached__file-members.html +++ b/classstdex_1_1stream_1_1cached__file-members.html @@ -167,7 +167,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1cached__file.html b/classstdex_1_1stream_1_1cached__file.html index dc5ebd5d0..e937bd290 100644 --- a/classstdex_1_1stream_1_1cached__file.html +++ b/classstdex_1_1stream_1_1cached__file.html @@ -544,7 +544,7 @@ void write_cache () diff --git a/classstdex_1_1stream_1_1converter-members.html b/classstdex_1_1stream_1_1converter-members.html index 4cd74ae5c..0b36df3e8 100644 --- a/classstdex_1_1stream_1_1converter-members.html +++ b/classstdex_1_1stream_1_1converter-members.html @@ -141,7 +141,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1converter.html b/classstdex_1_1stream_1_1converter.html index 9795208fd..27b000b61 100644 --- a/classstdex_1_1stream_1_1converter.html +++ b/classstdex_1_1stream_1_1converter.html @@ -482,7 +482,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1diag__file-members.html b/classstdex_1_1stream_1_1diag__file-members.html index c7b190711..5243b7cc5 100644 --- a/classstdex_1_1stream_1_1diag__file-members.html +++ b/classstdex_1_1stream_1_1diag__file-members.html @@ -156,7 +156,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1diag__file.html b/classstdex_1_1stream_1_1diag__file.html index fbda1ba01..11a039dcf 100644 --- a/classstdex_1_1stream_1_1diag__file.html +++ b/classstdex_1_1stream_1_1diag__file.html @@ -749,7 +749,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1fifo-members.html b/classstdex_1_1stream_1_1fifo-members.html index 52a4b07df..00648e7ff 100644 --- a/classstdex_1_1stream_1_1fifo-members.html +++ b/classstdex_1_1stream_1_1fifo-members.html @@ -144,7 +144,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1fifo.html b/classstdex_1_1stream_1_1fifo.html index d793e6ba3..601238b63 100644 --- a/classstdex_1_1stream_1_1fifo.html +++ b/classstdex_1_1stream_1_1fifo.html @@ -447,7 +447,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1file-members.html b/classstdex_1_1stream_1_1file-members.html index 3c547c931..dc7bf9ca9 100644 --- a/classstdex_1_1stream_1_1file-members.html +++ b/classstdex_1_1stream_1_1file-members.html @@ -172,7 +172,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file.html b/classstdex_1_1stream_1_1file.html index 4042f3b2c..79e689424 100644 --- a/classstdex_1_1stream_1_1file.html +++ b/classstdex_1_1stream_1_1file.html @@ -927,7 +927,7 @@ sys_handle m_h diff --git a/classstdex_1_1stream_1_1file__window-members.html b/classstdex_1_1stream_1_1file__window-members.html index 09d423958..8f0783434 100644 --- a/classstdex_1_1stream_1_1file__window-members.html +++ b/classstdex_1_1stream_1_1file__window-members.html @@ -157,7 +157,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1file__window.html b/classstdex_1_1stream_1_1file__window.html index 96a3d6755..ff6882526 100644 --- a/classstdex_1_1stream_1_1file__window.html +++ b/classstdex_1_1stream_1_1file__window.html @@ -785,7 +785,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1limiter-members.html b/classstdex_1_1stream_1_1limiter-members.html index 26da802df..bdcf809cf 100644 --- a/classstdex_1_1stream_1_1limiter-members.html +++ b/classstdex_1_1stream_1_1limiter-members.html @@ -144,7 +144,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1limiter.html b/classstdex_1_1stream_1_1limiter.html index 9f3322862..cd9318d95 100644 --- a/classstdex_1_1stream_1_1limiter.html +++ b/classstdex_1_1stream_1_1limiter.html @@ -437,7 +437,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1memory__file-members.html b/classstdex_1_1stream_1_1memory__file-members.html index 296b10cdf..8a4cc59b5 100644 --- a/classstdex_1_1stream_1_1memory__file-members.html +++ b/classstdex_1_1stream_1_1memory__file-members.html @@ -194,7 +194,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1memory__file.html b/classstdex_1_1stream_1_1memory__file.html index a0a08cd30..6cdd698b9 100644 --- a/classstdex_1_1stream_1_1memory__file.html +++ b/classstdex_1_1stream_1_1memory__file.html @@ -1485,7 +1485,7 @@ template<class T > diff --git a/classstdex_1_1stream_1_1replicator-members.html b/classstdex_1_1stream_1_1replicator-members.html index e1f4a97f5..f1feab92c 100644 --- a/classstdex_1_1stream_1_1replicator-members.html +++ b/classstdex_1_1stream_1_1replicator-members.html @@ -142,7 +142,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator.html b/classstdex_1_1stream_1_1replicator.html index 5531c1adb..4cece973c 100644 --- a/classstdex_1_1stream_1_1replicator.html +++ b/classstdex_1_1stream_1_1replicator.html @@ -430,7 +430,7 @@ state_t m_state diff --git a/classstdex_1_1stream_1_1replicator_1_1worker-members.html b/classstdex_1_1stream_1_1replicator_1_1worker-members.html index c9980caf6..6a25307bf 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker-members.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker-members.html @@ -94,7 +94,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1replicator_1_1worker.html b/classstdex_1_1stream_1_1replicator_1_1worker.html index 16be377dc..f6d504f7c 100644 --- a/classstdex_1_1stream_1_1replicator_1_1worker.html +++ b/classstdex_1_1stream_1_1replicator_1_1worker.html @@ -146,7 +146,7 @@ static void process_op diff --git a/classstdex_1_1stream_1_1window-members.html b/classstdex_1_1stream_1_1window-members.html index 8cb4b5289..31fb47835 100644 --- a/classstdex_1_1stream_1_1window-members.html +++ b/classstdex_1_1stream_1_1window-members.html @@ -147,7 +147,7 @@ $(function() { diff --git a/classstdex_1_1stream_1_1window.html b/classstdex_1_1stream_1_1window.html index 3416c4c97..f2466177a 100644 --- a/classstdex_1_1stream_1_1window.html +++ b/classstdex_1_1stream_1_1window.html @@ -452,7 +452,7 @@ state_t m_state diff --git a/classstdex_1_1sys__object-members.html b/classstdex_1_1sys__object-members.html index 7bb68d2fc..bf0ed573e 100644 --- a/classstdex_1_1sys__object-members.html +++ b/classstdex_1_1sys__object-members.html @@ -95,7 +95,7 @@ $(function() { diff --git a/classstdex_1_1sys__object.html b/classstdex_1_1sys__object.html index 4a17d209f..baf485ad9 100644 --- a/classstdex_1_1sys__object.html +++ b/classstdex_1_1sys__object.html @@ -182,7 +182,7 @@ sys_handle m_h diff --git a/classstdex_1_1user__cancelled-members.html b/classstdex_1_1user__cancelled-members.html index 12dbc14d4..ddfda4b01 100644 --- a/classstdex_1_1user__cancelled-members.html +++ b/classstdex_1_1user__cancelled-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/classstdex_1_1user__cancelled.html b/classstdex_1_1user__cancelled.html index d809265f4..0510bc436 100644 --- a/classstdex_1_1user__cancelled.html +++ b/classstdex_1_1user__cancelled.html @@ -141,7 +141,7 @@ Public Member Functions diff --git a/classstdex_1_1vector__queue-members.html b/classstdex_1_1vector__queue-members.html index 91d9b537b..20632ee45 100644 --- a/classstdex_1_1vector__queue-members.html +++ b/classstdex_1_1vector__queue-members.html @@ -122,7 +122,7 @@ $(function() { diff --git a/classstdex_1_1vector__queue.html b/classstdex_1_1vector__queue.html index f8ac6f1cb..0d532c979 100644 --- a/classstdex_1_1vector__queue.html +++ b/classstdex_1_1vector__queue.html @@ -795,7 +795,7 @@ template<class T > diff --git a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html index f57b095b2..c312bba47 100644 --- a/dir_4be4f7b278e009bf0f1906cf31fb73bd.html +++ b/dir_4be4f7b278e009bf0f1906cf31fb73bd.html @@ -86,7 +86,7 @@ Files diff --git a/dir_d44c64559bbebec7f509842c48db8b23.html b/dir_d44c64559bbebec7f509842c48db8b23.html index 5ff14679a..13a90f002 100644 --- a/dir_d44c64559bbebec7f509842c48db8b23.html +++ b/dir_d44c64559bbebec7f509842c48db8b23.html @@ -86,7 +86,7 @@ Directories diff --git a/dir_fca3c47b2ea228727bd6729832f89576.html b/dir_fca3c47b2ea228727bd6729832f89576.html index 3a1fb9d5a..c447c68f9 100644 --- a/dir_fca3c47b2ea228727bd6729832f89576.html +++ b/dir_fca3c47b2ea228727bd6729832f89576.html @@ -128,7 +128,7 @@ Files diff --git a/endian_8hpp_source.html b/endian_8hpp_source.html index 8a6c22a99..91760c22e 100644 --- a/endian_8hpp_source.html +++ b/endian_8hpp_source.html @@ -182,7 +182,7 @@ $(function() { diff --git a/errno_8hpp_source.html b/errno_8hpp_source.html index c2f95bb0b..837ce9807 100644 --- a/errno_8hpp_source.html +++ b/errno_8hpp_source.html @@ -136,7 +136,7 @@ $(function() { diff --git a/exception_8hpp_source.html b/exception_8hpp_source.html index f7fc88f10..b96397cd9 100644 --- a/exception_8hpp_source.html +++ b/exception_8hpp_source.html @@ -102,7 +102,7 @@ $(function() { diff --git a/files.html b/files.html index ff6e0bc99..d49e6b807 100644 --- a/files.html +++ b/files.html @@ -106,7 +106,7 @@ $(function() { diff --git a/functions.html b/functions.html index 4154b44d8..d4ad6b7de 100644 --- a/functions.html +++ b/functions.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_b.html b/functions_b.html index b1aea109f..d0c1a7214 100644 --- a/functions_b.html +++ b/functions_b.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_c.html b/functions_c.html index 6b8288f43..75e19f4c3 100644 --- a/functions_c.html +++ b/functions_c.html @@ -89,7 +89,7 @@ $(function() { diff --git a/functions_d.html b/functions_d.html index 77dd1b4a2..ade661786 100644 --- a/functions_d.html +++ b/functions_d.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_e.html b/functions_e.html index fcb08e530..b5ba9d4fd 100644 --- a/functions_e.html +++ b/functions_e.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_f.html b/functions_f.html index 33c9f13d0..055e0ba57 100644 --- a/functions_f.html +++ b/functions_f.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_func.html b/functions_func.html index c8ff8715b..ce8ba8d9b 100644 --- a/functions_func.html +++ b/functions_func.html @@ -82,7 +82,7 @@ $(function() { diff --git a/functions_func_b.html b/functions_func_b.html index d58887451..0f39eae75 100644 --- a/functions_func_b.html +++ b/functions_func_b.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_c.html b/functions_func_c.html index ad39ce7c3..ac028f797 100644 --- a/functions_func_c.html +++ b/functions_func_c.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_func_d.html b/functions_func_d.html index 12f5952df..9a5cc423d 100644 --- a/functions_func_d.html +++ b/functions_func_d.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_func_e.html b/functions_func_e.html index 512a84598..6d302e578 100644 --- a/functions_func_e.html +++ b/functions_func_e.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_func_f.html b/functions_func_f.html index 2c1ae57d0..dec4d78c3 100644 --- a/functions_func_f.html +++ b/functions_func_f.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_func_g.html b/functions_func_g.html index 03f354228..1bce2c1bb 100644 --- a/functions_func_g.html +++ b/functions_func_g.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_h.html b/functions_func_h.html index 3bc637e35..b87758720 100644 --- a/functions_func_h.html +++ b/functions_func_h.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_i.html b/functions_func_i.html index 2fa26fa0f..64f0f5197 100644 --- a/functions_func_i.html +++ b/functions_func_i.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_l.html b/functions_func_l.html index e0ce8dc62..4cda69597 100644 --- a/functions_func_l.html +++ b/functions_func_l.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_m.html b/functions_func_m.html index 510a06a09..6d9d71789 100644 --- a/functions_func_m.html +++ b/functions_func_m.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_func_n.html b/functions_func_n.html index 5964b53f7..8a7a4f839 100644 --- a/functions_func_n.html +++ b/functions_func_n.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_o.html b/functions_func_o.html index 307cce791..4c9698112 100644 --- a/functions_func_o.html +++ b/functions_func_o.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_func_p.html b/functions_func_p.html index b42d8232f..01493a9d2 100644 --- a/functions_func_p.html +++ b/functions_func_p.html @@ -83,7 +83,7 @@ $(function() { diff --git a/functions_func_q.html b/functions_func_q.html index 5f15ef746..5424615f7 100644 --- a/functions_func_q.html +++ b/functions_func_q.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_func_r.html b/functions_func_r.html index 39c06f027..9694fde83 100644 --- a/functions_func_r.html +++ b/functions_func_r.html @@ -89,7 +89,7 @@ $(function() { diff --git a/functions_func_s.html b/functions_func_s.html index 45cbf5f40..1ad952864 100644 --- a/functions_func_s.html +++ b/functions_func_s.html @@ -95,7 +95,7 @@ $(function() { diff --git a/functions_func_t.html b/functions_func_t.html index 4efb6f0fa..977b9a03b 100644 --- a/functions_func_t.html +++ b/functions_func_t.html @@ -83,7 +83,7 @@ $(function() { diff --git a/functions_func_u.html b/functions_func_u.html index 667c0b630..4a1c08028 100644 --- a/functions_func_u.html +++ b/functions_func_u.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_func_v.html b/functions_func_v.html index 1ffc43578..1148d347d 100644 --- a/functions_func_v.html +++ b/functions_func_v.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_func_w.html b/functions_func_w.html index 8d59f6f82..bd6ab367a 100644 --- a/functions_func_w.html +++ b/functions_func_w.html @@ -86,7 +86,7 @@ $(function() { diff --git a/functions_func_~.html b/functions_func_~.html index b59f0a780..1061df610 100644 --- a/functions_func_~.html +++ b/functions_func_~.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_g.html b/functions_g.html index 3d30db07a..5e5342539 100644 --- a/functions_g.html +++ b/functions_g.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_h.html b/functions_h.html index d2d85e39d..05bf840dd 100644 --- a/functions_h.html +++ b/functions_h.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_i.html b/functions_i.html index 767469abc..626930013 100644 --- a/functions_i.html +++ b/functions_i.html @@ -80,7 +80,7 @@ $(function() { diff --git a/functions_l.html b/functions_l.html index c62a6ad01..33b24d6be 100644 --- a/functions_l.html +++ b/functions_l.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_m.html b/functions_m.html index c12c72bfe..2dd517322 100644 --- a/functions_m.html +++ b/functions_m.html @@ -95,7 +95,7 @@ $(function() { diff --git a/functions_n.html b/functions_n.html index 7fe73b256..d9fb55be4 100644 --- a/functions_n.html +++ b/functions_n.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_o.html b/functions_o.html index 06a704f07..016fa2ca7 100644 --- a/functions_o.html +++ b/functions_o.html @@ -85,7 +85,7 @@ $(function() { diff --git a/functions_p.html b/functions_p.html index cec914c64..d3312e602 100644 --- a/functions_p.html +++ b/functions_p.html @@ -87,7 +87,7 @@ $(function() { diff --git a/functions_q.html b/functions_q.html index cad909bc1..4bd994f60 100644 --- a/functions_q.html +++ b/functions_q.html @@ -78,7 +78,7 @@ $(function() { diff --git a/functions_r.html b/functions_r.html index 9fee9b296..b6f88c3b0 100644 --- a/functions_r.html +++ b/functions_r.html @@ -93,7 +93,7 @@ $(function() { diff --git a/functions_s.html b/functions_s.html index fa7511c46..de0f2958c 100644 --- a/functions_s.html +++ b/functions_s.html @@ -101,7 +101,7 @@ $(function() { diff --git a/functions_t.html b/functions_t.html index 9d38554fa..a4c30a0a2 100644 --- a/functions_t.html +++ b/functions_t.html @@ -84,7 +84,7 @@ $(function() { diff --git a/functions_type.html b/functions_type.html index c0ba82bf3..66d3c71b6 100644 --- a/functions_type.html +++ b/functions_type.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_u.html b/functions_u.html index 80a1486da..5ad55003e 100644 --- a/functions_u.html +++ b/functions_u.html @@ -79,7 +79,7 @@ $(function() { diff --git a/functions_v.html b/functions_v.html index dd18c142e..a483d6042 100644 --- a/functions_v.html +++ b/functions_v.html @@ -81,7 +81,7 @@ $(function() { diff --git a/functions_vars.html b/functions_vars.html index 9049266e8..5b3a25c2c 100644 --- a/functions_vars.html +++ b/functions_vars.html @@ -204,7 +204,7 @@ $(function() { diff --git a/functions_w.html b/functions_w.html index 20b2d869a..8db9ebc4f 100644 --- a/functions_w.html +++ b/functions_w.html @@ -88,7 +88,7 @@ $(function() { diff --git a/functions_~.html b/functions_~.html index 3226b8526..bbdcd0bde 100644 --- a/functions_~.html +++ b/functions_~.html @@ -78,7 +78,7 @@ $(function() { diff --git a/hex_8hpp_source.html b/hex_8hpp_source.html index 00e4672a8..d3674b9cd 100644 --- a/hex_8hpp_source.html +++ b/hex_8hpp_source.html @@ -209,7 +209,7 @@ $(function() { diff --git a/hierarchy.html b/hierarchy.html index d6c9623b4..d3df6372a 100644 --- a/hierarchy.html +++ b/hierarchy.html @@ -230,7 +230,7 @@ $(function() { diff --git a/idrec_8hpp_source.html b/idrec_8hpp_source.html index 8363f1d8e..6c9f9f0f0 100644 --- a/idrec_8hpp_source.html +++ b/idrec_8hpp_source.html @@ -275,7 +275,7 @@ $(function() { diff --git a/index.html b/index.html index a8d20d7fd..946541255 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@ $(function() { diff --git a/interval_8hpp_source.html b/interval_8hpp_source.html index 03ca063ac..7a088ab7d 100644 --- a/interval_8hpp_source.html +++ b/interval_8hpp_source.html @@ -131,7 +131,7 @@ $(function() { diff --git a/mapping_8hpp_source.html b/mapping_8hpp_source.html index 9777b00bd..7071f21ce 100644 --- a/mapping_8hpp_source.html +++ b/mapping_8hpp_source.html @@ -117,7 +117,7 @@ $(function() { diff --git a/math_8hpp_source.html b/math_8hpp_source.html index 41793c931..3bdef4bf1 100644 --- a/math_8hpp_source.html +++ b/math_8hpp_source.html @@ -129,7 +129,7 @@ $(function() { diff --git a/memory_8hpp_source.html b/memory_8hpp_source.html index aedff4f23..0912f1c07 100644 --- a/memory_8hpp_source.html +++ b/memory_8hpp_source.html @@ -119,7 +119,7 @@ $(function() { diff --git a/parser_8hpp_source.html b/parser_8hpp_source.html index 8268ec951..e04b708d7 100644 --- a/parser_8hpp_source.html +++ b/parser_8hpp_source.html @@ -3916,15 +3916,15 @@ $(function() {
3998#endif
3999 using sgml_emoticon = basic_emoticon<char>;
4000
-
4004 ENUM_FLAGS(date_format_t, int) {
-
4005 none = 0,
-
4006 dmy = 0x1,
-
4007 mdy = 0x2,
-
4008 ymd = 0x4,
-
4009 ym = 0x8,
-
4010 my = 0x10,
-
4011 dm = 0x20,
-
4012 md = 0x40,
+
4004 enum date_format_t {
+
4005 date_format_none = 0,
+
4006 date_format_dmy = 0x1,
+
4007 date_format_mdy = 0x2,
+
4008 date_format_ymd = 0x4,
+
4009 date_format_ym = 0x8,
+
4010 date_format_my = 0x10,
+
4011 date_format_dm = 0x20,
+
4012 date_format_md = 0x40,
4013 };
4014
4018 template <class T>
@@ -3940,7 +3940,7 @@ $(function() {
4028 _In_ const std::shared_ptr<basic_parser<T>>& space,
4029 _In_ const std::locale& locale = std::locale()) :
4030 basic_parser<T>(locale),
-
4031 format(date_format_t::none),
+
4031 format(date_format_none),
4032 m_format_mask(format_mask),
4033 day(_day),
4034 month(_month),
@@ -3958,7 +3958,7 @@ $(function() {
4046 assert(text || start >= end);
4047
4048 const int space_match_flags = flags & ~match_multiline; // Spaces in dates must never be broken in new line.
-
4049 if ((m_format_mask & date_format_t::dmy) == date_format_t::dmy) {
+
4049 if ((m_format_mask & date_format_dmy) == date_format_dmy) {
4050 if (day->match(text, start, end, flags)) {
4051 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4052 if (m_separator->match(text, interval.end, end, flags)) {
@@ -3975,7 +3975,7 @@ $(function() {
4063 {
4064 interval.start = start;
4065 interval.end = year->interval.end;
-
4066 format = date_format_t::dmy;
+
4066 format = date_format_dmy;
4067 return true;
4068 }
4069 }
@@ -3984,7 +3984,7 @@ $(function() {
4072 }
4073 }
4074
-
4075 if ((m_format_mask & date_format_t::mdy) == date_format_t::mdy) {
+
4075 if ((m_format_mask & date_format_mdy) == date_format_mdy) {
4076 if (month->match(text, start, end, flags)) {
4077 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4078 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4001,7 +4001,7 @@ $(function() {
4089 {
4090 interval.start = start;
4091 interval.end = year->interval.end;
-
4092 format = date_format_t::mdy;
+
4092 format = date_format_mdy;
4093 return true;
4094 }
4095 }
@@ -4010,7 +4010,7 @@ $(function() {
4098 }
4099 }
4100
-
4101 if ((m_format_mask & date_format_t::ymd) == date_format_t::ymd) {
+
4101 if ((m_format_mask & date_format_ymd) == date_format_ymd) {
4102 if (year->match(text, start, end, flags)) {
4103 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4104 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4027,7 +4027,7 @@ $(function() {
4115 {
4116 interval.start = start;
4117 interval.end = day->interval.end;
-
4118 format = date_format_t::ymd;
+
4118 format = date_format_ymd;
4119 return true;
4120 }
4121 }
@@ -4036,7 +4036,7 @@ $(function() {
4124 }
4125 }
4126
-
4127 if ((m_format_mask & date_format_t::ym) == date_format_t::ym) {
+
4127 if ((m_format_mask & date_format_ym) == date_format_ym) {
4128 if (year->match(text, start, end, flags)) {
4129 for (interval.end = year->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4130 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4047,14 +4047,14 @@ $(function() {
4135 if (day) day->invalidate();
4136 interval.start = start;
4137 interval.end = month->interval.end;
-
4138 format = date_format_t::ym;
+
4138 format = date_format_ym;
4139 return true;
4140 }
4141 }
4142 }
4143 }
4144
-
4145 if ((m_format_mask & date_format_t::my) == date_format_t::my) {
+
4145 if ((m_format_mask & date_format_my) == date_format_my) {
4146 if (month->match(text, start, end, flags)) {
4147 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4148 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4065,14 +4065,14 @@ $(function() {
4153 if (day) day->invalidate();
4154 interval.start = start;
4155 interval.end = year->interval.end;
-
4156 format = date_format_t::my;
+
4156 format = date_format_my;
4157 return true;
4158 }
4159 }
4160 }
4161 }
4162
-
4163 if ((m_format_mask & date_format_t::dm) == date_format_t::dm) {
+
4163 if ((m_format_mask & date_format_dm) == date_format_dm) {
4164 if (day->match(text, start, end, flags)) {
4165 for (interval.end = day->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4166 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4089,14 +4089,14 @@ $(function() {
4177 interval.end = m_separator->interval.end;
4178 else
4179 interval.end = month->interval.end;
-
4180 format = date_format_t::dm;
+
4180 format = date_format_dm;
4181 return true;
4182 }
4183 }
4184 }
4185 }
4186
-
4187 if ((m_format_mask & date_format_t::md) == date_format_t::md) {
+
4187 if ((m_format_mask & date_format_md) == date_format_md) {
4188 if (month->match(text, start, end, flags)) {
4189 for (interval.end = month->interval.end; m_space->match(text, interval.end, end, space_match_flags); interval.end = m_space->interval.end);
4190 if (m_separator->match(text, interval.end, end, flags)) {
@@ -4113,7 +4113,7 @@ $(function() {
4201 interval.end = m_separator->interval.end;
4202 else
4203 interval.end = day->interval.end;
-
4204 format = date_format_t::md;
+
4204 format = date_format_md;
4205 return true;
4206 }
4207 }
@@ -4123,7 +4123,7 @@ $(function() {
4211 if (day) day->invalidate();
4212 if (month) month->invalidate();
4213 if (year) year->invalidate();
-
4214 format = date_format_t::none;
+
4214 format = date_format_none;
4215 interval.start = (interval.end = start) + 1;
4216 return false;
4217 }
@@ -4133,7 +4133,7 @@ $(function() {
4221 if (day) day->invalidate();
4222 if (month) month->invalidate();
4223 if (year) year->invalidate();
-
4224 format = date_format_t::none;
+
4224 format = date_format_none;
4225 basic_parser<T>::invalidate();
4226 }
4227
@@ -6546,7 +6546,7 @@ $(function() { diff --git a/pch_8h_source.html b/pch_8h_source.html index 330804cfb..319666178 100644 --- a/pch_8h_source.html +++ b/pch_8h_source.html @@ -114,7 +114,7 @@ $(function() { diff --git a/progress_8hpp_source.html b/progress_8hpp_source.html index e727931ea..8af662e81 100644 --- a/progress_8hpp_source.html +++ b/progress_8hpp_source.html @@ -282,7 +282,7 @@ $(function() { diff --git a/ring_8hpp_source.html b/ring_8hpp_source.html index c1eedeac0..7e0d64fef 100644 --- a/ring_8hpp_source.html +++ b/ring_8hpp_source.html @@ -205,7 +205,7 @@ $(function() { diff --git a/sal_8hpp_source.html b/sal_8hpp_source.html index a859c093f..8ea276df0 100644 --- a/sal_8hpp_source.html +++ b/sal_8hpp_source.html @@ -168,7 +168,7 @@ $(function() { diff --git a/sgml_8hpp_source.html b/sgml_8hpp_source.html index afb3b218a..d5ea13daf 100644 --- a/sgml_8hpp_source.html +++ b/sgml_8hpp_source.html @@ -89,41 +89,41 @@ $(function() {
10#include "sgml_unicode.hpp"
11#include "string.hpp"
12#include <assert.h>
-
13#include <string>
-
14
-
15namespace stdex
-
16{
-
18 template <class T>
-
19 inline const wchar_t* sgml2uni(_In_reads_or_z_(count) const T* entity, _In_ size_t count)
-
20 {
-
21 assert(entity && count);
-
22 assert(count < 2 || entity[0] != '#'); // No numeric entities
-
23
-
24 for (size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
-
25 size_t m = (i + j) / 2;
-
26 if (sgml_unicode[m].sgml[0] < entity[0])
-
27 i = m + 1;
-
28 else if (sgml_unicode[m].sgml[0] > entity[0])
-
29 j = m;
-
30 else {
-
31 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
-
32 if (r < 0)
-
33 i = m + 1;
-
34 else if (r > 0)
-
35 j = m;
-
36 else {
-
37 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
-
38 return sgml_unicode[m].unicode;
-
39 }
-
40 }
-
41 }
-
42 return nullptr;
-
43 }
-
44
-
45 template <class T>
-
46 inline const T* sgmlend(
-
47 _In_reads_or_z_opt_(count) const T* str,
-
48 _In_ size_t count)
+
13#include <exception>
+
14#include <string>
+
15
+
16namespace stdex
+
17{
+
19 template <class T>
+
20 inline const wchar_t* sgml2uni(_In_reads_or_z_(count) const T* entity, _In_ size_t count)
+
21 {
+
22 assert(entity && count);
+
23 assert(count < 2 || entity[0] != '#'); // No numeric entities
+
24
+
25 for (size_t i = 0, j = _countof(sgml_unicode); i < j; ) {
+
26 size_t m = (i + j) / 2;
+
27 if (sgml_unicode[m].sgml[0] < entity[0])
+
28 i = m + 1;
+
29 else if (sgml_unicode[m].sgml[0] > entity[0])
+
30 j = m;
+
31 else {
+
32 auto r = strncmp<char, T>(sgml_unicode[m].sgml + 1, _countof(sgml_unicode[0].sgml) - 1, entity + 1, count - 1);
+
33 if (r < 0)
+
34 i = m + 1;
+
35 else if (r > 0)
+
36 j = m;
+
37 else {
+
38 for (; i < m && strncmp<char, T>(sgml_unicode[m - 1].sgml, _countof(sgml_unicode[0].sgml), entity, count) == 0; m--);
+
39 return sgml_unicode[m].unicode;
+
40 }
+
41 }
+
42 }
+
43 return nullptr;
+
44 }
+
45
+
46 template <class T>
+
47 inline const T* sgmlend(
+
48 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
49 {
50 assert(str || !count);
51 for (size_t i = 0; i < count; i++) {
@@ -156,274 +156,486 @@ $(function() {
79 // constexpr int sgml_ajt_form = sgml_ajt_lemma;
80 // constexpr int sgml_kolos = sgml_amp | sgml_quot | sgml_dollar | sgml_percnt | sgml_lt_gt | sgml_bsol/* | sgml_commat | sgml_num*/ | sgml_lpar_rpar | sgml_lcub_rcub | sgml_lsqb_rsqb;
81
-
94 template <class T>
-
95 inline void sgml2wstr(
-
96 _Inout_ std::wstring& dst,
-
97 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
-
98 _In_ int skip = 0,
-
99 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
-
100 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
-
101 {
-
102 assert(src || !count_src);
-
103
-
104 const bool
-
105 skip_quot = (skip & sgml_quot) == 0,
-
106 skip_apos = (skip & sgml_apos) == 0,
-
107 skip_amp = (skip & sgml_amp) == 0,
-
108 skip_lt_gt = (skip & sgml_lt_gt) == 0,
-
109 skip_bsol = (skip & sgml_bsol) == 0,
-
110 skip_dollar = (skip & sgml_dollar) == 0,
-
111 skip_percnt = (skip & sgml_percnt) == 0,
-
112 skip_commat = (skip & sgml_commat) == 0,
-
113 skip_num = (skip & sgml_num) == 0,
-
114 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
-
115 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
-
116 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
-
117
-
118 count_src = strnlen(src, count_src);
-
119 dst.reserve(dst.size() + count_src);
-
120 for (size_t i = 0; i < count_src;) {
-
121 if (src[i] == '&') {
-
122 auto end = sgmlend(src + i + 1, count_src - i - 1);
-
123 if (end) {
-
124 const wchar_t* entity_w;
-
125 wchar_t chr[3];
-
126 size_t n = end - src - i - 1;
-
127 if (n >= 2 && src[i + 1] == '#') {
-
128 uint32_t unicode;
-
129 if (src[i + 2] == 'x' || src[i + 2] == 'X')
-
130 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
-
131 else
-
132 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
-
133#ifdef _WIN32
-
134 if (unicode < 0x10000) {
-
135 chr[0] = (wchar_t)unicode;
-
136 chr[1] = 0;
-
137 }
-
138 else {
-
139 ucs4_to_surrogate_pair(chr, unicode);
-
140 chr[2] = 0;
-
141 }
-
142#else
-
143 chr[0] = (wchar_t)unicode;
-
144 chr[1] = 0;
-
145#endif
-
146 entity_w = chr;
-
147 }
-
148 else
-
149 entity_w = sgml2uni(src + i + 1, n);
-
150
-
151 if (entity_w &&
-
152 (skip_quot || (entity_w[0] != L'"')) &&
-
153 (skip_apos || (entity_w[0] != L'\'')) &&
-
154 (skip_amp || (entity_w[0] != L'&')) &&
-
155 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
-
156 (skip_bsol || (entity_w[0] != L'\\')) &&
-
157 (skip_dollar || (entity_w[0] != L'$')) &&
-
158 (skip_percnt || (entity_w[0] != L'%')) &&
-
159 (skip_commat || (entity_w[0] != L'@')) &&
-
160 (skip_num || (entity_w[0] != L'#')) &&
-
161 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
-
162 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
-
163 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
-
164 {
-
165 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
-
166 dst.append(entity_w);
-
167 i = end - src + 1;
-
168 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
-
169 continue;
-
170 }
-
171 }
-
172 }
-
173 dst.append(1, src[i++]);
-
174 }
-
175 }
-
176
+
92 template <class T>
+
93 inline void sgml2wstr(
+
94 _Inout_ std::wstring& dst,
+
95 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
+
96 _In_ int skip = 0,
+
97 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
+
98 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
+
99 {
+
100 assert(src || !count_src);
+
101
+
102 const bool
+
103 skip_quot = (skip & sgml_quot) == 0,
+
104 skip_apos = (skip & sgml_apos) == 0,
+
105 skip_amp = (skip & sgml_amp) == 0,
+
106 skip_lt_gt = (skip & sgml_lt_gt) == 0,
+
107 skip_bsol = (skip & sgml_bsol) == 0,
+
108 skip_dollar = (skip & sgml_dollar) == 0,
+
109 skip_percnt = (skip & sgml_percnt) == 0,
+
110 skip_commat = (skip & sgml_commat) == 0,
+
111 skip_num = (skip & sgml_num) == 0,
+
112 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
+
113 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
+
114 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
+
115
+
116 count_src = strnlen(src, count_src);
+
117 dst.reserve(dst.size() + count_src);
+
118 for (size_t i = 0; i < count_src;) {
+
119 if (src[i] == '&') {
+
120 auto end = sgmlend(src + i + 1, count_src - i - 1);
+
121 if (end) {
+
122 const wchar_t* entity_w;
+
123 wchar_t chr[3];
+
124 size_t n = end - src - i - 1;
+
125 if (n >= 2 && src[i + 1] == '#') {
+
126 uint32_t unicode;
+
127 if (src[i + 2] == 'x' || src[i + 2] == 'X')
+
128 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
+
129 else
+
130 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
+
131#ifdef _WIN32
+
132 if (unicode < 0x10000) {
+
133 chr[0] = (wchar_t)unicode;
+
134 chr[1] = 0;
+
135 }
+
136 else {
+
137 ucs4_to_surrogate_pair(chr, unicode);
+
138 chr[2] = 0;
+
139 }
+
140#else
+
141 chr[0] = (wchar_t)unicode;
+
142 chr[1] = 0;
+
143#endif
+
144 entity_w = chr;
+
145 }
+
146 else
+
147 entity_w = sgml2uni(src + i + 1, n);
+
148
+
149 if (entity_w &&
+
150 (skip_quot || (entity_w[0] != L'"')) &&
+
151 (skip_apos || (entity_w[0] != L'\'')) &&
+
152 (skip_amp || (entity_w[0] != L'&')) &&
+
153 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
+
154 (skip_bsol || (entity_w[0] != L'\\')) &&
+
155 (skip_dollar || (entity_w[0] != L'$')) &&
+
156 (skip_percnt || (entity_w[0] != L'%')) &&
+
157 (skip_commat || (entity_w[0] != L'@')) &&
+
158 (skip_num || (entity_w[0] != L'#')) &&
+
159 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
+
160 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
+
161 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
+
162 {
+
163 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
+
164 dst.append(entity_w);
+
165 i = end - src + 1;
+
166 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + dst.size()));
+
167 continue;
+
168 }
+
169 }
+
170 }
+
171 dst.append(1, src[i++]);
+
172 }
+
173 }
+
174
188 template <class T>
-
189 inline void sgml2wstr(
-
190 _Inout_ std::wstring& dst,
-
191 _In_ const std::basic_string<T>& src,
+
189 inline size_t sgml2wstr(
+
190 _Inout_cap_(count_dst) wchar_t* dst, _In_ size_t count_dst,
+
191 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
192 _In_ int skip = 0,
193 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
194 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
195 {
-
196 sgml2wstr(dst, src.data(), src.size(), skip, offset, map);
-
197 }
-
198
-
210 template <class T>
-
211 inline std::wstring sgml2wstr(
-
212 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
-
213 _In_ int skip = 0,
-
214 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
-
215 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
-
216 {
-
217 std::wstring dst;
-
218 sgml2wstr(dst, src, count_src, skip, offset, map);
-
219 return dst;
-
220 }
-
221
-
232 template <class T>
-
233 inline std::wstring sgml2wstr(
-
234 _In_ const std::basic_string<T>& src,
-
235 _In_ int skip = 0,
-
236 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
-
237 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
-
238 {
-
239 return sgml2wstr(src.c_str(), src.size(), skip, offset, map);
-
240 }
-
241
-
243 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
-
244 {
-
245 assert(entity && count);
-
246
-
247 const wchar_t e2 = entity[0];
-
248 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
-
249 size_t m = (i + j) / 2;
-
250 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
-
251 if (e1 < e2)
-
252 i = m + 1;
-
253 else if (e1 > e2)
-
254 j = m;
-
255 else {
-
256 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
-
257 if (r < 0)
-
258 i = m + 1;
-
259 else if (r > 0)
-
260 j = m;
-
261 else {
-
262 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1) == 0; m--);
-
263 return sgml_unicode[unicode_sgml[m]].sgml;
-
264 }
-
265 }
-
266 }
-
267 return nullptr;
-
268 }
-
270
-
279 inline void wstr2sgml(
-
280 _Inout_ std::string& dst,
-
281 _In_reads_or_z_opt_(count_src) const wchar_t* src,
-
282 _In_ size_t count_src,
-
283 _In_ size_t what = 0)
-
284 {
-
285 assert(src || !count_src);
-
286
-
287 const bool
-
288 do_ascii = (what & sgml_full) == 0,
-
289 do_quot = (what & sgml_quot) == 0,
-
290 do_apos = (what & sgml_apos) == 0,
-
291 do_lt_gt = (what & sgml_lt_gt) == 0,
-
292 do_bsol = (what & sgml_bsol) == 0,
-
293 do_dollar = (what & sgml_dollar) == 0,
-
294 do_percnt = (what & sgml_percnt) == 0,
-
295 do_commat = (what & sgml_commat) == 0,
-
296 do_num = (what & sgml_num) == 0,
-
297 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
-
298 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
-
299 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
-
300
-
301 count_src = wcsnlen(src, count_src);
-
302 dst.reserve(dst.size() + count_src);
-
303 for (size_t i = 0; i < count_src;) {
-
304 size_t n = glyphlen(src + i, count_src - i);
-
305 if (n == 1 &&
-
306 do_ascii && (unsigned int)src[i] < 128 &&
-
307 src[i] != L'&' &&
-
308 (do_quot || (src[i] != L'"')) &&
-
309 (do_apos || (src[i] != L'\'')) &&
-
310 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
-
311 (do_bsol || (src[i] != L'\\')) &&
-
312 (do_dollar || (src[i] != L'$')) &&
-
313 (do_percnt || (src[i] != L'%')) &&
-
314 (do_commat || (src[i] != L'@')) &&
-
315 (do_num || (src[i] != L'#')) &&
-
316 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
-
317 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
-
318 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
-
319 {
-
320 // 7-bit ASCII and no desire to encode it as an SGML entity.
-
321 dst.append(1, (char)src[i++]);
-
322 }
-
323 else {
-
324 const char* entity = chr2sgml(src + i, n);
-
325 if (entity) {
-
326 dst.append(1, '&');
-
327 dst.append(entity);
-
328 dst.append(1, ';');
-
329 i += n;
-
330 }
-
331 else if (n == 1) {
-
332 // Trivial character (1 code unit, 1 glyph), no entity available.
-
333 if ((unsigned int)src[i] < 128)
-
334 dst.append(1, (char)src[i++]);
-
335 else {
-
336 char tmp[3 + 8 + 1 + 1];
-
337 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
-
338 dst.append(tmp);
-
339 }
-
340 }
-
341 else {
-
342 // Non-trivial character. Decompose.
-
343 const size_t end = i + n;
-
344 while (i < end) {
-
345 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
-
346 dst.append(1, '&');
-
347 dst.append(entity);
-
348 dst.append(1, ';');
-
349 i++;
-
350 }
-
351 else if ((unsigned int)src[i] < 128)
-
352 dst.append(1, (char)src[i++]);
-
353 else {
-
354 uint32_t unicode;
-
355#ifdef _WIN32
-
356 if (i + 1 < end && is_surrogate_pair(src + i)) {
-
357 unicode = surrogate_pair_to_ucs4(src + i);
-
358 i += 2;
-
359 }
-
360 else
-
361#endif
-
362 {
-
363 unicode = src[i++];
-
364 }
-
365 char tmp[3 + 8 + 1 + 1];
-
366 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
-
367 dst.append(tmp);
-
368 }
-
369 }
-
370 }
-
371 }
-
372 }
-
373 }
+
196 assert(src || !count_src);
+
197
+
198 static const std::invalid_argument buffer_overrun("buffer overrun");
+
199 const bool
+
200 skip_quot = (skip & sgml_quot) == 0,
+
201 skip_apos = (skip & sgml_apos) == 0,
+
202 skip_amp = (skip & sgml_amp) == 0,
+
203 skip_lt_gt = (skip & sgml_lt_gt) == 0,
+
204 skip_bsol = (skip & sgml_bsol) == 0,
+
205 skip_dollar = (skip & sgml_dollar) == 0,
+
206 skip_percnt = (skip & sgml_percnt) == 0,
+
207 skip_commat = (skip & sgml_commat) == 0,
+
208 skip_num = (skip & sgml_num) == 0,
+
209 skip_lpar_rpar = (skip & sgml_lpar_rpar) == 0,
+
210 skip_lcub_rcub = (skip & sgml_lcub_rcub) == 0,
+
211 skip_lsqb_rsqb = (skip & sgml_lsqb_rsqb) == 0;
+
212
+
213 size_t j = wcsnlen(dst, count_dst);
+
214 count_src = strnlen(src, count_src);
+
215 for (size_t i = 0; i < count_src;) {
+
216 if (src[i] == '&') {
+
217 auto end = sgmlend(src + i + 1, count_src - i - 1);
+
218 if (end) {
+
219 const wchar_t* entity_w;
+
220 wchar_t chr[3];
+
221 size_t n = end - src - i - 1;
+
222 if (n >= 2 && src[i + 1] == '#') {
+
223 uint32_t unicode;
+
224 if (src[i + 2] == 'x' || src[i + 2] == 'X')
+
225 unicode = strtou32(src + i + 3, n - 2, nullptr, 16);
+
226 else
+
227 unicode = strtou32(src + i + 2, n - 1, nullptr, 10);
+
228#ifdef _WIN32
+
229 if (unicode < 0x10000) {
+
230 chr[0] = (wchar_t)unicode;
+
231 chr[1] = 0;
+
232 }
+
233 else {
+
234 ucs4_to_surrogate_pair(chr, unicode);
+
235 chr[2] = 0;
+
236 }
+
237#else
+
238 chr[0] = (wchar_t)unicode;
+
239 chr[1] = 0;
+
240#endif
+
241 entity_w = chr;
+
242 }
+
243 else
+
244 entity_w = sgml2uni(src + i + 1, n);
+
245
+
246 if (entity_w &&
+
247 (skip_quot || (entity_w[0] != L'"')) &&
+
248 (skip_apos || (entity_w[0] != L'\'')) &&
+
249 (skip_amp || (entity_w[0] != L'&')) &&
+
250 (skip_lt_gt || (entity_w[0] != L'<' && entity_w[0] != L'>')) &&
+
251 (skip_bsol || (entity_w[0] != L'\\')) &&
+
252 (skip_dollar || (entity_w[0] != L'$')) &&
+
253 (skip_percnt || (entity_w[0] != L'%')) &&
+
254 (skip_commat || (entity_w[0] != L'@')) &&
+
255 (skip_num || (entity_w[0] != L'#')) &&
+
256 (skip_lpar_rpar || (entity_w[0] != L'(' && entity_w[0] != L')')) &&
+
257 (skip_lcub_rcub || (entity_w[0] != L'{' && entity_w[0] != L'}')) &&
+
258 (skip_lsqb_rsqb || (entity_w[0] != L'[' && entity_w[0] != L']')))
+
259 {
+
260 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
+
261 size_t m = wcslen(entity_w);
+
262 if (j + m >= count_dst)
+
263 throw buffer_overrun;
+
264 memcpy(dst + j, entity_w, m * sizeof(wchar_t)); j += m;
+
265 i = end - src + 1;
+
266 if (map) map->push_back(mapping<size_t>(offset.from + i, offset.to + j));
+
267 continue;
+
268 }
+
269 }
+
270 }
+
271 if (j + 1 >= count_dst)
+
272 throw buffer_overrun;
+
273 dst[j++] = src[i++];
+
274 }
+
275 if (j >= count_dst)
+
276 throw buffer_overrun;
+
277 dst[j] = 0;
+
278 return j;
+
279 }
+
280
+
292 template <class T>
+
293 inline void sgml2wstr(
+
294 _Inout_ std::wstring& dst,
+
295 _In_ const std::basic_string<T>& src,
+
296 _In_ int skip = 0,
+
297 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
+
298 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
+
299 {
+
300 sgml2wstr(dst, src.data(), src.size(), skip, offset, map);
+
301 }
+
302
+
314 template <class T>
+
315 inline std::wstring sgml2wstr(
+
316 _In_reads_or_z_opt_(count_src) const T* src, _In_ size_t count_src,
+
317 _In_ int skip = 0,
+
318 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
+
319 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
+
320 {
+
321 std::wstring dst;
+
322 sgml2wstr(dst, src, count_src, skip, offset, map);
+
323 return dst;
+
324 }
+
325
+
336 template <class T>
+
337 inline std::wstring sgml2wstr(
+
338 _In_ const std::basic_string<T>& src,
+
339 _In_ int skip = 0,
+
340 _In_ const mapping<size_t>& offset = mapping<size_t>(0, 0),
+
341 _Inout_opt_ mapping_vector<size_t>* map = nullptr)
+
342 {
+
343 return sgml2wstr(src.c_str(), src.size(), skip, offset, map);
+
344 }
+
345
+
347 inline const char* chr2sgml(_In_reads_or_z_(count) const wchar_t* entity, _In_ size_t count)
+
348 {
+
349 assert(entity && count);
+
350
+
351 const wchar_t e2 = entity[0];
+
352 for (size_t i = 0, j = _countof(unicode_sgml); i < j; ) {
+
353 size_t m = (i + j) / 2;
+
354 wchar_t e1 = sgml_unicode[unicode_sgml[m]].unicode[0];
+
355 if (e1 < e2)
+
356 i = m + 1;
+
357 else if (e1 > e2)
+
358 j = m;
+
359 else {
+
360 auto r = strncmp(sgml_unicode[unicode_sgml[m]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1);
+
361 if (r < 0)
+
362 i = m + 1;
+
363 else if (r > 0)
+
364 j = m;
+
365 else {
+
366 for (; i < m && sgml_unicode[unicode_sgml[m - 1]].unicode[0] == e2 && strncmp(sgml_unicode[unicode_sgml[m - 1]].unicode + 1, _countof(sgml_unicode[0].unicode) - 1, entity + 1, count - 1) == 0; m--);
+
367 return sgml_unicode[unicode_sgml[m]].sgml;
+
368 }
+
369 }
+
370 }
+
371 return nullptr;
+
372 }
374
-
382 inline void wstr2sgml(
-
383 _Inout_ std::string& dst,
-
384 _In_ const std::wstring& src,
-
385 _In_ size_t what = 0)
-
386 {
-
387 wstr2sgml(dst, src.c_str(), src.size(), what);
-
388 }
+
383 inline void wstr2sgml(
+
384 _Inout_ std::string& dst,
+
385 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
+
386 _In_ size_t what = 0)
+
387 {
+
388 assert(src || !count_src);
389
-
399 inline std::string wstr2sgml(
-
400 _In_reads_or_z_opt_(count_src) const wchar_t* src,
-
401 _In_ size_t count_src,
-
402 _In_ size_t what = 0)
-
403 {
-
404 std::string dst;
-
405 wstr2sgml(dst, src, count_src, what);
-
406 return dst;
-
407 }
-
408
-
417 inline std::string wstr2sgml(
-
418 _In_ const std::wstring& src,
-
419 _In_ size_t what = 0)
-
420 {
-
421 return wstr2sgml(src.c_str(), src.size(), what);
-
422 }
-
423}
+
390 const bool
+
391 do_ascii = (what & sgml_full) == 0,
+
392 do_quot = (what & sgml_quot) == 0,
+
393 do_apos = (what & sgml_apos) == 0,
+
394 do_lt_gt = (what & sgml_lt_gt) == 0,
+
395 do_bsol = (what & sgml_bsol) == 0,
+
396 do_dollar = (what & sgml_dollar) == 0,
+
397 do_percnt = (what & sgml_percnt) == 0,
+
398 do_commat = (what & sgml_commat) == 0,
+
399 do_num = (what & sgml_num) == 0,
+
400 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
+
401 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
+
402 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
+
403
+
404 count_src = wcsnlen(src, count_src);
+
405 dst.reserve(dst.size() + count_src);
+
406 for (size_t i = 0; i < count_src;) {
+
407 size_t n = glyphlen(src + i, count_src - i);
+
408 if (n == 1 &&
+
409 do_ascii && (unsigned int)src[i] < 128 &&
+
410 src[i] != L'&' &&
+
411 (do_quot || (src[i] != L'"')) &&
+
412 (do_apos || (src[i] != L'\'')) &&
+
413 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
+
414 (do_bsol || (src[i] != L'\\')) &&
+
415 (do_dollar || (src[i] != L'$')) &&
+
416 (do_percnt || (src[i] != L'%')) &&
+
417 (do_commat || (src[i] != L'@')) &&
+
418 (do_num || (src[i] != L'#')) &&
+
419 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
+
420 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
+
421 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
+
422 {
+
423 // 7-bit ASCII and no desire to encode it as an SGML entity.
+
424 dst.append(1, static_cast<char>(src[i++]));
+
425 }
+
426 else {
+
427 const char* entity = chr2sgml(src + i, n);
+
428 if (entity) {
+
429 dst.append(1, '&');
+
430 dst.append(entity);
+
431 dst.append(1, ';');
+
432 i += n;
+
433 }
+
434 else if (n == 1) {
+
435 // Trivial character (1 code unit, 1 glyph), no entity available.
+
436 if ((unsigned int)src[i] < 128)
+
437 dst.append(1, static_cast<char>(src[i++]));
+
438 else {
+
439 char tmp[3 + 8 + 1 + 1];
+
440 snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
+
441 dst.append(tmp);
+
442 }
+
443 }
+
444 else {
+
445 // Non-trivial character. Decompose.
+
446 const size_t end = i + n;
+
447 while (i < end) {
+
448 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
+
449 dst.append(1, '&');
+
450 dst.append(entity);
+
451 dst.append(1, ';');
+
452 i++;
+
453 }
+
454 else if ((unsigned int)src[i] < 128)
+
455 dst.append(1, static_cast<char>(src[i++]));
+
456 else {
+
457 uint32_t unicode;
+
458#ifdef _WIN32
+
459 if (i + 1 < end && is_surrogate_pair(src + i)) {
+
460 unicode = surrogate_pair_to_ucs4(src + i);
+
461 i += 2;
+
462 }
+
463 else
+
464#endif
+
465 {
+
466 unicode = src[i++];
+
467 }
+
468 char tmp[3 + 8 + 1 + 1];
+
469 snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
+
470 dst.append(tmp);
+
471 }
+
472 }
+
473 }
+
474 }
+
475 }
+
476 }
+
477
+
489 inline size_t wstr2sgml(
+
490 _Inout_cap_(count_dst) char* dst, _In_ size_t count_dst,
+
491 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
+
492 _In_ size_t what = 0)
+
493 {
+
494 assert(dst || !count_dst);
+
495 assert(src || !count_src);
+
496
+
497 static const std::invalid_argument buffer_overrun("buffer overrun");
+
498 const bool
+
499 do_ascii = (what & sgml_full) == 0,
+
500 do_quot = (what & sgml_quot) == 0,
+
501 do_apos = (what & sgml_apos) == 0,
+
502 do_lt_gt = (what & sgml_lt_gt) == 0,
+
503 do_bsol = (what & sgml_bsol) == 0,
+
504 do_dollar = (what & sgml_dollar) == 0,
+
505 do_percnt = (what & sgml_percnt) == 0,
+
506 do_commat = (what & sgml_commat) == 0,
+
507 do_num = (what & sgml_num) == 0,
+
508 do_lpar_rpar = (what & sgml_lpar_rpar) == 0,
+
509 do_lcub_rcub = (what & sgml_lcub_rcub) == 0,
+
510 do_lsqb_rsqb = (what & sgml_lsqb_rsqb) == 0;
+
511
+
512 size_t j = strnlen(dst, count_dst);
+
513 count_src = wcsnlen(src, count_src);
+
514 for (size_t i = 0; i < count_src;) {
+
515 size_t n = glyphlen(src + i, count_src - i);
+
516 if (n == 1 &&
+
517 do_ascii && (unsigned int)src[i] < 128 &&
+
518 src[i] != L'&' &&
+
519 (do_quot || (src[i] != L'"')) &&
+
520 (do_apos || (src[i] != L'\'')) &&
+
521 (do_lt_gt || (src[i] != L'<' && src[i] != L'>')) &&
+
522 (do_bsol || (src[i] != L'\\')) &&
+
523 (do_dollar || (src[i] != L'$')) &&
+
524 (do_percnt || (src[i] != L'%')) &&
+
525 (do_commat || (src[i] != L'@')) &&
+
526 (do_num || (src[i] != L'#')) &&
+
527 (do_lpar_rpar || (src[i] != L'(' && src[i] != L')')) &&
+
528 (do_lcub_rcub || (src[i] != L'{' && src[i] != L'}')) &&
+
529 (do_lsqb_rsqb || (src[i] != L'[' && src[i] != L']')))
+
530 {
+
531 // 7-bit ASCII and no desire to encode it as an SGML entity.
+
532 if (j + 1 >= count_dst)
+
533 throw buffer_overrun;
+
534 dst[j++] = static_cast<char>(src[i++]);
+
535 }
+
536 else {
+
537 const char* entity = chr2sgml(src + i, n);
+
538 if (entity) {
+
539 size_t m = strlen(entity);
+
540 if (j + m + 2 >= count_dst)
+
541 throw buffer_overrun;
+
542 dst[j++] = '&';
+
543 memcpy(dst + j, entity, m * sizeof(char)); j += m;
+
544 dst[j++] = ';';
+
545 i += n;
+
546 }
+
547 else if (n == 1) {
+
548 // Trivial character (1 code unit, 1 glyph), no entity available.
+
549 if ((unsigned int)src[i] < 128) {
+
550 if (j + 1 >= count_dst)
+
551 throw buffer_overrun;
+
552 dst[j++] = static_cast<char>(src[i++]);
+
553 }
+
554 else {
+
555 char tmp[3 + 8 + 1 + 1];
+
556 int m = snprintf(tmp, _countof(tmp), "&#x%x;", src[i++]);
+
557 assert(m >= 0);
+
558 if (static_cast<size_t>(m) >= count_dst)
+
559 throw buffer_overrun;
+
560 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
+
561 }
+
562 }
+
563 else {
+
564 // Non-trivial character. Decompose.
+
565 const size_t end = i + n;
+
566 while (i < end) {
+
567 if ((entity = chr2sgml(src + i, 1)) != nullptr) {
+
568 size_t m = strlen(entity);
+
569 if (j + m + 2 >= count_dst)
+
570 throw buffer_overrun;
+
571 dst[j++] = '&';
+
572 memcpy(dst + j, entity, m * sizeof(char)); j += m;
+
573 dst[j++] = ';';
+
574 i++;
+
575 }
+
576 else if ((unsigned int)src[i] < 128) {
+
577 if (j + 1 >= count_dst)
+
578 throw buffer_overrun;
+
579 dst[j++] = static_cast<char>(src[i++]);
+
580 }
+
581 else {
+
582 uint32_t unicode;
+
583#ifdef _WIN32
+
584 if (i + 1 < end && is_surrogate_pair(src + i)) {
+
585 unicode = surrogate_pair_to_ucs4(src + i);
+
586 i += 2;
+
587 }
+
588 else
+
589#endif
+
590 {
+
591 unicode = src[i++];
+
592 }
+
593 char tmp[3 + 8 + 1 + 1];
+
594 int m = snprintf(tmp, _countof(tmp), "&#x%x;", unicode);
+
595 assert(m >= 0);
+
596 if (static_cast<size_t>(m) >= count_dst)
+
597 throw buffer_overrun;
+
598 memcpy(dst + j, tmp, m * sizeof(char)); j += m;
+
599 }
+
600 }
+
601 }
+
602 }
+
603 }
+
604 if (j >= count_dst)
+
605 throw buffer_overrun;
+
606 dst[j] = 0;
+
607 return j;
+
608 }
+
609
+
617 inline void wstr2sgml(
+
618 _Inout_ std::string& dst,
+
619 _In_ const std::wstring& src,
+
620 _In_ size_t what = 0)
+
621 {
+
622 wstr2sgml(dst, src.c_str(), src.size(), what);
+
623 }
+
624
+
634 inline std::string wstr2sgml(
+
635 _In_reads_or_z_opt_(count_src) const wchar_t* src, _In_ size_t count_src,
+
636 _In_ size_t what = 0)
+
637 {
+
638 std::string dst;
+
639 wstr2sgml(dst, src, count_src, what);
+
640 return dst;
+
641 }
+
642
+
651 inline std::string wstr2sgml(
+
652 _In_ const std::wstring& src,
+
653 _In_ size_t what = 0)
+
654 {
+
655 return wstr2sgml(src.c_str(), src.size(), what);
+
656 }
+
657}
diff --git a/sgml__unicode_8hpp_source.html b/sgml__unicode_8hpp_source.html index 7b9251954..422528251 100644 --- a/sgml__unicode_8hpp_source.html +++ b/sgml__unicode_8hpp_source.html @@ -3170,7 +3170,7 @@ $(function() { diff --git a/stream_8hpp_source.html b/stream_8hpp_source.html index 1f6583b3f..b3d3d2449 100644 --- a/stream_8hpp_source.html +++ b/stream_8hpp_source.html @@ -97,3390 +97,3391 @@ $(function() {
18#include <stdlib.h>
19#if defined(_WIN32) && !defined(WIN32_LEAN_AND_MEAN)
20#include <asptlb.h>
-
21#endif
-
22#include <chrono>
-
23#include <condition_variable>
-
24#include <list>
-
25#include <memory>
-
26#include <string>
-
27#include <thread>
-
28#include <vector>
-
29
-
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
-
35#endif
-
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.")
-
39#else
-
40#define CHECK_STREAM_STATE 1
-
41#endif
-
42
-
43namespace stdex
-
44{
-
45 namespace stream
-
46 {
-
50 enum class state_t {
-
51 ok = 0,
-
52 eof,
-
53 fail,
-
54 };
-
55
-
59 using fsize_t = uint64_t;
-
60 constexpr fsize_t fsize_max = UINT64_MAX;
-
61
-
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' };
-
66
-
70 class basic
-
71 {
-
72 public:
-
73 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
-
74
-
86 virtual _Success_(return != 0 || length == 0) size_t read(
-
87 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
88 {
-
89 UNREFERENCED_PARAMETER(data);
-
90 UNREFERENCED_PARAMETER(length);
-
91 m_state = state_t::fail;
-
92 return 0;
-
93 }
-
94
-
104 virtual _Success_(return != 0) size_t write(
-
105 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
106 {
-
107 UNREFERENCED_PARAMETER(data);
-
108 UNREFERENCED_PARAMETER(length);
-
109 m_state = state_t::fail;
-
110 return 0;
-
111 }
-
112
-
116 virtual void flush()
-
117 {
-
118 m_state = state_t::ok;
-
119 }
-
120
-
124 virtual void close()
-
125 {
-
126 m_state = state_t::ok;
-
127 }
-
128
-
132 virtual void skip(_In_ fsize_t amount)
-
133 {
-
134 if (amount == 1)
-
135 read_byte();
-
136 else if (amount < iterate_count) {
-
137 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
-
138 read_byte();
-
139 if (!ok()) _Unlikely_
-
140 break;
-
141 }
-
142 }
-
143 else {
-
144 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
-
145 try {
-
146 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
-
147 while (amount) {
-
148 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
-
149 if (!ok()) _Unlikely_
-
150 break;
-
151 }
-
152 }
-
153 catch (std::bad_alloc) { m_state = state_t::fail; }
-
154 }
-
155 }
-
156
-
160 inline state_t state() const { return m_state; };
-
161
-
165 inline bool ok() const { return m_state == state_t::ok; };
-
166
-
174 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
-
175 {
-
176 std::vector<uint8_t> result;
-
177 size_t offset, length;
-
178 offset = 0;
-
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;
-
185 return result;
-
186 }
-
187 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
-
188 offset += num_read;
-
189 if (!ok()) _Unlikely_
-
190 break;
-
191 length += default_block_size;
-
192 }
-
193 result.resize(offset);
-
194 return result;
-
195 }
-
196
-
200 inline uint8_t read_byte()
-
201 {
-
202 uint8_t byte;
-
203 if (read_array(&byte, sizeof(byte), 1) == 1)
-
204 return byte;
-
205 throw std::runtime_error("failed to read");
-
206 }
-
207
-
211 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
-
212 {
-
213 if (amount == 1)
-
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_
-
219 break;
-
220 }
-
221 }
-
222 else {
-
223 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
-
224 try {
-
225 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
-
226 memset(dummy.get(), byte, block);
-
227 while (amount) {
-
228 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
-
229 if (!ok()) _Unlikely_
-
230 break;
-
231 }
-
232 }
-
233 catch (std::bad_alloc) { m_state = state_t::fail; }
-
234 }
-
235 }
-
236
-
248 template <class T>
-
249 inline basic& read_data(_Out_ T& data)
-
250 {
-
251 if (!ok()) _Unlikely_ {
-
252 data = 0;
-
253 return *this;
-
254 }
-
255 if (read_array(&data, sizeof(T), 1) == 1)
-
256 LE2HE(&data);
-
257 else {
-
258 data = 0;
-
259 if (ok())
-
260 m_state = state_t::eof;
-
261 }
-
262 return *this;
-
263 }
-
264
-
276 template <class T>
-
277 inline basic& write_data(_In_ const T data)
-
278 {
-
279 if (!ok()) _Unlikely_
-
280 return *this;
-
281#ifdef BIG_ENDIAN
-
282 T data_le = HE2LE(data);
-
283 write(&data_le, sizeof(T));
-
284#else
-
285 write(&data, sizeof(T));
-
286#endif
-
287 return *this;
-
288 }
-
289
-
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)
-
297 {
-
298 str.clear();
-
299 return readln_and_attach(str);
-
300 }
-
301
-
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)
-
309 {
-
310 wstr.clear();
-
311 return readln_and_attach(wstr);
-
312 }
-
313
-
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)
-
321 {
-
322 if (charset == charset_id::utf16)
-
323 return readln(wstr);
-
324 std::string str;
-
325 readln_and_attach(str);
-
326 wstr.clear();
-
327 str2wstr(wstr, str, charset);
-
328 return wstr.size();
-
329 }
-
330
-
336 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
-
337 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
-
338 {
-
339 bool initial = true;
-
340 _Elem chr, previous = (_Elem)0;
-
341 do {
-
342 read_array(&chr, sizeof(_Elem), 1);
-
343 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
-
344 str += previous;
-
345 else
-
346 initial = false;
-
347 previous = chr;
-
348 } while (ok() && chr != static_cast<_Elem>('\n'));
-
349 return str.size();
-
350 }
-
351
-
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)
-
359 {
-
360 if (charset == charset_id::utf16)
-
361 return readln_and_attach(wstr);
-
362 std::string str;
-
363 readln_and_attach(str);
-
364 str2wstr(wstr, str, charset);
-
365 return wstr.size();
-
366 }
-
367
-
373 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
-
374 {
-
375 for (size_t to_read = mul(size, count);;) {
-
376 size_t num_read = read(array, to_read);
-
377 to_read -= num_read;
-
378 if (!to_read)
-
379 return count;
-
380 if (!ok()) _Unlikely_
-
381 return count - to_read / size;
-
382 reinterpret_cast<uint8_t*&>(array) += num_read;
-
383 }
-
384 }
-
385
-
391 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
-
392 {
-
393 return write(array, mul(size, count)) / size;
-
394 }
-
395
-
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)
-
406 {
-
407 if (!ok()) _Unlikely_
-
408 return 0;
-
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());
-
413 }
-
414 return write_array(wstr, sizeof(wchar_t), num_chars);
-
415 }
-
416
-
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)
-
430 {
-
431 uint32_t num_chars;
-
432 read_data(num_chars);
-
433 if (!ok()) _Unlikely_ {
-
434 data.clear();
-
435 return *this;
-
436 }
-
437 data.resize(num_chars);
-
438 data.resize(read_array(data.data(), sizeof(_Elem), num_chars));
-
439 return *this;
-
440 }
-
441
-
453 template <class T>
-
454 inline basic& write_str(_In_z_ const T* data)
-
455 {
-
456 // Stream state will be checked in write_data.
-
457 size_t num_chars = stdex::strlen(data);
-
458 if (num_chars > UINT32_MAX)
-
459 throw std::invalid_argument("string too long");
-
460 write_data((uint32_t)num_chars);
-
461 if (!ok()) _Unlikely_
-
462 return *this;
-
463 write_array(data, sizeof(T), num_chars);
-
464 return *this;
-
465 }
-
466
-
467#ifdef _WIN32
-
473 size_t write_sa(_In_ LPSAFEARRAY sa)
-
474 {
-
475 safearray_accessor<void> a(sa);
-
476 long ubound, lbound;
-
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);
-
481 }
-
482#endif
-
483
-
489 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
-
490 {
-
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;
-
494 while (to_write) {
-
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) {
-
500 // EOF is not an error.
-
501 m_state = state_t::ok;
-
502 break;
-
503 }
-
504 m_state = stream.m_state;
-
505 if (!ok())
-
506 break;
-
507 }
-
508 return num_copied;
-
509 }
-
510
-
514 void write_charset(_In_ charset_id charset)
-
515 {
-
516 if (charset == charset_id::utf16)
-
517 write_data(utf16_bom);
-
518 else if (charset == charset_id::utf8)
-
519 write_array(utf8_bom, sizeof(utf8_bom), 1);
-
520 }
-
521
-
527 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
-
528 {
-
529 va_list params;
-
530 va_start(params, locale);
-
531 size_t num_chars = write_vsprintf(format, locale, params);
-
532 va_end(params);
-
533 return num_chars;
-
534 }
-
535
-
541 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
-
542 {
-
543 va_list params;
-
544 va_start(params, locale);
-
545 size_t num_chars = write_vsprintf(format, locale, params);
-
546 va_end(params);
-
547 return num_chars;
-
548 }
-
549
-
555 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
-
556 {
-
557 std::string str;
-
558 str.reserve(default_block_size);
-
559 vappendf(str, format, locale, params);
-
560 return write_array(str.data(), sizeof(char), str.size());
-
561 }
-
562
-
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)
-
569 {
-
570 std::wstring str;
-
571 str.reserve(default_block_size);
-
572 vappendf(str, format, locale, params);
-
573 return write_array(str.data(), sizeof(wchar_t), str.size());
-
574 }
-
575
-
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); }
-
595#endif
-
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); }
-
605#endif
-
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); }
-
608 template <class T>
-
609 inline basic& operator <<(_In_ const T* data) { return write_str(data); }
-
610
-
611 protected:
-
612 state_t m_state;
-
613 };
-
614
-
618 using fpos_t = uint64_t;
-
619 constexpr fpos_t fpos_max = UINT64_MAX;
-
620 constexpr fpos_t fpos_min = 0;
-
621
-
625 using foff_t = int64_t;
-
626 constexpr foff_t foff_max = INT64_MAX;
-
627 constexpr foff_t foff_min = INT64_MIN;
-
628
-
632 enum class seek_t {
-
633#ifdef _WIN32
-
634 beg = FILE_BEGIN,
-
635 cur = FILE_CURRENT,
-
636 end = FILE_END
-
637#else
-
638 beg = SEEK_SET,
-
639 cur = SEEK_CUR,
-
640 end = SEEK_END
-
641#endif
-
642 };
-
643
-
644#if _HAS_CXX20
-
645 using time_point = std::chrono::time_point<std::chrono::file_clock>;
-
646#else
-
647 using time_point = std::chrono::time_point<std::chrono::system_clock>;
-
648#endif
-
649
-
653 class basic_file : virtual public basic
-
654 {
-
655 public:
-
656 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
-
657 {
-
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;
-
663 return result;
-
664 }
-
665 result.resize(read_array(result.data(), sizeof(uint8_t), length));
-
666 return result;
-
667 }
-
668
-
674 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
-
675
-
681 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
-
682
-
688 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
-
689
-
695 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
-
696
-
697 virtual void skip(_In_ fsize_t amount)
-
698 {
-
699 seek(amount, seek_t::cur);
-
700 }
-
701
-
708 virtual fpos_t tell() const = 0;
-
709
-
713 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
-
714 {
-
715 UNREFERENCED_PARAMETER(offset);
-
716 UNREFERENCED_PARAMETER(length);
-
717 throw std::exception("not implemented");
-
718 }
-
719
-
723 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
-
724 {
-
725 UNREFERENCED_PARAMETER(offset);
-
726 UNREFERENCED_PARAMETER(length);
-
727 throw std::exception("not implemented");
-
728 }
-
729
-
734 virtual fsize_t size() = 0;
-
735
-
739 virtual void truncate() = 0;
-
740
-
744 virtual time_point ctime() const
-
745 {
-
746 return time_point::min();
-
747 }
-
748
-
752 virtual time_point atime() const
-
753 {
-
754 return time_point::min();
-
755 }
-
756
-
760 virtual time_point mtime() const
-
761 {
-
762 return time_point::min();
-
763 }
-
764
-
768 virtual void set_ctime(time_point date)
-
769 {
-
770 UNREFERENCED_PARAMETER(date);
-
771 throw std::exception("not implemented");
-
772 }
-
773
-
777 virtual void set_atime(time_point date)
-
778 {
-
779 UNREFERENCED_PARAMETER(date);
-
780 throw std::exception("not implemented");
-
781 }
-
782
-
786 virtual void set_mtime(time_point date)
-
787 {
-
788 UNREFERENCED_PARAMETER(date);
-
789 throw std::exception("not implemented");
-
790 }
-
791
-
792#ifdef _WIN32
-
796 LPSAFEARRAY read_sa()
-
797 {
-
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));
-
801 if (!sa)
-
802 throw std::runtime_error("SafeArrayCreateVector failed");
-
803 safearray_accessor<void> a(sa.get());
-
804 if (seek(0) != 0)
-
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");
-
808 return sa.release();
-
809 }
-
810#endif
-
811
-
817 charset_id read_charset(_In_ charset_id default_charset = charset_id::default)
-
818 {
-
819 if (seek(0) != 0)
-
820 throw std::runtime_error("failed to seek");
-
821 wchar_t id_utf16;
-
822 read_array(&id_utf16, sizeof(wchar_t), 1);
-
823 if (!ok()) _Unlikely_
-
824 return default_charset;
-
825 if (id_utf16 == utf16_bom)
-
826 return charset_id::utf16;
-
827
-
828 if (seek(0) != 0)
-
829 throw std::runtime_error("failed to seek");
-
830 char id_utf8[3] = { 0 };
-
831 read_array(id_utf8, sizeof(id_utf8), 1);
-
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;
-
836
-
837 if (seek(0) != 0)
-
838 throw std::runtime_error("failed to seek");
-
839 return default_charset;
-
840 }
-
841 };
-
842
-
846 class converter : public basic
-
847 {
-
848 protected:
-
849 explicit converter() :
-
850 basic(state_t::fail),
-
851 m_source(nullptr)
-
852 {}
-
853
-
854 void init(_Inout_ basic& source)
-
855 {
-
856 m_state = source.state();
-
857 m_source = &source;
-
858 }
-
859
-
860 public:
-
861 converter(_Inout_ basic& source) :
-
862 basic(source.state()),
-
863 m_source(&source)
-
864 {}
-
865
-
866 virtual _Success_(return != 0 || length == 0) size_t read(
-
867 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
868 {
-
869 size_t num_read = m_source->read(data, length);
-
870 m_state = m_source->state();
-
871 return num_read;
-
872 }
-
873
-
874 virtual _Success_(return != 0) size_t write(
-
875 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
876 {
-
877 size_t num_written = m_source->write(data, length);
-
878 m_state = m_source->state();
-
879 return num_written;
-
880 }
-
881
-
882 virtual void close()
-
883 {
-
884 m_source->close();
-
885 m_state = m_source->state();
-
886 }
-
887
-
888 virtual void flush()
-
889 {
-
890 m_source->flush();
-
891 m_state = m_source->state();
-
892 }
-
893
-
894 protected:
-
895 basic* m_source;
-
896 };
-
897
-
901 class replicator : public basic
-
902 {
-
903 public:
-
904 virtual ~replicator()
-
905 {
-
906 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
-
907 auto _w = w->get();
-
908 {
-
909 const std::lock_guard<std::mutex> lk(_w->mutex);
-
910 _w->op = worker::op_t::quit;
-
911 }
-
912 _w->cv.notify_one();
-
913 }
-
914 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
-
915 w->get()->thread.join();
-
916 }
-
917
-
921 void push_back(_In_ basic* source)
-
922 {
-
923 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
-
924 }
-
925
-
929 void remove(basic* source)
-
930 {
-
931 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
-
932 auto _w = w->get();
-
933 if (_w->source == source) {
-
934 {
-
935 const std::lock_guard<std::mutex> lk(_w->mutex);
-
936 _w->op = worker::op_t::quit;
-
937 }
-
938 _w->cv.notify_one();
-
939 _w->thread.join();
-
940 m_workers.erase(w);
-
941 return;
-
942 }
-
943 }
-
944 }
-
945
-
946 virtual _Success_(return != 0) size_t write(
-
947 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
948 {
-
949 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
-
950 auto _w = w->get();
-
951 {
-
952 const std::lock_guard<std::mutex> lk(_w->mutex);
-
953 _w->op = worker::op_t::write;
-
954 _w->data = data;
-
955 _w->length = length;
-
956 }
-
957 _w->cv.notify_one();
-
958 }
-
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) {
-
962 auto _w = w->get();
-
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();
-
969 }
-
970 return num_written;
-
971 }
-
972
-
973 virtual void close()
-
974 {
-
975 foreach_worker(worker::op_t::close);
-
976 }
-
977
-
978 virtual void flush()
-
979 {
-
980 foreach_worker(worker::op_t::flush);
-
981 }
-
982
-
983 protected:
-
984 class worker
-
985 {
-
986 public:
-
987 worker(_In_ basic* _source) :
-
988 source(_source),
-
989 op(op_t::noop),
-
990 data(nullptr),
-
991 length(0),
-
992 num_written(0),
-
993 thread(process_op, std::ref(*this))
-
994 {}
-
995
-
996 protected:
-
997 static void process_op(_Inout_ worker& w)
-
998 {
-
999 for (;;) {
-
1000 std::unique_lock<std::mutex> lk(w.mutex);
-
1001 w.cv.wait(lk, [&] {return w.op != op_t::noop; });
-
1002 switch (w.op) {
-
1003 case op_t::quit:
-
1004 return;
-
1005 case op_t::write:
-
1006 w.num_written = w.source->write(w.data, w.length);
-
1007 break;
-
1008 case op_t::close:
-
1009 w.source->close();
-
1010 break;
-
1011 case op_t::flush:
-
1012 w.source->flush();
-
1013 break;
-
1014 }
-
1015 w.op = op_t::noop;
-
1016 lk.unlock();
-
1017 w.cv.notify_one();
-
1018 }
-
1019 }
-
1020
-
1021 public:
-
1022 basic* source;
-
1023 enum class op_t {
-
1024 noop = 0,
-
1025 quit,
-
1026 write,
-
1027 close,
-
1028 flush,
-
1029 } op;
-
1030 const void* data;
-
1031 size_t length;
-
1032 size_t num_written;
-
1033 std::mutex mutex;
-
1034 std::condition_variable cv;
-
1035 std::thread thread;
-
1036 };
-
1037
-
1038 void foreach_worker(_In_ worker::op_t op)
-
1039 {
-
1040 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
-
1041 auto _w = w->get();
-
1042 {
-
1043 const std::lock_guard<std::mutex> lk(_w->mutex);
-
1044 _w->op = op;
-
1045 }
-
1046 _w->cv.notify_one();
-
1047 }
-
1048 m_state = state_t::ok;
-
1049 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
-
1050 auto _w = w->get();
-
1051 std::unique_lock<std::mutex> lk(_w->mutex);
-
1052 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
-
1053 if (ok())
-
1054 m_state = _w->source->state();
-
1055 }
-
1056 }
-
1057
-
1058 std::list<std::unique_ptr<worker>> m_workers;
-
1059 };
-
1060
-
1061 constexpr size_t default_async_limit = 0x100000;
-
1062
-
1068 template <size_t CAPACITY = default_async_limit>
-
1069 class async_reader : public converter
-
1070 {
-
1071 public:
-
1072 async_reader(_Inout_ basic& source) :
-
1073 converter(source),
-
1074 m_worker(process, std::ref(*this))
-
1075 {}
-
1076
-
1077 virtual ~async_reader()
-
1078 {
-
1079 m_ring.quit();
-
1080 m_worker.join();
-
1081 }
-
1082
-
1083#pragma warning(suppress: 6101) // See [1] below
-
1084 virtual _Success_(return != 0 || length == 0) size_t read(
-
1085 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1086 {
-
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_ {
-
1092 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
-
1093 m_state = to_read < length || !length ? state_t::ok : m_source->state();
-
1094 return length - to_read;
-
1095 }
-
1096 if (to_read < num_read)
-
1097 num_read = to_read;
-
1098 memcpy(data, ptr, num_read);
-
1099 m_ring.pop(num_read);
-
1100 to_read -= num_read;
-
1101 if (!to_read) {
-
1102 m_state = state_t::ok;
-
1103 return length;
-
1104 }
-
1105 reinterpret_cast<uint8_t*&>(data) += num_read;
-
1106 }
-
1107 }
-
1108
-
1109 protected:
-
1110 static void process(_Inout_ async_reader& w)
-
1111 {
-
1112 for (;;) {
-
1113 uint8_t* ptr; size_t num_write;
-
1114 std::tie(ptr, num_write) = w.m_ring.back();
-
1115 if (!ptr) _Unlikely_
-
1116 break;
-
1117 num_write = w.m_source->read(ptr, num_write);
-
1118 w.m_ring.push(num_write);
-
1119 if (!w.m_source->ok()) {
-
1120 w.m_ring.quit();
-
1121 break;
-
1122 }
-
1123 }
-
1124 }
-
1125
-
1126 protected:
-
1127 ring<uint8_t, CAPACITY> m_ring;
-
1128 std::thread m_worker;
-
1129 };
-
1130
-
1136 template <size_t CAPACITY = default_async_limit>
-
1137 class async_writer : public converter
-
1138 {
-
1139 public:
-
1140 async_writer(_Inout_ basic& source) :
-
1141 converter(source),
-
1142 m_worker(process, std::ref(*this))
-
1143 {}
-
1144
-
1145 virtual ~async_writer()
-
1146 {
-
1147 m_ring.quit();
-
1148 m_worker.join();
-
1149 }
-
1150
-
1151 virtual _Success_(return != 0) size_t write(
-
1152 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1153 {
-
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;
-
1161 }
-
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;
-
1167 if (!to_write) {
-
1168 m_state = state_t::ok;
-
1169 return length;
-
1170 }
-
1171 reinterpret_cast<const uint8_t*&>(data) += num_write;
-
1172 }
-
1173 }
-
1174
-
1175 virtual void flush()
-
1176 {
-
1177 m_ring.sync();
-
1178 converter::flush();
-
1179 }
-
1180
-
1181 protected:
-
1182 static void process(_Inout_ async_writer& w)
-
1183 {
-
1184 for (;;) {
-
1185 uint8_t* ptr; size_t num_read;
-
1186 std::tie(ptr, num_read) = w.m_ring.front();
-
1187 if (!ptr)
-
1188 break;
-
1189 num_read = w.m_source->write(ptr, num_read);
-
1190 w.m_ring.pop(num_read);
-
1191 if (!w.m_source->ok()) {
-
1192 w.m_ring.quit();
-
1193 break;
-
1194 }
-
1195 }
-
1196 }
-
1197
-
1198 protected:
-
1199 ring<uint8_t, CAPACITY> m_ring;
-
1200 std::thread m_worker;
-
1201 };
-
1202
-
1203 constexpr size_t default_buffer_size = 0x400;
-
1204
-
1208 class buffer : public converter
-
1209 {
-
1210 protected:
-
1211 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
-
1212 converter(),
-
1213 m_read_buffer(read_buffer_size),
-
1214 m_write_buffer(write_buffer_size)
-
1215 {}
-
1216
-
1217 public:
-
1218 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
-
1219 converter(source),
-
1220 m_read_buffer(read_buffer_size),
-
1221 m_write_buffer(write_buffer_size)
-
1222 {}
-
1223
-
1224 virtual ~buffer()
-
1225 {
-
1226 if (m_source)
-
1227 flush_write();
-
1228 }
-
1229
-
1230 virtual _Success_(return != 0 || length == 0) size_t read(
-
1231 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1232 {
-
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;
-
1240 return length;
-
1241 }
-
1242 if (buffer_size) {
-
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;
-
1246 }
-
1247 m_read_buffer.head = 0;
-
1248 if (to_read > m_read_buffer.capacity) {
-
1249 // When needing to read more data than buffer capacity, bypass the buffer.
-
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;
-
1254 }
-
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;
-
1262 }
-
1263 }
-
1264 }
-
1265
-
1266 virtual _Success_(return != 0) size_t write(
-
1267 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1268 {
-
1269 assert(data || !length);
-
1270 if (!length) _Unlikely_ {
-
1271 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
-
1272 flush_write();
-
1273 if (!ok()) _Unlikely_
-
1274 return 0;
-
1275 m_source->write(nullptr, 0);
-
1276 m_state = m_source->state();
-
1277 return 0;
-
1278 }
-
1279
-
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;
-
1286 return length;
-
1287 }
-
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;
-
1293 }
-
1294 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
-
1295 if (buffer_size) {
-
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;
-
1300 else
-
1301 return length - to_write;
-
1302 }
-
1303 if (to_write > m_write_buffer.capacity) {
-
1304 // When needing to write more data than buffer capacity, bypass the buffer.
-
1305 to_write -= m_source->write(data, to_write);
-
1306 m_state = m_source->state();
-
1307 return length - to_write;
-
1308 }
-
1309 }
-
1310 }
-
1311
-
1312 virtual void flush()
-
1313 {
-
1314 flush_write();
-
1315 if (ok())
-
1316 converter::flush();
-
1317 }
-
1318
-
1319 protected:
-
1320 void flush_write()
-
1321 {
-
1322 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
-
1323 if (buffer_size) {
-
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;
-
1328 }
-
1329 else {
-
1330 m_state = m_source->state();
-
1331 return;
-
1332 }
-
1333 }
-
1334 m_state = state_t::ok;
-
1335 }
-
1336
-
1337 struct buffer_t {
-
1338 uint8_t* data;
-
1339 size_t head, tail, capacity;
-
1340
-
1341 buffer_t(_In_ size_t buffer_size) :
-
1342 head(0),
-
1343 tail(0),
-
1344 capacity(buffer_size),
-
1345 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
-
1346 {}
-
1347
-
1348 ~buffer_t()
-
1349 {
-
1350 if (data)
-
1351 delete[] data;
-
1352 }
-
1353 } m_read_buffer, m_write_buffer;
-
1354 };
-
1355
-
1359 class limiter : public converter
-
1360 {
-
1361 public:
-
1362 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
-
1363 converter(source),
-
1364 read_limit(_read_limit),
-
1365 write_limit(_write_limit)
-
1366 {}
-
1367
-
1368 virtual _Success_(return != 0 || length == 0) size_t read(
-
1369 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1370 {
-
1371 size_t num_read;
-
1372 if (read_limit == fsize_max) {
-
1373 num_read = m_source->read(data, length);
-
1374 m_state = m_source->state();
-
1375 }
-
1376 else if (length <= read_limit) {
-
1377 num_read = m_source->read(data, length);
-
1378 m_state = m_source->state();
-
1379 read_limit -= num_read;
-
1380 }
-
1381 else if (length && !read_limit) {
-
1382 num_read = 0;
-
1383 m_state = state_t::eof;
-
1384 }
-
1385 else {
-
1386 num_read = m_source->read(data, static_cast<size_t>(read_limit));
-
1387 m_state = m_source->state();
-
1388 read_limit -= num_read;
-
1389 }
-
1390 return num_read;
-
1391 }
-
1392
-
1393 virtual _Success_(return != 0) size_t write(
-
1394 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1395 {
-
1396 size_t num_written;
-
1397 if (write_limit == fsize_max) {
-
1398 num_written = m_source->write(data, length);
-
1399 m_state = m_source->state();
-
1400 }
-
1401 else if (length <= write_limit) {
-
1402 num_written = m_source->write(data, length);
-
1403 m_state = m_source->state();
-
1404 write_limit -= num_written;
-
1405 }
-
1406 else if (length && !write_limit) {
-
1407 num_written = 0;
-
1408 m_state = state_t::fail;
-
1409 }
-
1410 else {
-
1411 num_written = m_source->write(data, static_cast<size_t>(write_limit));
-
1412 m_state = m_source->state();
-
1413 write_limit -= num_written;
-
1414 }
-
1415 return num_written;
-
1416 }
-
1417
-
1418 public:
-
1419 fsize_t
-
1420 read_limit,
-
1421 write_limit;
-
1422 };
-
1423
-
1427 class window : public limiter
-
1428 {
-
1429 public:
-
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) :
-
1431 limiter(source, read_limit, write_limit),
-
1432 read_offset(_read_offset),
-
1433 write_offset(_write_offset)
-
1434 {}
-
1435
-
1436 virtual _Success_(return != 0 || length == 0) size_t read(
-
1437 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1438 {
-
1439 if (read_offset) {
-
1440 m_source->skip(read_offset);
-
1441 m_state = m_source->state();
-
1442 if (!ok()) _Unlikely_
-
1443 return 0;
-
1444 read_offset = 0;
-
1445 }
-
1446 size_t num_read;
-
1447 if (read_limit == fsize_max) {
-
1448 num_read = m_source->read(data, length);
-
1449 m_state = m_source->state();
-
1450 }
-
1451 else if (length <= read_limit) {
-
1452 num_read = m_source->read(data, length);
-
1453 m_state = m_source->state();
-
1454 read_limit -= num_read;
-
1455 }
-
1456 else if (length && !read_limit) {
-
1457 num_read = 0;
-
1458 m_source->skip(length);
-
1459 m_state = state_t::eof;
-
1460 }
-
1461 else {
-
1462 num_read = m_source->read(data, static_cast<size_t>(read_limit));
-
1463 m_state = m_source->state();
-
1464 read_limit -= num_read;
-
1465 }
-
1466 return num_read;
-
1467 }
-
1468
-
1469 virtual _Success_(return != 0) size_t write(
-
1470 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1471 {
-
1472 size_t num_skipped, num_written;
-
1473 if (length <= write_offset) {
-
1474 write_offset -= length;
-
1475 m_state = state_t::ok;
-
1476 return length;
-
1477 }
-
1478 if (write_offset) {
-
1479 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
-
1480 length -= static_cast<size_t>(write_offset);
-
1481 num_skipped = static_cast<size_t>(write_offset);
-
1482 write_offset = 0;
-
1483 }
-
1484 else
-
1485 num_skipped = 0;
-
1486 if (write_limit == fsize_max) {
-
1487 num_written = m_source->write(data, length);
-
1488 m_state = m_source->state();
-
1489 }
-
1490 else if (length <= write_limit) {
-
1491 num_written = m_source->write(data, length);
-
1492 m_state = m_source->state();
-
1493 write_limit -= num_written;
-
1494 }
-
1495 else if (length && !write_limit) {
-
1496 num_skipped += length;
-
1497 num_written = 0;
-
1498 m_state = state_t::ok;
-
1499 }
-
1500 else {
-
1501 num_skipped += length - static_cast<size_t>(write_limit);
-
1502 num_written = m_source->write(data, static_cast<size_t>(write_limit));
-
1503 m_state = m_source->state();
-
1504 write_limit -= num_written;
-
1505 }
-
1506 return num_skipped + num_written;
-
1507 }
-
1508
-
1509 public:
-
1510 fpos_t
-
1511 read_offset,
-
1512 write_offset;
-
1513 };
-
1514
-
1518 class file_window : public basic_file
-
1519 {
-
1520 public:
-
1521 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
-
1522 basic(source.state()),
-
1523 m_source(source),
-
1524 m_offset(source.tell()),
-
1525 m_region(offset, offset + length)
-
1526 {}
-
1527
-
1528 virtual _Success_(return != 0 || length == 0) size_t read(
-
1529 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1530 {
-
1531 assert(data || !length);
-
1532 if (m_region.contains(m_offset)) {
-
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;
-
1536 return num_read;
-
1537 }
-
1538 m_state = length ? state_t::eof : state_t::ok;
-
1539 return 0;
-
1540 }
-
1541
-
1542 virtual _Success_(return != 0) size_t write(
-
1543 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1544 {
-
1545 assert(data || !length);
-
1546 if (m_region.contains(m_offset)) {
-
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;
-
1550 return num_written;
-
1551 }
-
1552 m_state = state_t::fail;
-
1553 return 0;
-
1554 }
-
1555
-
1556 virtual void close()
-
1557 {
-
1558 m_source.close();
-
1559 m_state = m_source.state();
-
1560 }
-
1561
-
1562 virtual void flush()
-
1563 {
-
1564 m_source.flush();
-
1565 m_state = m_source.state();
-
1566 }
-
1567
-
1568 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
-
1569 {
-
1570 m_offset = m_source.seek(offset, how);
-
1571 m_state = m_source.state();
-
1572 return ok() ? m_offset - m_region.start : fpos_max;
-
1573 }
-
1574
-
1575 virtual void skip(_In_ fsize_t amount)
-
1576 {
-
1577 m_source.skip(amount);
-
1578 m_state = m_source.state();
-
1579 }
-
1580
-
1581 virtual fpos_t tell() const
-
1582 {
-
1583 fpos_t offset = m_source.tell();
-
1584 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
-
1585 }
-
1586
-
1587 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
-
1588 {
-
1589 if (m_region.contains(offset)) {
-
1590 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
-
1591 m_state = m_source.state();
-
1592 }
-
1593 else
-
1594 m_state = state_t::fail;
-
1595 }
-
1596
-
1597 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
-
1598 {
-
1599 if (m_region.contains(offset)) {
-
1600 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
-
1601 m_state = m_source.state();
-
1602 }
-
1603 else
-
1604 m_state = state_t::fail;
-
1605 }
-
1606
-
1607 virtual fsize_t size()
-
1608 {
-
1609 return m_region.size();
-
1610 }
-
1611
-
1612 virtual void truncate()
-
1613 {
-
1614 m_state = state_t::fail;
-
1615 }
-
1616
-
1617 protected:
-
1618 basic_file& m_source;
-
1619 fpos_t m_offset;
-
1620 interval<fpos_t> m_region;
-
1621 };
-
1622
-
1623 constexpr size_t default_cache_size = 0x1000;
-
1624
-
1628 class cache : public basic_file
-
1629 {
-
1630 protected:
-
1631 explicit cache(_In_ size_t cache_size = default_cache_size) :
-
1632 basic(state_t::fail),
-
1633 m_source(nullptr),
-
1634 m_cache(cache_size),
-
1635 m_offset(0)
-
1636#if SET_FILE_OP_TIMES
-
1637 , m_atime(time_point::min()),
-
1638 m_mtime(time_point::min())
-
1639#endif
-
1640 {}
-
1641
-
1642 void init(_Inout_ basic_file& source)
-
1643 {
-
1644 m_state = source.state();
-
1645 m_source = &source;
-
1646 m_offset = source.tell();
-
1647#if SET_FILE_OP_TIMES
-
1648 m_atime = source.atime();
-
1649 m_mtime = source.mtime();
-
1650#endif
-
1651 }
-
1652
-
1653 public:
-
1654 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
-
1655 basic(source.state()),
-
1656 m_source(&source),
-
1657 m_cache(cache_size),
-
1658 m_offset(source.tell())
-
1659#if SET_FILE_OP_TIMES
-
1660 , m_atime(source.atime()),
-
1661 m_mtime(source.mtime())
-
1662#endif
-
1663 {}
-
1664
-
1665 virtual ~cache() noexcept(false)
-
1666 {
-
1667 if (m_source) {
-
1668 flush_cache();
-
1669 if (!ok()) _Unlikely_
-
1670 throw std::runtime_error("cache flush failed"); // Data loss occured
-
1671 m_source->seek(m_offset);
-
1672 }
-
1673 }
-
1674
-
1675 virtual _Success_(return != 0 || length == 0) size_t read(
-
1676 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
1677 {
-
1678 assert(data || !length);
-
1679#if SET_FILE_OP_TIMES
-
1680 m_atime = time_point::now();
-
1681#endif
-
1682 for (size_t to_read = length;;) {
-
1683 if (m_cache.status != cache_t::cache_t::status_t::empty) {
-
1684 if (m_cache.region.contains(m_offset)) {
-
1685 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
-
1686 if (to_read <= remaining_cache) {
-
1687 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
-
1688 m_offset += to_read;
-
1689 m_state = state_t::ok;
-
1690 return length;
-
1691 }
-
1692 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
-
1693 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
-
1694 to_read -= remaining_cache;
-
1695 m_offset += remaining_cache;
-
1696 }
-
1697 flush_cache();
-
1698 if (!ok()) _Unlikely_ {
-
1699 if (to_read < length)
-
1700 m_state = state_t::ok;
-
1701 return length - to_read;
-
1702 }
-
1703 }
-
1704 {
-
1705 fpos_t end_max = m_offset + to_read;
-
1706 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
-
1707 // Read spans multiple cache blocks. Bypass cache to the last block.
-
1708 m_source->seek(m_offset);
-
1709 if (!m_source->ok()) _Unlikely_ {
-
1710 m_state = to_read < length ? state_t::ok : state_t::fail;
-
1711 return length - to_read;
-
1712 }
-
1713 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
-
1714 m_offset += num_read;
-
1715 to_read -= num_read;
-
1716 if (!to_read) {
-
1717 m_state = state_t::ok;
-
1718 return length;
-
1719 }
-
1720 reinterpret_cast<uint8_t*&>(data) += num_read;
-
1721 m_state = m_source->state();
-
1722 if (!ok()) {
-
1723 if (to_read < length)
-
1724 m_state = state_t::ok;
-
1725 return length - to_read;
-
1726 }
-
1727 }
-
1728 }
-
1729 load_cache(m_offset);
-
1730 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
-
1731 m_state = to_read < length ? state_t::ok : state_t::fail;
-
1732 return length - to_read;
-
1733 }
-
1734 }
-
1735 }
-
1736
-
1737 virtual _Success_(return != 0) size_t write(
-
1738 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
1739 {
-
1740 assert(data || !length);
-
1741#if SET_FILE_OP_TIMES
-
1742 m_atime = m_mtime = time_point::now();
-
1743#endif
-
1744 for (size_t to_write = length;;) {
-
1745 if (m_cache.status != cache_t::cache_t::status_t::empty) {
-
1746 fpos_t end_max = m_cache.region.start + m_cache.capacity;
-
1747 if (m_cache.region.start <= m_offset && m_offset < end_max) {
-
1748 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
-
1749 if (to_write <= remaining_cache) {
-
1750 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
-
1751 m_offset += to_write;
-
1752 m_cache.status = cache_t::cache_t::status_t::dirty;
-
1753 m_cache.region.end = std::max(m_cache.region.end, m_offset);
-
1754 m_state = state_t::ok;
-
1755 return length;
-
1756 }
-
1757 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
-
1758 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
-
1759 to_write -= remaining_cache;
-
1760 m_offset += remaining_cache;
-
1761 m_cache.status = cache_t::cache_t::status_t::dirty;
-
1762 m_cache.region.end = end_max;
-
1763 }
-
1764 flush_cache();
-
1765 if (!ok()) _Unlikely_
-
1766 return length - to_write;
-
1767 }
-
1768 {
-
1769 fpos_t end_max = m_offset + to_write;
-
1770 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
-
1771 // Write spans multiple cache blocks. Bypass cache to the last block.
-
1772 m_source->seek(m_offset);
-
1773 if (!ok()) _Unlikely_
-
1774 return length - to_write;
-
1775 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
-
1776 m_offset += num_written;
-
1777 m_state = m_source->state();
-
1778 to_write -= num_written;
-
1779 if (!to_write || !ok())
-
1780 return length - to_write;
-
1781 reinterpret_cast<const uint8_t*&>(data) += num_written;
-
1782 }
-
1783 }
-
1784 load_cache(m_offset);
-
1785 if (!ok()) _Unlikely_
-
1786 return length - to_write;
-
1787 }
-
1788 }
-
1789
-
1790 virtual void close()
-
1791 {
-
1792 invalidate_cache();
-
1793 if (!ok()) _Unlikely_
-
1794 throw std::runtime_error("cache flush failed"); // Data loss occured
-
1795 m_source->close();
-
1796 m_state = m_source->state();
-
1797 }
-
1798
-
1799 virtual void flush()
-
1800 {
-
1801#if SET_FILE_OP_TIMES
-
1802 m_atime = m_mtime = time_point::min();
-
1803#endif
-
1804 flush_cache();
-
1805 if (!ok()) _Unlikely_
-
1806 return;
-
1807 m_source->flush();
-
1808 }
-
1809
-
1810 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
-
1811 {
-
1812 m_state = state_t::ok;
-
1813 switch (how) {
-
1814 case seek_t::beg:
-
1815 return m_offset = offset;
-
1816 case seek_t::cur:
-
1817 return m_offset += offset;
-
1818 case seek_t::end:
-
1819 return m_offset = size() + offset;
-
1820 default:
-
1821 throw std::invalid_argument("unknown seek origin");
-
1822 }
-
1823 }
-
1824
-
1825 virtual fpos_t tell() const
-
1826 {
-
1827 return m_offset;
-
1828 }
-
1829
-
1830 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
-
1831 {
-
1832 m_source->lock(offset, length);
-
1833 m_state = m_source->state();
-
1834 }
-
1835
-
1836 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
-
1837 {
-
1838 m_source->unlock(offset, length);
-
1839 m_state = m_source->state();
-
1840 }
-
1841
-
1842 virtual fsize_t size()
-
1843 {
-
1844 return m_cache.status != cache_t::cache_t::status_t::empty ?
-
1845 std::max(m_source->size(), m_cache.region.end) :
-
1846 m_source->size();
-
1847 }
-
1848
-
1849 virtual void truncate()
-
1850 {
-
1851#if SET_FILE_OP_TIMES
-
1852 m_atime = m_mtime = time_point::now();
-
1853#endif
-
1854 m_source->seek(m_offset);
-
1855 if (m_cache.region.end <= m_offset) {
-
1856 // Truncation does not affect cache.
-
1857 }
-
1858 else if (m_cache.region.start <= m_offset) {
-
1859 // Truncation truncates cache.
-
1860 m_cache.region.end = m_offset;
-
1861 }
-
1862 else {
-
1863 // Truncation invalidates cache.
-
1864 m_cache.status = cache_t::cache_t::status_t::empty;
-
1865 }
-
1866 m_source->truncate();
-
1867 m_state = m_source->state();
-
1868 }
-
1869
-
1870 virtual time_point ctime() const
-
1871 {
-
1872 return m_source->ctime();
-
1873 }
-
1874
-
1875 virtual time_point atime() const
-
1876 {
-
1877#if SET_FILE_OP_TIMES
-
1878 return std::max(m_atime, m_source->atime());
-
1879#else
-
1880 return m_source->atime();
-
1881#endif
-
1882 }
-
1883
-
1884 virtual time_point mtime() const
-
1885 {
-
1886#if SET_FILE_OP_TIMES
-
1887 return std::max(m_mtime, m_source->mtime());
-
1888#else
-
1889 return m_source->mtime();
-
1890#endif
-
1891 }
-
1892
-
1893 virtual void set_ctime(time_point date)
-
1894 {
-
1895 m_source->set_ctime(date);
-
1896 }
-
1897
-
1898 virtual void set_atime(time_point date)
-
1899 {
-
1900#if SET_FILE_OP_TIMES
-
1901 m_atime = date;
-
1902#endif
-
1903 m_source->set_atime(date);
-
1904 }
-
1905
-
1906 virtual void set_mtime(time_point date)
-
1907 {
-
1908#if SET_FILE_OP_TIMES
-
1909 m_mtime = date;
-
1910#endif
-
1911 m_source->set_mtime(date);
-
1912 }
-
1913
-
1914 protected:
-
1915 void flush_cache()
-
1916 {
-
1917 if (m_cache.status != cache_t::cache_t::status_t::dirty)
-
1918 m_state = state_t::ok;
-
1919 else if (!m_cache.region.empty()) {
-
1920 write_cache();
-
1921 if (ok())
-
1922 m_cache.status = cache_t::cache_t::status_t::loaded;
-
1923 }
-
1924 else {
-
1925 m_state = state_t::ok;
-
1926 m_cache.status = cache_t::cache_t::status_t::loaded;
-
1927 }
-
1928 }
-
1929
-
1930 void invalidate_cache()
-
1931 {
-
1932 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
-
1933 write_cache();
-
1934 if (!ok()) _Unlikely_
-
1935 return;
-
1936 } else
-
1937 m_state = state_t::ok;
-
1938 m_cache.status = cache_t::cache_t::status_t::empty;
-
1939 }
-
1940
-
1941 void load_cache(_In_ fpos_t start)
-
1942 {
-
1943 assert(m_cache.status != cache_t::cache_t::status_t::dirty);
-
1944 start -= start % m_cache.capacity; // Align to cache block size.
-
1945 m_source->seek(m_cache.region.start = start);
-
1946 if (m_source->ok()) {
-
1947 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
-
1948 m_cache.status = cache_t::cache_t::status_t::loaded;
-
1949 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
-
1950 }
-
1951 else
-
1952 m_state = state_t::fail;
-
1953 }
-
1954
-
1955 void write_cache()
-
1956 {
-
1957 assert(m_cache.status == cache_t::cache_t::status_t::dirty);
-
1958 m_source->seek(m_cache.region.start);
-
1959 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
-
1960 m_state = m_source->state();
-
1961 }
-
1962
-
1963 basic_file* m_source;
-
1964 struct cache_t {
-
1965 uint8_t* data;
-
1966 size_t capacity;
-
1967 enum class status_t {
-
1968 empty = 0,
-
1969 loaded,
-
1970 dirty,
-
1971 } status;
-
1972 interval<fpos_t> region;
-
1973
-
1974 cache_t(_In_ size_t _capacity) :
-
1975 data(new uint8_t[_capacity]),
-
1976 capacity(_capacity),
-
1977 status(status_t::empty),
-
1978 region(0)
-
1979 {}
-
1980
-
1981 ~cache_t()
-
1982 {
-
1983 delete[] data;
-
1984 }
-
1985 } m_cache;
-
1986 fpos_t m_offset;
-
1987#if SET_FILE_OP_TIMES
-
1988 time_point
-
1989 m_atime,
-
1990 m_mtime;
-
1991#endif
-
1992 };
-
1993
-
1997 class basic_sys : virtual public basic, public sys_object
-
1998 {
-
1999 public:
-
2000 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
-
2001 basic(state),
-
2002 sys_object(h)
-
2003 {}
-
2004
-
2005 virtual _Success_(return != 0 || length == 0) size_t read(
-
2006 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
2007 {
-
2008 assert(data || !length);
-
2009 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
-
2010 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
-
2011 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
-
2012 size_t
-
2013#if defined(_WIN64)
-
2014 block_size = 0x1F80000;
-
2015#elif defined(_WIN32)
-
2016 block_size = 0x3f00000;
-
2017#else
-
2018 block_size = SSIZE_MAX;
-
2019#endif
-
2020 for (size_t to_read = length;;) {
-
2021#ifdef _WIN32
-
2022 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
-
2023 BOOL succeeded;
-
2024 DWORD num_read;
-
2025 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
-
2026 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
-
2027 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
-
2028 // Error "Insufficient system resources exist to complete the requested service." occurs
-
2029 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
-
2030 block_size = default_block_size;
-
2031 continue;
-
2032 }
-
2033 if (!succeeded) _Unlikely_
-
2034#else
-
2035 ssize_t num_read = static_cast<ssize_t>(std::min<size_t>(to_read, block_size));
-
2036 num_read = read(m_h, data, num_read);
-
2037 if (num_read < 0) _Unlikely_
-
2038#endif
-
2039 {
-
2040 m_state = to_read < length ? state_t::ok : state_t::fail;
-
2041 return length - to_read;
-
2042 }
-
2043 if (!num_read) _Unlikely_ {
-
2044 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
-
2045 return length - to_read;
-
2046 }
-
2047 to_read -= num_read;
-
2048 if (!to_read) {
-
2049 m_state = state_t::ok;
-
2050 return length;
-
2051 }
-
2052 reinterpret_cast<uint8_t*&>(data) += num_read;
-
2053 }
-
2054 }
-
2055
-
2056 virtual _Success_(return != 0) size_t write(
-
2057 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
2058 {
-
2059 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
-
2060 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
-
2061 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
-
2062 constexpr size_t
-
2063#if defined(_WIN64)
-
2064 block_size = 0x1F80000;
-
2065#elif defined(_WIN32)
-
2066 block_size = 0x3f00000;
-
2067#else
-
2068 block_size = SSIZE_MAX;
-
2069#endif
-
2070 for (size_t to_write = length;;) {
-
2071#ifdef _WIN32
-
2072 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
-
2073 BOOL succeeded;
-
2074 DWORD num_written;
-
2075 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
-
2076 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
-
2077 to_write -= num_written;
-
2078 if (!to_write) {
-
2079 m_state = state_t::ok;
-
2080 return length;
-
2081 }
-
2082 reinterpret_cast<const uint8_t*&>(data) += num_written;
-
2083 if (!succeeded) _Unlikely_ {
-
2084 m_state = state_t::fail;
-
2085 return length - to_write;
-
2086 }
-
2087#else
-
2088 ssize_t num_written = write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
-
2089 if (num_written < 0) _Unlikely_ {
-
2090 m_state = state_t::fail;
-
2091 return length - to_write;
-
2092 }
-
2093 to_write -= num_written;
-
2094 if (!to_write) {
-
2095 m_state = state_t::ok;
-
2096 return length;
-
2097 }
-
2098 reinterpret_cast<const uint8_t*&>(data) += num_written;
-
2099#endif
-
2100 }
-
2101 }
-
2102
-
2103 virtual void close()
-
2104 {
-
2105 try {
-
2106 sys_object::close();
-
2107 m_state = state_t::ok;
-
2108 }
-
2109 catch (std::exception) {
-
2110 m_state = state_t::fail;
-
2111 }
-
2112 }
-
2113
-
2114 virtual void flush()
-
2115 {
-
2116#ifdef _WIN32
-
2117 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
-
2118#else
-
2119 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
-
2120#endif
-
2121 }
-
2122 };
-
2123
-
2127 class buffered_sys : public buffer
-
2128 {
-
2129 public:
-
2130 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) :
-
2131 buffer(read_buffer_size, write_buffer_size),
-
2132 m_source(h)
-
2133 {
-
2134 init(m_source);
-
2135 }
-
2136
-
2137 protected:
-
2138 basic_sys m_source;
-
2139 };
-
2140
-
2141#ifdef _WIN32
-
2145 class ISequentialStream : public basic
-
2146 {
-
2147 public:
-
2148 ISequentialStream(_In_::ISequentialStream* source) : m_source(source)
-
2149 {
-
2150 m_source->AddRef();
-
2151 }
-
2152
-
2153 virtual ~ISequentialStream()
-
2154 {
-
2155 m_source->Release();
-
2156 }
-
2157
-
2158 virtual _Success_(return != 0 || length == 0) size_t read(
-
2159 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
2160 {
-
2161 assert(data || !length);
-
2162 for (size_t to_read = length;;) {
-
2163 HRESULT hr;
-
2164 ULONG num_read = 0;
-
2165 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
-
2166 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
-
2167 if (FAILED(hr)) _Unlikely_ {
-
2168 m_state = to_read < length ? state_t::ok : state_t::fail;
-
2169 return length - to_read;
-
2170 }
-
2171 to_read -= num_read;
-
2172 if (hr == S_FALSE) _Unlikely_ {
-
2173 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
-
2174 return length - to_read;
-
2175 }
-
2176 if (!to_read) {
-
2177 m_state = state_t::ok;
-
2178 return length;
-
2179 }
-
2180 reinterpret_cast<uint8_t*&>(data) += num_read;
-
2181 }
-
2182 }
-
2183
-
2184 virtual _Success_(return != 0) size_t write(
-
2185 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
2186 {
-
2187 assert(data || !length);
-
2188 for (size_t to_write = length;;) {
-
2189 HRESULT hr;
-
2190 ULONG num_written = 0;
-
2191 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
-
2192 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
-
2193 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
-
2194 // assume write failed completely.
-
2195 if (FAILED(hr)) _Unlikely_ {
-
2196 m_state = state_t::fail;
-
2197 return length - to_write;
-
2198 }
-
2199 to_write -= num_written;
-
2200 if (!to_write) {
-
2201 m_state = state_t::ok;
-
2202 return length;
-
2203 }
-
2204 reinterpret_cast<const uint8_t*&>(data) += num_written;
-
2205 }
-
2206 }
-
2207
-
2208 protected:
-
2209 ::ISequentialStream* m_source;
-
2210 };
-
2211
-
2212#ifndef WIN32_LEAN_AND_MEAN
-
2216 class asp : public basic
-
2217 {
-
2218 public:
-
2219 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
-
2220 m_request(request),
-
2221 m_response(response)
-
2222 {
-
2223 if (m_request)
-
2224 m_request->AddRef();
-
2225 if (m_response)
-
2226 m_response->AddRef();
-
2227 }
-
2228
-
2229 virtual ~asp()
-
2230 {
-
2231 if (m_request)
-
2232 m_request->Release();
-
2233 if (m_response)
-
2234 m_response->Release();
-
2235 }
-
2236
-
2237 virtual _Success_(return != 0 || length == 0) size_t read(
-
2238 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
2239 {
-
2240 assert(data || !length);
-
2241 if (!m_request) _Unlikely_ {
-
2242 m_state = state_t::fail;
-
2243 return 0;
-
2244 }
-
2245 for (size_t to_read = length;;) {
-
2246 VARIANT var_amount, var_data;
-
2247 V_VT(&var_amount) = VT_I4;
-
2248 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
-
2249 V_VT(&var_data) = VT_EMPTY;
-
2250 HRESULT hr = [&]() {
-
2251 __try { return m_request->BinaryRead(&var_amount, &var_data); }
-
2252 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
-
2253 }();
-
2254 if (FAILED(hr)) _Unlikely_ {
-
2255 m_state = to_read < length ? state_t::ok : state_t::fail;
-
2256 return length - to_read;
-
2257 }
-
2258 assert(V_VT(&var_amount) == VT_I4);
-
2259 assert(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
-
2260 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
-
2261 if (!V_I4(&var_amount)) _Unlikely_ {
-
2262 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
-
2263 return length - to_read;
-
2264 }
-
2265 safearray_accessor<uint8_t> a(sa.get());
-
2266 memcpy(data, a.data(), V_I4(&var_amount));
-
2267 to_read -= V_I4(&var_amount);
-
2268 if (!to_read) {
-
2269 m_state = state_t::ok;
-
2270 return length;
-
2271 }
-
2272 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
-
2273 }
-
2274 }
-
2275
-
2276 virtual _Success_(return != 0) size_t write(
-
2277 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
2278 {
-
2279 if (!m_response) {
-
2280 m_state = state_t::fail;
-
2281 return 0;
-
2282 }
-
2283 for (size_t to_write = length;;) {
-
2284 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
-
2285 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
-
2286 VARIANT var_data;
-
2287 V_VT(&var_data) = VT_BSTR;
-
2288 V_BSTR(&var_data) = bstr_data.get();
-
2289 HRESULT hr = [&]() {
-
2290 __try { return m_response->BinaryWrite(var_data); }
-
2291 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
-
2292 }();
-
2293 if (FAILED(hr)) _Unlikely_ {
-
2294 m_state = state_t::fail;
-
2295 return length - to_write;
-
2296 }
-
2297 to_write -= num_written;
-
2298 if (!to_write) {
-
2299 m_state = state_t::ok;
-
2300 return length;
-
2301 }
-
2302 reinterpret_cast<const uint8_t*&>(data) += num_written;
-
2303 }
-
2304 }
-
2305
-
2306 virtual void close()
-
2307 {
-
2308 if (m_response) {
-
2309 __try { m_response->End(); }
-
2310 __except (EXCEPTION_EXECUTE_HANDLER) {}
-
2311 }
-
2312 m_state = state_t::ok;
-
2313 }
-
2314
-
2315 virtual void flush()
-
2316 {
-
2317 if (m_response) {
-
2318 HRESULT hr;
-
2319 __try { hr = m_response->Flush(); }
-
2320 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
-
2321 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
-
2322 }
-
2323 }
-
2324
-
2325 protected:
-
2326 IRequest* m_request;
-
2327 IResponse* m_response;
-
2328 };
-
2329#endif
+
21#include <objidl.h>
+
22#endif
+
23#include <chrono>
+
24#include <condition_variable>
+
25#include <list>
+
26#include <memory>
+
27#include <string>
+
28#include <thread>
+
29#include <vector>
+
30
+
31#if !defined(SET_FILE_OP_TIMES) && defined(RDAT_BELEZI_CAS_DOSTOPA_VER)
+
32#define SET_FILE_OP_TIMES 1
+
33#pragma message("RDAT_BELEZI_CAS_DOSTOPA_VER is deprecated. Use SET_FILE_OP_TIMES instead.")
+
34#elif !defined(SET_FILE_OP_TIMES)
+
35#define SET_FILE_OP_TIMES 0
+
36#endif
+
37#if !defined(CHECK_STREAM_STATE) && defined(RDAT_NE_PREVERJAJ_STANJA_VER)
+
38#define CHECK_STREAM_STATE 0
+
39#pragma message("RDAT_NE_PREVERJAJ_EOF_VER is deprecated. Use CHECK_STREAM_STATE=0 instead.")
+
40#else
+
41#define CHECK_STREAM_STATE 1
+
42#endif
+
43
+
44namespace stdex
+
45{
+
46 namespace stream
+
47 {
+
51 enum class state_t {
+
52 ok = 0,
+
53 eof,
+
54 fail,
+
55 };
+
56
+
60 using fsize_t = uint64_t;
+
61 constexpr fsize_t fsize_max = UINT64_MAX;
+
62
+
63 constexpr size_t iterate_count = 0x10;
+
64 constexpr size_t default_block_size = 0x10000;
+
65 constexpr wchar_t utf16_bom = L'\ufeff';
+
66 constexpr const char utf8_bom[3] = { '\xef', '\xbb', '\xbf' };
+
67
+
71 class basic
+
72 {
+
73 public:
+
74 basic(_In_ state_t state = state_t::ok) : m_state(state) {}
+
75
+
87 virtual _Success_(return != 0 || length == 0) size_t read(
+
88 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
89 {
+
90 UNREFERENCED_PARAMETER(data);
+
91 UNREFERENCED_PARAMETER(length);
+
92 m_state = state_t::fail;
+
93 return 0;
+
94 }
+
95
+
105 virtual _Success_(return != 0) size_t write(
+
106 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
107 {
+
108 UNREFERENCED_PARAMETER(data);
+
109 UNREFERENCED_PARAMETER(length);
+
110 m_state = state_t::fail;
+
111 return 0;
+
112 }
+
113
+
117 virtual void flush()
+
118 {
+
119 m_state = state_t::ok;
+
120 }
+
121
+
125 virtual void close()
+
126 {
+
127 m_state = state_t::ok;
+
128 }
+
129
+
133 virtual void skip(_In_ fsize_t amount)
+
134 {
+
135 if (amount == 1)
+
136 read_byte();
+
137 else if (amount < iterate_count) {
+
138 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
+
139 read_byte();
+
140 if (!ok()) _Unlikely_
+
141 break;
+
142 }
+
143 }
+
144 else {
+
145 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
+
146 try {
+
147 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
+
148 while (amount) {
+
149 amount -= read_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
+
150 if (!ok()) _Unlikely_
+
151 break;
+
152 }
+
153 }
+
154 catch (std::bad_alloc) { m_state = state_t::fail; }
+
155 }
+
156 }
+
157
+
161 inline state_t state() const { return m_state; };
+
162
+
166 inline bool ok() const { return m_state == state_t::ok; };
+
167
+
175 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
+
176 {
+
177 std::vector<uint8_t> result;
+
178 size_t offset, length;
+
179 offset = 0;
+
180 length = default_block_size;
+
181 while (offset < max_length) {
+
182 length = std::min(length, max_length);
+
183 try { result.resize(length); }
+
184 catch (std::bad_alloc) {
+
185 m_state = state_t::fail;
+
186 return result;
+
187 }
+
188 auto num_read = read_array(result.data() + offset, sizeof(uint8_t), length - offset);
+
189 offset += num_read;
+
190 if (!ok()) _Unlikely_
+
191 break;
+
192 length += default_block_size;
+
193 }
+
194 result.resize(offset);
+
195 return result;
+
196 }
+
197
+
201 inline uint8_t read_byte()
+
202 {
+
203 uint8_t byte;
+
204 if (read_array(&byte, sizeof(byte), 1) == 1)
+
205 return byte;
+
206 throw std::runtime_error("failed to read");
+
207 }
+
208
+
212 void write_byte(_In_ uint8_t byte, _In_ fsize_t amount = 1)
+
213 {
+
214 if (amount == 1)
+
215 write(&byte, sizeof(uint8_t));
+
216 else if (amount < iterate_count) {
+
217 for (size_t i = 0; i < static_cast<size_t>(amount); i++) {
+
218 write(&byte, sizeof(uint8_t));
+
219 if (!ok()) _Unlikely_
+
220 break;
+
221 }
+
222 }
+
223 else {
+
224 size_t block = static_cast<size_t>(std::min<fsize_t>(amount, default_block_size));
+
225 try {
+
226 std::unique_ptr<uint8_t[]> dummy(new uint8_t[block]);
+
227 memset(dummy.get(), byte, block);
+
228 while (amount) {
+
229 amount -= write_array(dummy.get(), sizeof(uint8_t), static_cast<size_t>(std::min<fsize_t>(amount, block)));
+
230 if (!ok()) _Unlikely_
+
231 break;
+
232 }
+
233 }
+
234 catch (std::bad_alloc) { m_state = state_t::fail; }
+
235 }
+
236 }
+
237
+
249 template <class T>
+
250 inline basic& read_data(_Out_ T& data)
+
251 {
+
252 if (!ok()) _Unlikely_ {
+
253 data = 0;
+
254 return *this;
+
255 }
+
256 if (read_array(&data, sizeof(T), 1) == 1)
+
257 LE2HE(&data);
+
258 else {
+
259 data = 0;
+
260 if (ok())
+
261 m_state = state_t::eof;
+
262 }
+
263 return *this;
+
264 }
+
265
+
277 template <class T>
+
278 inline basic& write_data(_In_ const T data)
+
279 {
+
280 if (!ok()) _Unlikely_
+
281 return *this;
+
282#ifdef BIG_ENDIAN
+
283 T data_le = HE2LE(data);
+
284 write(&data_le, sizeof(T));
+
285#else
+
286 write(&data, sizeof(T));
+
287#endif
+
288 return *this;
+
289 }
+
290
+
296 template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>>
+
297 inline size_t readln(_Inout_ std::basic_string<char, _Traits, _Ax>& str)
+
298 {
+
299 str.clear();
+
300 return readln_and_attach(str);
+
301 }
+
302
+
308 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
+
309 inline size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr)
+
310 {
+
311 wstr.clear();
+
312 return readln_and_attach(wstr);
+
313 }
+
314
+
320 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
+
321 size_t readln(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
+
322 {
+
323 if (charset == charset_id::utf16)
+
324 return readln(wstr);
+
325 std::string str;
+
326 readln_and_attach(str);
+
327 wstr.clear();
+
328 str2wstr(wstr, str, charset);
+
329 return wstr.size();
+
330 }
+
331
+
337 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
338 size_t readln_and_attach(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
+
339 {
+
340 bool initial = true;
+
341 _Elem chr, previous = (_Elem)0;
+
342 do {
+
343 read_array(&chr, sizeof(_Elem), 1);
+
344 if (!initial && !(previous == static_cast<_Elem>('\r') && chr == static_cast<_Elem>('\n')))
+
345 str += previous;
+
346 else
+
347 initial = false;
+
348 previous = chr;
+
349 } while (ok() && chr != static_cast<_Elem>('\n'));
+
350 return str.size();
+
351 }
+
352
+
358 template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>>
+
359 size_t readln_and_attach(_Inout_ std::basic_string<wchar_t, _Traits, _Ax>& wstr, _In_ charset_id charset)
+
360 {
+
361 if (charset == charset_id::utf16)
+
362 return readln_and_attach(wstr);
+
363 std::string str;
+
364 readln_and_attach(str);
+
365 str2wstr(wstr, str, charset);
+
366 return wstr.size();
+
367 }
+
368
+
374 size_t read_array(_Out_writes_bytes_(size* count) void* array, _In_ size_t size, _In_ size_t count)
+
375 {
+
376 for (size_t to_read = mul(size, count);;) {
+
377 size_t num_read = read(array, to_read);
+
378 to_read -= num_read;
+
379 if (!to_read)
+
380 return count;
+
381 if (!ok()) _Unlikely_
+
382 return count - to_read / size;
+
383 reinterpret_cast<uint8_t*&>(array) += num_read;
+
384 }
+
385 }
+
386
+
392 inline size_t write_array(_In_reads_bytes_opt_(size* count) const void* array, _In_ size_t size, _In_ size_t count)
+
393 {
+
394 return write(array, mul(size, count)) / size;
+
395 }
+
396
+
406 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 {
+
408 if (!ok()) _Unlikely_
+
409 return 0;
+
410 num_chars = stdex::strnlen(wstr, num_chars);
+
411 if (charset != charset_id::utf16) {
+
412 std::string str(wstr2str(wstr, num_chars, charset));
+
413 return write_array(str.data(), sizeof(char), str.size());
+
414 }
+
415 return write_array(wstr, sizeof(wchar_t), num_chars);
+
416 }
+
417
+
429 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
430 inline basic& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data)
+
431 {
+
432 uint32_t num_chars;
+
433 read_data(num_chars);
+
434 if (!ok()) _Unlikely_ {
+
435 data.clear();
+
436 return *this;
+
437 }
+
438 data.resize(num_chars);
+
439 data.resize(read_array(data.data(), sizeof(_Elem), num_chars));
+
440 return *this;
+
441 }
+
442
+
454 template <class T>
+
455 inline basic& write_str(_In_z_ const T* data)
+
456 {
+
457 // Stream state will be checked in write_data.
+
458 size_t num_chars = stdex::strlen(data);
+
459 if (num_chars > UINT32_MAX)
+
460 throw std::invalid_argument("string too long");
+
461 write_data((uint32_t)num_chars);
+
462 if (!ok()) _Unlikely_
+
463 return *this;
+
464 write_array(data, sizeof(T), num_chars);
+
465 return *this;
+
466 }
+
467
+
468#ifdef _WIN32
+
474 size_t write_sa(_In_ LPSAFEARRAY sa)
+
475 {
+
476 safearray_accessor<void> a(sa);
+
477 long ubound, lbound;
+
478 if (FAILED(SafeArrayGetUBound(sa, 1, &ubound)) ||
+
479 FAILED(SafeArrayGetLBound(sa, 1, &lbound)))
+
480 throw std::invalid_argument("SafeArrayGet[UL]Bound failed");
+
481 return write(a.data(), static_cast<size_t>(ubound) - lbound + 1);
+
482 }
+
483#endif
+
484
+
490 fsize_t write_stream(_Inout_ basic& stream, _In_ fsize_t amount = fsize_max)
+
491 {
+
492 std::unique_ptr<uint8_t[]> data(new uint8_t[static_cast<size_t>(std::min<fsize_t>(amount, default_block_size))]);
+
493 fsize_t num_copied = 0, to_write = amount;
+
494 m_state = state_t::ok;
+
495 while (to_write) {
+
496 size_t num_read = stream.read(data.get(), static_cast<size_t>(std::min<fsize_t>(default_block_size, to_write)));
+
497 size_t num_written = write(data.get(), num_read);
+
498 num_copied += num_written;
+
499 to_write -= num_written;
+
500 if (stream.m_state == state_t::eof) {
+
501 // EOF is not an error.
+
502 m_state = state_t::ok;
+
503 break;
+
504 }
+
505 m_state = stream.m_state;
+
506 if (!ok())
+
507 break;
+
508 }
+
509 return num_copied;
+
510 }
+
511
+
515 void write_charset(_In_ charset_id charset)
+
516 {
+
517 if (charset == charset_id::utf16)
+
518 write_data(utf16_bom);
+
519 else if (charset == charset_id::utf8)
+
520 write_array(utf8_bom, sizeof(utf8_bom), 1);
+
521 }
+
522
+
528 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, ...)
+
529 {
+
530 va_list params;
+
531 va_start(params, locale);
+
532 size_t num_chars = write_vsprintf(format, locale, params);
+
533 va_end(params);
+
534 return num_chars;
+
535 }
+
536
+
542 size_t write_sprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, ...)
+
543 {
+
544 va_list params;
+
545 va_start(params, locale);
+
546 size_t num_chars = write_vsprintf(format, locale, params);
+
547 va_end(params);
+
548 return num_chars;
+
549 }
+
550
+
556 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const char* format, _In_opt_ locale_t locale, _In_ va_list params)
+
557 {
+
558 std::string str;
+
559 str.reserve(default_block_size);
+
560 vappendf(str, format, locale, params);
+
561 return write_array(str.data(), sizeof(char), str.size());
+
562 }
+
563
+
569 size_t write_vsprintf(_In_z_ _Printf_format_string_params_(2) const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list params)
+
570 {
+
571 std::wstring str;
+
572 str.reserve(default_block_size);
+
573 vappendf(str, format, locale, params);
+
574 return write_array(str.data(), sizeof(wchar_t), str.size());
+
575 }
+
576
+
577 inline basic& operator >>(_Out_ int8_t& data) { return read_data(data); }
+
578 inline basic& operator <<(_In_ const int8_t data) { return write_data(data); }
+
579 inline basic& operator >>(_Out_ int16_t& data) { return read_data(data); }
+
580 inline basic& operator <<(_In_ const int16_t data) { return write_data(data); }
+
581 inline basic& operator >>(_Out_ int32_t& data) { return read_data(data); }
+
582 inline basic& operator <<(_In_ const int32_t data) { return write_data(data); }
+
583 inline basic& operator >>(_Out_ int64_t& data) { return read_data(data); }
+
584 inline basic& operator <<(_In_ const int64_t data) { return write_data(data); }
+
585 inline basic& operator >>(_Out_ uint8_t& data) { return read_data(data); }
+
586 inline basic& operator <<(_In_ const uint8_t data) { return write_data(data); }
+
587 inline basic& operator >>(_Out_ uint16_t& data) { return read_data(data); }
+
588 inline basic& operator <<(_In_ const uint16_t data) { return write_data(data); }
+
589 inline basic& operator >>(_Out_ uint32_t& data) { return read_data(data); }
+
590 inline basic& operator <<(_In_ const uint32_t data) { return write_data(data); }
+
591 inline basic& operator >>(_Out_ uint64_t& data) { return read_data(data); }
+
592 inline basic& operator <<(_In_ const uint64_t data) { return write_data(data); }
+
593#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
+
594 inline basic& operator >>(_Out_ size_t& data) { return read_data(data); }
+
595 inline basic& operator <<(_In_ const size_t data) { return write_data(data); }
+
596#endif
+
597 inline basic& operator >>(_Out_ float& data) { return read_data(data); }
+
598 inline basic& operator <<(_In_ const float data) { return write_data(data); }
+
599 inline basic& operator >>(_Out_ double& data) { return read_data(data); }
+
600 inline basic& operator <<(_In_ const double data) { return write_data(data); }
+
601 inline basic& operator >>(_Out_ char& data) { return read_data(data); }
+
602 inline basic& operator <<(_In_ const char data) { return write_data(data); }
+
603#ifdef _NATIVE_WCHAR_T_DEFINED
+
604 inline basic& operator >>(_Out_ wchar_t& data) { return read_data(data); }
+
605 inline basic& operator <<(_In_ const wchar_t data) { return write_data(data); }
+
606#endif
+
607 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
608 inline basic& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& data) { return read_str(data); }
+
609 template <class T>
+
610 inline basic& operator <<(_In_ const T* data) { return write_str(data); }
+
611
+
612 protected:
+
613 state_t m_state;
+
614 };
+
615
+
619 using fpos_t = uint64_t;
+
620 constexpr fpos_t fpos_max = UINT64_MAX;
+
621 constexpr fpos_t fpos_min = 0;
+
622
+
626 using foff_t = int64_t;
+
627 constexpr foff_t foff_max = INT64_MAX;
+
628 constexpr foff_t foff_min = INT64_MIN;
+
629
+
633 enum class seek_t {
+
634#ifdef _WIN32
+
635 beg = FILE_BEGIN,
+
636 cur = FILE_CURRENT,
+
637 end = FILE_END
+
638#else
+
639 beg = SEEK_SET,
+
640 cur = SEEK_CUR,
+
641 end = SEEK_END
+
642#endif
+
643 };
+
644
+
645#if _HAS_CXX20
+
646 using time_point = std::chrono::time_point<std::chrono::file_clock>;
+
647#else
+
648 using time_point = std::chrono::time_point<std::chrono::system_clock>;
+
649#endif
+
650
+
654 class basic_file : virtual public basic
+
655 {
+
656 public:
+
657 virtual std::vector<uint8_t> read_remainder(_In_ size_t max_length = SIZE_MAX)
+
658 {
+
659 size_t length = std::min<size_t>(max_length, static_cast<size_t>(size() - tell()));
+
660 std::vector<uint8_t> result;
+
661 try { result.resize(length); }
+
662 catch (std::bad_alloc) {
+
663 m_state = state_t::fail;
+
664 return result;
+
665 }
+
666 result.resize(read_array(result.data(), sizeof(uint8_t), length));
+
667 return result;
+
668 }
+
669
+
675 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg) = 0;
+
676
+
682 inline fpos_t seekbeg(_In_ fpos_t offset) { return seek(offset, seek_t::beg); }
+
683
+
689 inline fpos_t seekcur(_In_ foff_t offset) { return seek(offset, seek_t::cur); }
+
690
+
696 inline fpos_t seekend(_In_ foff_t offset) { return seek(offset, seek_t::end); }
+
697
+
698 virtual void skip(_In_ fsize_t amount)
+
699 {
+
700 seek(amount, seek_t::cur);
+
701 }
+
702
+
709 virtual fpos_t tell() const = 0;
+
710
+
714 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
+
715 {
+
716 UNREFERENCED_PARAMETER(offset);
+
717 UNREFERENCED_PARAMETER(length);
+
718 throw std::exception("not implemented");
+
719 }
+
720
+
724 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
+
725 {
+
726 UNREFERENCED_PARAMETER(offset);
+
727 UNREFERENCED_PARAMETER(length);
+
728 throw std::exception("not implemented");
+
729 }
+
730
+
735 virtual fsize_t size() = 0;
+
736
+
740 virtual void truncate() = 0;
+
741
+
745 virtual time_point ctime() const
+
746 {
+
747 return time_point::min();
+
748 }
+
749
+
753 virtual time_point atime() const
+
754 {
+
755 return time_point::min();
+
756 }
+
757
+
761 virtual time_point mtime() const
+
762 {
+
763 return time_point::min();
+
764 }
+
765
+
769 virtual void set_ctime(time_point date)
+
770 {
+
771 UNREFERENCED_PARAMETER(date);
+
772 throw std::exception("not implemented");
+
773 }
+
774
+
778 virtual void set_atime(time_point date)
+
779 {
+
780 UNREFERENCED_PARAMETER(date);
+
781 throw std::exception("not implemented");
+
782 }
+
783
+
787 virtual void set_mtime(time_point date)
+
788 {
+
789 UNREFERENCED_PARAMETER(date);
+
790 throw std::exception("not implemented");
+
791 }
+
792
+
793#ifdef _WIN32
+
797 LPSAFEARRAY read_sa()
+
798 {
+
799 assert(size() <= SIZE_MAX);
+
800 size_t length = static_cast<size_t>(size());
+
801 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(SafeArrayCreateVector(VT_UI1, 0, (ULONG)length));
+
802 if (!sa)
+
803 throw std::runtime_error("SafeArrayCreateVector failed");
+
804 safearray_accessor<void> a(sa.get());
+
805 if (seek(0) != 0)
+
806 throw std::runtime_error("failed to seek");
+
807 if (read_array(a.data(), 1, length) != length)
+
808 throw std::runtime_error("failed to read");
+
809 return sa.release();
+
810 }
+
811#endif
+
812
+
818 charset_id read_charset(_In_ charset_id default_charset = charset_id::default)
+
819 {
+
820 if (seek(0) != 0)
+
821 throw std::runtime_error("failed to seek");
+
822 wchar_t id_utf16;
+
823 read_array(&id_utf16, sizeof(wchar_t), 1);
+
824 if (!ok()) _Unlikely_
+
825 return default_charset;
+
826 if (id_utf16 == utf16_bom)
+
827 return charset_id::utf16;
+
828
+
829 if (seek(0) != 0)
+
830 throw std::runtime_error("failed to seek");
+
831 char id_utf8[3] = { 0 };
+
832 read_array(id_utf8, sizeof(id_utf8), 1);
+
833 if (!ok()) _Unlikely_
+
834 return default_charset;
+
835 if (strncmp(id_utf8, _countof(id_utf8), utf8_bom, _countof(utf8_bom)) == 0)
+
836 return charset_id::utf8;
+
837
+
838 if (seek(0) != 0)
+
839 throw std::runtime_error("failed to seek");
+
840 return default_charset;
+
841 }
+
842 };
+
843
+
847 class converter : public basic
+
848 {
+
849 protected:
+
850 explicit converter() :
+
851 basic(state_t::fail),
+
852 m_source(nullptr)
+
853 {}
+
854
+
855 void init(_Inout_ basic& source)
+
856 {
+
857 m_state = source.state();
+
858 m_source = &source;
+
859 }
+
860
+
861 public:
+
862 converter(_Inout_ basic& source) :
+
863 basic(source.state()),
+
864 m_source(&source)
+
865 {}
+
866
+
867 virtual _Success_(return != 0 || length == 0) size_t read(
+
868 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
869 {
+
870 size_t num_read = m_source->read(data, length);
+
871 m_state = m_source->state();
+
872 return num_read;
+
873 }
+
874
+
875 virtual _Success_(return != 0) size_t write(
+
876 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
877 {
+
878 size_t num_written = m_source->write(data, length);
+
879 m_state = m_source->state();
+
880 return num_written;
+
881 }
+
882
+
883 virtual void close()
+
884 {
+
885 m_source->close();
+
886 m_state = m_source->state();
+
887 }
+
888
+
889 virtual void flush()
+
890 {
+
891 m_source->flush();
+
892 m_state = m_source->state();
+
893 }
+
894
+
895 protected:
+
896 basic* m_source;
+
897 };
+
898
+
902 class replicator : public basic
+
903 {
+
904 public:
+
905 virtual ~replicator()
+
906 {
+
907 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
908 auto _w = w->get();
+
909 {
+
910 const std::lock_guard<std::mutex> lk(_w->mutex);
+
911 _w->op = worker::op_t::quit;
+
912 }
+
913 _w->cv.notify_one();
+
914 }
+
915 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w)
+
916 w->get()->thread.join();
+
917 }
+
918
+
922 void push_back(_In_ basic* source)
+
923 {
+
924 m_workers.push_back(std::unique_ptr<worker>(new worker(source)));
+
925 }
+
926
+
930 void remove(basic* source)
+
931 {
+
932 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
933 auto _w = w->get();
+
934 if (_w->source == source) {
+
935 {
+
936 const std::lock_guard<std::mutex> lk(_w->mutex);
+
937 _w->op = worker::op_t::quit;
+
938 }
+
939 _w->cv.notify_one();
+
940 _w->thread.join();
+
941 m_workers.erase(w);
+
942 return;
+
943 }
+
944 }
+
945 }
+
946
+
947 virtual _Success_(return != 0) size_t write(
+
948 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
949 {
+
950 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
951 auto _w = w->get();
+
952 {
+
953 const std::lock_guard<std::mutex> lk(_w->mutex);
+
954 _w->op = worker::op_t::write;
+
955 _w->data = data;
+
956 _w->length = length;
+
957 }
+
958 _w->cv.notify_one();
+
959 }
+
960 size_t num_written = length;
+
961 m_state = state_t::ok;
+
962 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
963 auto _w = w->get();
+
964 std::unique_lock<std::mutex> lk(_w->mutex);
+
965 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
+
966 if (_w->num_written < num_written)
+
967 num_written = _w->num_written;
+
968 if (ok() && !_w->source->ok())
+
969 m_state = _w->source->state();
+
970 }
+
971 return num_written;
+
972 }
+
973
+
974 virtual void close()
+
975 {
+
976 foreach_worker(worker::op_t::close);
+
977 }
+
978
+
979 virtual void flush()
+
980 {
+
981 foreach_worker(worker::op_t::flush);
+
982 }
+
983
+
984 protected:
+
985 class worker
+
986 {
+
987 public:
+
988 worker(_In_ basic* _source) :
+
989 source(_source),
+
990 op(op_t::noop),
+
991 data(nullptr),
+
992 length(0),
+
993 num_written(0),
+
994 thread(process_op, std::ref(*this))
+
995 {}
+
996
+
997 protected:
+
998 static void process_op(_Inout_ worker& w)
+
999 {
+
1000 for (;;) {
+
1001 std::unique_lock<std::mutex> lk(w.mutex);
+
1002 w.cv.wait(lk, [&] {return w.op != op_t::noop; });
+
1003 switch (w.op) {
+
1004 case op_t::quit:
+
1005 return;
+
1006 case op_t::write:
+
1007 w.num_written = w.source->write(w.data, w.length);
+
1008 break;
+
1009 case op_t::close:
+
1010 w.source->close();
+
1011 break;
+
1012 case op_t::flush:
+
1013 w.source->flush();
+
1014 break;
+
1015 }
+
1016 w.op = op_t::noop;
+
1017 lk.unlock();
+
1018 w.cv.notify_one();
+
1019 }
+
1020 }
+
1021
+
1022 public:
+
1023 basic* source;
+
1024 enum class op_t {
+
1025 noop = 0,
+
1026 quit,
+
1027 write,
+
1028 close,
+
1029 flush,
+
1030 } op;
+
1031 const void* data;
+
1032 size_t length;
+
1033 size_t num_written;
+
1034 std::mutex mutex;
+
1035 std::condition_variable cv;
+
1036 std::thread thread;
+
1037 };
+
1038
+
1039 void foreach_worker(_In_ worker::op_t op)
+
1040 {
+
1041 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
1042 auto _w = w->get();
+
1043 {
+
1044 const std::lock_guard<std::mutex> lk(_w->mutex);
+
1045 _w->op = op;
+
1046 }
+
1047 _w->cv.notify_one();
+
1048 }
+
1049 m_state = state_t::ok;
+
1050 for (auto w = m_workers.begin(), w_end = m_workers.end(); w != w_end; ++w) {
+
1051 auto _w = w->get();
+
1052 std::unique_lock<std::mutex> lk(_w->mutex);
+
1053 _w->cv.wait(lk, [&] {return _w->op == worker::op_t::noop; });
+
1054 if (ok())
+
1055 m_state = _w->source->state();
+
1056 }
+
1057 }
+
1058
+
1059 std::list<std::unique_ptr<worker>> m_workers;
+
1060 };
+
1061
+
1062 constexpr size_t default_async_limit = 0x100000;
+
1063
+
1069 template <size_t CAPACITY = default_async_limit>
+
1070 class async_reader : public converter
+
1071 {
+
1072 public:
+
1073 async_reader(_Inout_ basic& source) :
+
1074 converter(source),
+
1075 m_worker(process, std::ref(*this))
+
1076 {}
+
1077
+
1078 virtual ~async_reader()
+
1079 {
+
1080 m_ring.quit();
+
1081 m_worker.join();
+
1082 }
+
1083
+
1084#pragma warning(suppress: 6101) // See [1] below
+
1085 virtual _Success_(return != 0 || length == 0) size_t read(
+
1086 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1087 {
+
1088 assert(data || !length);
+
1089 for (size_t to_read = length;;) {
+
1090 uint8_t* ptr; size_t num_read;
+
1091 std::tie(ptr, num_read) = m_ring.front();
+
1092 if (!ptr) _Unlikely_ {
+
1093 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
+
1094 m_state = to_read < length || !length ? state_t::ok : m_source->state();
+
1095 return length - to_read;
+
1096 }
+
1097 if (to_read < num_read)
+
1098 num_read = to_read;
+
1099 memcpy(data, ptr, num_read);
+
1100 m_ring.pop(num_read);
+
1101 to_read -= num_read;
+
1102 if (!to_read) {
+
1103 m_state = state_t::ok;
+
1104 return length;
+
1105 }
+
1106 reinterpret_cast<uint8_t*&>(data) += num_read;
+
1107 }
+
1108 }
+
1109
+
1110 protected:
+
1111 static void process(_Inout_ async_reader& w)
+
1112 {
+
1113 for (;;) {
+
1114 uint8_t* ptr; size_t num_write;
+
1115 std::tie(ptr, num_write) = w.m_ring.back();
+
1116 if (!ptr) _Unlikely_
+
1117 break;
+
1118 num_write = w.m_source->read(ptr, num_write);
+
1119 w.m_ring.push(num_write);
+
1120 if (!w.m_source->ok()) {
+
1121 w.m_ring.quit();
+
1122 break;
+
1123 }
+
1124 }
+
1125 }
+
1126
+
1127 protected:
+
1128 ring<uint8_t, CAPACITY> m_ring;
+
1129 std::thread m_worker;
+
1130 };
+
1131
+
1137 template <size_t CAPACITY = default_async_limit>
+
1138 class async_writer : public converter
+
1139 {
+
1140 public:
+
1141 async_writer(_Inout_ basic& source) :
+
1142 converter(source),
+
1143 m_worker(process, std::ref(*this))
+
1144 {}
+
1145
+
1146 virtual ~async_writer()
+
1147 {
+
1148 m_ring.quit();
+
1149 m_worker.join();
+
1150 }
+
1151
+
1152 virtual _Success_(return != 0) size_t write(
+
1153 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1154 {
+
1155 assert(data || !length);
+
1156 for (size_t to_write = length;;) {
+
1157 uint8_t* ptr; size_t num_write;
+
1158 std::tie(ptr, num_write) = m_ring.back();
+
1159 if (!ptr) _Unlikely_ {
+
1160 m_state = state_t::fail;
+
1161 return length - to_write;
+
1162 }
+
1163 if (to_write < num_write)
+
1164 num_write = to_write;
+
1165 memcpy(ptr, data, num_write);
+
1166 m_ring.push(num_write);
+
1167 to_write -= num_write;
+
1168 if (!to_write) {
+
1169 m_state = state_t::ok;
+
1170 return length;
+
1171 }
+
1172 reinterpret_cast<const uint8_t*&>(data) += num_write;
+
1173 }
+
1174 }
+
1175
+
1176 virtual void flush()
+
1177 {
+
1178 m_ring.sync();
+
1179 converter::flush();
+
1180 }
+
1181
+
1182 protected:
+
1183 static void process(_Inout_ async_writer& w)
+
1184 {
+
1185 for (;;) {
+
1186 uint8_t* ptr; size_t num_read;
+
1187 std::tie(ptr, num_read) = w.m_ring.front();
+
1188 if (!ptr)
+
1189 break;
+
1190 num_read = w.m_source->write(ptr, num_read);
+
1191 w.m_ring.pop(num_read);
+
1192 if (!w.m_source->ok()) {
+
1193 w.m_ring.quit();
+
1194 break;
+
1195 }
+
1196 }
+
1197 }
+
1198
+
1199 protected:
+
1200 ring<uint8_t, CAPACITY> m_ring;
+
1201 std::thread m_worker;
+
1202 };
+
1203
+
1204 constexpr size_t default_buffer_size = 0x400;
+
1205
+
1209 class buffer : public converter
+
1210 {
+
1211 protected:
+
1212 explicit buffer(_In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
+
1213 converter(),
+
1214 m_read_buffer(read_buffer_size),
+
1215 m_write_buffer(write_buffer_size)
+
1216 {}
+
1217
+
1218 public:
+
1219 buffer(_Inout_ basic& source, _In_ size_t read_buffer_size = default_buffer_size, _In_ size_t write_buffer_size = default_buffer_size) :
+
1220 converter(source),
+
1221 m_read_buffer(read_buffer_size),
+
1222 m_write_buffer(write_buffer_size)
+
1223 {}
+
1224
+
1225 virtual ~buffer()
+
1226 {
+
1227 if (m_source)
+
1228 flush_write();
+
1229 }
+
1230
+
1231 virtual _Success_(return != 0 || length == 0) size_t read(
+
1232 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1233 {
+
1234 assert(data || !length);
+
1235 for (size_t to_read = length;;) {
+
1236 size_t buffer_size = m_read_buffer.tail - m_read_buffer.head;
+
1237 if (to_read <= buffer_size) {
+
1238 memcpy(data, m_read_buffer.data + m_read_buffer.head, to_read);
+
1239 m_read_buffer.head += to_read;
+
1240 m_state = state_t::ok;
+
1241 return length;
+
1242 }
+
1243 if (buffer_size) {
+
1244 memcpy(data, m_read_buffer.data + m_read_buffer.head, buffer_size);
+
1245 reinterpret_cast<uint8_t*&>(data) += buffer_size;
+
1246 to_read -= buffer_size;
+
1247 }
+
1248 m_read_buffer.head = 0;
+
1249 if (to_read > m_read_buffer.capacity) {
+
1250 // When needing to read more data than buffer capacity, bypass the buffer.
+
1251 m_read_buffer.tail = 0;
+
1252 to_read -= m_source->read(data, to_read);
+
1253 m_state = to_read < length ? state_t::ok : m_source->state();
+
1254 return length - to_read;
+
1255 }
+
1256 m_read_buffer.tail = m_source->read(m_read_buffer.data, m_read_buffer.capacity);
+
1257 if (m_read_buffer.tail < m_read_buffer.capacity && m_read_buffer.tail < to_read) _Unlikely_ {
+
1258 memcpy(data, m_read_buffer.data, m_read_buffer.tail);
+
1259 m_read_buffer.head = m_read_buffer.tail;
+
1260 to_read -= m_read_buffer.tail;
+
1261 m_state = to_read < length ? state_t::ok : m_source->state();
+
1262 return length - to_read;
+
1263 }
+
1264 }
+
1265 }
+
1266
+
1267 virtual _Success_(return != 0) size_t write(
+
1268 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1269 {
+
1270 assert(data || !length);
+
1271 if (!length) _Unlikely_ {
+
1272 // Pass null writes (zero-byte length). Null write operations have special meaning with with Windows pipes.
+
1273 flush_write();
+
1274 if (!ok()) _Unlikely_
+
1275 return 0;
+
1276 m_source->write(nullptr, 0);
+
1277 m_state = m_source->state();
+
1278 return 0;
+
1279 }
+
1280
+
1281 for (size_t to_write = length;;) {
+
1282 size_t available_buffer = m_write_buffer.capacity - m_write_buffer.tail;
+
1283 if (to_write <= available_buffer) {
+
1284 memcpy(m_write_buffer.data + m_write_buffer.tail, data, to_write);
+
1285 m_write_buffer.tail += to_write;
+
1286 m_state = state_t::ok;
+
1287 return length;
+
1288 }
+
1289 if (available_buffer) {
+
1290 memcpy(m_write_buffer.data + m_write_buffer.tail, data, available_buffer);
+
1291 reinterpret_cast<const uint8_t*&>(data) += available_buffer;
+
1292 to_write -= available_buffer;
+
1293 m_write_buffer.tail += available_buffer;
+
1294 }
+
1295 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
+
1296 if (buffer_size) {
+
1297 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
+
1298 m_state = m_source->state();
+
1299 if (m_write_buffer.head == m_write_buffer.tail)
+
1300 m_write_buffer.head = m_write_buffer.tail = 0;
+
1301 else
+
1302 return length - to_write;
+
1303 }
+
1304 if (to_write > m_write_buffer.capacity) {
+
1305 // When needing to write more data than buffer capacity, bypass the buffer.
+
1306 to_write -= m_source->write(data, to_write);
+
1307 m_state = m_source->state();
+
1308 return length - to_write;
+
1309 }
+
1310 }
+
1311 }
+
1312
+
1313 virtual void flush()
+
1314 {
+
1315 flush_write();
+
1316 if (ok())
+
1317 converter::flush();
+
1318 }
+
1319
+
1320 protected:
+
1321 void flush_write()
+
1322 {
+
1323 size_t buffer_size = m_write_buffer.tail - m_write_buffer.head;
+
1324 if (buffer_size) {
+
1325 m_write_buffer.head += m_source->write(m_write_buffer.data + m_write_buffer.head, buffer_size);
+
1326 if (m_write_buffer.head == m_write_buffer.tail) {
+
1327 m_write_buffer.head = 0;
+
1328 m_write_buffer.tail = 0;
+
1329 }
+
1330 else {
+
1331 m_state = m_source->state();
+
1332 return;
+
1333 }
+
1334 }
+
1335 m_state = state_t::ok;
+
1336 }
+
1337
+
1338 struct buffer_t {
+
1339 uint8_t* data;
+
1340 size_t head, tail, capacity;
+
1341
+
1342 buffer_t(_In_ size_t buffer_size) :
+
1343 head(0),
+
1344 tail(0),
+
1345 capacity(buffer_size),
+
1346 data(buffer_size ? new uint8_t[buffer_size] : nullptr)
+
1347 {}
+
1348
+
1349 ~buffer_t()
+
1350 {
+
1351 if (data)
+
1352 delete[] data;
+
1353 }
+
1354 } m_read_buffer, m_write_buffer;
+
1355 };
+
1356
+
1360 class limiter : public converter
+
1361 {
+
1362 public:
+
1363 limiter(_Inout_ basic& source, _In_ fsize_t _read_limit = 0, _In_ fsize_t _write_limit = 0) :
+
1364 converter(source),
+
1365 read_limit(_read_limit),
+
1366 write_limit(_write_limit)
+
1367 {}
+
1368
+
1369 virtual _Success_(return != 0 || length == 0) size_t read(
+
1370 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1371 {
+
1372 size_t num_read;
+
1373 if (read_limit == fsize_max) {
+
1374 num_read = m_source->read(data, length);
+
1375 m_state = m_source->state();
+
1376 }
+
1377 else if (length <= read_limit) {
+
1378 num_read = m_source->read(data, length);
+
1379 m_state = m_source->state();
+
1380 read_limit -= num_read;
+
1381 }
+
1382 else if (length && !read_limit) {
+
1383 num_read = 0;
+
1384 m_state = state_t::eof;
+
1385 }
+
1386 else {
+
1387 num_read = m_source->read(data, static_cast<size_t>(read_limit));
+
1388 m_state = m_source->state();
+
1389 read_limit -= num_read;
+
1390 }
+
1391 return num_read;
+
1392 }
+
1393
+
1394 virtual _Success_(return != 0) size_t write(
+
1395 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1396 {
+
1397 size_t num_written;
+
1398 if (write_limit == fsize_max) {
+
1399 num_written = m_source->write(data, length);
+
1400 m_state = m_source->state();
+
1401 }
+
1402 else if (length <= write_limit) {
+
1403 num_written = m_source->write(data, length);
+
1404 m_state = m_source->state();
+
1405 write_limit -= num_written;
+
1406 }
+
1407 else if (length && !write_limit) {
+
1408 num_written = 0;
+
1409 m_state = state_t::fail;
+
1410 }
+
1411 else {
+
1412 num_written = m_source->write(data, static_cast<size_t>(write_limit));
+
1413 m_state = m_source->state();
+
1414 write_limit -= num_written;
+
1415 }
+
1416 return num_written;
+
1417 }
+
1418
+
1419 public:
+
1420 fsize_t
+
1421 read_limit,
+
1422 write_limit;
+
1423 };
+
1424
+
1428 class window : public limiter
+
1429 {
+
1430 public:
+
1431 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) :
+
1432 limiter(source, read_limit, write_limit),
+
1433 read_offset(_read_offset),
+
1434 write_offset(_write_offset)
+
1435 {}
+
1436
+
1437 virtual _Success_(return != 0 || length == 0) size_t read(
+
1438 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1439 {
+
1440 if (read_offset) {
+
1441 m_source->skip(read_offset);
+
1442 m_state = m_source->state();
+
1443 if (!ok()) _Unlikely_
+
1444 return 0;
+
1445 read_offset = 0;
+
1446 }
+
1447 size_t num_read;
+
1448 if (read_limit == fsize_max) {
+
1449 num_read = m_source->read(data, length);
+
1450 m_state = m_source->state();
+
1451 }
+
1452 else if (length <= read_limit) {
+
1453 num_read = m_source->read(data, length);
+
1454 m_state = m_source->state();
+
1455 read_limit -= num_read;
+
1456 }
+
1457 else if (length && !read_limit) {
+
1458 num_read = 0;
+
1459 m_source->skip(length);
+
1460 m_state = state_t::eof;
+
1461 }
+
1462 else {
+
1463 num_read = m_source->read(data, static_cast<size_t>(read_limit));
+
1464 m_state = m_source->state();
+
1465 read_limit -= num_read;
+
1466 }
+
1467 return num_read;
+
1468 }
+
1469
+
1470 virtual _Success_(return != 0) size_t write(
+
1471 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1472 {
+
1473 size_t num_skipped, num_written;
+
1474 if (length <= write_offset) {
+
1475 write_offset -= length;
+
1476 m_state = state_t::ok;
+
1477 return length;
+
1478 }
+
1479 if (write_offset) {
+
1480 reinterpret_cast<const uint8_t*&>(data) += static_cast<size_t>(write_offset);
+
1481 length -= static_cast<size_t>(write_offset);
+
1482 num_skipped = static_cast<size_t>(write_offset);
+
1483 write_offset = 0;
+
1484 }
+
1485 else
+
1486 num_skipped = 0;
+
1487 if (write_limit == fsize_max) {
+
1488 num_written = m_source->write(data, length);
+
1489 m_state = m_source->state();
+
1490 }
+
1491 else if (length <= write_limit) {
+
1492 num_written = m_source->write(data, length);
+
1493 m_state = m_source->state();
+
1494 write_limit -= num_written;
+
1495 }
+
1496 else if (length && !write_limit) {
+
1497 num_skipped += length;
+
1498 num_written = 0;
+
1499 m_state = state_t::ok;
+
1500 }
+
1501 else {
+
1502 num_skipped += length - static_cast<size_t>(write_limit);
+
1503 num_written = m_source->write(data, static_cast<size_t>(write_limit));
+
1504 m_state = m_source->state();
+
1505 write_limit -= num_written;
+
1506 }
+
1507 return num_skipped + num_written;
+
1508 }
+
1509
+
1510 public:
+
1511 fpos_t
+
1512 read_offset,
+
1513 write_offset;
+
1514 };
+
1515
+
1519 class file_window : public basic_file
+
1520 {
+
1521 public:
+
1522 file_window(_Inout_ basic_file& source, fpos_t offset = 0, fsize_t length = 0) :
+
1523 basic(source.state()),
+
1524 m_source(source),
+
1525 m_offset(source.tell()),
+
1526 m_region(offset, offset + length)
+
1527 {}
+
1528
+
1529 virtual _Success_(return != 0 || length == 0) size_t read(
+
1530 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1531 {
+
1532 assert(data || !length);
+
1533 if (m_region.contains(m_offset)) {
+
1534 size_t num_read = m_source.read(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
+
1535 m_state = m_source.state();
+
1536 m_offset += num_read;
+
1537 return num_read;
+
1538 }
+
1539 m_state = length ? state_t::eof : state_t::ok;
+
1540 return 0;
+
1541 }
+
1542
+
1543 virtual _Success_(return != 0) size_t write(
+
1544 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1545 {
+
1546 assert(data || !length);
+
1547 if (m_region.contains(m_offset)) {
+
1548 size_t num_written = m_source.write(data, static_cast<size_t>(std::min<fpos_t>(length, m_region.end - m_offset)));
+
1549 m_state = m_source.state();
+
1550 m_offset += num_written;
+
1551 return num_written;
+
1552 }
+
1553 m_state = state_t::fail;
+
1554 return 0;
+
1555 }
+
1556
+
1557 virtual void close()
+
1558 {
+
1559 m_source.close();
+
1560 m_state = m_source.state();
+
1561 }
+
1562
+
1563 virtual void flush()
+
1564 {
+
1565 m_source.flush();
+
1566 m_state = m_source.state();
+
1567 }
+
1568
+
1569 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
+
1570 {
+
1571 m_offset = m_source.seek(offset, how);
+
1572 m_state = m_source.state();
+
1573 return ok() ? m_offset - m_region.start : fpos_max;
+
1574 }
+
1575
+
1576 virtual void skip(_In_ fsize_t amount)
+
1577 {
+
1578 m_source.skip(amount);
+
1579 m_state = m_source.state();
+
1580 }
+
1581
+
1582 virtual fpos_t tell() const
+
1583 {
+
1584 fpos_t offset = m_source.tell();
+
1585 return m_region.contains(offset) ? offset - m_region.start : fpos_max;
+
1586 }
+
1587
+
1588 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
+
1589 {
+
1590 if (m_region.contains(offset)) {
+
1591 m_source.lock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
+
1592 m_state = m_source.state();
+
1593 }
+
1594 else
+
1595 m_state = state_t::fail;
+
1596 }
+
1597
+
1598 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
+
1599 {
+
1600 if (m_region.contains(offset)) {
+
1601 m_source.unlock(m_region.start + offset, std::min<fsize_t>(length, m_region.end - offset));
+
1602 m_state = m_source.state();
+
1603 }
+
1604 else
+
1605 m_state = state_t::fail;
+
1606 }
+
1607
+
1608 virtual fsize_t size()
+
1609 {
+
1610 return m_region.size();
+
1611 }
+
1612
+
1613 virtual void truncate()
+
1614 {
+
1615 m_state = state_t::fail;
+
1616 }
+
1617
+
1618 protected:
+
1619 basic_file& m_source;
+
1620 fpos_t m_offset;
+
1621 interval<fpos_t> m_region;
+
1622 };
+
1623
+
1624 constexpr size_t default_cache_size = 0x1000;
+
1625
+
1629 class cache : public basic_file
+
1630 {
+
1631 protected:
+
1632 explicit cache(_In_ size_t cache_size = default_cache_size) :
+
1633 basic(state_t::fail),
+
1634 m_source(nullptr),
+
1635 m_cache(cache_size),
+
1636 m_offset(0)
+
1637#if SET_FILE_OP_TIMES
+
1638 , m_atime(time_point::min()),
+
1639 m_mtime(time_point::min())
+
1640#endif
+
1641 {}
+
1642
+
1643 void init(_Inout_ basic_file& source)
+
1644 {
+
1645 m_state = source.state();
+
1646 m_source = &source;
+
1647 m_offset = source.tell();
+
1648#if SET_FILE_OP_TIMES
+
1649 m_atime = source.atime();
+
1650 m_mtime = source.mtime();
+
1651#endif
+
1652 }
+
1653
+
1654 public:
+
1655 cache(_Inout_ basic_file& source, _In_ size_t cache_size = default_cache_size) :
+
1656 basic(source.state()),
+
1657 m_source(&source),
+
1658 m_cache(cache_size),
+
1659 m_offset(source.tell())
+
1660#if SET_FILE_OP_TIMES
+
1661 , m_atime(source.atime()),
+
1662 m_mtime(source.mtime())
+
1663#endif
+
1664 {}
+
1665
+
1666 virtual ~cache() noexcept(false)
+
1667 {
+
1668 if (m_source) {
+
1669 flush_cache();
+
1670 if (!ok()) _Unlikely_
+
1671 throw std::runtime_error("cache flush failed"); // Data loss occured
+
1672 m_source->seek(m_offset);
+
1673 }
+
1674 }
+
1675
+
1676 virtual _Success_(return != 0 || length == 0) size_t read(
+
1677 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
1678 {
+
1679 assert(data || !length);
+
1680#if SET_FILE_OP_TIMES
+
1681 m_atime = time_point::now();
+
1682#endif
+
1683 for (size_t to_read = length;;) {
+
1684 if (m_cache.status != cache_t::cache_t::status_t::empty) {
+
1685 if (m_cache.region.contains(m_offset)) {
+
1686 size_t remaining_cache = static_cast<size_t>(m_cache.region.end - m_offset);
+
1687 if (to_read <= remaining_cache) {
+
1688 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), to_read);
+
1689 m_offset += to_read;
+
1690 m_state = state_t::ok;
+
1691 return length;
+
1692 }
+
1693 memcpy(data, m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), remaining_cache);
+
1694 reinterpret_cast<uint8_t*&>(data) += remaining_cache;
+
1695 to_read -= remaining_cache;
+
1696 m_offset += remaining_cache;
+
1697 }
+
1698 flush_cache();
+
1699 if (!ok()) _Unlikely_ {
+
1700 if (to_read < length)
+
1701 m_state = state_t::ok;
+
1702 return length - to_read;
+
1703 }
+
1704 }
+
1705 {
+
1706 fpos_t end_max = m_offset + to_read;
+
1707 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
+
1708 // Read spans multiple cache blocks. Bypass cache to the last block.
+
1709 m_source->seek(m_offset);
+
1710 if (!m_source->ok()) _Unlikely_ {
+
1711 m_state = to_read < length ? state_t::ok : state_t::fail;
+
1712 return length - to_read;
+
1713 }
+
1714 size_t num_read = m_source->read(data, to_read - static_cast<size_t>(end_max % m_cache.capacity));
+
1715 m_offset += num_read;
+
1716 to_read -= num_read;
+
1717 if (!to_read) {
+
1718 m_state = state_t::ok;
+
1719 return length;
+
1720 }
+
1721 reinterpret_cast<uint8_t*&>(data) += num_read;
+
1722 m_state = m_source->state();
+
1723 if (!ok()) {
+
1724 if (to_read < length)
+
1725 m_state = state_t::ok;
+
1726 return length - to_read;
+
1727 }
+
1728 }
+
1729 }
+
1730 load_cache(m_offset);
+
1731 if (!ok() || m_cache.region.end <= m_offset) _Unlikely_ {
+
1732 m_state = to_read < length ? state_t::ok : state_t::fail;
+
1733 return length - to_read;
+
1734 }
+
1735 }
+
1736 }
+
1737
+
1738 virtual _Success_(return != 0) size_t write(
+
1739 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
1740 {
+
1741 assert(data || !length);
+
1742#if SET_FILE_OP_TIMES
+
1743 m_atime = m_mtime = time_point::now();
+
1744#endif
+
1745 for (size_t to_write = length;;) {
+
1746 if (m_cache.status != cache_t::cache_t::status_t::empty) {
+
1747 fpos_t end_max = m_cache.region.start + m_cache.capacity;
+
1748 if (m_cache.region.start <= m_offset && m_offset < end_max) {
+
1749 size_t remaining_cache = static_cast<size_t>(end_max - m_offset);
+
1750 if (to_write <= remaining_cache) {
+
1751 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, to_write);
+
1752 m_offset += to_write;
+
1753 m_cache.status = cache_t::cache_t::status_t::dirty;
+
1754 m_cache.region.end = std::max(m_cache.region.end, m_offset);
+
1755 m_state = state_t::ok;
+
1756 return length;
+
1757 }
+
1758 memcpy(m_cache.data + static_cast<size_t>(m_offset - m_cache.region.start), data, remaining_cache);
+
1759 reinterpret_cast<const uint8_t*&>(data) += remaining_cache;
+
1760 to_write -= remaining_cache;
+
1761 m_offset += remaining_cache;
+
1762 m_cache.status = cache_t::cache_t::status_t::dirty;
+
1763 m_cache.region.end = end_max;
+
1764 }
+
1765 flush_cache();
+
1766 if (!ok()) _Unlikely_
+
1767 return length - to_write;
+
1768 }
+
1769 {
+
1770 fpos_t end_max = m_offset + to_write;
+
1771 if (m_offset / m_cache.capacity < end_max / m_cache.capacity) {
+
1772 // Write spans multiple cache blocks. Bypass cache to the last block.
+
1773 m_source->seek(m_offset);
+
1774 if (!ok()) _Unlikely_
+
1775 return length - to_write;
+
1776 size_t num_written = m_source->write(data, to_write - static_cast<size_t>(end_max % m_cache.capacity));
+
1777 m_offset += num_written;
+
1778 m_state = m_source->state();
+
1779 to_write -= num_written;
+
1780 if (!to_write || !ok())
+
1781 return length - to_write;
+
1782 reinterpret_cast<const uint8_t*&>(data) += num_written;
+
1783 }
+
1784 }
+
1785 load_cache(m_offset);
+
1786 if (!ok()) _Unlikely_
+
1787 return length - to_write;
+
1788 }
+
1789 }
+
1790
+
1791 virtual void close()
+
1792 {
+
1793 invalidate_cache();
+
1794 if (!ok()) _Unlikely_
+
1795 throw std::runtime_error("cache flush failed"); // Data loss occured
+
1796 m_source->close();
+
1797 m_state = m_source->state();
+
1798 }
+
1799
+
1800 virtual void flush()
+
1801 {
+
1802#if SET_FILE_OP_TIMES
+
1803 m_atime = m_mtime = time_point::min();
+
1804#endif
+
1805 flush_cache();
+
1806 if (!ok()) _Unlikely_
+
1807 return;
+
1808 m_source->flush();
+
1809 }
+
1810
+
1811 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
+
1812 {
+
1813 m_state = state_t::ok;
+
1814 switch (how) {
+
1815 case seek_t::beg:
+
1816 return m_offset = offset;
+
1817 case seek_t::cur:
+
1818 return m_offset += offset;
+
1819 case seek_t::end:
+
1820 return m_offset = size() + offset;
+
1821 default:
+
1822 throw std::invalid_argument("unknown seek origin");
+
1823 }
+
1824 }
+
1825
+
1826 virtual fpos_t tell() const
+
1827 {
+
1828 return m_offset;
+
1829 }
+
1830
+
1831 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
+
1832 {
+
1833 m_source->lock(offset, length);
+
1834 m_state = m_source->state();
+
1835 }
+
1836
+
1837 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
+
1838 {
+
1839 m_source->unlock(offset, length);
+
1840 m_state = m_source->state();
+
1841 }
+
1842
+
1843 virtual fsize_t size()
+
1844 {
+
1845 return m_cache.status != cache_t::cache_t::status_t::empty ?
+
1846 std::max(m_source->size(), m_cache.region.end) :
+
1847 m_source->size();
+
1848 }
+
1849
+
1850 virtual void truncate()
+
1851 {
+
1852#if SET_FILE_OP_TIMES
+
1853 m_atime = m_mtime = time_point::now();
+
1854#endif
+
1855 m_source->seek(m_offset);
+
1856 if (m_cache.region.end <= m_offset) {
+
1857 // Truncation does not affect cache.
+
1858 }
+
1859 else if (m_cache.region.start <= m_offset) {
+
1860 // Truncation truncates cache.
+
1861 m_cache.region.end = m_offset;
+
1862 }
+
1863 else {
+
1864 // Truncation invalidates cache.
+
1865 m_cache.status = cache_t::cache_t::status_t::empty;
+
1866 }
+
1867 m_source->truncate();
+
1868 m_state = m_source->state();
+
1869 }
+
1870
+
1871 virtual time_point ctime() const
+
1872 {
+
1873 return m_source->ctime();
+
1874 }
+
1875
+
1876 virtual time_point atime() const
+
1877 {
+
1878#if SET_FILE_OP_TIMES
+
1879 return std::max(m_atime, m_source->atime());
+
1880#else
+
1881 return m_source->atime();
+
1882#endif
+
1883 }
+
1884
+
1885 virtual time_point mtime() const
+
1886 {
+
1887#if SET_FILE_OP_TIMES
+
1888 return std::max(m_mtime, m_source->mtime());
+
1889#else
+
1890 return m_source->mtime();
+
1891#endif
+
1892 }
+
1893
+
1894 virtual void set_ctime(time_point date)
+
1895 {
+
1896 m_source->set_ctime(date);
+
1897 }
+
1898
+
1899 virtual void set_atime(time_point date)
+
1900 {
+
1901#if SET_FILE_OP_TIMES
+
1902 m_atime = date;
+
1903#endif
+
1904 m_source->set_atime(date);
+
1905 }
+
1906
+
1907 virtual void set_mtime(time_point date)
+
1908 {
+
1909#if SET_FILE_OP_TIMES
+
1910 m_mtime = date;
+
1911#endif
+
1912 m_source->set_mtime(date);
+
1913 }
+
1914
+
1915 protected:
+
1916 void flush_cache()
+
1917 {
+
1918 if (m_cache.status != cache_t::cache_t::status_t::dirty)
+
1919 m_state = state_t::ok;
+
1920 else if (!m_cache.region.empty()) {
+
1921 write_cache();
+
1922 if (ok())
+
1923 m_cache.status = cache_t::cache_t::status_t::loaded;
+
1924 }
+
1925 else {
+
1926 m_state = state_t::ok;
+
1927 m_cache.status = cache_t::cache_t::status_t::loaded;
+
1928 }
+
1929 }
+
1930
+
1931 void invalidate_cache()
+
1932 {
+
1933 if (m_cache.status == cache_t::cache_t::status_t::dirty && !m_cache.region.empty()) {
+
1934 write_cache();
+
1935 if (!ok()) _Unlikely_
+
1936 return;
+
1937 } else
+
1938 m_state = state_t::ok;
+
1939 m_cache.status = cache_t::cache_t::status_t::empty;
+
1940 }
+
1941
+
1942 void load_cache(_In_ fpos_t start)
+
1943 {
+
1944 assert(m_cache.status != cache_t::cache_t::status_t::dirty);
+
1945 start -= start % m_cache.capacity; // Align to cache block size.
+
1946 m_source->seek(m_cache.region.start = start);
+
1947 if (m_source->ok()) {
+
1948 m_cache.region.end = start + m_source->read(m_cache.data, m_cache.capacity);
+
1949 m_cache.status = cache_t::cache_t::status_t::loaded;
+
1950 m_state = state_t::ok; // Regardless the read failure, we still might have cached some data.
+
1951 }
+
1952 else
+
1953 m_state = state_t::fail;
+
1954 }
+
1955
+
1956 void write_cache()
+
1957 {
+
1958 assert(m_cache.status == cache_t::cache_t::status_t::dirty);
+
1959 m_source->seek(m_cache.region.start);
+
1960 m_source->write(m_cache.data, static_cast<size_t>(m_cache.region.size()));
+
1961 m_state = m_source->state();
+
1962 }
+
1963
+
1964 basic_file* m_source;
+
1965 struct cache_t {
+
1966 uint8_t* data;
+
1967 size_t capacity;
+
1968 enum class status_t {
+
1969 empty = 0,
+
1970 loaded,
+
1971 dirty,
+
1972 } status;
+
1973 interval<fpos_t> region;
+
1974
+
1975 cache_t(_In_ size_t _capacity) :
+
1976 data(new uint8_t[_capacity]),
+
1977 capacity(_capacity),
+
1978 status(status_t::empty),
+
1979 region(0)
+
1980 {}
+
1981
+
1982 ~cache_t()
+
1983 {
+
1984 delete[] data;
+
1985 }
+
1986 } m_cache;
+
1987 fpos_t m_offset;
+
1988#if SET_FILE_OP_TIMES
+
1989 time_point
+
1990 m_atime,
+
1991 m_mtime;
+
1992#endif
+
1993 };
+
1994
+
1998 class basic_sys : virtual public basic, public sys_object
+
1999 {
+
2000 public:
+
2001 basic_sys(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) :
+
2002 basic(state),
+
2003 sys_object(h)
+
2004 {}
+
2005
+
2006 virtual _Success_(return != 0 || length == 0) size_t read(
+
2007 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
2008 {
+
2009 assert(data || !length);
+
2010 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
+
2011 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
+
2012 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
+
2013 size_t
+
2014#if defined(_WIN64)
+
2015 block_size = 0x1F80000;
+
2016#elif defined(_WIN32)
+
2017 block_size = 0x3f00000;
+
2018#else
+
2019 block_size = SSIZE_MAX;
+
2020#endif
+
2021 for (size_t to_read = length;;) {
+
2022#ifdef _WIN32
+
2023 // ReadFile() might raise exception (e.g. STATUS_FILE_BAD_FORMAT/0xE0000002).
+
2024 BOOL succeeded;
+
2025 DWORD num_read;
+
2026 __try { succeeded = ReadFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_read, block_size)), &num_read, nullptr); }
+
2027 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_read = 0; }
+
2028 if (!succeeded && GetLastError() == ERROR_NO_SYSTEM_RESOURCES && block_size > default_block_size) _Unlikely_ {
+
2029 // Error "Insufficient system resources exist to complete the requested service." occurs
+
2030 // ocasionally, when attempting to read too much data at once (e.g. over \\TSClient).
+
2031 block_size = default_block_size;
+
2032 continue;
+
2033 }
+
2034 if (!succeeded) _Unlikely_
+
2035#else
+
2036 ssize_t num_read = static_cast<ssize_t>(std::min<size_t>(to_read, block_size));
+
2037 num_read = read(m_h, data, num_read);
+
2038 if (num_read < 0) _Unlikely_
+
2039#endif
+
2040 {
+
2041 m_state = to_read < length ? state_t::ok : state_t::fail;
+
2042 return length - to_read;
+
2043 }
+
2044 if (!num_read) _Unlikely_ {
+
2045 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
+
2046 return length - to_read;
+
2047 }
+
2048 to_read -= num_read;
+
2049 if (!to_read) {
+
2050 m_state = state_t::ok;
+
2051 return length;
+
2052 }
+
2053 reinterpret_cast<uint8_t*&>(data) += num_read;
+
2054 }
+
2055 }
+
2056
+
2057 virtual _Success_(return != 0) size_t write(
+
2058 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
2059 {
+
2060 // Windows Server 2003 and Windows XP: Pipe write operations across a network are limited in size per write.
+
2061 // The amount varies per platform. For x86 platforms it's 63.97 MB. For x64 platforms it's 31.97 MB. For Itanium
+
2062 // it's 63.95 MB. For more information regarding pipes, see the Remarks section.
+
2063 constexpr size_t
+
2064#if defined(_WIN64)
+
2065 block_size = 0x1F80000;
+
2066#elif defined(_WIN32)
+
2067 block_size = 0x3f00000;
+
2068#else
+
2069 block_size = SSIZE_MAX;
+
2070#endif
+
2071 for (size_t to_write = length;;) {
+
2072#ifdef _WIN32
+
2073 // ReadFile() might raise an exception. Be cautious with WriteFile() too.
+
2074 BOOL succeeded;
+
2075 DWORD num_written;
+
2076 __try { succeeded = WriteFile(m_h, data, static_cast<DWORD>(std::min<size_t>(to_write, block_size)), &num_written, nullptr); }
+
2077 __except (EXCEPTION_EXECUTE_HANDLER) { succeeded = FALSE; SetLastError(ERROR_UNHANDLED_EXCEPTION); num_written = 0; }
+
2078 to_write -= num_written;
+
2079 if (!to_write) {
+
2080 m_state = state_t::ok;
+
2081 return length;
+
2082 }
+
2083 reinterpret_cast<const uint8_t*&>(data) += num_written;
+
2084 if (!succeeded) _Unlikely_ {
+
2085 m_state = state_t::fail;
+
2086 return length - to_write;
+
2087 }
+
2088#else
+
2089 ssize_t num_written = write(m_h, data, static_cast<ssize_t>(std::min<size_t>(to_write, block_size)));
+
2090 if (num_written < 0) _Unlikely_ {
+
2091 m_state = state_t::fail;
+
2092 return length - to_write;
+
2093 }
+
2094 to_write -= num_written;
+
2095 if (!to_write) {
+
2096 m_state = state_t::ok;
+
2097 return length;
+
2098 }
+
2099 reinterpret_cast<const uint8_t*&>(data) += num_written;
+
2100#endif
+
2101 }
+
2102 }
+
2103
+
2104 virtual void close()
+
2105 {
+
2106 try {
+
2107 sys_object::close();
+
2108 m_state = state_t::ok;
+
2109 }
+
2110 catch (std::exception) {
+
2111 m_state = state_t::fail;
+
2112 }
+
2113 }
+
2114
+
2115 virtual void flush()
+
2116 {
+
2117#ifdef _WIN32
+
2118 m_state = FlushFileBuffers(m_h) ? state_t::ok : state_t::fail;
+
2119#else
+
2120 m_state = fsync(m_h) >= 0 ? state_t::ok : state_t::fail;
+
2121#endif
+
2122 }
+
2123 };
+
2124
+
2128 class buffered_sys : public buffer
+
2129 {
+
2130 public:
+
2131 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) :
+
2132 buffer(read_buffer_size, write_buffer_size),
+
2133 m_source(h)
+
2134 {
+
2135 init(m_source);
+
2136 }
+
2137
+
2138 protected:
+
2139 basic_sys m_source;
+
2140 };
+
2141
+
2142#ifdef _WIN32
+
2146 class sequential_stream : public basic
+
2147 {
+
2148 public:
+
2149 sequential_stream(_In_ ISequentialStream* source) : m_source(source)
+
2150 {
+
2151 m_source->AddRef();
+
2152 }
+
2153
+
2154 virtual ~sequential_stream()
+
2155 {
+
2156 m_source->Release();
+
2157 }
+
2158
+
2159 virtual _Success_(return != 0 || length == 0) size_t read(
+
2160 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
2161 {
+
2162 assert(data || !length);
+
2163 for (size_t to_read = length;;) {
+
2164 HRESULT hr;
+
2165 ULONG num_read = 0;
+
2166 __try { hr = m_source->Read(data, (ULONG)std::min<size_t>(to_read, ULONG_MAX), &num_read); }
+
2167 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
+
2168 if (FAILED(hr)) _Unlikely_ {
+
2169 m_state = to_read < length ? state_t::ok : state_t::fail;
+
2170 return length - to_read;
+
2171 }
+
2172 to_read -= num_read;
+
2173 if (hr == S_FALSE) _Unlikely_ {
+
2174 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
+
2175 return length - to_read;
+
2176 }
+
2177 if (!to_read) {
+
2178 m_state = state_t::ok;
+
2179 return length;
+
2180 }
+
2181 reinterpret_cast<uint8_t*&>(data) += num_read;
+
2182 }
+
2183 }
+
2184
+
2185 virtual _Success_(return != 0) size_t write(
+
2186 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
2187 {
+
2188 assert(data || !length);
+
2189 for (size_t to_write = length;;) {
+
2190 HRESULT hr;
+
2191 ULONG num_written = 0;
+
2192 __try { hr = m_source->Write(data, static_cast<ULONG>(std::min<size_t>(to_write, ULONG_MAX)), &num_written); }
+
2193 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
+
2194 // In abscence of documentation whether num_written gets set when FAILED(hr) (i.e. partially succesful writes),
+
2195 // assume write failed completely.
+
2196 if (FAILED(hr)) _Unlikely_ {
+
2197 m_state = state_t::fail;
+
2198 return length - to_write;
+
2199 }
+
2200 to_write -= num_written;
+
2201 if (!to_write) {
+
2202 m_state = state_t::ok;
+
2203 return length;
+
2204 }
+
2205 reinterpret_cast<const uint8_t*&>(data) += num_written;
+
2206 }
+
2207 }
+
2208
+
2209 protected:
+
2210 ISequentialStream* m_source;
+
2211 };
+
2212
+
2213#ifndef WIN32_LEAN_AND_MEAN
+
2217 class asp : public basic
+
2218 {
+
2219 public:
+
2220 asp(_In_opt_ IRequest* request, _In_opt_ IResponse* response) :
+
2221 m_request(request),
+
2222 m_response(response)
+
2223 {
+
2224 if (m_request)
+
2225 m_request->AddRef();
+
2226 if (m_response)
+
2227 m_response->AddRef();
+
2228 }
+
2229
+
2230 virtual ~asp()
+
2231 {
+
2232 if (m_request)
+
2233 m_request->Release();
+
2234 if (m_response)
+
2235 m_response->Release();
+
2236 }
+
2237
+
2238 virtual _Success_(return != 0 || length == 0) size_t read(
+
2239 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
2240 {
+
2241 assert(data || !length);
+
2242 if (!m_request) _Unlikely_ {
+
2243 m_state = state_t::fail;
+
2244 return 0;
+
2245 }
+
2246 for (size_t to_read = length;;) {
+
2247 VARIANT var_amount, var_data;
+
2248 V_VT(&var_amount) = VT_I4;
+
2249 V_I4(&var_amount) = (LONG)std::min<size_t>(to_read, LONG_MAX);
+
2250 V_VT(&var_data) = VT_EMPTY;
+
2251 HRESULT hr = [&]() {
+
2252 __try { return m_request->BinaryRead(&var_amount, &var_data); }
+
2253 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
+
2254 }();
+
2255 if (FAILED(hr)) _Unlikely_ {
+
2256 m_state = to_read < length ? state_t::ok : state_t::fail;
+
2257 return length - to_read;
+
2258 }
+
2259 assert(V_VT(&var_amount) == VT_I4);
+
2260 assert(V_VT(&var_data) == (VT_ARRAY | VT_UI1));
+
2261 std::unique_ptr<SAFEARRAY, SafeArrayDestroy_delete> sa(V_ARRAY(&var_data));
+
2262 if (!V_I4(&var_amount)) _Unlikely_ {
+
2263 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
+
2264 return length - to_read;
+
2265 }
+
2266 safearray_accessor<uint8_t> a(sa.get());
+
2267 memcpy(data, a.data(), V_I4(&var_amount));
+
2268 to_read -= V_I4(&var_amount);
+
2269 if (!to_read) {
+
2270 m_state = state_t::ok;
+
2271 return length;
+
2272 }
+
2273 reinterpret_cast<uint8_t*&>(data) += V_I4(&var_amount);
+
2274 }
+
2275 }
+
2276
+
2277 virtual _Success_(return != 0) size_t write(
+
2278 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
2279 {
+
2280 if (!m_response) {
+
2281 m_state = state_t::fail;
+
2282 return 0;
+
2283 }
+
2284 for (size_t to_write = length;;) {
+
2285 UINT num_written = static_cast<UINT>(std::min<size_t>(to_write, UINT_MAX));
+
2286 std::unique_ptr<OLECHAR, SysFreeString_delete> bstr_data(SysAllocStringByteLen(reinterpret_cast<LPCSTR>(data), num_written));
+
2287 VARIANT var_data;
+
2288 V_VT(&var_data) = VT_BSTR;
+
2289 V_BSTR(&var_data) = bstr_data.get();
+
2290 HRESULT hr = [&]() {
+
2291 __try { return m_response->BinaryWrite(var_data); }
+
2292 __except (EXCEPTION_EXECUTE_HANDLER) { return E_FAIL; }
+
2293 }();
+
2294 if (FAILED(hr)) _Unlikely_ {
+
2295 m_state = state_t::fail;
+
2296 return length - to_write;
+
2297 }
+
2298 to_write -= num_written;
+
2299 if (!to_write) {
+
2300 m_state = state_t::ok;
+
2301 return length;
+
2302 }
+
2303 reinterpret_cast<const uint8_t*&>(data) += num_written;
+
2304 }
+
2305 }
+
2306
+
2307 virtual void close()
+
2308 {
+
2309 if (m_response) {
+
2310 __try { m_response->End(); }
+
2311 __except (EXCEPTION_EXECUTE_HANDLER) {}
+
2312 }
+
2313 m_state = state_t::ok;
+
2314 }
+
2315
+
2316 virtual void flush()
+
2317 {
+
2318 if (m_response) {
+
2319 HRESULT hr;
+
2320 __try { hr = m_response->Flush(); }
+
2321 __except (EXCEPTION_EXECUTE_HANDLER) { hr = E_FAIL; }
+
2322 m_state = SUCCEEDED(hr) ? state_t::ok : state_t::fail;
+
2323 }
+
2324 }
+
2325
+
2326 protected:
+
2327 IRequest* m_request;
+
2328 IResponse* m_response;
+
2329 };
2330#endif
-
2331
-
2335 enum mode_t
-
2336 {
-
2337 mode_for_reading = 1 << 0,
-
2338 mode_for_writing = 1 << 1,
-
2339 mode_for_chmod = 1 << 2,
-
2340 mode_create = 1 << 3,
-
2341 mode_preserve_existing = mode_create | (1 << 4),
-
2342 mode_append = 1 << 5,
-
2343 mode_text = 0,
-
2344 mode_binary = 1 << 6,
-
2345
-
2346 share_none = 0,
-
2347 share_reading = 1 << 7,
-
2348 share_writing = 1 << 8,
-
2349 share_deleting = 1 << 9,
-
2350 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
-
2351
-
2352 inherit_handle = 1 << 10,
-
2353
-
2354 hint_write_thru = 1 << 11,
-
2355 hint_no_buffering = 1 << 12,
-
2356 hint_random_access = 1 << 13,
-
2357 hint_sequential_access = 1 << 14,
-
2358 };
-
2359
-
2360#pragma warning(push)
-
2361#pragma warning(disable: 4250)
-
2365 class file : virtual public basic_file, virtual public basic_sys
-
2366 {
-
2367 public:
-
2368 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
-
2369
-
2376 file(_In_z_ const sys_char* filename, _In_ int mode)
-
2377 {
-
2378 open(filename, mode);
-
2379 }
-
2380
-
2387 void open(_In_z_ const sys_char* filename, _In_ int mode)
-
2388 {
-
2389 if (m_h != invalid_handle)
-
2390 close();
-
2391
-
2392#ifdef _WIN32
-
2393 DWORD dwDesiredAccess = 0;
-
2394 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
-
2395 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
-
2396 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
-
2397
-
2398 DWORD dwShareMode = 0;
-
2399 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
-
2400 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
-
2401 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
-
2402
-
2403 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
-
2404 sa.bInheritHandle = mode & inherit_handle ? true : false;
-
2405
-
2406 DWORD dwCreationDisposition;
-
2407 switch (mode & mode_preserve_existing) {
-
2408 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
-
2409 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
-
2410 case 0: dwCreationDisposition = OPEN_EXISTING; break;
-
2411 default: throw std::invalid_argument("invalid mode");
-
2412 }
-
2413
-
2414 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
-
2415 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
-
2416 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
-
2417 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
-
2418 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
-
2419
-
2420 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
-
2421#else
-
2422 int flags = 0;
-
2423 if (mode & mode_for_reading) flags |= O_RDONLY;
-
2424 if (mode & mode_for_writing) flags |= O_WRONLY;
-
2425 if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
-
2426 if (mode & hint_write_thru) flags |= O_DSYNC;
-
2427 if (mode & hint_no_buffering) flags |= O_RSYNC;
-
2428
-
2429 m_h = open(filename, flags, DEFFILEMODE);
-
2430#endif
-
2431 if (m_h != invalid_handle) {
-
2432 m_state = state_t::ok;
-
2433 if (mode & mode_append)
-
2434 seek(0, seek_t::end);
-
2435 }
-
2436 else
-
2437 m_state = state_t::fail;
-
2438 }
-
2439
-
2440 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
-
2441 {
-
2442#ifdef _WIN32
-
2443 LARGE_INTEGER li;
-
2444 li.QuadPart = offset;
-
2445 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
-
2446 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
-
2447 m_state = state_t::ok;
-
2448 return li.QuadPart;
-
2449 }
-
2450#else
-
2451 off64_t result = lseek64(m_h, offset, how);
-
2452 if (result >= 0) {
-
2453 m_state = state_t::ok;
-
2454 return result;
-
2455 }
-
2456#endif
-
2457 m_state = state_t::fail;
-
2458 return fpos_max;
-
2459 }
-
2460
-
2461 virtual fpos_t tell() const
-
2462 {
-
2463 if (m_h != invalid_handle) {
-
2464#ifdef _WIN32
-
2465 LARGE_INTEGER li;
-
2466 li.QuadPart = 0;
-
2467 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
-
2468 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
-
2469 return li.QuadPart;
-
2470#else
-
2471 off64_t result = lseek64(m_h, 0, SEEK_CUR);
-
2472 if (result >= 0)
-
2473 return result;
-
2474#endif
-
2475 }
-
2476 return fpos_max;
-
2477 }
-
2478
-
2479 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
-
2480 {
-
2481#ifdef _WIN32
-
2482 LARGE_INTEGER liOffset;
-
2483 LARGE_INTEGER liSize;
-
2484 liOffset.QuadPart = offset;
-
2485 liSize.QuadPart = length;
-
2486 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
-
2487 m_state = state_t::ok;
-
2488 return;
-
2489 }
-
2490#else
-
2491 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
-
2492 if (orig >= 0) {
-
2493 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
-
2494 lseek64(m_h, orig, SEEK_SET);
-
2495 m_state = state_t::ok;
-
2496 return;
-
2497 }
-
2498#endif
-
2499 m_state = state_t::fail;
-
2500 }
-
2501
-
2502 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
-
2503 {
-
2504#ifdef _WIN32
-
2505 LARGE_INTEGER liOffset;
-
2506 LARGE_INTEGER liSize;
-
2507 liOffset.QuadPart = offset;
-
2508 liSize.QuadPart = length;
-
2509 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
-
2510 m_state = state_t::ok;
-
2511 return;
-
2512 }
-
2513#else
-
2514 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
-
2515 if (orig >= 0) {
-
2516 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
-
2517 lseek64(m_h, orig, SEEK_SET);
-
2518 m_state = state_t::ok;
-
2519 return;
-
2520 }
-
2521 lseek64(m_h, orig, SEEK_SET);
-
2522 }
-
2523#endif
-
2524 m_state = state_t::fail;
-
2525 }
-
2526
-
2527 virtual fsize_t size()
-
2528 {
-
2529#ifdef _WIN32
-
2530 LARGE_INTEGER li;
-
2531 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
-
2532 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
-
2533 li.QuadPart = -1;
-
2534 return li.QuadPart;
-
2535#else
-
2536 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
-
2537 if (orig >= 0) {
-
2538 length = lseek64(m_h, 0, SEEK_END);
-
2539 lseek64(m_h, orig, SEEK_SET);
-
2540 }
-
2541 return length;
-
2542#endif
-
2543 }
-
2544
-
2545 virtual void truncate()
-
2546 {
-
2547#ifdef _WIN32
-
2548 if (SetEndOfFile(m_h)) {
-
2549 m_state = state_t::ok;
-
2550 return;
-
2551 }
-
2552#else
-
2553 off64_t length = lseek64(m_h, 0, SEEK_CUR);
-
2554 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
-
2555 m_state = state_t::ok;
-
2556 return;
-
2557 }
-
2558#endif
-
2559 m_state = state_t::fail;
-
2560 }
-
2561
-
2562#ifdef _WIN32
-
2563 static inline time_point ft2tp(_In_ const FILETIME& ft)
-
2564 {
-
2565#if _HAS_CXX20
-
2566 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
-
2567#else
-
2568 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
-
2569#endif
-
2570 return time_point(time_point::duration(t));
-
2571 }
-
2572
-
2573 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
-
2574 {
-
2575#if _HAS_CXX20
-
2576 uint64_t t = tp.time_since_epoch().count();
-
2577#else
-
2578 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
-
2579#endif
-
2580 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
-
2581 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
-
2582 }
-
2583#endif
-
2584
-
2585 virtual time_point ctime() const
-
2586 {
-
2587#ifdef _WIN32
-
2588 FILETIME ft;
-
2589 if (GetFileTime(m_h, &ft, nullptr, nullptr))
-
2590 return ft2tp(ft);
-
2591#endif
-
2592 return time_point::min();
-
2593 }
-
2594
-
2595 virtual time_point atime() const
-
2596 {
-
2597#ifdef _WIN32
-
2598 FILETIME ft;
-
2599 if (GetFileTime(m_h, nullptr, &ft, nullptr))
-
2600 return ft2tp(ft);
-
2601#else
-
2602 struct stat buf;
-
2603 if (fstat(m_h, &buf) >= 0);
-
2604 return time_point::from_time_t(buf.st_atim);
-
2605#endif
-
2606 return time_point::min();
-
2607 }
-
2608
-
2609 virtual time_point mtime() const
-
2610 {
-
2611#ifdef _WIN32
-
2612 FILETIME ft;
-
2613 if (GetFileTime(m_h, nullptr, nullptr, &ft))
-
2614 return ft2tp(ft);
-
2615#else
-
2616 struct stat buf;
-
2617 if (fstat(m_h, &buf) >= 0)
-
2618 return time_point::from_time_t(buf.st_mtim);
-
2619#endif
-
2620 return time_point::min();
-
2621 }
-
2622
-
2623 virtual void set_ctime(time_point date)
-
2624 {
-
2625 assert(m_h != invalid_handle);
-
2626#ifdef _WIN32
-
2627 FILETIME ft;
-
2628 tp2ft(date, ft);
-
2629 if (SetFileTime(m_h, &ft, nullptr, nullptr))
-
2630 return;
-
2631#endif
-
2632 throw std::runtime_error("failed to set file ctime");
-
2633 }
-
2634
-
2635 virtual void set_atime(time_point date)
-
2636 {
-
2637 assert(m_h != invalid_handle);
-
2638#ifdef _WIN32
-
2639 FILETIME ft;
-
2640 tp2ft(date, ft);
-
2641 if (SetFileTime(m_h, nullptr, &ft, nullptr))
-
2642 return;
-
2643#else
-
2644 struct timespec ts[2];
-
2645 ts[0].tv_sec = date;
-
2646 ts[1].tv_nsec = UTIME_OMIT;
-
2647 if (futimens(m_h, ts) >= 0)
-
2648 return;
-
2649#endif
-
2650 throw std::runtime_error("failed to set file atime");
-
2651 }
-
2652
-
2653 virtual void set_mtime(time_point date)
-
2654 {
-
2655#ifdef _WIN32
-
2656 FILETIME ft;
-
2657 tp2ft(date, ft);
-
2658 if (SetFileTime(m_h, nullptr, nullptr, &ft))
-
2659 return;
-
2660#else
-
2661 struct timespec ts[2];
-
2662 ts[0].tv_nsec = UTIME_OMIT;
-
2663 ts[1].tv_sec = date;
-
2664 if (futimens(m_h, ts) >= 0)
-
2665 return;
-
2666#endif
-
2667 throw std::runtime_error("failed to set file mtime");
-
2668 }
-
2669 };
-
2670#pragma warning(pop)
-
2671
-
2675 class cached_file : public cache
-
2676 {
-
2677 public:
-
2678 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
-
2679 cache(cache_size),
-
2680 m_source(h, state)
-
2681 {
-
2682 init(m_source);
-
2683 }
-
2684
-
2692 cached_file(_In_z_ const sys_char* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
-
2693 cache(cache_size),
-
2694 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
-
2695 {
-
2696 init(m_source);
-
2697 }
-
2698
-
2706 void open(_In_z_ const sys_char* filename, _In_ int mode)
-
2707 {
-
2708 invalidate_cache();
-
2709 if (!ok()) _Unlikely_{
-
2710 m_state = state_t::fail;
-
2711 return;
-
2712 }
-
2713 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
-
2714 if (m_source.ok()) {
-
2715#if SET_FILE_OP_TIMES
-
2716 m_atime = m_source.atime();
-
2717 m_mtime = m_source.mtime();
-
2718#endif
-
2719 m_offset = m_source.tell();
-
2720 m_state = state_t::ok;
-
2721 return;
-
2722 }
-
2723 m_state = state_t::fail;
-
2724 }
-
2725
-
2726 protected:
-
2727 file m_source;
-
2728 };
-
2729
-
2733 class memory_file : public basic_file
-
2734 {
-
2735 public:
-
2736 memory_file(_In_ state_t state = state_t::ok) :
-
2737 basic(state),
-
2738 m_data(nullptr),
-
2739 m_offset(0),
-
2740 m_size(0),
-
2741 m_reserved(0),
-
2742 m_manage(true)
-
2743 {
-
2744#if SET_FILE_OP_TIMES
-
2745 m_ctime = m_atime = m_mtime = time_point::now();
-
2746#endif
-
2747 }
-
2748
-
2755 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
-
2756 basic(state),
-
2757 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
-
2758 m_offset(0),
-
2759 m_size(0),
-
2760 m_reserved(size),
-
2761 m_manage(true)
-
2762 {
-
2763 if (!m_data)
-
2764 throw std::bad_alloc();
-
2765#if SET_FILE_OP_TIMES
-
2766 m_ctime = m_atime = m_mtime = time_point::now();
-
2767#endif
-
2768 }
-
2769
-
2779 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
-
2780 basic(state),
-
2781 m_data(reinterpret_cast<uint8_t*>(data)),
-
2782 m_offset(0),
-
2783 m_size(size),
-
2784 m_reserved(reserved),
-
2785 m_manage(manage)
-
2786 {
-
2787 assert(data || !size);
-
2788 assert(reserved >= size);
-
2789#if SET_FILE_OP_TIMES
-
2790 m_ctime = m_atime = m_mtime = time_point::now();
-
2791#endif
-
2792 }
-
2793
-
2802 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
-
2803 memory_file(data, size, size, manage, state)
-
2804 {}
-
2805
-
2812 memory_file(_In_z_ const sys_char* filename, _In_ int mode) : memory_file()
-
2813 {
-
2814 load(filename, mode);
-
2815 }
-
2816
-
2817 virtual ~memory_file()
-
2818 {
-
2819 if (m_manage && m_data)
-
2820 free(m_data);
-
2821 }
-
2822
-
2829 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
-
2830 {
-
2831 if (required <= m_reserved && (!tight || required >= m_reserved)) {
-
2832 m_state = state_t::ok;
-
2833 return;
-
2834 }
-
2835 if (!m_manage) {
-
2836 m_state = state_t::fail;
-
2837 return;
-
2838 }
-
2839 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
-
2840 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
-
2841 if (!data && reserved) _Unlikely_ {
-
2842 m_state = state_t::fail;
-
2843 return;
-
2844 }
-
2845 m_data = data;
-
2846 if (reserved < m_size)
-
2847 m_size = reserved;
-
2848 m_reserved = reserved;
-
2849 m_state = state_t::ok;
-
2850 }
-
2851
-
2858 void load(_In_z_ const sys_char* filename, _In_ int mode)
-
2859 {
-
2860 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
-
2861 if (!f.ok()) {
-
2862 m_state = state_t::fail;
-
2863 return;
-
2864 }
-
2865 fsize_t size = f.size();
-
2866 if (size > SIZE_MAX) {
-
2867 m_state = state_t::fail;
-
2868 return;
-
2869 }
-
2870 reserve(static_cast<size_t>(size), true);
-
2871 if (!ok()) _Unlikely_ {
-
2872 return;
-
2873 }
-
2874 m_offset = m_size = 0;
-
2875 write_stream(f);
-
2876 if (ok())
-
2877 m_offset = 0;
-
2878#if SET_FILE_OP_TIMES
-
2879 m_ctime = f.ctime();
-
2880 m_atime = f.atime();
-
2881 m_mtime = f.mtime();
-
2882#endif
-
2883 }
-
2884
-
2891 void save(_In_z_ const sys_char* filename, _In_ int mode)
-
2892 {
-
2893 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
-
2894 if (!f.ok()) {
-
2895 m_state = state_t::fail;
-
2896 return;
-
2897 }
-
2898 f.write(m_data, m_size);
-
2899 if (!f.ok()) {
-
2900 m_state = state_t::fail;
-
2901 return;
-
2902 }
-
2903 f.truncate();
-
2904#if SET_FILE_OP_TIMES
-
2905 f.set_ctime(m_ctime);
-
2906 f.set_atime(m_atime);
-
2907 f.set_mtime(m_mtime);
-
2908#endif
-
2909 }
-
2910
-
2914 inline const void* data() const { return m_data; }
-
2915
-
2916 virtual _Success_(return != 0 || length == 0) size_t read(
-
2917 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
2918 {
-
2919 assert(data || !length);
-
2920#if SET_FILE_OP_TIMES
-
2921 m_atime = time_point::now();
-
2922#endif
-
2923 size_t available = m_size - m_offset;
-
2924 if (length <= available) {
-
2925 memcpy(data, m_data + m_offset, length);
-
2926 m_offset += length;
-
2927 m_state = state_t::ok;
-
2928 return length;
-
2929 }
-
2930 if (length && !available) {
-
2931 m_state = state_t::eof;
-
2932 return 0;
-
2933 }
-
2934 memcpy(data, m_data + m_offset, available);
-
2935 m_offset += available;
-
2936 m_state = state_t::ok;
-
2937 return available;
-
2938 }
-
2939
-
2954 template <class T>
-
2955 inline memory_file& read_data(T & data)
-
2956 {
-
2957#if SET_FILE_OP_TIMES
-
2958 m_atime = time_point::now();
-
2959#endif
-
2960 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
-
2961 data = 0;
-
2962 return *this;
-
2963 }
-
2964 size_t end_offset = m_offset + sizeof(T);
-
2965 if (end_offset <= m_size) {
-
2966 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
-
2967 m_offset = end_offset;
-
2968#if !CHECK_STREAM_STATE
-
2969 m_state = state_t::ok;
-
2970#endif
-
2971 }
-
2972 else {
-
2973 data = 0;
-
2974 m_offset = m_size;
-
2975 m_state = state_t::eof;
-
2976 }
-
2977 return *this;
-
2978 }
-
2979
-
2994 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
-
2995 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
-
2996 {
-
2997#if SET_FILE_OP_TIMES
-
2998 m_atime = time_point::now();
-
2999#endif
-
3000 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
-
3001 data.clear();
-
3002 return *this;
-
3003 }
-
3004 size_t end_offset = m_offset + sizeof(uint32_t);
-
3005 if (end_offset <= m_size) {
-
3006 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
-
3007 m_offset = end_offset;
-
3008 end_offset = stdex::add(m_offset + stdex::mul(num_chars, sizeof(_Elem)));
-
3009 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
-
3010 if (end_offset <= m_size) {
-
3011 data.assign(start, start + num_chars);
-
3012 m_offset = end_offset;
-
3013#if !CHECK_STREAM_STATE
-
3014 m_state = state_t::ok;
-
3015#endif
-
3016 return *this;
-
3017 }
-
3018 if (end_offset <= m_size)
-
3019 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
-
3020 }
-
3021 m_offset = m_size;
-
3022 m_state = state_t::eof;
-
3023 return *this;
-
3024 }
-
3025
-
3026 virtual _Success_(return != 0) size_t write(
-
3027 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
3028 {
-
3029 assert(data || !length);
-
3030#if SET_FILE_OP_TIMES
-
3031 m_atime = m_mtime = time_point::now();
-
3032#endif
-
3033 size_t end_offset = m_offset + length;
-
3034 if (end_offset > m_reserved) {
-
3035 reserve(end_offset);
-
3036 if (!ok()) _Unlikely_
-
3037 return 0;
-
3038 }
-
3039 memcpy(m_data + m_offset, data, length);
-
3040 m_offset = end_offset;
-
3041 if (m_offset > m_size)
-
3042 m_size = m_offset;
-
3043 m_state = state_t::ok;
-
3044 return length;
-
3045 }
-
3046
-
3050 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
-
3051 {
-
3052#if SET_FILE_OP_TIMES
-
3053 m_atime = m_mtime = time_point::now();
-
3054#endif
-
3055 size_t end_offset = m_offset + amount;
-
3056 if (end_offset > m_reserved) {
-
3057 reserve(end_offset);
-
3058 if (!ok()) _Unlikely_
-
3059 return;
-
3060 }
-
3061 memset(m_data + m_offset, byte, amount);
-
3062 m_offset = end_offset;
-
3063 if (m_offset > m_size)
-
3064 m_size = m_offset;
-
3065 m_state = state_t::ok;
-
3066 }
-
3067
-
3082 template <class T>
-
3083 inline memory_file& write_data(const T data)
-
3084 {
-
3085#if SET_FILE_OP_TIMES
-
3086 m_atime = m_mtime = time_point::now();
-
3087#endif
-
3088 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
-
3089 return *this;
-
3090 size_t end_offset = m_offset + sizeof(T);
-
3091 if (end_offset > m_reserved) {
-
3092 reserve(end_offset);
-
3093 if (!ok()) _Unlikely_
-
3094 return *this;
-
3095 }
-
3096 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
-
3097 m_offset = end_offset;
-
3098 if (m_offset > m_size)
-
3099 m_size = m_offset;
-
3100#if !CHECK_STREAM_STATE
-
3101 m_state = state_t::ok;
-
3102#endif
-
3103 return *this;
-
3104 }
-
3105
-
3120 template <class T>
-
3121 inline memory_file& write_str(_In_z_ const T * data)
-
3122 {
-
3123#if SET_FILE_OP_TIMES
-
3124 m_atime = m_mtime = time_point::now();
-
3125#endif
-
3126 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
-
3127 return *this;
-
3128 size_t num_chars = stdex::strlen(data);
-
3129 if (num_chars > UINT32_MAX)
-
3130 throw std::invalid_argument("string too long");
-
3131 size_t size_chars = num_chars * sizeof(T);
-
3132 size_t size = sizeof(uint32_t) + size_chars;
-
3133 size_t end_offset = m_offset + size;
-
3134 if (end_offset > m_reserved) {
-
3135 reserve(end_offset);
-
3136 if (!ok()) _Unlikely_
-
3137 return *this;
-
3138 }
-
3139 auto p = tok.m_podatki + m_offset;
-
3140 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
-
3141 memcpy(p + sizeof(uint32_t), data, size_chars);
-
3142 m_offset = end_offset;
-
3143 if (m_offset > m_size)
-
3144 m_size = m_offset;
-
3145#if !CHECK_STREAM_STATE
-
3146 m_state = state_t::ok;
-
3147#endif
-
3148 return *this;
-
3149 }
-
3150
-
3156 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
-
3157 {
-
3158#if SET_FILE_OP_TIMES
-
3159 m_atime = m_mtime = time_point::now();
-
3160#endif
-
3161 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
-
3162 size_t num_copied = 0, to_write = amount;
-
3163 m_state = state_t::ok;
-
3164 if (amount != SIZE_MAX) {
-
3165 dst_size = stdex::add(dst_size, amount);
-
3166 reserve(dst_size);
-
3167 if (!ok()) _Unlikely_
-
3168 return 0;
-
3169 while (to_write) {
-
3170 num_read = stream.read(m_data + dst_offset, to_write);
-
3171 dst_size = dst_offset += num_read;
-
3172 num_copied += num_read;
-
3173 to_write -= num_read;
-
3174 if (!stream.ok()) {
-
3175 if (stream.state() != state_t::eof)
-
3176 m_state = state_t::fail;
-
3177 break;
-
3178 }
-
3179 };
-
3180 }
-
3181 else {
-
3182 size_t block_size;
-
3183 while (to_write) {
-
3184 block_size = std::min(to_write, default_block_size);
-
3185 dst_size = stdex::add(dst_size, block_size);
-
3186 reserve(dst_size);
-
3187 if (!ok()) _Unlikely_
-
3188 break;
-
3189 num_read = stream.read(m_data + dst_offset, block_size);
-
3190 dst_size = dst_offset += num_read;
-
3191 num_copied += num_read;
-
3192 to_write -= num_read;
-
3193 if (!stream.ok()) {
-
3194 if (stream.state() != state_t::eof)
-
3195 m_state = state_t::fail;
-
3196 break;
-
3197 }
-
3198 };
-
3199 }
-
3200 m_offset = dst_offset;
-
3201 if (m_offset > m_size)
-
3202 m_size = m_offset;
-
3203 return num_copied;
-
3204 }
-
3205
-
3206 virtual void close()
-
3207 {
-
3208 if (m_manage && m_data)
-
3209 free(m_data);
-
3210 m_data = nullptr;
-
3211 m_manage = true;
-
3212 m_offset = 0;
-
3213 m_size = m_reserved = 0;
-
3214#if SET_FILE_OP_TIMES
-
3215 m_ctime = m_atime = m_mtime = time_point::min();
-
3216#endif
-
3217 m_state = state_t::ok;
-
3218 }
-
3219
-
3220 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
-
3221 {
-
3222 fpos_t target;
-
3223 switch (how) {
-
3224 case seek_t::beg: target = offset; break;
-
3225 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
-
3226 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
-
3227 default: throw std::invalid_argument("unknown seek origin");
-
3228 }
-
3229 if (target <= SIZE_MAX) {
-
3230 m_state = state_t::ok;
-
3231 return m_offset = static_cast<size_t>(target);
-
3232 }
-
3233 m_state = state_t::fail;
-
3234 return fpos_max;
-
3235 }
-
3236
-
3237 virtual fpos_t tell() const
-
3238 {
-
3239 return m_offset;
-
3240 }
-
3241
-
3242 virtual fsize_t size()
-
3243 {
-
3244 return m_size;
-
3245 }
-
3246
-
3247 virtual void truncate()
-
3248 {
-
3249#if SET_FILE_OP_TIMES
-
3250 m_atime = m_mtime = time_point::now();
-
3251#endif
-
3252 m_size = m_offset;
-
3253 reserve(m_offset);
-
3254 }
-
3255
-
3256#if SET_FILE_OP_TIMES
-
3257 virtual time_point ctime() const
-
3258 {
-
3259 return m_ctime;
-
3260 }
-
3261
-
3262 virtual time_point atime() const
-
3263 {
-
3264 return m_atime;
-
3265 }
-
3266
-
3267 virtual time_point mtime() const
-
3268 {
-
3269 return m_mtime;
-
3270 }
-
3271
-
3272 virtual void set_ctime(time_point date)
-
3273 {
-
3274 m_ctime = date;
-
3275 }
-
3276
-
3277 virtual void set_atime(time_point date)
-
3278 {
-
3279 m_atime = date;
-
3280 }
-
3281
-
3282 virtual void set_mtime(time_point date)
-
3283 {
-
3284 m_mtime = date;
-
3285 }
-
3286#endif
-
3287
-
3288 protected:
-
3296 template <class T>
-
3297 inline void set(_In_ fpos_t offset, _In_ const T data)
-
3298 {
-
3299#if SET_FILE_OP_TIMES
-
3300 m_atime = m_mtime = time_point::now();
-
3301#endif
-
3302 assert(offset + sizeof(T) < m_size);
-
3303 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
-
3304 }
-
3305
-
3306 public:
-
3307 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
-
3308 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
-
3309 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
-
3310 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
-
3311 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
-
3312 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
-
3313 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
-
3314 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
-
3315#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
-
3316 inline void set(_In_ fpos_t offset, _In_ const size_t data) { set<size_t>(offset, data); }
-
3317#endif
-
3318 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
-
3319 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
-
3320 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
-
3321#ifdef _NATIVE_WCHAR_T_DEFINED
-
3322 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
-
3323#endif
-
3324
-
3332 protected:
-
3333 template <class T>
-
3334 inline void get(_In_ fpos_t offset, _Out_ T & data)
-
3335 {
-
3336 assert(offset + sizeof(T) < m_size);
-
3337 data = LE2HE(*(T*)(m_data + offset));
-
3338#if SET_FILE_OP_TIMES
-
3339 m_atime = time_point::now();
-
3340#endif
-
3341 }
-
3342
-
3343 public:
-
3344 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
-
3345 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
-
3346 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
-
3347 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
-
3348 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
-
3349 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
-
3350 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
-
3351 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
-
3352#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
-
3353 inline void get(_In_ fpos_t offset, _Out_ size_t & data) { get<size_t>(offset, data); }
-
3354#endif
-
3355 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
-
3356 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
-
3357 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
-
3358#ifdef _NATIVE_WCHAR_T_DEFINED
-
3359 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
-
3360#endif
-
3361
-
3362 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
-
3363 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
-
3364 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
-
3365 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
-
3366 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
-
3367 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
-
3368 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
-
3369 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
-
3370 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
-
3371 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
-
3372 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
-
3373 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
-
3374 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
-
3375 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
-
3376 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
-
3377 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
-
3378#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
-
3379 inline memory_file& operator <<(_In_ const size_t data) { return write_data(data); }
-
3380 inline memory_file& operator >>(_Out_ size_t & data) { return read_data(data); }
-
3381#endif
-
3382 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
-
3383 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
-
3384 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
-
3385 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
-
3386 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
-
3387 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
-
3388#ifdef _NATIVE_WCHAR_T_DEFINED
-
3389 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
-
3390 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
-
3391#endif
-
3392 template <class T>
-
3393 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
-
3394 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
-
3395 inline memory_file& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
-
3396
-
3397 protected:
-
3398 uint8_t* m_data;
-
3399 bool m_manage;
-
3400 size_t m_offset;
-
3401 size_t m_size;
-
3402 size_t m_reserved;
-
3403#if SET_FILE_OP_TIMES
-
3404 time_point
-
3405 m_ctime,
-
3406 m_atime,
-
3407 m_mtime;
-
3408#endif
-
3409 };
-
3410
-
3414 class fifo : public basic {
-
3415 public:
-
3416 fifo() :
-
3417 m_offset(0),
-
3418 m_size(0),
-
3419 m_head(nullptr),
-
3420 m_tail(nullptr)
-
3421 {}
-
3422
-
3423 virtual ~fifo()
-
3424 {
-
3425 while (m_head) {
-
3426 auto p = m_head;
-
3427 m_head = p->next;
-
3428 delete p;
-
3429 }
-
3430 }
-
3431
-
3432#pragma warning(suppress: 6101) // See [2] below
-
3433 virtual _Success_(return != 0 || length == 0) size_t read(
-
3434 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
3435 {
-
3436 assert(data || !length);
-
3437 for (size_t to_read = length;;) {
-
3438 if (!m_head) _Unlikely_ {
-
3439 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
-
3440 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
-
3441 return length - to_read;
-
3442 }
-
3443 size_t remaining = m_head->size - m_offset;
-
3444 if (remaining > to_read) {
-
3445 memcpy(data, m_head->data + m_offset, to_read);
-
3446 m_offset += to_read;
-
3447 m_size -= to_read;
-
3448 m_state = state_t::ok;
-
3449 return length;
-
3450 }
-
3451 memcpy(data, m_head->data + m_offset, remaining);
-
3452 m_offset = 0;
-
3453 m_size -= remaining;
-
3454 reinterpret_cast<uint8_t*&>(data) += remaining;
-
3455 to_read -= remaining;
-
3456 auto p = m_head;
-
3457 m_head = p->next;
-
3458 delete p;
-
3459 }
-
3460 }
-
3461
-
3462 virtual _Success_(return != 0) size_t write(
-
3463 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
3464 {
-
3465 assert(data || !length);
-
3466 try {
-
3467 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
-
3468 n->next = nullptr;
-
3469 n->size = length;
-
3470 memcpy(n->data, data, length);
-
3471 m_size += length;
-
3472 if (m_head)
-
3473 m_tail = m_tail->next = n.release();
-
3474 else
-
3475 m_head = m_tail = n.release();
-
3476 m_state = state_t::ok;
-
3477 return length;
-
3478 }
-
3479 catch (std::bad_alloc) {
-
3480 m_state = state_t::fail;
-
3481 return 0;
-
3482 }
-
3483 }
-
3484
-
3485 virtual void close()
-
3486 {
-
3487 m_size = m_offset = 0;
-
3488 while (m_head) {
-
3489 auto p = m_head;
-
3490 m_head = p->next;
-
3491 delete p;
-
3492 }
-
3493 m_state = state_t::ok;
-
3494 }
-
3495
-
3499 inline size_t size() const { return m_size; };
-
3500
-
3501 protected:
-
3502 size_t m_offset, m_size;
-
3503 struct node_t {
-
3504 node_t* next;
-
3505 size_t size;
-
3506#pragma warning(suppress:4200)
-
3507 uint8_t data[0];
-
3508 } *m_head, * m_tail;
-
3509 };
-
3510
-
3514 class diag_file : public basic_file {
-
3515 public:
-
3516 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
-
3517 basic(num_files ? files[0]->state() : state_t::fail),
-
3518 m_files(files, files + num_files)
-
3519 {
-
3520 }
-
3521
-
3522 virtual _Success_(return != 0 || length == 0) size_t read(
-
3523 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
-
3524 {
-
3525 assert(data || !length);
-
3526 if (m_files.empty()) {
-
3527 m_state = state_t::fail;
-
3528 return 0;
-
3529 }
-
3530 size_t result = m_files[0]->read(data, length);
-
3531 _Analysis_assume_(result <= length);
-
3532 m_state = m_files[0]->state();
-
3533 if (length > m_tmp.size())
-
3534 m_tmp.resize(length);
-
3535 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3536 if (m_files[i]->read(m_tmp.data(), length) != result ||
-
3537 memcmp(m_tmp.data(), data, result))
-
3538 throw std::runtime_error("read mismatch");
-
3539 if (m_files[i]->state() != m_state)
-
3540 throw std::runtime_error("state mismatch");
-
3541 }
-
3542 return result;
-
3543 }
-
3544
-
3545 virtual _Success_(return != 0) size_t write(
-
3546 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
-
3547 {
-
3548 if (m_files.empty()) {
-
3549 m_state = state_t::fail;
-
3550 return 0;
-
3551 }
-
3552 size_t result = m_files[0]->write(data, length);
-
3553 m_state = m_files[0]->state();
-
3554 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3555 if (m_files[i]->write(data, length) != result)
-
3556 throw std::runtime_error("write mismatch");
-
3557 if (m_files[i]->state() != m_state)
-
3558 throw std::runtime_error("state mismatch");
-
3559 }
-
3560 return result;
-
3561 }
-
3562
-
3563 virtual void flush()
-
3564 {
-
3565 if (m_files.empty()) {
-
3566 m_state = state_t::ok;
-
3567 return;
-
3568 }
-
3569 m_files[0]->flush();
-
3570 m_state = m_files[0]->state();
-
3571 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3572 m_files[i]->flush();
-
3573 if (m_files[i]->state() != m_state)
-
3574 throw std::runtime_error("state mismatch");
-
3575 }
-
3576 }
-
3577
-
3578 virtual void close()
-
3579 {
-
3580 if (m_files.empty()) {
-
3581 m_state = state_t::ok;
-
3582 return;
-
3583 }
-
3584 m_files[0]->close();
-
3585 m_state = m_files[0]->state();
-
3586 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3587 m_files[i]->close();
-
3588 if (m_files[i]->state() != m_state)
-
3589 throw std::runtime_error("state mismatch");
-
3590 }
-
3591 m_tmp.clear();
-
3592 m_tmp.shrink_to_fit();
-
3593 }
-
3594
-
3595 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
-
3596 {
-
3597 if (m_files.empty()) {
-
3598 m_state = state_t::fail;
-
3599 return fpos_max;
-
3600 }
-
3601 fpos_t result = m_files[0]->seek(offset, how);
-
3602 m_state = m_files[0]->state();
-
3603 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3604 if (m_files[i]->seek(offset, how) != result)
-
3605 throw std::runtime_error("seek mismatch");
-
3606 if (m_files[i]->state() != m_state)
-
3607 throw std::runtime_error("state mismatch");
-
3608 }
-
3609 return result;
-
3610 }
-
3611
-
3612 virtual fpos_t tell() const
-
3613 {
-
3614 if (m_files.empty())
-
3615 return fpos_max;
-
3616 fpos_t result = m_files[0]->tell();
-
3617 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3618 if (m_files[i]->tell() != result)
-
3619 throw std::runtime_error("tell mismatch");
-
3620 }
-
3621 return result;
-
3622 }
-
3623
-
3624 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
-
3625 {
-
3626 if (m_files.empty())
-
3627 m_state = state_t::fail;
-
3628 m_files[0]->lock(offset, length);
-
3629 m_state = m_files[0]->state();
-
3630 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3631 m_files[i]->lock(offset, length);
-
3632 if (m_files[i]->state() != m_state)
-
3633 throw std::runtime_error("state mismatch");
-
3634 }
-
3635 }
-
3636
-
3637 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
-
3638 {
-
3639 if (m_files.empty())
-
3640 m_state = state_t::fail;
-
3641 m_files[0]->unlock(offset, length);
-
3642 m_state = m_files[0]->state();
-
3643 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3644 m_files[i]->unlock(offset, length);
-
3645 if (m_files[i]->state() != m_state)
-
3646 throw std::runtime_error("state mismatch");
-
3647 }
-
3648 }
-
3649
-
3650 virtual fsize_t size()
-
3651 {
-
3652 if (m_files.empty()) {
-
3653 m_state = state_t::fail;
-
3654 return 0;
-
3655 }
-
3656 fsize_t result = m_files[0]->size();
-
3657 m_state = m_files[0]->state();
-
3658 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3659 if (m_files[i]->size() != result)
-
3660 throw std::runtime_error("size mismatch");
-
3661 if (m_files[i]->state() != m_state)
-
3662 throw std::runtime_error("state mismatch");
-
3663 }
-
3664 return result;
-
3665 }
-
3666
-
3667 virtual void truncate()
-
3668 {
-
3669 if (m_files.empty())
-
3670 m_state = state_t::fail;
-
3671 m_files[0]->truncate();
-
3672 m_state = m_files[0]->state();
-
3673 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
-
3674 m_files[i]->truncate();
-
3675 if (m_files[i]->state() != m_state)
-
3676 throw std::runtime_error("state mismatch");
-
3677 }
-
3678 }
-
3679
-
3680 protected:
-
3681 std::vector<basic_file*> m_files;
-
3682 std::vector<uint8_t> m_tmp;
-
3683 };
-
3684 }
-
3685}
-
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
+
2331#endif
+
2332
+
2336 enum mode_t
+
2337 {
+
2338 mode_for_reading = 1 << 0,
+
2339 mode_for_writing = 1 << 1,
+
2340 mode_for_chmod = 1 << 2,
+
2341 mode_create = 1 << 3,
+
2342 mode_preserve_existing = mode_create | (1 << 4),
+
2343 mode_append = 1 << 5,
+
2344 mode_text = 0,
+
2345 mode_binary = 1 << 6,
+
2346
+
2347 share_none = 0,
+
2348 share_reading = 1 << 7,
+
2349 share_writing = 1 << 8,
+
2350 share_deleting = 1 << 9,
+
2351 share_all = share_reading | share_writing | share_deleting, // Allow others all operations on our file
+
2352
+
2353 inherit_handle = 1 << 10,
+
2354
+
2355 hint_write_thru = 1 << 11,
+
2356 hint_no_buffering = 1 << 12,
+
2357 hint_random_access = 1 << 13,
+
2358 hint_sequential_access = 1 << 14,
+
2359 };
+
2360
+
2361#pragma warning(push)
+
2362#pragma warning(disable: 4250)
+
2366 class file : virtual public basic_file, virtual public basic_sys
+
2367 {
+
2368 public:
+
2369 file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok) : basic_sys(h, state) {}
+
2370
+
2377 file(_In_z_ const sys_char* filename, _In_ int mode)
+
2378 {
+
2379 open(filename, mode);
+
2380 }
+
2381
+
2388 void open(_In_z_ const sys_char* filename, _In_ int mode)
+
2389 {
+
2390 if (m_h != invalid_handle)
+
2391 close();
+
2392
+
2393#ifdef _WIN32
+
2394 DWORD dwDesiredAccess = 0;
+
2395 if (mode & mode_for_reading) dwDesiredAccess |= GENERIC_READ;
+
2396 if (mode & mode_for_writing) dwDesiredAccess |= GENERIC_WRITE;
+
2397 if (mode & mode_for_chmod) dwDesiredAccess |= FILE_WRITE_ATTRIBUTES;
+
2398
+
2399 DWORD dwShareMode = 0;
+
2400 if (mode & share_reading) dwShareMode |= FILE_SHARE_READ;
+
2401 if (mode & share_writing) dwShareMode |= FILE_SHARE_WRITE;
+
2402 if (mode & share_deleting) dwShareMode |= FILE_SHARE_DELETE;
+
2403
+
2404 SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES) };
+
2405 sa.bInheritHandle = mode & inherit_handle ? true : false;
+
2406
+
2407 DWORD dwCreationDisposition;
+
2408 switch (mode & mode_preserve_existing) {
+
2409 case mode_create: dwCreationDisposition = CREATE_ALWAYS; break;
+
2410 case mode_preserve_existing: dwCreationDisposition = OPEN_ALWAYS; break;
+
2411 case 0: dwCreationDisposition = OPEN_EXISTING; break;
+
2412 default: throw std::invalid_argument("invalid mode");
+
2413 }
+
2414
+
2415 DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
+
2416 if (mode & hint_write_thru) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH;
+
2417 if (mode & hint_no_buffering) dwFlagsAndAttributes |= FILE_FLAG_NO_BUFFERING;
+
2418 if (mode & hint_random_access) dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
+
2419 if (mode & hint_sequential_access) dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+
2420
+
2421 m_h = CreateFile(filename, dwDesiredAccess, dwShareMode, &sa, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
+
2422#else
+
2423 int flags = 0;
+
2424 if (mode & mode_for_reading) flags |= O_RDONLY;
+
2425 if (mode & mode_for_writing) flags |= O_WRONLY;
+
2426 if (mode & mode_create) flags |= mode & mode_preserve_existing ? O_CREAT : (O_CREAT | O_EXCL);
+
2427 if (mode & hint_write_thru) flags |= O_DSYNC;
+
2428 if (mode & hint_no_buffering) flags |= O_RSYNC;
+
2429
+
2430 m_h = open(filename, flags, DEFFILEMODE);
+
2431#endif
+
2432 if (m_h != invalid_handle) {
+
2433 m_state = state_t::ok;
+
2434 if (mode & mode_append)
+
2435 seek(0, seek_t::end);
+
2436 }
+
2437 else
+
2438 m_state = state_t::fail;
+
2439 }
+
2440
+
2441 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
+
2442 {
+
2443#ifdef _WIN32
+
2444 LARGE_INTEGER li;
+
2445 li.QuadPart = offset;
+
2446 li.LowPart = SetFilePointer(m_h, li.LowPart, &li.HighPart, static_cast<DWORD>(how));
+
2447 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR) {
+
2448 m_state = state_t::ok;
+
2449 return li.QuadPart;
+
2450 }
+
2451#else
+
2452 off64_t result = lseek64(m_h, offset, how);
+
2453 if (result >= 0) {
+
2454 m_state = state_t::ok;
+
2455 return result;
+
2456 }
+
2457#endif
+
2458 m_state = state_t::fail;
+
2459 return fpos_max;
+
2460 }
+
2461
+
2462 virtual fpos_t tell() const
+
2463 {
+
2464 if (m_h != invalid_handle) {
+
2465#ifdef _WIN32
+
2466 LARGE_INTEGER li;
+
2467 li.QuadPart = 0;
+
2468 li.LowPart = SetFilePointer(m_h, 0, &li.HighPart, FILE_CURRENT);
+
2469 if (li.LowPart != 0xFFFFFFFF || GetLastError() == NO_ERROR)
+
2470 return li.QuadPart;
+
2471#else
+
2472 off64_t result = lseek64(m_h, 0, SEEK_CUR);
+
2473 if (result >= 0)
+
2474 return result;
+
2475#endif
+
2476 }
+
2477 return fpos_max;
+
2478 }
+
2479
+
2480 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
+
2481 {
+
2482#ifdef _WIN32
+
2483 LARGE_INTEGER liOffset;
+
2484 LARGE_INTEGER liSize;
+
2485 liOffset.QuadPart = offset;
+
2486 liSize.QuadPart = length;
+
2487 if (LockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
+
2488 m_state = state_t::ok;
+
2489 return;
+
2490 }
+
2491#else
+
2492 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
+
2493 if (orig >= 0) {
+
2494 m_state = lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_LOCK, length) >= 0 ? state_t::ok : state_t::fail;
+
2495 lseek64(m_h, orig, SEEK_SET);
+
2496 m_state = state_t::ok;
+
2497 return;
+
2498 }
+
2499#endif
+
2500 m_state = state_t::fail;
+
2501 }
+
2502
+
2503 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
+
2504 {
+
2505#ifdef _WIN32
+
2506 LARGE_INTEGER liOffset;
+
2507 LARGE_INTEGER liSize;
+
2508 liOffset.QuadPart = offset;
+
2509 liSize.QuadPart = length;
+
2510 if (UnlockFile(m_h, liOffset.LowPart, liOffset.HighPart, liSize.LowPart, liSize.HighPart)) {
+
2511 m_state = state_t::ok;
+
2512 return;
+
2513 }
+
2514#else
+
2515 off64_t orig = lseek64(m_h, 0, SEEK_CUR);
+
2516 if (orig >= 0) {
+
2517 if (lseek64(m_h, offset, SEEK_SET) >= 0 && lockf64(m_h, F_ULOCK, length) >= 0) {
+
2518 lseek64(m_h, orig, SEEK_SET);
+
2519 m_state = state_t::ok;
+
2520 return;
+
2521 }
+
2522 lseek64(m_h, orig, SEEK_SET);
+
2523 }
+
2524#endif
+
2525 m_state = state_t::fail;
+
2526 }
+
2527
+
2528 virtual fsize_t size()
+
2529 {
+
2530#ifdef _WIN32
+
2531 LARGE_INTEGER li;
+
2532 li.LowPart = GetFileSize(m_h, (LPDWORD)&li.HighPart);
+
2533 if (li.LowPart == 0xFFFFFFFF && GetLastError() != NO_ERROR)
+
2534 li.QuadPart = -1;
+
2535 return li.QuadPart;
+
2536#else
+
2537 off64_t length = -1, orig = lseek64(m_h, 0, SEEK_CUR);
+
2538 if (orig >= 0) {
+
2539 length = lseek64(m_h, 0, SEEK_END);
+
2540 lseek64(m_h, orig, SEEK_SET);
+
2541 }
+
2542 return length;
+
2543#endif
+
2544 }
+
2545
+
2546 virtual void truncate()
+
2547 {
+
2548#ifdef _WIN32
+
2549 if (SetEndOfFile(m_h)) {
+
2550 m_state = state_t::ok;
+
2551 return;
+
2552 }
+
2553#else
+
2554 off64_t length = lseek64(m_h, 0, SEEK_CUR);
+
2555 if (length >= 0 && ftruncate64(m_h, length) >= 0) {
+
2556 m_state = state_t::ok;
+
2557 return;
+
2558 }
+
2559#endif
+
2560 m_state = state_t::fail;
+
2561 }
+
2562
+
2563#ifdef _WIN32
+
2564 static inline time_point ft2tp(_In_ const FILETIME& ft)
+
2565 {
+
2566#if _HAS_CXX20
+
2567 uint64_t t = (static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+
2568#else
+
2569 uint64_t t = ((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll;
+
2570#endif
+
2571 return time_point(time_point::duration(t));
+
2572 }
+
2573
+
2574 static inline void tp2ft(_In_ time_point tp, _Out_ FILETIME& ft)
+
2575 {
+
2576#if _HAS_CXX20
+
2577 uint64_t t = tp.time_since_epoch().count();
+
2578#else
+
2579 uint64_t t = tp.time_since_epoch().count() + 116444736000000000ll;
+
2580#endif
+
2581 ft.dwHighDateTime = static_cast<DWORD>((t >> 32) & 0xffffffff);
+
2582 ft.dwLowDateTime = static_cast<DWORD>(t & 0xffffffff);
+
2583 }
+
2584#endif
+
2585
+
2586 virtual time_point ctime() const
+
2587 {
+
2588#ifdef _WIN32
+
2589 FILETIME ft;
+
2590 if (GetFileTime(m_h, &ft, nullptr, nullptr))
+
2591 return ft2tp(ft);
+
2592#endif
+
2593 return time_point::min();
+
2594 }
+
2595
+
2596 virtual time_point atime() const
+
2597 {
+
2598#ifdef _WIN32
+
2599 FILETIME ft;
+
2600 if (GetFileTime(m_h, nullptr, &ft, nullptr))
+
2601 return ft2tp(ft);
+
2602#else
+
2603 struct stat buf;
+
2604 if (fstat(m_h, &buf) >= 0);
+
2605 return time_point::from_time_t(buf.st_atim);
+
2606#endif
+
2607 return time_point::min();
+
2608 }
+
2609
+
2610 virtual time_point mtime() const
+
2611 {
+
2612#ifdef _WIN32
+
2613 FILETIME ft;
+
2614 if (GetFileTime(m_h, nullptr, nullptr, &ft))
+
2615 return ft2tp(ft);
+
2616#else
+
2617 struct stat buf;
+
2618 if (fstat(m_h, &buf) >= 0)
+
2619 return time_point::from_time_t(buf.st_mtim);
+
2620#endif
+
2621 return time_point::min();
+
2622 }
+
2623
+
2624 virtual void set_ctime(time_point date)
+
2625 {
+
2626 assert(m_h != invalid_handle);
+
2627#ifdef _WIN32
+
2628 FILETIME ft;
+
2629 tp2ft(date, ft);
+
2630 if (SetFileTime(m_h, &ft, nullptr, nullptr))
+
2631 return;
+
2632#endif
+
2633 throw std::runtime_error("failed to set file ctime");
+
2634 }
+
2635
+
2636 virtual void set_atime(time_point date)
+
2637 {
+
2638 assert(m_h != invalid_handle);
+
2639#ifdef _WIN32
+
2640 FILETIME ft;
+
2641 tp2ft(date, ft);
+
2642 if (SetFileTime(m_h, nullptr, &ft, nullptr))
+
2643 return;
+
2644#else
+
2645 struct timespec ts[2];
+
2646 ts[0].tv_sec = date;
+
2647 ts[1].tv_nsec = UTIME_OMIT;
+
2648 if (futimens(m_h, ts) >= 0)
+
2649 return;
+
2650#endif
+
2651 throw std::runtime_error("failed to set file atime");
+
2652 }
+
2653
+
2654 virtual void set_mtime(time_point date)
+
2655 {
+
2656#ifdef _WIN32
+
2657 FILETIME ft;
+
2658 tp2ft(date, ft);
+
2659 if (SetFileTime(m_h, nullptr, nullptr, &ft))
+
2660 return;
+
2661#else
+
2662 struct timespec ts[2];
+
2663 ts[0].tv_nsec = UTIME_OMIT;
+
2664 ts[1].tv_sec = date;
+
2665 if (futimens(m_h, ts) >= 0)
+
2666 return;
+
2667#endif
+
2668 throw std::runtime_error("failed to set file mtime");
+
2669 }
+
2670 };
+
2671#pragma warning(pop)
+
2672
+
2676 class cached_file : public cache
+
2677 {
+
2678 public:
+
2679 cached_file(_In_opt_ sys_handle h = invalid_handle, _In_ state_t state = state_t::ok, _In_ size_t cache_size = default_cache_size) :
+
2680 cache(cache_size),
+
2681 m_source(h, state)
+
2682 {
+
2683 init(m_source);
+
2684 }
+
2685
+
2693 cached_file(_In_z_ const sys_char* filename, _In_ int mode, _In_ size_t cache_size = default_cache_size) :
+
2694 cache(cache_size),
+
2695 m_source(filename, mode & mode_for_writing ? mode | mode_for_reading : mode)
+
2696 {
+
2697 init(m_source);
+
2698 }
+
2699
+
2707 void open(_In_z_ const sys_char* filename, _In_ int mode)
+
2708 {
+
2709 invalidate_cache();
+
2710 if (!ok()) _Unlikely_{
+
2711 m_state = state_t::fail;
+
2712 return;
+
2713 }
+
2714 m_source.open(filename, mode & mode_for_writing ? mode | mode_for_reading : mode);
+
2715 if (m_source.ok()) {
+
2716#if SET_FILE_OP_TIMES
+
2717 m_atime = m_source.atime();
+
2718 m_mtime = m_source.mtime();
+
2719#endif
+
2720 m_offset = m_source.tell();
+
2721 m_state = state_t::ok;
+
2722 return;
+
2723 }
+
2724 m_state = state_t::fail;
+
2725 }
+
2726
+
2727 protected:
+
2728 file m_source;
+
2729 };
+
2730
+
2734 class memory_file : public basic_file
+
2735 {
+
2736 public:
+
2737 memory_file(_In_ state_t state = state_t::ok) :
+
2738 basic(state),
+
2739 m_data(nullptr),
+
2740 m_offset(0),
+
2741 m_size(0),
+
2742 m_reserved(0),
+
2743 m_manage(true)
+
2744 {
+
2745#if SET_FILE_OP_TIMES
+
2746 m_ctime = m_atime = m_mtime = time_point::now();
+
2747#endif
+
2748 }
+
2749
+
2756 memory_file(_In_ size_t size, _In_ state_t state = state_t::ok) :
+
2757 basic(state),
+
2758 m_data(reinterpret_cast<uint8_t*>(malloc(size))),
+
2759 m_offset(0),
+
2760 m_size(0),
+
2761 m_reserved(size),
+
2762 m_manage(true)
+
2763 {
+
2764 if (!m_data)
+
2765 throw std::bad_alloc();
+
2766#if SET_FILE_OP_TIMES
+
2767 m_ctime = m_atime = m_mtime = time_point::now();
+
2768#endif
+
2769 }
+
2770
+
2780 memory_file(_Inout_ void* data, _In_ size_t size, _In_ size_t reserved, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
+
2781 basic(state),
+
2782 m_data(reinterpret_cast<uint8_t*>(data)),
+
2783 m_offset(0),
+
2784 m_size(size),
+
2785 m_reserved(reserved),
+
2786 m_manage(manage)
+
2787 {
+
2788 assert(data || !size);
+
2789 assert(reserved >= size);
+
2790#if SET_FILE_OP_TIMES
+
2791 m_ctime = m_atime = m_mtime = time_point::now();
+
2792#endif
+
2793 }
+
2794
+
2803 memory_file(_Inout_ void* data, _In_ size_t size, _In_ bool manage = false, _In_ state_t state = state_t::ok) :
+
2804 memory_file(data, size, size, manage, state)
+
2805 {}
+
2806
+
2813 memory_file(_In_z_ const sys_char* filename, _In_ int mode) : memory_file()
+
2814 {
+
2815 load(filename, mode);
+
2816 }
+
2817
+
2818 virtual ~memory_file()
+
2819 {
+
2820 if (m_manage && m_data)
+
2821 free(m_data);
+
2822 }
+
2823
+
2830 void reserve(_In_ size_t required, _In_ bool tight = false) noexcept
+
2831 {
+
2832 if (required <= m_reserved && (!tight || required >= m_reserved)) {
+
2833 m_state = state_t::ok;
+
2834 return;
+
2835 }
+
2836 if (!m_manage) {
+
2837 m_state = state_t::fail;
+
2838 return;
+
2839 }
+
2840 size_t reserved = tight ? required : ((required + required / 4 + (default_block_size - 1)) / default_block_size) * default_block_size;
+
2841 auto data = reinterpret_cast<uint8_t*>(realloc(m_data, reserved));
+
2842 if (!data && reserved) _Unlikely_ {
+
2843 m_state = state_t::fail;
+
2844 return;
+
2845 }
+
2846 m_data = data;
+
2847 if (reserved < m_size)
+
2848 m_size = reserved;
+
2849 m_reserved = reserved;
+
2850 m_state = state_t::ok;
+
2851 }
+
2852
+
2859 void load(_In_z_ const sys_char* filename, _In_ int mode)
+
2860 {
+
2861 file f(filename, (mode & ~hint_random_access) | mode_for_reading | hint_sequential_access);
+
2862 if (!f.ok()) {
+
2863 m_state = state_t::fail;
+
2864 return;
+
2865 }
+
2866 fsize_t size = f.size();
+
2867 if (size > SIZE_MAX) {
+
2868 m_state = state_t::fail;
+
2869 return;
+
2870 }
+
2871 reserve(static_cast<size_t>(size), true);
+
2872 if (!ok()) _Unlikely_ {
+
2873 return;
+
2874 }
+
2875 m_offset = m_size = 0;
+
2876 write_stream(f);
+
2877 if (ok())
+
2878 m_offset = 0;
+
2879#if SET_FILE_OP_TIMES
+
2880 m_ctime = f.ctime();
+
2881 m_atime = f.atime();
+
2882 m_mtime = f.mtime();
+
2883#endif
+
2884 }
+
2885
+
2892 void save(_In_z_ const sys_char* filename, _In_ int mode)
+
2893 {
+
2894 file f(filename, (mode & ~hint_random_access) | mode_for_writing | hint_sequential_access);
+
2895 if (!f.ok()) {
+
2896 m_state = state_t::fail;
+
2897 return;
+
2898 }
+
2899 f.write(m_data, m_size);
+
2900 if (!f.ok()) {
+
2901 m_state = state_t::fail;
+
2902 return;
+
2903 }
+
2904 f.truncate();
+
2905#if SET_FILE_OP_TIMES
+
2906 f.set_ctime(m_ctime);
+
2907 f.set_atime(m_atime);
+
2908 f.set_mtime(m_mtime);
+
2909#endif
+
2910 }
+
2911
+
2915 inline const void* data() const { return m_data; }
+
2916
+
2917 virtual _Success_(return != 0 || length == 0) size_t read(
+
2918 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
2919 {
+
2920 assert(data || !length);
+
2921#if SET_FILE_OP_TIMES
+
2922 m_atime = time_point::now();
+
2923#endif
+
2924 size_t available = m_size - m_offset;
+
2925 if (length <= available) {
+
2926 memcpy(data, m_data + m_offset, length);
+
2927 m_offset += length;
+
2928 m_state = state_t::ok;
+
2929 return length;
+
2930 }
+
2931 if (length && !available) {
+
2932 m_state = state_t::eof;
+
2933 return 0;
+
2934 }
+
2935 memcpy(data, m_data + m_offset, available);
+
2936 m_offset += available;
+
2937 m_state = state_t::ok;
+
2938 return available;
+
2939 }
+
2940
+
2955 template <class T>
+
2956 inline memory_file& read_data(T & data)
+
2957 {
+
2958#if SET_FILE_OP_TIMES
+
2959 m_atime = time_point::now();
+
2960#endif
+
2961 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
+
2962 data = 0;
+
2963 return *this;
+
2964 }
+
2965 size_t end_offset = m_offset + sizeof(T);
+
2966 if (end_offset <= m_size) {
+
2967 data = LE2HE(*reinterpret_cast<T*>(m_data + m_offset));
+
2968 m_offset = end_offset;
+
2969#if !CHECK_STREAM_STATE
+
2970 m_state = state_t::ok;
+
2971#endif
+
2972 }
+
2973 else {
+
2974 data = 0;
+
2975 m_offset = m_size;
+
2976 m_state = state_t::eof;
+
2977 }
+
2978 return *this;
+
2979 }
+
2980
+
2995 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
2996 memory_file& read_str(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data)
+
2997 {
+
2998#if SET_FILE_OP_TIMES
+
2999 m_atime = time_point::now();
+
3000#endif
+
3001 if (CHECK_STREAM_STATE && !ok()) _Unlikely_ {
+
3002 data.clear();
+
3003 return *this;
+
3004 }
+
3005 size_t end_offset = m_offset + sizeof(uint32_t);
+
3006 if (end_offset <= m_size) {
+
3007 uint32_t num_chars = LE2HE(*reinterpret_cast<uint32_t*>(m_data + m_offset));
+
3008 m_offset = end_offset;
+
3009 end_offset = stdex::add(m_offset + stdex::mul(num_chars, sizeof(_Elem)));
+
3010 _Elem* start = reinterpret_cast<_Elem*>(m_data + m_offset);
+
3011 if (end_offset <= m_size) {
+
3012 data.assign(start, start + num_chars);
+
3013 m_offset = end_offset;
+
3014#if !CHECK_STREAM_STATE
+
3015 m_state = state_t::ok;
+
3016#endif
+
3017 return *this;
+
3018 }
+
3019 if (end_offset <= m_size)
+
3020 data.assign(start, reinterpret_cast<_Elem*>(m_data + m_size));
+
3021 }
+
3022 m_offset = m_size;
+
3023 m_state = state_t::eof;
+
3024 return *this;
+
3025 }
+
3026
+
3027 virtual _Success_(return != 0) size_t write(
+
3028 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
3029 {
+
3030 assert(data || !length);
+
3031#if SET_FILE_OP_TIMES
+
3032 m_atime = m_mtime = time_point::now();
+
3033#endif
+
3034 size_t end_offset = m_offset + length;
+
3035 if (end_offset > m_reserved) {
+
3036 reserve(end_offset);
+
3037 if (!ok()) _Unlikely_
+
3038 return 0;
+
3039 }
+
3040 memcpy(m_data + m_offset, data, length);
+
3041 m_offset = end_offset;
+
3042 if (m_offset > m_size)
+
3043 m_size = m_offset;
+
3044 m_state = state_t::ok;
+
3045 return length;
+
3046 }
+
3047
+
3051 void write_byte(_In_ uint8_t byte, _In_ size_t amount = 1)
+
3052 {
+
3053#if SET_FILE_OP_TIMES
+
3054 m_atime = m_mtime = time_point::now();
+
3055#endif
+
3056 size_t end_offset = m_offset + amount;
+
3057 if (end_offset > m_reserved) {
+
3058 reserve(end_offset);
+
3059 if (!ok()) _Unlikely_
+
3060 return;
+
3061 }
+
3062 memset(m_data + m_offset, byte, amount);
+
3063 m_offset = end_offset;
+
3064 if (m_offset > m_size)
+
3065 m_size = m_offset;
+
3066 m_state = state_t::ok;
+
3067 }
+
3068
+
3083 template <class T>
+
3084 inline memory_file& write_data(const T data)
+
3085 {
+
3086#if SET_FILE_OP_TIMES
+
3087 m_atime = m_mtime = time_point::now();
+
3088#endif
+
3089 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
+
3090 return *this;
+
3091 size_t end_offset = m_offset + sizeof(T);
+
3092 if (end_offset > m_reserved) {
+
3093 reserve(end_offset);
+
3094 if (!ok()) _Unlikely_
+
3095 return *this;
+
3096 }
+
3097 (*reinterpret_cast<T*>(m_data + m_offset)) = HE2LE(data);
+
3098 m_offset = end_offset;
+
3099 if (m_offset > m_size)
+
3100 m_size = m_offset;
+
3101#if !CHECK_STREAM_STATE
+
3102 m_state = state_t::ok;
+
3103#endif
+
3104 return *this;
+
3105 }
+
3106
+
3121 template <class T>
+
3122 inline memory_file& write_str(_In_z_ const T * data)
+
3123 {
+
3124#if SET_FILE_OP_TIMES
+
3125 m_atime = m_mtime = time_point::now();
+
3126#endif
+
3127 if (CHECK_STREAM_STATE && !ok()) _Unlikely_
+
3128 return *this;
+
3129 size_t num_chars = stdex::strlen(data);
+
3130 if (num_chars > UINT32_MAX)
+
3131 throw std::invalid_argument("string too long");
+
3132 size_t size_chars = num_chars * sizeof(T);
+
3133 size_t size = sizeof(uint32_t) + size_chars;
+
3134 size_t end_offset = m_offset + size;
+
3135 if (end_offset > m_reserved) {
+
3136 reserve(end_offset);
+
3137 if (!ok()) _Unlikely_
+
3138 return *this;
+
3139 }
+
3140 auto p = tok.m_podatki + m_offset;
+
3141 *reinterpret_cast<uint32_t*>(p) = HE2LE((uint32_t)num_chars);
+
3142 memcpy(p + sizeof(uint32_t), data, size_chars);
+
3143 m_offset = end_offset;
+
3144 if (m_offset > m_size)
+
3145 m_size = m_offset;
+
3146#if !CHECK_STREAM_STATE
+
3147 m_state = state_t::ok;
+
3148#endif
+
3149 return *this;
+
3150 }
+
3151
+
3157 size_t write_stream(_Inout_ basic & stream, _In_ size_t amount = SIZE_MAX)
+
3158 {
+
3159#if SET_FILE_OP_TIMES
+
3160 m_atime = m_mtime = time_point::now();
+
3161#endif
+
3162 size_t num_read, dst_offset = m_offset, dst_size = m_offset;
+
3163 size_t num_copied = 0, to_write = amount;
+
3164 m_state = state_t::ok;
+
3165 if (amount != SIZE_MAX) {
+
3166 dst_size = stdex::add(dst_size, amount);
+
3167 reserve(dst_size);
+
3168 if (!ok()) _Unlikely_
+
3169 return 0;
+
3170 while (to_write) {
+
3171 num_read = stream.read(m_data + dst_offset, to_write);
+
3172 dst_size = dst_offset += num_read;
+
3173 num_copied += num_read;
+
3174 to_write -= num_read;
+
3175 if (!stream.ok()) {
+
3176 if (stream.state() != state_t::eof)
+
3177 m_state = state_t::fail;
+
3178 break;
+
3179 }
+
3180 };
+
3181 }
+
3182 else {
+
3183 size_t block_size;
+
3184 while (to_write) {
+
3185 block_size = std::min(to_write, default_block_size);
+
3186 dst_size = stdex::add(dst_size, block_size);
+
3187 reserve(dst_size);
+
3188 if (!ok()) _Unlikely_
+
3189 break;
+
3190 num_read = stream.read(m_data + dst_offset, block_size);
+
3191 dst_size = dst_offset += num_read;
+
3192 num_copied += num_read;
+
3193 to_write -= num_read;
+
3194 if (!stream.ok()) {
+
3195 if (stream.state() != state_t::eof)
+
3196 m_state = state_t::fail;
+
3197 break;
+
3198 }
+
3199 };
+
3200 }
+
3201 m_offset = dst_offset;
+
3202 if (m_offset > m_size)
+
3203 m_size = m_offset;
+
3204 return num_copied;
+
3205 }
+
3206
+
3207 virtual void close()
+
3208 {
+
3209 if (m_manage && m_data)
+
3210 free(m_data);
+
3211 m_data = nullptr;
+
3212 m_manage = true;
+
3213 m_offset = 0;
+
3214 m_size = m_reserved = 0;
+
3215#if SET_FILE_OP_TIMES
+
3216 m_ctime = m_atime = m_mtime = time_point::min();
+
3217#endif
+
3218 m_state = state_t::ok;
+
3219 }
+
3220
+
3221 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
+
3222 {
+
3223 fpos_t target;
+
3224 switch (how) {
+
3225 case seek_t::beg: target = offset; break;
+
3226 case seek_t::cur: target = static_cast<fpos_t>(m_offset) + offset; break;
+
3227 case seek_t::end: target = static_cast<fpos_t>(m_size) + offset; break;
+
3228 default: throw std::invalid_argument("unknown seek origin");
+
3229 }
+
3230 if (target <= SIZE_MAX) {
+
3231 m_state = state_t::ok;
+
3232 return m_offset = static_cast<size_t>(target);
+
3233 }
+
3234 m_state = state_t::fail;
+
3235 return fpos_max;
+
3236 }
+
3237
+
3238 virtual fpos_t tell() const
+
3239 {
+
3240 return m_offset;
+
3241 }
+
3242
+
3243 virtual fsize_t size()
+
3244 {
+
3245 return m_size;
+
3246 }
+
3247
+
3248 virtual void truncate()
+
3249 {
+
3250#if SET_FILE_OP_TIMES
+
3251 m_atime = m_mtime = time_point::now();
+
3252#endif
+
3253 m_size = m_offset;
+
3254 reserve(m_offset);
+
3255 }
+
3256
+
3257#if SET_FILE_OP_TIMES
+
3258 virtual time_point ctime() const
+
3259 {
+
3260 return m_ctime;
+
3261 }
+
3262
+
3263 virtual time_point atime() const
+
3264 {
+
3265 return m_atime;
+
3266 }
+
3267
+
3268 virtual time_point mtime() const
+
3269 {
+
3270 return m_mtime;
+
3271 }
+
3272
+
3273 virtual void set_ctime(time_point date)
+
3274 {
+
3275 m_ctime = date;
+
3276 }
+
3277
+
3278 virtual void set_atime(time_point date)
+
3279 {
+
3280 m_atime = date;
+
3281 }
+
3282
+
3283 virtual void set_mtime(time_point date)
+
3284 {
+
3285 m_mtime = date;
+
3286 }
+
3287#endif
+
3288
+
3289 protected:
+
3297 template <class T>
+
3298 inline void set(_In_ fpos_t offset, _In_ const T data)
+
3299 {
+
3300#if SET_FILE_OP_TIMES
+
3301 m_atime = m_mtime = time_point::now();
+
3302#endif
+
3303 assert(offset + sizeof(T) < m_size);
+
3304 (*reinterpret_cast<T*>(m_data + offset)) = HE2LE(data);
+
3305 }
+
3306
+
3307 public:
+
3308 inline void set(_In_ fpos_t offset, _In_ const int8_t data) { set<int8_t>(offset, data); }
+
3309 inline void set(_In_ fpos_t offset, _In_ const int16_t data) { set<int16_t>(offset, data); }
+
3310 inline void set(_In_ fpos_t offset, _In_ const int32_t data) { set<int32_t>(offset, data); }
+
3311 inline void set(_In_ fpos_t offset, _In_ const int64_t data) { set<int64_t>(offset, data); }
+
3312 inline void set(_In_ fpos_t offset, _In_ const uint8_t data) { set<uint8_t>(offset, data); }
+
3313 inline void set(_In_ fpos_t offset, _In_ const uint16_t data) { set<uint16_t>(offset, data); }
+
3314 inline void set(_In_ fpos_t offset, _In_ const uint32_t data) { set<uint32_t>(offset, data); }
+
3315 inline void set(_In_ fpos_t offset, _In_ const uint64_t data) { set<uint64_t>(offset, data); }
+
3316#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
+
3317 inline void set(_In_ fpos_t offset, _In_ const size_t data) { set<size_t>(offset, data); }
+
3318#endif
+
3319 inline void set(_In_ fpos_t offset, _In_ const float data) { set<float>(offset, data); }
+
3320 inline void set(_In_ fpos_t offset, _In_ const double data) { set<double>(offset, data); }
+
3321 inline void set(_In_ fpos_t offset, _In_ const char data) { set<char>(offset, data); }
+
3322#ifdef _NATIVE_WCHAR_T_DEFINED
+
3323 inline void set(_In_ fpos_t offset, _In_ const wchar_t data) { set<wchar_t>(offset, data); }
+
3324#endif
+
3325
+
3333 protected:
+
3334 template <class T>
+
3335 inline void get(_In_ fpos_t offset, _Out_ T & data)
+
3336 {
+
3337 assert(offset + sizeof(T) < m_size);
+
3338 data = LE2HE(*(T*)(m_data + offset));
+
3339#if SET_FILE_OP_TIMES
+
3340 m_atime = time_point::now();
+
3341#endif
+
3342 }
+
3343
+
3344 public:
+
3345 inline void get(_In_ fpos_t offset, _Out_ int8_t & data) { get<int8_t>(offset, data); }
+
3346 inline void get(_In_ fpos_t offset, _Out_ int16_t & data) { get<int16_t>(offset, data); }
+
3347 inline void get(_In_ fpos_t offset, _Out_ int32_t & data) { get<int32_t>(offset, data); }
+
3348 inline void get(_In_ fpos_t offset, _Out_ int64_t & data) { get<int64_t>(offset, data); }
+
3349 inline void get(_In_ fpos_t offset, _Out_ uint8_t & data) { get<uint8_t>(offset, data); }
+
3350 inline void get(_In_ fpos_t offset, _Out_ uint16_t & data) { get<uint16_t>(offset, data); }
+
3351 inline void get(_In_ fpos_t offset, _Out_ uint32_t & data) { get<uint32_t>(offset, data); }
+
3352 inline void get(_In_ fpos_t offset, _Out_ uint64_t & data) { get<uint64_t>(offset, data); }
+
3353#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
+
3354 inline void get(_In_ fpos_t offset, _Out_ size_t & data) { get<size_t>(offset, data); }
+
3355#endif
+
3356 inline void get(_In_ fpos_t offset, _Out_ float& data) { get<float>(offset, data); }
+
3357 inline void get(_In_ fpos_t offset, _Out_ double& data) { get<double>(offset, data); }
+
3358 inline void get(_In_ fpos_t offset, _Out_ char& data) { get<char>(offset, data); }
+
3359#ifdef _NATIVE_WCHAR_T_DEFINED
+
3360 inline void get(_In_ fpos_t offset, _Out_ wchar_t& data) { get<wchar_t>(offset, data); }
+
3361#endif
+
3362
+
3363 inline memory_file& operator <<(_In_ const int8_t data) { return write_data(data); }
+
3364 inline memory_file& operator >>(_Out_ int8_t & data) { return read_data(data); }
+
3365 inline memory_file& operator <<(_In_ const int16_t data) { return write_data(data); }
+
3366 inline memory_file& operator >>(_Out_ int16_t & data) { return read_data(data); }
+
3367 inline memory_file& operator <<(_In_ const int32_t data) { return write_data(data); }
+
3368 inline memory_file& operator >>(_Out_ int32_t & data) { return read_data(data); }
+
3369 inline memory_file& operator <<(_In_ const int64_t data) { return write_data(data); }
+
3370 inline memory_file& operator >>(_Out_ int64_t & data) { return read_data(data); }
+
3371 inline memory_file& operator <<(_In_ const uint8_t data) { return write_data(data); }
+
3372 inline memory_file& operator >>(_Out_ uint8_t & data) { return read_data(data); }
+
3373 inline memory_file& operator <<(_In_ const uint16_t data) { return write_data(data); }
+
3374 inline memory_file& operator >>(_Out_ uint16_t & data) { return read_data(data); }
+
3375 inline memory_file& operator <<(_In_ const uint32_t data) { return write_data(data); }
+
3376 inline memory_file& operator >>(_Out_ uint32_t & data) { return read_data(data); }
+
3377 inline memory_file& operator <<(_In_ const uint64_t data) { return write_data(data); }
+
3378 inline memory_file& operator >>(_Out_ uint64_t & data) { return read_data(data); }
+
3379#if defined(_WIN64) && defined(_NATIVE_SIZE_T_DEFINED)
+
3380 inline memory_file& operator <<(_In_ const size_t data) { return write_data(data); }
+
3381 inline memory_file& operator >>(_Out_ size_t & data) { return read_data(data); }
+
3382#endif
+
3383 inline memory_file& operator <<(_In_ const float data) { return write_data(data); }
+
3384 inline memory_file& operator >>(_Out_ float& data) { return read_data(data); }
+
3385 inline memory_file& operator <<(_In_ const double data) { return write_data(data); }
+
3386 inline memory_file& operator >>(_Out_ double& data) { return read_data(data); }
+
3387 inline memory_file& operator <<(_In_ const char data) { return write_data(data); }
+
3388 inline memory_file& operator >>(_Out_ char& data) { return read_data(data); }
+
3389#ifdef _NATIVE_WCHAR_T_DEFINED
+
3390 inline memory_file& operator <<(_In_ const wchar_t data) { return write_data(data); }
+
3391 inline memory_file& operator >>(_Out_ wchar_t& data) { return read_data(data); }
+
3392#endif
+
3393 template <class T>
+
3394 inline memory_file& operator <<(_In_ const T * data) { return write_str(data); }
+
3395 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
3396 inline memory_file& operator >>(_Inout_ std::basic_string<_Elem, _Traits, _Ax>&data) { return read_str(data); }
+
3397
+
3398 protected:
+
3399 uint8_t* m_data;
+
3400 bool m_manage;
+
3401 size_t m_offset;
+
3402 size_t m_size;
+
3403 size_t m_reserved;
+
3404#if SET_FILE_OP_TIMES
+
3405 time_point
+
3406 m_ctime,
+
3407 m_atime,
+
3408 m_mtime;
+
3409#endif
+
3410 };
+
3411
+
3415 class fifo : public basic {
+
3416 public:
+
3417 fifo() :
+
3418 m_offset(0),
+
3419 m_size(0),
+
3420 m_head(nullptr),
+
3421 m_tail(nullptr)
+
3422 {}
+
3423
+
3424 virtual ~fifo()
+
3425 {
+
3426 while (m_head) {
+
3427 auto p = m_head;
+
3428 m_head = p->next;
+
3429 delete p;
+
3430 }
+
3431 }
+
3432
+
3433#pragma warning(suppress: 6101) // See [2] below
+
3434 virtual _Success_(return != 0 || length == 0) size_t read(
+
3435 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
3436 {
+
3437 assert(data || !length);
+
3438 for (size_t to_read = length;;) {
+
3439 if (!m_head) _Unlikely_ {
+
3440 // [1] Code analysis misses length - to_read bytes were written to data in previous loop iterations.
+
3441 m_state = to_read < length || !length ? state_t::ok : state_t::eof;
+
3442 return length - to_read;
+
3443 }
+
3444 size_t remaining = m_head->size - m_offset;
+
3445 if (remaining > to_read) {
+
3446 memcpy(data, m_head->data + m_offset, to_read);
+
3447 m_offset += to_read;
+
3448 m_size -= to_read;
+
3449 m_state = state_t::ok;
+
3450 return length;
+
3451 }
+
3452 memcpy(data, m_head->data + m_offset, remaining);
+
3453 m_offset = 0;
+
3454 m_size -= remaining;
+
3455 reinterpret_cast<uint8_t*&>(data) += remaining;
+
3456 to_read -= remaining;
+
3457 auto p = m_head;
+
3458 m_head = p->next;
+
3459 delete p;
+
3460 }
+
3461 }
+
3462
+
3463 virtual _Success_(return != 0) size_t write(
+
3464 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
3465 {
+
3466 assert(data || !length);
+
3467 try {
+
3468 std::unique_ptr<node_t> n(reinterpret_cast<node_t*>(new uint8_t[sizeof(node_t) + length]));
+
3469 n->next = nullptr;
+
3470 n->size = length;
+
3471 memcpy(n->data, data, length);
+
3472 m_size += length;
+
3473 if (m_head)
+
3474 m_tail = m_tail->next = n.release();
+
3475 else
+
3476 m_head = m_tail = n.release();
+
3477 m_state = state_t::ok;
+
3478 return length;
+
3479 }
+
3480 catch (std::bad_alloc) {
+
3481 m_state = state_t::fail;
+
3482 return 0;
+
3483 }
+
3484 }
+
3485
+
3486 virtual void close()
+
3487 {
+
3488 m_size = m_offset = 0;
+
3489 while (m_head) {
+
3490 auto p = m_head;
+
3491 m_head = p->next;
+
3492 delete p;
+
3493 }
+
3494 m_state = state_t::ok;
+
3495 }
+
3496
+
3500 inline size_t size() const { return m_size; };
+
3501
+
3502 protected:
+
3503 size_t m_offset, m_size;
+
3504 struct node_t {
+
3505 node_t* next;
+
3506 size_t size;
+
3507#pragma warning(suppress:4200)
+
3508 uint8_t data[0];
+
3509 } *m_head, * m_tail;
+
3510 };
+
3511
+
3515 class diag_file : public basic_file {
+
3516 public:
+
3517 diag_file(_In_count_(num_files) basic_file* const* files, _In_ size_t num_files) :
+
3518 basic(num_files ? files[0]->state() : state_t::fail),
+
3519 m_files(files, files + num_files)
+
3520 {
+
3521 }
+
3522
+
3523 virtual _Success_(return != 0 || length == 0) size_t read(
+
3524 _Out_writes_bytes_to_opt_(length, return) void* data, _In_ size_t length)
+
3525 {
+
3526 assert(data || !length);
+
3527 if (m_files.empty()) {
+
3528 m_state = state_t::fail;
+
3529 return 0;
+
3530 }
+
3531 size_t result = m_files[0]->read(data, length);
+
3532 _Analysis_assume_(result <= length);
+
3533 m_state = m_files[0]->state();
+
3534 if (length > m_tmp.size())
+
3535 m_tmp.resize(length);
+
3536 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3537 if (m_files[i]->read(m_tmp.data(), length) != result ||
+
3538 memcmp(m_tmp.data(), data, result))
+
3539 throw std::runtime_error("read mismatch");
+
3540 if (m_files[i]->state() != m_state)
+
3541 throw std::runtime_error("state mismatch");
+
3542 }
+
3543 return result;
+
3544 }
+
3545
+
3546 virtual _Success_(return != 0) size_t write(
+
3547 _In_reads_bytes_opt_(length) const void* data, _In_ size_t length)
+
3548 {
+
3549 if (m_files.empty()) {
+
3550 m_state = state_t::fail;
+
3551 return 0;
+
3552 }
+
3553 size_t result = m_files[0]->write(data, length);
+
3554 m_state = m_files[0]->state();
+
3555 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3556 if (m_files[i]->write(data, length) != result)
+
3557 throw std::runtime_error("write mismatch");
+
3558 if (m_files[i]->state() != m_state)
+
3559 throw std::runtime_error("state mismatch");
+
3560 }
+
3561 return result;
+
3562 }
+
3563
+
3564 virtual void flush()
+
3565 {
+
3566 if (m_files.empty()) {
+
3567 m_state = state_t::ok;
+
3568 return;
+
3569 }
+
3570 m_files[0]->flush();
+
3571 m_state = m_files[0]->state();
+
3572 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3573 m_files[i]->flush();
+
3574 if (m_files[i]->state() != m_state)
+
3575 throw std::runtime_error("state mismatch");
+
3576 }
+
3577 }
+
3578
+
3579 virtual void close()
+
3580 {
+
3581 if (m_files.empty()) {
+
3582 m_state = state_t::ok;
+
3583 return;
+
3584 }
+
3585 m_files[0]->close();
+
3586 m_state = m_files[0]->state();
+
3587 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3588 m_files[i]->close();
+
3589 if (m_files[i]->state() != m_state)
+
3590 throw std::runtime_error("state mismatch");
+
3591 }
+
3592 m_tmp.clear();
+
3593 m_tmp.shrink_to_fit();
+
3594 }
+
3595
+
3596 virtual fpos_t seek(_In_ foff_t offset, _In_ seek_t how = seek_t::beg)
+
3597 {
+
3598 if (m_files.empty()) {
+
3599 m_state = state_t::fail;
+
3600 return fpos_max;
+
3601 }
+
3602 fpos_t result = m_files[0]->seek(offset, how);
+
3603 m_state = m_files[0]->state();
+
3604 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3605 if (m_files[i]->seek(offset, how) != result)
+
3606 throw std::runtime_error("seek mismatch");
+
3607 if (m_files[i]->state() != m_state)
+
3608 throw std::runtime_error("state mismatch");
+
3609 }
+
3610 return result;
+
3611 }
+
3612
+
3613 virtual fpos_t tell() const
+
3614 {
+
3615 if (m_files.empty())
+
3616 return fpos_max;
+
3617 fpos_t result = m_files[0]->tell();
+
3618 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3619 if (m_files[i]->tell() != result)
+
3620 throw std::runtime_error("tell mismatch");
+
3621 }
+
3622 return result;
+
3623 }
+
3624
+
3625 virtual void lock(_In_ fpos_t offset, _In_ fsize_t length)
+
3626 {
+
3627 if (m_files.empty())
+
3628 m_state = state_t::fail;
+
3629 m_files[0]->lock(offset, length);
+
3630 m_state = m_files[0]->state();
+
3631 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3632 m_files[i]->lock(offset, length);
+
3633 if (m_files[i]->state() != m_state)
+
3634 throw std::runtime_error("state mismatch");
+
3635 }
+
3636 }
+
3637
+
3638 virtual void unlock(_In_ fpos_t offset, _In_ fsize_t length)
+
3639 {
+
3640 if (m_files.empty())
+
3641 m_state = state_t::fail;
+
3642 m_files[0]->unlock(offset, length);
+
3643 m_state = m_files[0]->state();
+
3644 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3645 m_files[i]->unlock(offset, length);
+
3646 if (m_files[i]->state() != m_state)
+
3647 throw std::runtime_error("state mismatch");
+
3648 }
+
3649 }
+
3650
+
3651 virtual fsize_t size()
+
3652 {
+
3653 if (m_files.empty()) {
+
3654 m_state = state_t::fail;
+
3655 return 0;
+
3656 }
+
3657 fsize_t result = m_files[0]->size();
+
3658 m_state = m_files[0]->state();
+
3659 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3660 if (m_files[i]->size() != result)
+
3661 throw std::runtime_error("size mismatch");
+
3662 if (m_files[i]->state() != m_state)
+
3663 throw std::runtime_error("state mismatch");
+
3664 }
+
3665 return result;
+
3666 }
+
3667
+
3668 virtual void truncate()
+
3669 {
+
3670 if (m_files.empty())
+
3671 m_state = state_t::fail;
+
3672 m_files[0]->truncate();
+
3673 m_state = m_files[0]->state();
+
3674 for (size_t i = 1, n = m_files.size(); i < n; ++i) {
+
3675 m_files[i]->truncate();
+
3676 if (m_files[i]->state() != m_state)
+
3677 throw std::runtime_error("state mismatch");
+
3678 }
+
3679 }
+
3680
+
3681 protected:
+
3682 std::vector<basic_file*> m_files;
+
3683 std::vector<uint8_t> m_tmp;
+
3684 };
+
3685 }
+
3686}
+
Provides read-ahead stream capability.
Definition stream.hpp:1071
+
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:1085
+
Provides write-back stream capability.
Definition stream.hpp:1139
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1176
+
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:1152
+
Basic seekable stream operations.
Definition stream.hpp:655
+
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:698
+
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:745
+
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:714
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
+
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:818
+
fpos_t seekbeg(fpos_t offset)
Seeks to absolute file position.
Definition stream.hpp:682
+
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:657
+
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:787
+
fpos_t seekcur(foff_t offset)
Seeks to relative from current file position.
Definition stream.hpp:689
+
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:753
+
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:769
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 void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:724
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 time_point mtime() const
Returns file modification time.
Definition stream.hpp:761
+
fpos_t seekend(foff_t offset)
Seeks to relative from end file position.
Definition stream.hpp:696
+
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:778
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:1998
-
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:2056
-
virtual void flush()
Persists volatile element data.
Definition stream.hpp:2114
-
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:2005
-
virtual void close()
Closes the stream.
Definition stream.hpp:2103
-
‍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:2128
-
Cached file.
Definition stream.hpp:1629
-
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:1870
-
fpos_t m_offset
Logical absolute file position.
Definition stream.hpp:1986
-
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1849
-
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:1675
-
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:1875
-
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:1842
-
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1836
-
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:1884
-
virtual void close()
Closes the stream.
Definition stream.hpp:1790
-
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:1906
-
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1830
-
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1799
-
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:1737
-
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:1893
-
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:1825
-
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:1898
-
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1810
-
Cached file-system file.
Definition stream.hpp:2676
-
cached_file(const sys_char *filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:2692
-
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2706
-
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:3514
-
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:3650
-
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3667
-
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:3545
-
virtual void close()
Closes the stream.
Definition stream.hpp:3578
-
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:3624
-
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:3637
-
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3595
-
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:3612
-
virtual void flush()
Persists volatile element data.
Definition stream.hpp:3563
-
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:3522
-
In-memory FIFO queue.
Definition stream.hpp:3414
-
virtual void close()
Closes the stream.
Definition stream.hpp:3485
-
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:3462
-
size_t size() const
Returns total size of pending data in the queue.
Definition stream.hpp:3499
-
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:3433
-
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:2366
-
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2609
-
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2502
-
file(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2376
-
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2623
-
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2595
-
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:2653
-
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2635
-
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2387
-
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2479
-
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2545
-
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2585
-
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:2527
-
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2440
-
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:2461
-
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:2734
-
void load(const sys_char *filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:2858
-
size_t m_size
file size
Definition stream.hpp:3401
-
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:3334
-
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3156
-
uint8_t * m_data
file data
Definition stream.hpp:3398
-
memory_file & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:2955
-
virtual void close()
Closes the stream.
Definition stream.hpp:3206
-
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:2916
-
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:3237
-
size_t m_reserved
reserved file size
Definition stream.hpp:3402
-
memory_file(size_t size, state_t state=state_t::ok)
Creates an empty file of reserved size.
Definition stream.hpp:2755
-
void reserve(size_t required, bool tight=false) noexcept
Reallocates memory.
Definition stream.hpp:2829
-
memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:2995
-
void write_byte(uint8_t byte, size_t amount=1)
Writes a byte of data.
Definition stream.hpp:3050
-
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:3297
-
size_t m_offset
file pointer
Definition stream.hpp:3400
-
memory_file(const sys_char *filename, int mode)
Loads content from file-system file.
Definition stream.hpp:2812
-
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:3242
-
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3220
-
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3247
-
memory_file & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:3083
-
memory_file & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3121
-
bool m_manage
may reallocate m_data?
Definition stream.hpp:3399
-
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:2802
-
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:3026
-
void save(const sys_char *filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:2891
-
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:2779
-
const void * data() const
Returns pointer to data.
Definition stream.hpp:2914
-
Definition stream.hpp:985
+
OS data stream (file, pipe, socket...)
Definition stream.hpp:1999
+
virtual size_t write(_In_reads_bytes_opt_(length) const void *data, size_t length)
Writes block of data to the stream.
Definition stream.hpp:2057
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:2115
+
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:2006
+
virtual void close()
Closes the stream.
Definition stream.hpp:2104
+
‍UTF-8 byte-order-mark
Definition stream.hpp:72
+
bool ok() const
Returns true if the stream state is clean i.e. previous operation was succesful.
Definition stream.hpp:166
+
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:556
+
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:406
+
state_t state() const
Returns stream state after last operation.
Definition stream.hpp:161
+
basic & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:430
+
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:542
+
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:569
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:117
+
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:133
+
virtual void close()
Closes the stream.
Definition stream.hpp:125
+
uint8_t read_byte()
Reads one byte of data.
Definition stream.hpp:201
+
virtual std::vector< uint8_t > read_remainder(size_t max_length=SIZE_MAX)
Reads and returns remainder of the stream.
Definition stream.hpp:175
+
size_t write_sprintf(_Printf_format_string_params_(2) const char *format, locale_t locale,...)
Writes formatted string to the stream.
Definition stream.hpp:528
+
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:359
+
size_t readln(std::basic_string< char, _Traits, _Ax > &str)
Reads stream to the end-of-line or end-of-file.
Definition stream.hpp:297
+
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:338
+
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:374
+
basic & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:455
+
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:87
+
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:309
+
void write_charset(charset_id charset)
Writes UTF8 or UTF-16 byte-order-mark.
Definition stream.hpp:515
+
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:321
+
basic & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:278
+
fsize_t write_stream(basic &stream, fsize_t amount=fsize_max)
Writes content of another stream.
Definition stream.hpp:490
+
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:105
+
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:392
+
void write_byte(uint8_t byte, fsize_t amount=1)
Writes a byte of data.
Definition stream.hpp:212
+
basic & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:250
+
Buffered read/write stream.
Definition stream.hpp:1210
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1313
+
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:1231
+
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:1267
+
Buffered OS data stream (file, pipe, socket...)
Definition stream.hpp:2129
+
Cached file.
Definition stream.hpp:1630
+
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:1871
+
fpos_t m_offset
Logical absolute file position.
Definition stream.hpp:1987
+
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1850
+
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:1676
+
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:1876
+
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:1843
+
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1837
+
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:1885
+
virtual void close()
Closes the stream.
Definition stream.hpp:1791
+
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:1907
+
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1831
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1800
+
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:1738
+
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:1894
+
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:1826
+
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:1899
+
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1811
+
Cached file-system file.
Definition stream.hpp:2677
+
cached_file(const sys_char *filename, int mode, size_t cache_size=default_cache_size)
Opens file.
Definition stream.hpp:2693
+
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2707
+
Modifies data on the fly when reading from/writing to a source stream.
Definition stream.hpp:848
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:889
+
virtual void close()
Closes the stream.
Definition stream.hpp:883
+
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:867
+
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:875
+
Compares multiple files to perform the same.
Definition stream.hpp:3515
+
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:3651
+
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3668
+
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:3546
+
virtual void close()
Closes the stream.
Definition stream.hpp:3579
+
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:3625
+
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:3638
+
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3596
+
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:3613
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:3564
+
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:3523
+
In-memory FIFO queue.
Definition stream.hpp:3415
+
virtual void close()
Closes the stream.
Definition stream.hpp:3486
+
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:3463
+
size_t size() const
Returns total size of pending data in the queue.
Definition stream.hpp:3500
+
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:3434
+
Limits file reading/writing to a predefined window.
Definition stream.hpp:1520
+
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:1613
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:1563
+
virtual void skip(fsize_t amount)
Skips given amount of bytes of data on the stream.
Definition stream.hpp:1576
+
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:1569
+
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:1608
+
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:1543
+
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:1588
+
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:1529
+
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:1598
+
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:1582
+
virtual void close()
Closes the stream.
Definition stream.hpp:1557
+
File-system file.
Definition stream.hpp:2367
+
virtual time_point mtime() const
Returns file modification time.
Definition stream.hpp:2610
+
virtual void unlock(fpos_t offset, fsize_t length)
Unlocks file section for exclusive access.
Definition stream.hpp:2503
+
file(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2377
+
virtual void set_ctime(time_point date)
Sets file create time.
Definition stream.hpp:2624
+
virtual time_point atime() const
Returns file access time.
Definition stream.hpp:2596
+
virtual void set_mtime(time_point date)
Sets file modification time.
Definition stream.hpp:2654
+
virtual void set_atime(time_point date)
Sets file access time.
Definition stream.hpp:2636
+
void open(const sys_char *filename, int mode)
Opens file.
Definition stream.hpp:2388
+
virtual void lock(fpos_t offset, fsize_t length)
Locks file section for exclusive access.
Definition stream.hpp:2480
+
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:2546
+
virtual time_point ctime() const
Returns file creation time.
Definition stream.hpp:2586
+
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:2528
+
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:2441
+
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:2462
+
Limits reading from/writing to stream to a predefined number of bytes.
Definition stream.hpp:1361
+
fsize_t read_limit
Number of bytes left that may be read from the stream.
Definition stream.hpp:1421
+
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:1369
+
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:1394
+
fsize_t write_limit
Number of bytes left, that can be written to the stream.
Definition stream.hpp:1422
+
In-memory file.
Definition stream.hpp:2735
+
void load(const sys_char *filename, int mode)
Loads content from a file-system file.
Definition stream.hpp:2859
+
size_t m_size
file size
Definition stream.hpp:3402
+
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:3335
+
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3157
+
uint8_t * m_data
file data
Definition stream.hpp:3399
+
memory_file & read_data(T &data)
Reads one primitive data type.
Definition stream.hpp:2956
+
virtual void close()
Closes the stream.
Definition stream.hpp:3207
+
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:2917
+
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:3238
+
size_t m_reserved
reserved file size
Definition stream.hpp:3403
+
memory_file(size_t size, state_t state=state_t::ok)
Creates an empty file of reserved size.
Definition stream.hpp:2756
+
void reserve(size_t required, bool tight=false) noexcept
Reallocates memory.
Definition stream.hpp:2830
+
memory_file & read_str(std::basic_string< _Elem, _Traits, _Ax > &data)
Reads length-prefixed string from the stream.
Definition stream.hpp:2996
+
void write_byte(uint8_t byte, size_t amount=1)
Writes a byte of data.
Definition stream.hpp:3051
+
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:3298
+
size_t m_offset
file pointer
Definition stream.hpp:3401
+
memory_file(const sys_char *filename, int mode)
Loads content from file-system file.
Definition stream.hpp:2813
+
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:3243
+
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3221
+
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3248
+
memory_file & write_data(const T data)
Writes one primitive data type.
Definition stream.hpp:3084
+
memory_file & write_str(const T *data)
Writes string to the stream length-prefixed.
Definition stream.hpp:3122
+
bool m_manage
may reallocate m_data?
Definition stream.hpp:3400
+
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:2803
+
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:3027
+
void save(const sys_char *filename, int mode)
Saves content to a file-system file.
Definition stream.hpp:2892
+
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:2780
+
const void * data() const
Returns pointer to data.
Definition stream.hpp:2915
+
Definition stream.hpp:986
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:63
-
virtual void close()
Closes object.
Definition system.hpp:104
+
size_t num_written
Number of bytes written.
Definition stream.hpp:1033
+
size_t length
Byte limit of data to write.
Definition stream.hpp:1032
+
const void * data
Data to write.
Definition stream.hpp:1031
+
Replicates writing of the same data to multiple streams.
Definition stream.hpp:903
+
void push_back(basic *source)
Adds stream on the list.
Definition stream.hpp:922
+
virtual void flush()
Persists volatile element data.
Definition stream.hpp:979
+
void remove(basic *source)
Removes stream from the list.
Definition stream.hpp:930
+
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:947
+
virtual void close()
Closes the stream.
Definition stream.hpp:974
+
Limits reading from/writing to stream to a predefined window.
Definition stream.hpp:1429
+
fpos_t write_offset
Number of bytes to discard on write.
Definition stream.hpp:1513
+
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:1470
+
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:1437
+
fpos_t read_offset
Number of bytes to skip on read.
Definition stream.hpp:1512
+
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:64
+
virtual void close()
Closes object.
Definition system.hpp:105
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:1964
-
interval< fpos_t > region
valid data region
Definition stream.hpp:1972
-
Definition stream.hpp:3503
+
Definition stream.hpp:1338
+
Definition stream.hpp:1965
+
interval< fpos_t > region
valid data region
Definition stream.hpp:1973
+
Definition stream.hpp:3504
diff --git a/string_8hpp_source.html b/string_8hpp_source.html index de4c3dd46..50374b8f5 100644 --- a/string_8hpp_source.html +++ b/string_8hpp_source.html @@ -87,718 +87,730 @@ $(function() {
8#include "sal.hpp"
9#include <assert.h>
10#include <ctype.h>
-
11#include <stdarg.h>
-
12#include <stdint.h>
-
13#include <stdexcept>
-
14
-
15namespace stdex
-
16{
-
17#ifdef _WIN32
-
18 using locale_t = _locale_t;
-
19#else
-
20 using locale_t = ::locale_t;
-
21#endif
-
22
-
26#ifdef _WIN32
-
27 typedef wchar_t utf16_t;
-
28#else
-
29 typedef char16_t utf16_t;
-
30#endif
-
31
-
37 inline bool is_high_surrogate(_In_ utf16_t chr)
-
38 {
-
39 return 0xd800 < chr && chr < 0xdc00;
-
40 }
-
41
-
47 inline bool is_low_surrogate(_In_ utf16_t chr)
-
48 {
-
49 return 0xdc00 < chr && chr < 0xe000;
-
50 }
-
51
-
57 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
-
58 {
-
59 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
-
60 }
-
61
-
67 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
-
68 {
-
69 assert(is_surrogate_pair(str));
-
70 return
-
71 ((char32_t)(str[0] - 0xd800) << 10) +
-
72 (char32_t)(str[1] - 0xdc00) +
-
73 0x10000;
-
74 }
-
75
-
81 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
-
82 {
-
83 assert(chr >= 0x10000);
-
84 chr -= 0x10000;
-
85 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
-
86 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
-
87 }
-
88
-
94 inline bool iscombining(_In_ char32_t chr)
-
95 {
-
96 return
-
97 0x0300 <= chr && chr < 0x0370 ||
-
98 0x1dc0 <= chr && chr < 0x1e00 ||
-
99 0x20d0 <= chr && chr < 0x2100 ||
-
100 0xfe20 <= chr && chr < 0xfe30;
-
101 }
-
102
-
108 template <class T>
-
109 inline size_t islbreak(_In_ T chr)
-
110 {
-
111 return chr == '\n' || chr == '\r';
-
112 }
-
113
-
120 template <class T>
-
121 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
-
122 {
-
123 _Analysis_assume_(chr || !count);
-
124 if (count >= 2 && (chr[0] == '\r' && chr[1] == '\n' || chr[0] == '\n' && chr[1] == '\r'))
-
125 return 2;
-
126 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
-
127 return 1;
-
128 return 0;
-
129 }
-
130
-
137 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
-
138 {
-
139 _Analysis_assume_(glyph || !count);
-
140 if (count) {
-
141#ifdef _WIN32
-
142 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
-
143#else
-
144 size_t i = 1;
-
145#endif
-
146 for (; i < count && iscombining(glyph[i]); ++i);
-
147 return i;
-
148 }
-
149 return 0;
-
150 }
-
151
-
159 template <class T>
-
160 inline size_t strlen(_In_z_ const T* str)
-
161 {
-
162 assert(str);
-
163 size_t i;
-
164 for (i = 0; str[i]; ++i);
-
165 return i;
-
166 }
-
167
-
176 template <class T>
-
177 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
-
178 {
-
179 assert(str);
-
180 size_t i;
-
181 for (i = 0; i < count && str[i]; ++i);
-
182 return i;
-
183 }
-
184
-
185 constexpr auto npos{ static_cast<size_t>(-1) };
-
186
-
196 template <class T>
-
197 inline size_t strnchr(
-
198 _In_reads_or_z_opt_(count) const T* str,
-
199 _In_ size_t count,
-
200 _In_ T chr)
-
201 {
-
202 assert(str || !count);
-
203 for (size_t i = 0; i < count && str[i]; ++i)
-
204 if (str[i] == chr) return i;
-
205 return npos;
-
206 }
-
207
-
217 template <class T>
-
218 inline size_t strrnchr(
-
219 _In_reads_or_z_opt_(count) const T* str,
-
220 _In_ size_t count,
-
221 _In_ T chr)
-
222 {
-
223 assert(str || !count);
-
224 size_t z = npos;
-
225 for (size_t i = 0; i < count && str[i]; ++i)
-
226 if (str[i] == chr) z = i;
-
227 return z;
-
228 }
-
229
-
239 template <class T>
-
240 inline size_t strnichr(
-
241 _In_reads_or_z_opt_(count) const T* str,
-
242 _In_ size_t count,
-
243 _In_ T chr,
-
244 _In_ const std::locale& locale)
-
245 {
-
246 assert(str || !count);
-
247 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
-
248 chr = ctype.tolower(chr);
-
249 for (size_t i = 0; i < count && str[i]; ++i)
-
250 if (ctype.tolower(str[i]) == chr) return i;
-
251 return npos;
-
252 }
-
253
-
263 template <class T>
-
264 inline size_t strrnichr(
-
265 _In_reads_or_z_opt_(count) const T* str,
-
266 _In_ size_t count,
-
267 _In_ T chr,
-
268 _In_ const std::locale& locale)
-
269 {
-
270 assert(str || !count);
-
271 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
-
272 chr = ctype.tolower(chr);
-
273 size_t z = npos;
-
274 for (size_t i = 0; i < count && str[i]; ++i)
-
275 if (ctype.tolower(str[i]) == chr) z = i;
-
276 return z;
-
277 }
-
278
-
289 template <class T1, class T2>
-
290 inline int strncmp(
-
291 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
-
292 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
-
293 {
-
294 assert(str1 || !count1);
-
295 assert(str2 || !count2);
-
296 size_t i; T1 a; T2 b;
-
297 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
-
298 if (a > b) return +1;
-
299 if (a < b) return -1;
-
300 }
-
301 if (i < count1 && str1[i]) return +1;
-
302 if (i < count2 && str2[i]) return -1;
-
303 return 0;
-
304 }
-
305
-
316 template <class T>
-
317 inline int strncoll(
-
318 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
-
319 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
-
320 _In_ const std::locale& locale)
-
321 {
-
322 assert(str1 || !count1);
-
323 assert(str2 || !count2);
-
324 auto& collate = std::use_facet<std::collate<T>>(locale);
-
325 return collate.compare(str1, str1 + count1, str2, str2 + count2);
-
326 }
-
327
-
338 template <class T1, class T2>
-
339 inline int strnicmp(
-
340 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
-
341 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
-
342 _In_ const std::locale& locale)
-
343 {
-
344 assert(str1 || !count1);
-
345 assert(str2 || !count2);
-
346 size_t i; T1 a; T2 b;
-
347 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
-
348 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
-
349 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
-
350 if (a > b) return +1;
-
351 if (a < b) return -1;
-
352 }
-
353 if (i < count1 && str1[i]) return +1;
-
354 if (i < count2 && str2[i]) return -1;
-
355 return 0;
-
356 }
-
357
-
367 template <class T1, class T2>
-
368 inline size_t strnstr(
-
369 _In_reads_or_z_opt_(count) const T1* str,
-
370 _In_ size_t count,
-
371 _In_z_ const T2* sample)
-
372 {
-
373 assert(str || !count);
-
374 assert(sample);
-
375 for (size_t offset = 0;; ++offset) {
-
376 for (size_t i = offset, j = 0;; ++i, ++j) {
-
377 if (!sample[j])
-
378 return offset;
-
379 if (i >= count || !str[i])
-
380 return npos;
-
381 if (str[i] != sample[j])
-
382 break;
-
383 }
-
384 }
-
385 }
-
386
-
396 template <class T1, class T2>
-
397 inline size_t strnistr(
-
398 _In_reads_or_z_opt_(count) const T1* str,
-
399 _In_ size_t count,
-
400 _In_z_ const T2* sample,
-
401 _In_ const std::locale& locale)
-
402 {
-
403 assert(str || !count);
-
404 assert(sample);
-
405 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
-
406 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
-
407 for (size_t offset = 0;; ++offset) {
-
408 for (size_t i = offset, j = 0;; ++i, ++j) {
-
409 if (!sample[j])
-
410 return offset;
-
411 if (i >= count || !str[i])
-
412 return npos;
-
413 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
-
414 break;
-
415 }
-
416 }
-
417 }
-
418
-
427 template <class T1, class T2>
-
428 inline size_t strcpy(
-
429 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
-
430 _In_z_ const T2* src)
-
431 {
-
432 assert(dst && src);
-
433 for (size_t i = 0; ; ++i) {
-
434 if ((dst[i] = src[i]) == 0)
-
435 return i;
-
436 }
-
437 }
-
438
-
448 template <class T1, class T2>
-
449 inline size_t strncpy(
-
450 _Out_writes_(count) _Post_maybez_ T1* dst,
-
451 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
-
452 {
-
453 assert(dst && src || !count);
-
454 for (size_t i = 0; ; ++i) {
-
455 if (i >= count)
-
456 return i;
-
457 if ((dst[i] = src[i]) == 0)
-
458 return i;
-
459 }
-
460 }
-
461
-
472 template <class T1, class T2>
-
473 inline size_t strncpy(
-
474 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
-
475 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
-
476 {
-
477 assert(dst || !count_dst);
-
478 assert(src || !count_src);
-
479 for (size_t i = 0; ; ++i)
-
480 {
-
481 if (i > count_dst)
-
482 return i;
-
483 if (i > count_src) {
-
484 dst[i] = 0;
-
485 return i;
-
486 }
-
487 if ((dst[i] = src[i]) == 0)
-
488 return i;
-
489 }
-
490 }
-
491
-
500 template <class T1, class T2>
-
501 inline size_t strcat(
-
502 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
-
503 _In_z_ const T2* src)
-
504 {
-
505 assert(dst && src);
-
506 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
-
507 if ((dst[j] = src[i]) == 0)
-
508 return j;
-
509 }
-
510 }
-
511
-
521 template <class T1, class T2>
-
522 inline size_t strncat(
-
523 _Out_writes_(count) _Post_maybez_ T1* dst,
-
524 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
-
525 {
-
526 assert(dst && src || !count);
-
527 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
-
528 if (i >= count)
-
529 return j;
-
530 if ((dst[j] = src[i]) == 0)
-
531 return j;
-
532 }
-
533 }
-
534
-
545 template <class T1, class T2>
-
546 inline size_t strncat(
-
547 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
-
548 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
-
549 {
-
550 assert(dst || !count_dst);
-
551 assert(src || !count_src);
-
552 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
-
553 {
-
554 if (j > count_dst)
-
555 return j;
-
556 if (i > count_src) {
-
557 dst[j] = 0;
-
558 return j;
-
559 }
-
560 if ((dst[j] = src[i]) == 0)
-
561 return j;
-
562 }
-
563 }
-
564
-
574 template <class T>
-
575 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
-
576 {
-
577 assert(dst);
-
578 assert(src);
-
579 size_t i, j;
-
580 for (i = j = 0; src[j];) {
-
581 if (src[j] != '\r' || src[j + 1] != '\n')
-
582 dst[i++] = src[j++];
-
583 else {
-
584 dst[i++] = '\n';
-
585 j += 2;
-
586 }
-
587 }
-
588 dst[i] = 0;
-
589 return i;
-
590 }
-
591
-
593 template <class T, class T_bin>
-
594 inline T_bin strtoint(
-
595 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
596 _Out_opt_ size_t* end,
-
597 _In_ int radix,
-
598 _Out_ uint8_t& flags)
-
599 {
-
600 assert(str || !count);
-
601 assert(radix == 0 || 2 <= radix && radix <= 36);
-
602
-
603 size_t i = 0;
-
604 T_bin value = 0, digit,
-
605 max_ui = (T_bin)-1,
-
606 max_ui_pre1, max_ui_pre2;
-
607
-
608 flags = 0;
+
11#include <locale.h>
+
12#include <stdarg.h>
+
13#include <stdint.h>
+
14#include <memory>
+
15#include <stdexcept>
+
16
+
17namespace stdex
+
18{
+
19#ifdef _WIN32
+
20 using locale_t = _locale_t;
+
21
+
25 struct free_locale_delete
+
26 {
+
30 void operator()(_In_ locale_t locale) const
+
31 {
+
32 _free_locale(locale);
+
33 }
+
34 };
+
35
+
36 static std::unique_ptr<__crt_locale_pointers, free_locale_delete> locale_C(_create_locale(LC_ALL, "C"));
+
37#else
+
38 using locale_t = ::locale_t;
+
39#endif
+
40
+
44#ifdef _WIN32
+
45 typedef wchar_t utf16_t;
+
46#else
+
47 typedef char16_t utf16_t;
+
48#endif
+
49
+
55 inline bool is_high_surrogate(_In_ utf16_t chr)
+
56 {
+
57 return 0xd800 < chr && chr < 0xdc00;
+
58 }
+
59
+
65 inline bool is_low_surrogate(_In_ utf16_t chr)
+
66 {
+
67 return 0xdc00 < chr && chr < 0xe000;
+
68 }
+
69
+
75 inline bool is_surrogate_pair(_In_reads_(2) const utf16_t* str)
+
76 {
+
77 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
+
78 }
+
79
+
85 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2) const utf16_t* str)
+
86 {
+
87 assert(is_surrogate_pair(str));
+
88 return
+
89 ((char32_t)(str[0] - 0xd800) << 10) +
+
90 (char32_t)(str[1] - 0xdc00) +
+
91 0x10000;
+
92 }
+
93
+
99 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ char32_t chr)
+
100 {
+
101 assert(chr >= 0x10000);
+
102 chr -= 0x10000;
+
103 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
+
104 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
+
105 }
+
106
+
112 inline bool iscombining(_In_ char32_t chr)
+
113 {
+
114 return
+
115 0x0300 <= chr && chr < 0x0370 ||
+
116 0x1dc0 <= chr && chr < 0x1e00 ||
+
117 0x20d0 <= chr && chr < 0x2100 ||
+
118 0xfe20 <= chr && chr < 0xfe30;
+
119 }
+
120
+
126 template <class T>
+
127 inline size_t islbreak(_In_ T chr)
+
128 {
+
129 return chr == '\n' || chr == '\r';
+
130 }
+
131
+
138 template <class T>
+
139 inline size_t islbreak(_In_reads_or_z_opt_(count) const T* chr, _In_ size_t count)
+
140 {
+
141 _Analysis_assume_(chr || !count);
+
142 if (count >= 2 && (chr[0] == '\r' && chr[1] == '\n' || chr[0] == '\n' && chr[1] == '\r'))
+
143 return 2;
+
144 if (count > 1 && (chr[0] == '\n' || chr[0] == '\r'))
+
145 return 1;
+
146 return 0;
+
147 }
+
148
+
155 inline size_t glyphlen(_In_reads_or_z_opt_(count) const wchar_t* glyph, _In_ size_t count)
+
156 {
+
157 _Analysis_assume_(glyph || !count);
+
158 if (count) {
+
159#ifdef _WIN32
+
160 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
+
161#else
+
162 size_t i = 1;
+
163#endif
+
164 for (; i < count && iscombining(glyph[i]); ++i);
+
165 return i;
+
166 }
+
167 return 0;
+
168 }
+
169
+
177 template <class T>
+
178 inline size_t strlen(_In_z_ const T* str)
+
179 {
+
180 assert(str);
+
181 size_t i;
+
182 for (i = 0; str[i]; ++i);
+
183 return i;
+
184 }
+
185
+
194 template <class T>
+
195 inline size_t strnlen(_In_reads_or_z_opt_(count) const T* str, _In_ size_t count)
+
196 {
+
197 assert(str);
+
198 size_t i;
+
199 for (i = 0; i < count && str[i]; ++i);
+
200 return i;
+
201 }
+
202
+
203 constexpr auto npos{ static_cast<size_t>(-1) };
+
204
+
214 template <class T>
+
215 inline size_t strnchr(
+
216 _In_reads_or_z_opt_(count) const T* str,
+
217 _In_ size_t count,
+
218 _In_ T chr)
+
219 {
+
220 assert(str || !count);
+
221 for (size_t i = 0; i < count && str[i]; ++i)
+
222 if (str[i] == chr) return i;
+
223 return npos;
+
224 }
+
225
+
235 template <class T>
+
236 inline size_t strrnchr(
+
237 _In_reads_or_z_opt_(count) const T* str,
+
238 _In_ size_t count,
+
239 _In_ T chr)
+
240 {
+
241 assert(str || !count);
+
242 size_t z = npos;
+
243 for (size_t i = 0; i < count && str[i]; ++i)
+
244 if (str[i] == chr) z = i;
+
245 return z;
+
246 }
+
247
+
257 template <class T>
+
258 inline size_t strnichr(
+
259 _In_reads_or_z_opt_(count) const T* str,
+
260 _In_ size_t count,
+
261 _In_ T chr,
+
262 _In_ const std::locale& locale)
+
263 {
+
264 assert(str || !count);
+
265 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
+
266 chr = ctype.tolower(chr);
+
267 for (size_t i = 0; i < count && str[i]; ++i)
+
268 if (ctype.tolower(str[i]) == chr) return i;
+
269 return npos;
+
270 }
+
271
+
281 template <class T>
+
282 inline size_t strrnichr(
+
283 _In_reads_or_z_opt_(count) const T* str,
+
284 _In_ size_t count,
+
285 _In_ T chr,
+
286 _In_ const std::locale& locale)
+
287 {
+
288 assert(str || !count);
+
289 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
+
290 chr = ctype.tolower(chr);
+
291 size_t z = npos;
+
292 for (size_t i = 0; i < count && str[i]; ++i)
+
293 if (ctype.tolower(str[i]) == chr) z = i;
+
294 return z;
+
295 }
+
296
+
307 template <class T1, class T2>
+
308 inline int strncmp(
+
309 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
+
310 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2)
+
311 {
+
312 assert(str1 || !count1);
+
313 assert(str2 || !count2);
+
314 size_t i; T1 a; T2 b;
+
315 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
+
316 if (a > b) return +1;
+
317 if (a < b) return -1;
+
318 }
+
319 if (i < count1 && str1[i]) return +1;
+
320 if (i < count2 && str2[i]) return -1;
+
321 return 0;
+
322 }
+
323
+
334 template <class T>
+
335 inline int strncoll(
+
336 _In_reads_or_z_opt_(count1) const T* str1, _In_ size_t count1,
+
337 _In_reads_or_z_opt_(count2) const T* str2, _In_ size_t count2,
+
338 _In_ const std::locale& locale)
+
339 {
+
340 assert(str1 || !count1);
+
341 assert(str2 || !count2);
+
342 auto& collate = std::use_facet<std::collate<T>>(locale);
+
343 return collate.compare(str1, str1 + count1, str2, str2 + count2);
+
344 }
+
345
+
356 template <class T1, class T2>
+
357 inline int strnicmp(
+
358 _In_reads_or_z_opt_(count1) const T1* str1, _In_ size_t count1,
+
359 _In_reads_or_z_opt_(count2) const T2* str2, _In_ size_t count2,
+
360 _In_ const std::locale& locale)
+
361 {
+
362 assert(str1 || !count1);
+
363 assert(str2 || !count2);
+
364 size_t i; T1 a; T2 b;
+
365 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
+
366 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
+
367 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
+
368 if (a > b) return +1;
+
369 if (a < b) return -1;
+
370 }
+
371 if (i < count1 && str1[i]) return +1;
+
372 if (i < count2 && str2[i]) return -1;
+
373 return 0;
+
374 }
+
375
+
385 template <class T1, class T2>
+
386 inline size_t strnstr(
+
387 _In_reads_or_z_opt_(count) const T1* str,
+
388 _In_ size_t count,
+
389 _In_z_ const T2* sample)
+
390 {
+
391 assert(str || !count);
+
392 assert(sample);
+
393 for (size_t offset = 0;; ++offset) {
+
394 for (size_t i = offset, j = 0;; ++i, ++j) {
+
395 if (!sample[j])
+
396 return offset;
+
397 if (i >= count || !str[i])
+
398 return npos;
+
399 if (str[i] != sample[j])
+
400 break;
+
401 }
+
402 }
+
403 }
+
404
+
414 template <class T1, class T2>
+
415 inline size_t strnistr(
+
416 _In_reads_or_z_opt_(count) const T1* str,
+
417 _In_ size_t count,
+
418 _In_z_ const T2* sample,
+
419 _In_ const std::locale& locale)
+
420 {
+
421 assert(str || !count);
+
422 assert(sample);
+
423 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
+
424 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
+
425 for (size_t offset = 0;; ++offset) {
+
426 for (size_t i = offset, j = 0;; ++i, ++j) {
+
427 if (!sample[j])
+
428 return offset;
+
429 if (i >= count || !str[i])
+
430 return npos;
+
431 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
+
432 break;
+
433 }
+
434 }
+
435 }
+
436
+
445 template <class T1, class T2>
+
446 inline size_t strcpy(
+
447 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
+
448 _In_z_ const T2* src)
+
449 {
+
450 assert(dst && src);
+
451 for (size_t i = 0; ; ++i) {
+
452 if ((dst[i] = src[i]) == 0)
+
453 return i;
+
454 }
+
455 }
+
456
+
466 template <class T1, class T2>
+
467 inline size_t strncpy(
+
468 _Out_writes_(count) _Post_maybez_ T1* dst,
+
469 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
+
470 {
+
471 assert(dst && src || !count);
+
472 for (size_t i = 0; ; ++i) {
+
473 if (i >= count)
+
474 return i;
+
475 if ((dst[i] = src[i]) == 0)
+
476 return i;
+
477 }
+
478 }
+
479
+
490 template <class T1, class T2>
+
491 inline size_t strncpy(
+
492 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
+
493 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
+
494 {
+
495 assert(dst || !count_dst);
+
496 assert(src || !count_src);
+
497 for (size_t i = 0; ; ++i)
+
498 {
+
499 if (i > count_dst)
+
500 return i;
+
501 if (i > count_src) {
+
502 dst[i] = 0;
+
503 return i;
+
504 }
+
505 if ((dst[i] = src[i]) == 0)
+
506 return i;
+
507 }
+
508 }
+
509
+
518 template <class T1, class T2>
+
519 inline size_t strcat(
+
520 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
+
521 _In_z_ const T2* src)
+
522 {
+
523 assert(dst && src);
+
524 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
+
525 if ((dst[j] = src[i]) == 0)
+
526 return j;
+
527 }
+
528 }
+
529
+
539 template <class T1, class T2>
+
540 inline size_t strncat(
+
541 _Out_writes_(count) _Post_maybez_ T1* dst,
+
542 _In_reads_or_z_opt_(count) const T2* src, _In_ size_t count)
+
543 {
+
544 assert(dst && src || !count);
+
545 for (size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
+
546 if (i >= count)
+
547 return j;
+
548 if ((dst[j] = src[i]) == 0)
+
549 return j;
+
550 }
+
551 }
+
552
+
563 template <class T1, class T2>
+
564 inline size_t strncat(
+
565 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_ size_t count_dst,
+
566 _In_reads_or_z_opt_(count_src) const T2* src, _In_ size_t count_src)
+
567 {
+
568 assert(dst || !count_dst);
+
569 assert(src || !count_src);
+
570 for (size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
+
571 {
+
572 if (j > count_dst)
+
573 return j;
+
574 if (i > count_src) {
+
575 dst[j] = 0;
+
576 return j;
+
577 }
+
578 if ((dst[j] = src[i]) == 0)
+
579 return j;
+
580 }
+
581 }
+
582
+
592 template <class T>
+
593 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_ const T* src)
+
594 {
+
595 assert(dst);
+
596 assert(src);
+
597 size_t i, j;
+
598 for (i = j = 0; src[j];) {
+
599 if (src[j] != '\r' || src[j + 1] != '\n')
+
600 dst[i++] = src[j++];
+
601 else {
+
602 dst[i++] = '\n';
+
603 j += 2;
+
604 }
+
605 }
+
606 dst[i] = 0;
+
607 return i;
+
608 }
609
-
610 // Skip leading spaces.
-
611 for (;; ++i) {
-
612 if (i >= count || !str[i]) goto error;
-
613 if (!isspace(str[i])) break;
-
614 }
-
615
-
616 // Read the sign.
-
617 if (str[i] == '+') {
-
618 flags &= ~0x01;
-
619 ++i;
-
620 if (i >= count || !str[i]) goto error;
-
621 }
-
622 else if (str[i] == '-') {
-
623 flags |= 0x01;
-
624 ++i;
-
625 if (i >= count || !str[i]) goto error;
-
626 }
+
611 template <class T, class T_bin>
+
612 inline T_bin strtoint(
+
613 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
614 _Out_opt_ size_t* end,
+
615 _In_ int radix,
+
616 _Out_ uint8_t& flags)
+
617 {
+
618 assert(str || !count);
+
619 assert(radix == 0 || 2 <= radix && radix <= 36);
+
620
+
621 size_t i = 0;
+
622 T_bin value = 0, digit,
+
623 max_ui = (T_bin)-1,
+
624 max_ui_pre1, max_ui_pre2;
+
625
+
626 flags = 0;
627
-
628 if (radix == 16) {
-
629 // On hexadecimal, allow leading 0x.
-
630 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
-
631 i += 2;
-
632 if (i >= count || !str[i]) goto error;
-
633 }
-
634 }
-
635 else if (!radix) {
-
636 // Autodetect radix.
-
637 if (str[i] == '0') {
-
638 ++i;
-
639 if (i >= count || !str[i]) goto error;
-
640 if (str[i] == 'x' || str[i] == 'X') {
-
641 radix = 16;
-
642 ++i;
-
643 if (i >= count || !str[i]) goto error;
-
644 }
-
645 else
-
646 radix = 8;
-
647 }
-
648 else
-
649 radix = 10;
-
650 }
-
651
-
652 // We have the radix.
-
653 max_ui_pre1 = max_ui / (T_bin)radix;
-
654 max_ui_pre2 = max_ui % (T_bin)radix;
-
655 for (;;) {
-
656 if ('0' <= str[i] && str[i] <= '9')
-
657 digit = (T_bin)str[i] - '0';
-
658 else if ('A' <= str[i] && str[i] <= 'Z')
-
659 digit = (T_bin)str[i] - 'A' + '\x0a';
-
660 else if ('a' <= str[i] && str[i] <= 'z')
-
661 digit = (T_bin)str[i] - 'a' + '\x0a';
-
662 else
-
663 goto error;
-
664 if (digit >= (T_bin)radix)
-
665 goto error;
-
666
-
667 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
-
668 value == max_ui_pre1 && digit <= max_ui_pre2) // Small digits will not overflow.
-
669 value = value * (T_bin)radix + digit;
-
670 else {
-
671 // Overflow!
-
672 flags |= 0x02;
-
673 }
-
674
-
675 ++i;
-
676 if (i >= count || !str[i])
-
677 goto error;
-
678 }
-
679
-
680 error:
-
681 if (end) *end = i;
-
682 return value;
-
683 }
-
685
-
696 template <class T, class T_bin>
-
697 T_bin strtoint(
-
698 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
699 _Out_opt_ size_t* end,
-
700 _In_ int radix)
-
701 {
-
702 uint8_t flags;
-
703 T_bin value;
-
704
-
705 switch (sizeof(T_bin)) {
-
706 case 1:
-
707 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
-
708 if ((flags & 0x01) && (value & 0x80)) {
-
709 // Sign bit is 1 => overflow.
-
710 flags |= 0x02;
-
711 }
-
712 return (flags & 0x02) ?
-
713 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
-
714 (flags & 0x01) ? -value : value;
-
715
-
716 case 2:
-
717 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
-
718 if ((flags & 0x01) && (value & 0x8000)) {
-
719 // Sign bit is 1 => overflow.
-
720 flags |= 0x02;
-
721 }
-
722 return (flags & 0x02) ?
-
723 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
-
724 (flags & 0x01) ? -value : value;
-
725
-
726 case 4:
-
727 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
-
728 if ((flags & 0x01) && (value & 0x80000000)) {
-
729 // Sign bit is 1 => overflow.
-
730 flags |= 0x02;
-
731 }
-
732 return (flags & 0x02) ?
-
733 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
-
734 (flags & 0x01) ? -value : value;
-
735
-
736 case 8:
-
737 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
-
738 if ((flags & 0x01) && (value & 0x8000000000000000)) {
-
739 // Sign bit is 1 => overflow.
-
740 flags |= 0x02;
-
741 }
-
742 return (flags & 0x02) ?
-
743 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
-
744 (flags & 0x01) ? -value : value;
-
745
-
746 default:
-
747 throw std::invalid_argument("Unsupported bit length");
-
748 }
-
749 }
-
750
-
761 template <class T, class T_bin>
-
762 inline T_bin strtouint(
-
763 _In_reads_or_z_opt_(count) const T* str,
-
764 _In_ size_t count,
-
765 _Out_opt_ size_t* end,
-
766 _In_ int radix)
-
767 {
-
768 uint8_t flags;
-
769 T_bin value;
-
770
-
771 switch (sizeof(T_bin)) {
-
772 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
-
773 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
-
774 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
-
775 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
-
776 default: throw std::invalid_argument("Unsupported bit length");
-
777 }
-
778
-
779 return (flags & 0x02) ?
-
780 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
-
781 (flags & 0x01) ? ~value : value;
-
782 }
-
783
-
794 template <class T>
-
795 inline int32_t strto32(
-
796 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
797 _Out_opt_ size_t* end,
-
798 _In_ int radix)
-
799 {
-
800 return strtoint<T, int32_t>(str, count, end, radix);
-
801 }
-
802
-
813 template <class T>
-
814 inline int64_t strto64(
-
815 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
816 _Out_opt_ size_t* end,
-
817 _In_ int radix)
-
818 {
-
819 return strtoint<T, int64_t>(str, count, end, radix);
-
820 }
-
821
-
833 template <class T>
-
834 inline intptr_t strtoi(
-
835 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
836 _Out_opt_ size_t* end,
-
837 _In_ int radix)
-
838 {
-
839#if defined(_WIN64) || defined(__LP64__)
-
840 return (intptr_t)strto64(str, count, end, radix);
-
841#else
-
842 return (intptr_t)strto32(str, count, end, radix);
-
843#endif
-
844 }
-
845
-
856 template <class T>
-
857 inline uint32_t strtou32(
-
858 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
859 _Out_opt_ size_t* end,
-
860 _In_ int radix)
-
861 {
-
862 return strtouint<T, uint32_t>(str, count, end, radix);
-
863 }
-
864
-
875 template <class T>
-
876 inline uint64_t strtou64(
-
877 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
878 _Out_opt_ size_t* end,
-
879 _In_ int radix)
-
880 {
-
881 return strtouint<T, uint64_t>(str, count, end, radix);
-
882 }
-
883
-
895 template <class T>
-
896 inline size_t strtoui(
-
897 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
-
898 _Out_opt_ size_t* end,
-
899 _In_ int radix)
-
900 {
-
901#if defined(_WIN64) || defined(__LP64__)
-
902 return (size_t)strtou64(str, count, end, radix);
-
903#else
-
904 return (size_t)strtou32(str, count, end, radix);
-
905#endif
-
906 }
-
907
-
909 inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const char *format, _In_opt_ locale_t locale, _In_ va_list arg)
-
910 {
-
911 int r;
-
912#ifdef _WIN32
-
913 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
-
914#pragma warning(suppress: 4996)
-
915 r = _vsnprintf_l(str, capacity, format, locale, arg);
-
916#else
-
917 r = vsnprintf(str, capacity, format, arg);
-
918#endif
-
919 if (r == -1 && strnlen(str, capacity) == capacity) {
-
920 // Buffer overrun. Estimate buffer size for the next iteration.
-
921 capacity += std::max<size_t>(capacity / 8, 0x80);
-
922 if (capacity > INT_MAX)
-
923 throw std::invalid_argument("string too big");
-
924 return (int)capacity;
-
925 }
-
926 return r;
-
927 }
-
928
-
929 inline int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const wchar_t *format, _In_opt_ locale_t locale, _In_ va_list arg)
-
930 {
-
931 int r;
-
932
-
933#ifdef _WIN32
-
934 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
-
935#pragma warning(suppress: 4996)
-
936 r = _vsnwprintf_l(str, capacity, format, locale, arg);
-
937#else
-
938 r = vswprintf(str, capacity, format, arg);
-
939#endif
-
940 if (r == -1 && strnlen(str, capacity) == capacity) {
-
941 // Buffer overrun. Estimate buffer size for the next iteration.
-
942 capacity += std::max<size_t>(capacity / 8, 0x80);
-
943 if (capacity > INT_MAX)
-
944 throw std::invalid_argument("string too big");
-
945 return (int)capacity;
-
946 }
-
947 return r;
-
948 }
+
628 // Skip leading spaces.
+
629 for (;; ++i) {
+
630 if (i >= count || !str[i]) goto error;
+
631 if (!isspace(str[i])) break;
+
632 }
+
633
+
634 // Read the sign.
+
635 if (str[i] == '+') {
+
636 flags &= ~0x01;
+
637 ++i;
+
638 if (i >= count || !str[i]) goto error;
+
639 }
+
640 else if (str[i] == '-') {
+
641 flags |= 0x01;
+
642 ++i;
+
643 if (i >= count || !str[i]) goto error;
+
644 }
+
645
+
646 if (radix == 16) {
+
647 // On hexadecimal, allow leading 0x.
+
648 if (str[i] == '0' && i + 1 < count && (str[i + 1] == 'x' || str[i + 1] == 'X')) {
+
649 i += 2;
+
650 if (i >= count || !str[i]) goto error;
+
651 }
+
652 }
+
653 else if (!radix) {
+
654 // Autodetect radix.
+
655 if (str[i] == '0') {
+
656 ++i;
+
657 if (i >= count || !str[i]) goto error;
+
658 if (str[i] == 'x' || str[i] == 'X') {
+
659 radix = 16;
+
660 ++i;
+
661 if (i >= count || !str[i]) goto error;
+
662 }
+
663 else
+
664 radix = 8;
+
665 }
+
666 else
+
667 radix = 10;
+
668 }
+
669
+
670 // We have the radix.
+
671 max_ui_pre1 = max_ui / (T_bin)radix;
+
672 max_ui_pre2 = max_ui % (T_bin)radix;
+
673 for (;;) {
+
674 if ('0' <= str[i] && str[i] <= '9')
+
675 digit = (T_bin)str[i] - '0';
+
676 else if ('A' <= str[i] && str[i] <= 'Z')
+
677 digit = (T_bin)str[i] - 'A' + '\x0a';
+
678 else if ('a' <= str[i] && str[i] <= 'z')
+
679 digit = (T_bin)str[i] - 'a' + '\x0a';
+
680 else
+
681 goto error;
+
682 if (digit >= (T_bin)radix)
+
683 goto error;
+
684
+
685 if (value < max_ui_pre1 || // Multiplication nor addition will not overflow.
+
686 value == max_ui_pre1 && digit <= max_ui_pre2) // Small digits will not overflow.
+
687 value = value * (T_bin)radix + digit;
+
688 else {
+
689 // Overflow!
+
690 flags |= 0x02;
+
691 }
+
692
+
693 ++i;
+
694 if (i >= count || !str[i])
+
695 goto error;
+
696 }
+
697
+
698 error:
+
699 if (end) *end = i;
+
700 return value;
+
701 }
+
703
+
714 template <class T, class T_bin>
+
715 T_bin strtoint(
+
716 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
717 _Out_opt_ size_t* end,
+
718 _In_ int radix)
+
719 {
+
720 uint8_t flags;
+
721 T_bin value;
+
722
+
723 switch (sizeof(T_bin)) {
+
724 case 1:
+
725 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
+
726 if ((flags & 0x01) && (value & 0x80)) {
+
727 // Sign bit is 1 => overflow.
+
728 flags |= 0x02;
+
729 }
+
730 return (flags & 0x02) ?
+
731 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
+
732 (flags & 0x01) ? -value : value;
+
733
+
734 case 2:
+
735 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
+
736 if ((flags & 0x01) && (value & 0x8000)) {
+
737 // Sign bit is 1 => overflow.
+
738 flags |= 0x02;
+
739 }
+
740 return (flags & 0x02) ?
+
741 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
+
742 (flags & 0x01) ? -value : value;
+
743
+
744 case 4:
+
745 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
+
746 if ((flags & 0x01) && (value & 0x80000000)) {
+
747 // Sign bit is 1 => overflow.
+
748 flags |= 0x02;
+
749 }
+
750 return (flags & 0x02) ?
+
751 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
+
752 (flags & 0x01) ? -value : value;
+
753
+
754 case 8:
+
755 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
+
756 if ((flags & 0x01) && (value & 0x8000000000000000)) {
+
757 // Sign bit is 1 => overflow.
+
758 flags |= 0x02;
+
759 }
+
760 return (flags & 0x02) ?
+
761 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
+
762 (flags & 0x01) ? -value : value;
+
763
+
764 default:
+
765 throw std::invalid_argument("Unsupported bit length");
+
766 }
+
767 }
+
768
+
779 template <class T, class T_bin>
+
780 inline T_bin strtouint(
+
781 _In_reads_or_z_opt_(count) const T* str,
+
782 _In_ size_t count,
+
783 _Out_opt_ size_t* end,
+
784 _In_ int radix)
+
785 {
+
786 uint8_t flags;
+
787 T_bin value;
+
788
+
789 switch (sizeof(T_bin)) {
+
790 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags); break;
+
791 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags); break;
+
792 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags); break;
+
793 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags); break;
+
794 default: throw std::invalid_argument("Unsupported bit length");
+
795 }
+
796
+
797 return (flags & 0x02) ?
+
798 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
+
799 (flags & 0x01) ? ~value : value;
+
800 }
+
801
+
812 template <class T>
+
813 inline int32_t strto32(
+
814 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
815 _Out_opt_ size_t* end,
+
816 _In_ int radix)
+
817 {
+
818 return strtoint<T, int32_t>(str, count, end, radix);
+
819 }
+
820
+
831 template <class T>
+
832 inline int64_t strto64(
+
833 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
834 _Out_opt_ size_t* end,
+
835 _In_ int radix)
+
836 {
+
837 return strtoint<T, int64_t>(str, count, end, radix);
+
838 }
+
839
+
851 template <class T>
+
852 inline intptr_t strtoi(
+
853 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
854 _Out_opt_ size_t* end,
+
855 _In_ int radix)
+
856 {
+
857#if defined(_WIN64) || defined(__LP64__)
+
858 return (intptr_t)strto64(str, count, end, radix);
+
859#else
+
860 return (intptr_t)strto32(str, count, end, radix);
+
861#endif
+
862 }
+
863
+
874 template <class T>
+
875 inline uint32_t strtou32(
+
876 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
877 _Out_opt_ size_t* end,
+
878 _In_ int radix)
+
879 {
+
880 return strtouint<T, uint32_t>(str, count, end, radix);
+
881 }
+
882
+
893 template <class T>
+
894 inline uint64_t strtou64(
+
895 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
896 _Out_opt_ size_t* end,
+
897 _In_ int radix)
+
898 {
+
899 return strtouint<T, uint64_t>(str, count, end, radix);
+
900 }
+
901
+
913 template <class T>
+
914 inline size_t strtoui(
+
915 _In_reads_or_z_opt_(count) const T* str, _In_ size_t count,
+
916 _Out_opt_ size_t* end,
+
917 _In_ int radix)
+
918 {
+
919#if defined(_WIN64) || defined(__LP64__)
+
920 return (size_t)strtou64(str, count, end, radix);
+
921#else
+
922 return (size_t)strtou32(str, count, end, radix);
+
923#endif
+
924 }
+
925
+
927 inline int vsnprintf(_Out_z_cap_(capacity) char *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const char *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
928 {
+
929 int r;
+
930#ifdef _WIN32
+
931 // Don't use _vsnprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
+
932#pragma warning(suppress: 4996)
+
933 r = _vsnprintf_l(str, capacity, format, locale, arg);
+
934#else
+
935 r = vsnprintf(str, capacity, format, arg);
+
936#endif
+
937 if (r == -1 && strnlen(str, capacity) == capacity) {
+
938 // Buffer overrun. Estimate buffer size for the next iteration.
+
939 capacity += std::max<size_t>(capacity / 8, 0x80);
+
940 if (capacity > INT_MAX)
+
941 throw std::invalid_argument("string too big");
+
942 return (int)capacity;
+
943 }
+
944 return r;
+
945 }
+
946
+
947 inline int vsnprintf(_Out_z_cap_(capacity) wchar_t *str, _In_ size_t capacity, _In_z_ _Printf_format_string_params_(2) const wchar_t *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
948 {
+
949 int r;
950
-
959 template<class _Elem, class _Traits, class _Ax>
-
960 inline void vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
-
961 {
-
962 _Elem buf[1024/sizeof(_Elem)];
-
963
-
964 // Try with stack buffer first.
-
965 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
-
966 if (count >= 0) {
-
967 // Copy from stack.
-
968 str.append(buf, count);
-
969 } else {
-
970 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
-
971 // Allocate on heap and retry.
-
972 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
-
973 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
-
974 if (count >= 0) {
-
975 str.append(buf_dyn.get(), count);
-
976 break;
-
977 }
-
978 }
-
979 }
-
980 }
+
951#ifdef _WIN32
+
952 // Don't use _vsnwprintf_s(). It terminates the string even if we want to print to the edge of the buffer.
+
953#pragma warning(suppress: 4996)
+
954 r = _vsnwprintf_l(str, capacity, format, locale, arg);
+
955#else
+
956 r = vswprintf(str, capacity, format, arg);
+
957#endif
+
958 if (r == -1 && strnlen(str, capacity) == capacity) {
+
959 // Buffer overrun. Estimate buffer size for the next iteration.
+
960 capacity += std::max<size_t>(capacity / 8, 0x80);
+
961 if (capacity > INT_MAX)
+
962 throw std::invalid_argument("string too big");
+
963 return (int)capacity;
+
964 }
+
965 return r;
+
966 }
+
968
+
977 template<class _Elem, class _Traits, class _Ax>
+
978 inline void vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
979 {
+
980 _Elem buf[1024/sizeof(_Elem)];
981
-
989 template<class _Elem, class _Traits, class _Ax>
-
990 inline void appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
-
991 {
-
992 va_list arg;
-
993 va_start(arg, locale);
-
994 vappendf(str, format, locale, arg);
-
995 va_end(arg);
-
996 }
-
997
-
1006 template<class _Elem, class _Traits, class _Ax>
-
1007 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
-
1008 {
-
1009 str.clear();
-
1010 vappendf(str, format, locale, arg);
-
1011 }
-
1012
-
1020 template<class _Elem, class _Traits, class _Ax>
-
1021 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
-
1022 {
-
1023 va_list arg;
-
1024 va_start(arg, locale);
-
1025 vsprintf(str, format, locale, arg);
-
1026 va_end(arg);
-
1027 }
-
1028
-
1038 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
-
1039 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
982 // Try with stack buffer first.
+
983 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
+
984 if (count >= 0) {
+
985 // Copy from stack.
+
986 str.append(buf, count);
+
987 } else {
+
988 for (size_t capacity = 2*1024/sizeof(_Elem);; capacity *= 2) {
+
989 // Allocate on heap and retry.
+
990 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
+
991 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
+
992 if (count >= 0) {
+
993 str.append(buf_dyn.get(), count);
+
994 break;
+
995 }
+
996 }
+
997 }
+
998 }
+
999
+
1007 template<class _Elem, class _Traits, class _Ax>
+
1008 inline void appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
+
1009 {
+
1010 va_list arg;
+
1011 va_start(arg, locale);
+
1012 vappendf(str, format, locale, arg);
+
1013 va_end(arg);
+
1014 }
+
1015
+
1024 template<class _Elem, class _Traits, class _Ax>
+
1025 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
1026 {
+
1027 str.clear();
+
1028 vappendf(str, format, locale, arg);
+
1029 }
+
1030
+
1038 template<class _Elem, class _Traits, class _Ax>
+
1039 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
1040 {
-
1041 std::basic_string<_Elem, _Traits, _Ax> str;
-
1042 vappendf(str, format, locale, arg);
-
1043 return str;
-
1044 }
-
1045
-
1054 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
-
1055 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
-
1056 {
-
1057 va_list arg;
-
1058 va_start(arg, locale);
-
1059 auto str = vsprintf(format, locale, arg);
-
1060 va_end(arg);
+
1041 va_list arg;
+
1042 va_start(arg, locale);
+
1043 vsprintf(str, format, locale, arg);
+
1044 va_end(arg);
+
1045 }
+
1046
+
1056 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
1057 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
+
1058 {
+
1059 std::basic_string<_Elem, _Traits, _Ax> str;
+
1060 vappendf(str, format, locale, arg);
1061 return str;
1062 }
-
1063}
+
1063
+
1072 template<class _Elem, class _Traits = std::char_traits<_Elem>, class _Ax = std::allocator<_Elem>>
+
1073 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2) const _Elem *format, _In_opt_ locale_t locale, ...)
+
1074 {
+
1075 va_list arg;
+
1076 va_start(arg, locale);
+
1077 auto str = vsprintf(format, locale, arg);
+
1078 va_end(arg);
+
1079 return str;
+
1080 }
+
1081}
diff --git a/structstdex_1_1chrono_1_1aosn__date-members.html b/structstdex_1_1chrono_1_1aosn__date-members.html index f970fc06c..cbf837710 100644 --- a/structstdex_1_1chrono_1_1aosn__date-members.html +++ b/structstdex_1_1chrono_1_1aosn__date-members.html @@ -96,7 +96,7 @@ $(function() { diff --git a/structstdex_1_1chrono_1_1aosn__date.html b/structstdex_1_1chrono_1_1aosn__date.html index fa31a5875..b6f0f0440 100644 --- a/structstdex_1_1chrono_1_1aosn__date.html +++ b/structstdex_1_1chrono_1_1aosn__date.html @@ -152,7 +152,7 @@ static constexpr bool is_s diff --git a/structstdex_1_1chrono_1_1aosn__timestamp-members.html b/structstdex_1_1chrono_1_1aosn__timestamp-members.html index 7578ec701..0b29de2ad 100644 --- a/structstdex_1_1chrono_1_1aosn__timestamp-members.html +++ b/structstdex_1_1chrono_1_1aosn__timestamp-members.html @@ -102,11 +102,15 @@ $(function() { time_point typedef (defined in stdex::chrono::aosn_timestamp)stdex::chrono::aosn_timestamp to_date(time_point tp) noexceptstdex::chrono::aosn_timestampinlinestatic to_dmy(const time_point tp, uint8_t *day, uint8_t *month, int32_t *year, uint8_t *hour, uint8_t *minute, uint8_t *second, uint16_t *millisecond) noexceptstdex::chrono::aosn_timestampinlinestatic + to_rfc822(const time_point tp) (defined in stdex::chrono::aosn_timestamp)stdex::chrono::aosn_timestampinlinestatic + to_str(const time_point tp, const char *format, locale_t locale) (defined in stdex::chrono::aosn_timestamp)stdex::chrono::aosn_timestampinlinestatic + to_str(const time_point tp, const wchar_t *format, locale_t locale) (defined in stdex::chrono::aosn_timestamp)stdex::chrono::aosn_timestampinlinestatic + to_system(time_point tp, struct tm &date) noexcept (defined in stdex::chrono::aosn_timestamp)stdex::chrono::aosn_timestampinlinestatic to_time_t(const time_point tp) noexceptstdex::chrono::aosn_timestampinlinestatic diff --git a/structstdex_1_1chrono_1_1aosn__timestamp.html b/structstdex_1_1chrono_1_1aosn__timestamp.html index 7014b3fac..2949b5c58 100644 --- a/structstdex_1_1chrono_1_1aosn__timestamp.html +++ b/structstdex_1_1chrono_1_1aosn__timestamp.html @@ -121,6 +121,9 @@ static time_point from_tim static time_point from_system (const struct timespec &t) noexcept  Returns time point from struct timespec.
  + +static void to_system (time_point tp, struct tm &date) noexcept +  static aosn_date::time_point to_date (time_point tp) noexcept  Returns aosn_date::time_point from time point.
@@ -137,6 +140,18 @@ static time_point from_dmy static void to_dmy (const time_point tp, uint8_t *day, uint8_t *month, int32_t *year, uint8_t *hour, uint8_t *minute, uint8_t *second, uint16_t *millisecond) noexcept  Returns calendar day, month, year and time from time point.
  + +template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>> +static std::basic_string< char, _Traits, _Ax > to_str (const time_point tp, const char *format, locale_t locale) +  + +template<class _Traits = std::char_traits<wchar_t>, class _Ax = std::allocator<wchar_t>> +static std::basic_string< wchar_t, _Traits, _Ax > to_str (const time_point tp, const wchar_t *format, locale_t locale) +  + +template<class _Traits = std::char_traits<char>, class _Ax = std::allocator<char>> +static std::basic_string< char, _Traits, _Ax > to_rfc822 (const time_point tp) +  @@ -182,7 +197,7 @@ static constexpr rep 

Static Public Attributes

p_wee diff --git a/structstdex_1_1interval-members.html b/structstdex_1_1interval-members.html index c161d194f..dac82b9d2 100644 --- a/structstdex_1_1interval-members.html +++ b/structstdex_1_1interval-members.html @@ -94,7 +94,7 @@ $(function() {
diff --git a/structstdex_1_1interval.html b/structstdex_1_1interval.html index 5a5aef98c..ccc30fac8 100644 --- a/structstdex_1_1interval.html +++ b/structstdex_1_1interval.html @@ -424,7 +424,7 @@ template<class T > diff --git a/structstdex_1_1mapping-members.html b/structstdex_1_1mapping-members.html index 97631020c..397083d51 100644 --- a/structstdex_1_1mapping-members.html +++ b/structstdex_1_1mapping-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/structstdex_1_1mapping.html b/structstdex_1_1mapping.html index a324685ac..0434cd9ff 100644 --- a/structstdex_1_1mapping.html +++ b/structstdex_1_1mapping.html @@ -283,7 +283,7 @@ template<class T > diff --git a/structstdex_1_1no__delete-members.html b/structstdex_1_1no__delete-members.html index 65bf31b10..55c8b553f 100644 --- a/structstdex_1_1no__delete-members.html +++ b/structstdex_1_1no__delete-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/structstdex_1_1no__delete.html b/structstdex_1_1no__delete.html index fb6663877..df3b1bbe7 100644 --- a/structstdex_1_1no__delete.html +++ b/structstdex_1_1no__delete.html @@ -105,7 +105,7 @@ struct stdex::no_delete< T >

Noop deleter.

diff --git a/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html b/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html index dc8bbf815..06589523e 100644 --- a/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html +++ b/structstdex_1_1no__delete_3_01_t_0f_0e_4-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/structstdex_1_1no__delete_3_01_t_0f_0e_4.html b/structstdex_1_1no__delete_3_01_t_0f_0e_4.html index 830505533..87563d7cc 100644 --- a/structstdex_1_1no__delete_3_01_t_0f_0e_4.html +++ b/structstdex_1_1no__delete_3_01_t_0f_0e_4.html @@ -106,7 +106,7 @@ struct stdex::no_delete< T[]>

Noop array deleter.

diff --git a/structstdex_1_1parser_1_1http__factor__more-members.html b/structstdex_1_1parser_1_1http__factor__more-members.html index f122db6ad..77ee38bee 100644 --- a/structstdex_1_1parser_1_1http__factor__more-members.html +++ b/structstdex_1_1parser_1_1http__factor__more-members.html @@ -84,7 +84,7 @@ $(function() { diff --git a/structstdex_1_1parser_1_1http__factor__more.html b/structstdex_1_1parser_1_1http__factor__more.html index f8fb85d25..6f81a4ce9 100644 --- a/structstdex_1_1parser_1_1http__factor__more.html +++ b/structstdex_1_1parser_1_1http__factor__more.html @@ -93,7 +93,7 @@ constexpr bool operator()< diff --git a/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html b/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html index 702ea1342..33150846d 100644 --- a/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html +++ b/structstdex_1_1stream_1_1buffer_1_1buffer__t-members.html @@ -89,7 +89,7 @@ $(function() { diff --git a/structstdex_1_1stream_1_1buffer_1_1buffer__t.html b/structstdex_1_1stream_1_1buffer_1_1buffer__t.html index b7548db39..e53bb0e80 100644 --- a/structstdex_1_1stream_1_1buffer_1_1buffer__t.html +++ b/structstdex_1_1stream_1_1buffer_1_1buffer__t.html @@ -109,7 +109,7 @@ size_t capacity diff --git a/structstdex_1_1stream_1_1cache_1_1cache__t-members.html b/structstdex_1_1stream_1_1cache_1_1cache__t-members.html index c511dc4ea..d487babb0 100644 --- a/structstdex_1_1stream_1_1cache_1_1cache__t-members.html +++ b/structstdex_1_1stream_1_1cache_1_1cache__t-members.html @@ -90,7 +90,7 @@ $(function() { diff --git a/structstdex_1_1stream_1_1cache_1_1cache__t.html b/structstdex_1_1stream_1_1cache_1_1cache__t.html index fa0e7a8ee..ef1db787f 100644 --- a/structstdex_1_1stream_1_1cache_1_1cache__t.html +++ b/structstdex_1_1stream_1_1cache_1_1cache__t.html @@ -119,7 +119,7 @@ enum stdex::stream::cache::cache_t::status_t  diff --git a/structstdex_1_1stream_1_1fifo_1_1node__t-members.html b/structstdex_1_1stream_1_1fifo_1_1node__t-members.html index 8cfab6071..cb253a929 100644 --- a/structstdex_1_1stream_1_1fifo_1_1node__t-members.html +++ b/structstdex_1_1stream_1_1fifo_1_1node__t-members.html @@ -86,7 +86,7 @@ $(function() { diff --git a/structstdex_1_1stream_1_1fifo_1_1node__t.html b/structstdex_1_1stream_1_1fifo_1_1node__t.html index 41e258070..6d2ecbd99 100644 --- a/structstdex_1_1stream_1_1fifo_1_1node__t.html +++ b/structstdex_1_1stream_1_1fifo_1_1node__t.html @@ -99,7 +99,7 @@ uint8_t data [0]< diff --git a/system_8hpp_source.html b/system_8hpp_source.html index b81198a4d..cb014aa8b 100644 --- a/system_8hpp_source.html +++ b/system_8hpp_source.html @@ -88,175 +88,176 @@ $(function() {
9#define NOMINMAX // Collides with std::min/max
10#include <windows.h>
11#include <intsafe.h>
-
12#include <tchar.h>
-
13#else
-
14#include <unistd.h>
-
15#endif
-
16#include "sal.hpp"
-
17#include <assert.h>
-
18#include <stdexcept>
-
19#include <string>
-
20
-
21// In case somebody #included <windows.h> before us and didn't #define NOMINMAX
-
22#ifdef _WIN32
-
23#ifdef min
-
24#undef min
-
25#endif
-
26#ifdef max
-
27#undef max
-
28#endif
+
12#include <oaidl.h>
+
13#include <tchar.h>
+
14#else
+
15#include <unistd.h>
+
16#endif
+
17#include "sal.hpp"
+
18#include <assert.h>
+
19#include <stdexcept>
+
20#include <string>
+
21
+
22// In case somebody #included <windows.h> before us and didn't #define NOMINMAX
+
23#ifdef _WIN32
+
24#ifdef min
+
25#undef min
+
26#endif
+
27#ifdef max
+
28#undef max
29#endif
-
30
-
31namespace stdex
-
32{
-
36#if defined(_WIN32)
-
37 using sys_handle = HANDLE;
-
38 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
-
39#else
-
40 using sys_handle = int;
-
41 const sys_handle invalid_handle = (sys_handle)-1;
-
42#endif
-
43
-
47#if defined(_WIN32)
-
48 using sys_char = TCHAR;
-
49#else
-
50 using sys_char = char;
-
51#define _T(x) x
-
52#endif
-
53
-
57 using sys_string = std::basic_string<stdex::sys_char>;
-
58
- -
63 {
-
64 public:
-
65 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
-
66
-
67 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
-
68
-
69 sys_object& operator =(_In_ const sys_object& other)
-
70 {
-
71 if (this != std::addressof(other)) {
-
72 if (m_h != invalid_handle)
-
73 close(m_h);
-
74 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
-
75 }
-
76 return *this;
-
77 }
-
78
-
79 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
-
80 {
-
81 other.m_h = invalid_handle;
-
82 }
-
83
-
84 sys_object& operator =(_Inout_ sys_object&& other) noexcept
-
85 {
-
86 if (this != std::addressof(other)) {
-
87 if (m_h != invalid_handle)
-
88 close(m_h);
-
89 m_h = other.m_h;
-
90 other.m_h = invalid_handle;
-
91 }
-
92 return *this;
-
93 }
-
94
-
95 virtual ~sys_object()
-
96 {
-
97 if (m_h != invalid_handle)
-
98 close(m_h);
-
99 }
-
100
-
104 virtual void close()
-
105 {
-
106 if (m_h != invalid_handle) {
-
107 close(m_h);
-
108 m_h = invalid_handle;
-
109 }
-
110 }
-
111
-
115 inline operator bool() const noexcept { return m_h != invalid_handle; }
-
116
-
120 inline sys_handle get() const noexcept { return m_h; }
-
121
-
122 protected:
-
126 static void close(sys_handle h)
-
127 {
-
128#ifdef _WIN32
-
129 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
-
130#else
-
131 if (close(h) >= 0 || errno == EBADF)
-
132#endif
-
133 return;
-
134 throw std::runtime_error("failed to close handle");
-
135 }
-
136
-
140 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
-
141 {
-
142 sys_handle h_new;
-
143#ifdef _WIN32
-
144 HANDLE process = GetCurrentProcess();
-
145 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
-
146#else
-
147 UNREFERENCED_PARAMETER(inherit);
-
148 if ((h_new = dup(h)) >= 0)
-
149#endif
-
150 return h_new;
-
151 throw std::runtime_error("failed to duplicate handle");
-
152 }
-
153
-
154 protected:
-
155 sys_handle m_h;
-
156 };
-
157
-
158#ifdef _WIN32
-
159 template <class T>
-
160 class safearray_accessor
-
161 {
-
162 public:
-
163 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
-
164 {
-
165 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
-
166 if (FAILED(hr))
-
167 throw std::invalid_argument("SafeArrayAccessData failed");
-
168 }
-
169
-
170 ~safearray_accessor()
-
171 {
-
172 SafeArrayUnaccessData(m_sa);
-
173 }
-
174
-
175 T* data() const { return m_data; }
-
176
-
177 protected:
-
178 LPSAFEARRAY m_sa;
-
179 T* m_data;
-
180 };
-
181
-
185 struct SafeArrayDestroy_delete
-
186 {
-
190 void operator()(_In_ LPSAFEARRAY sa) const
-
191 {
-
192 SafeArrayDestroy(sa);
-
193 }
-
194 };
-
195
-
199 struct SysFreeString_delete
-
200 {
-
204 void operator()(_In_ BSTR sa) const
-
205 {
-
206 SysFreeString(sa);
-
207 }
-
208 };
-
209#endif
-
210}
-
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:63
-
sys_handle get() const noexcept
Returns object handle.
Definition system.hpp:120
-
virtual void close()
Closes object.
Definition system.hpp:104
-
static sys_handle duplicate(sys_handle h, bool inherit)
Duplicates given object.
Definition system.hpp:140
-
static void close(sys_handle h)
Closes object.
Definition system.hpp:126
+
30#endif
+
31
+
32namespace stdex
+
33{
+
37#if defined(_WIN32)
+
38 using sys_handle = HANDLE;
+
39 const sys_handle invalid_handle = INVALID_HANDLE_VALUE;
+
40#else
+
41 using sys_handle = int;
+
42 const sys_handle invalid_handle = (sys_handle)-1;
+
43#endif
+
44
+
48#if defined(_WIN32)
+
49 using sys_char = TCHAR;
+
50#else
+
51 using sys_char = char;
+
52#define _T(x) x
+
53#endif
+
54
+
58 using sys_string = std::basic_string<stdex::sys_char>;
+
59
+ +
64 {
+
65 public:
+
66 sys_object(_In_opt_ sys_handle h = invalid_handle) : m_h(h) {}
+
67
+
68 sys_object(_In_ const sys_object& other) : m_h(other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle) {}
+
69
+
70 sys_object& operator =(_In_ const sys_object& other)
+
71 {
+
72 if (this != std::addressof(other)) {
+
73 if (m_h != invalid_handle)
+
74 close(m_h);
+
75 m_h = other.m_h != invalid_handle ? duplicate(other.m_h, false) : invalid_handle;
+
76 }
+
77 return *this;
+
78 }
+
79
+
80 sys_object(_Inout_ sys_object&& other) noexcept : m_h(other.m_h)
+
81 {
+
82 other.m_h = invalid_handle;
+
83 }
+
84
+
85 sys_object& operator =(_Inout_ sys_object&& other) noexcept
+
86 {
+
87 if (this != std::addressof(other)) {
+
88 if (m_h != invalid_handle)
+
89 close(m_h);
+
90 m_h = other.m_h;
+
91 other.m_h = invalid_handle;
+
92 }
+
93 return *this;
+
94 }
+
95
+
96 virtual ~sys_object()
+
97 {
+
98 if (m_h != invalid_handle)
+
99 close(m_h);
+
100 }
+
101
+
105 virtual void close()
+
106 {
+
107 if (m_h != invalid_handle) {
+
108 close(m_h);
+
109 m_h = invalid_handle;
+
110 }
+
111 }
+
112
+
116 inline operator bool() const noexcept { return m_h != invalid_handle; }
+
117
+
121 inline sys_handle get() const noexcept { return m_h; }
+
122
+
123 protected:
+
127 static void close(sys_handle h)
+
128 {
+
129#ifdef _WIN32
+
130 if (CloseHandle(h) || GetLastError() == ERROR_INVALID_HANDLE)
+
131#else
+
132 if (close(h) >= 0 || errno == EBADF)
+
133#endif
+
134 return;
+
135 throw std::runtime_error("failed to close handle");
+
136 }
+
137
+
141 static sys_handle duplicate(_In_ sys_handle h, _In_ bool inherit)
+
142 {
+
143 sys_handle h_new;
+
144#ifdef _WIN32
+
145 HANDLE process = GetCurrentProcess();
+
146 if (DuplicateHandle(process, h, process, &h_new, 0, inherit, DUPLICATE_SAME_ACCESS))
+
147#else
+
148 UNREFERENCED_PARAMETER(inherit);
+
149 if ((h_new = dup(h)) >= 0)
+
150#endif
+
151 return h_new;
+
152 throw std::runtime_error("failed to duplicate handle");
+
153 }
+
154
+
155 protected:
+
156 sys_handle m_h;
+
157 };
+
158
+
159#ifdef _WIN32
+
160 template <class T>
+
161 class safearray_accessor
+
162 {
+
163 public:
+
164 safearray_accessor(_In_ LPSAFEARRAY sa) : m_sa(sa)
+
165 {
+
166 HRESULT hr = SafeArrayAccessData(sa, reinterpret_cast<void HUGEP**>(&m_data));
+
167 if (FAILED(hr))
+
168 throw std::invalid_argument("SafeArrayAccessData failed");
+
169 }
+
170
+
171 ~safearray_accessor()
+
172 {
+
173 SafeArrayUnaccessData(m_sa);
+
174 }
+
175
+
176 T* data() const { return m_data; }
+
177
+
178 protected:
+
179 LPSAFEARRAY m_sa;
+
180 T* m_data;
+
181 };
+
182
+
186 struct SafeArrayDestroy_delete
+
187 {
+
191 void operator()(_In_ LPSAFEARRAY sa) const
+
192 {
+
193 SafeArrayDestroy(sa);
+
194 }
+
195 };
+
196
+
200 struct SysFreeString_delete
+
201 {
+
205 void operator()(_In_ BSTR sa) const
+
206 {
+
207 SysFreeString(sa);
+
208 }
+
209 };
+
210#endif
+
211}
+
Operating system object (file, pipe, anything with an OS handle etc.)
Definition system.hpp:64
+
sys_handle get() const noexcept
Returns object handle.
Definition system.hpp:121
+
virtual void close()
Closes object.
Definition system.hpp:105
+
static sys_handle duplicate(sys_handle h, bool inherit)
Duplicates given object.
Definition system.hpp:141
+
static void close(sys_handle h)
Closes object.
Definition system.hpp:127
diff --git a/unicode_8hpp_source.html b/unicode_8hpp_source.html index 0ff54fd40..e96508394 100644 --- a/unicode_8hpp_source.html +++ b/unicode_8hpp_source.html @@ -215,7 +215,7 @@ $(function() { diff --git a/vector__queue_8hpp_source.html b/vector__queue_8hpp_source.html index 063911a05..bf4a8883a 100644 --- a/vector__queue_8hpp_source.html +++ b/vector__queue_8hpp_source.html @@ -386,7 +386,7 @@ $(function() {