4#include "InternallySynchronizedInputStream.h"
8namespace Stroika::Foundation::Streams::InputSubStream {
11 template <
typename ELEMENT_TYPE>
12 class Rep_ :
public InputStream::IRep<ELEMENT_TYPE> {
14 Rep_ (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn,
const optional<SeekOffsetType>& start,
const optional<SeekOffsetType>& end)
16 , fOffsetMine2Real_{start.value_or (realIn.GetOffset ())}
17 , fForcedEndInReal_{end}
21 if (fRealIn_.IsSeekable ()) {
22 fRealIn_.Seek (Whence::eFromStart, *start);
27 if (realSeekOffset < *start) {
28 Assert (*start - realSeekOffset <
sizeof (
size_t));
29 Memory::StackBuffer<ELEMENT_TYPE> buf;
30 if constexpr (is_trivially_copyable_v<ELEMENT_TYPE>) {
31 buf.resize_uninitialized (
static_cast<size_t> (*start - realSeekOffset));
34 buf.resize (
static_cast<size_t> (*start - realSeekOffset));
36 (void)realIn.ReadAll (span{buf});
41 Rep_ (
const Rep_&) =
delete;
43 virtual bool IsSeekable ()
const override
45 return fRealIn_.IsSeekable ();
47 virtual void CloseRead ()
override
53 Assert (fRealIn_ ==
nullptr);
54 Ensure (not IsOpenRead ());
56 virtual bool IsOpenRead ()
const override
58 return fRealIn_ !=
nullptr;
63 Require (IsOpenRead ());
65 ValidateRealOffset_ (realOffset);
66 return realOffset - fOffsetMine2Real_;
68 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset)
override
71 Require (IsOpenRead ());
72 if (fForcedEndInReal_) {
76 effectiveRealTarget = fRealIn_.GetOffset () + offset;
79 effectiveRealTarget = fOffsetMine2Real_ + offset;
82 if (fForcedEndInReal_) {
84 effectiveRealTarget = *fForcedEndInReal_;
87 auto getOffsetToEndOfStream = [] (
typename InputStream::Ptr<ELEMENT_TYPE> in) {
90 in.Seek (eFromStart, savedReadFrom);
91 Assert (size >= savedReadFrom);
92 size -= savedReadFrom;
95 effectiveRealTarget = fRealIn_.GetOffset () + getOffsetToEndOfStream (fRealIn_) + offset;
99 effectiveRealTarget = 0;
102 ValidateRealOffset_ (effectiveRealTarget);
104 ValidateRealOffset_ (result);
105 return result - fOffsetMine2Real_;
108 return fRealIn_.Seek (whence, offset + fOffsetMine2Real_) - fOffsetMine2Real_;
111 virtual optional<size_t> AvailableToRead ()
override
114 Require (IsOpenRead ());
116 if (fForcedEndInReal_ and myOffset >= *fForcedEndInReal_) {
120 return fRealIn_.AvailableToRead ();
122 virtual optional<SeekOffsetType> RemainingLength ()
override
127 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag)
override
129 Require (not intoBuffer.empty ());
131 Require (IsOpenRead ());
132 if (fForcedEndInReal_) {
137 if (maxNewReal > *fForcedEndInReal_) {
138 if (curReal == *fForcedEndInReal_) {
139 return span<ELEMENT_TYPE>{};
142 ELEMENT_TYPE* newIntoEnd{intoBuffer.data () + *fForcedEndInReal_ - curReal};
143 Assert (newIntoEnd < intoBuffer.data () + intoBuffer.size ());
144 return fRealIn_.ReadOrThrow (span{intoBuffer.data (), newIntoEnd}, blockFlag);
148 return fRealIn_.Read (intoBuffer, blockFlag);
152 nonvirtual
void ValidateRealOffset_ (SignedSeekOffsetType offset)
const
157 if (fForcedEndInReal_) {
163 typename InputStream::Ptr<ELEMENT_TYPE> fRealIn_;
165 optional<SeekOffsetType> fForcedEndInReal_;
166 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
175 template <
typename ELEMENT_TYPE>
179 return Ptr<ELEMENT_TYPE>{make_shared<Private_::Rep_<ELEMENT_TYPE>> (realIn, start, end)};
181 template <
typename ELEMENT_TYPE>
183 const optional<SeekOffsetType>& start,
const optional<SeekOffsetType>& end) ->
Ptr<ELEMENT_TYPE>
185 switch (internallySynchronized) {
186 case Execution::eInternallySynchronized:
187 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE>> ({}, realIn, start, end);
188 case Execution::eNotKnownInternallySynchronized:
189 return New<ELEMENT_TYPE> (start, end);
#define AssertNotImplemented()
#define RequireNotReached()
int64_t SignedSeekOffsetType
unique_lock< AssertExternallySynchronizedMutex > WriteContext
Instantiate AssertExternallySynchronizedMutex::WriteContext to designate an area of code where protec...
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...