4#include "InternallySynchronizedInputStream.h"
9namespace Stroika::Foundation::Streams::InputSubStream {
12 template <
typename ELEMENT_TYPE>
13 class Rep_ :
public InputStream::IRep<ELEMENT_TYPE> {
15 Rep_ (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn,
const optional<SeekOffsetType>& start,
const optional<SeekOffsetType>& end)
17 , fOffsetMine2Real_{start.value_or (realIn.GetOffset ())}
18 , fForcedEndInReal_{end}
22 if (fRealIn_.IsSeekable ()) {
23 fRealIn_.Seek (Whence::eFromStart, *start);
28 if (realSeekOffset < *start) {
29 Assert (*start - realSeekOffset <
sizeof (
size_t));
30 Memory::StackBuffer<ELEMENT_TYPE> buf;
31 if constexpr (is_trivially_copyable_v<ELEMENT_TYPE>) {
32 buf.resize_uninitialized (
static_cast<size_t> (*start - realSeekOffset));
35 buf.resize (
static_cast<size_t> (*start - realSeekOffset));
37 (void)realIn.ReadAll (span{buf});
42 Rep_ (
const Rep_&) =
delete;
44 virtual bool IsSeekable ()
const override
46 return fRealIn_.IsSeekable ();
48 virtual void CloseRead ()
override
54 Assert (fRealIn_ ==
nullptr);
55 Ensure (not IsOpenRead ());
57 virtual bool IsOpenRead ()
const override
59 return fRealIn_ !=
nullptr;
64 Require (IsOpenRead ());
66 ValidateRealOffset_ (realOffset);
67 return realOffset - fOffsetMine2Real_;
69 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset)
override
72 Require (IsOpenRead ());
73 if (fForcedEndInReal_) {
77 effectiveRealTarget = fRealIn_.GetOffset () + offset;
80 effectiveRealTarget = fOffsetMine2Real_ + offset;
83 if (fForcedEndInReal_) {
85 effectiveRealTarget = *fForcedEndInReal_;
88 auto getOffsetToEndOfStream = [] (
typename InputStream::Ptr<ELEMENT_TYPE> in) {
91 in.Seek (eFromStart, savedReadFrom);
92 Assert (size >= savedReadFrom);
93 size -= savedReadFrom;
96 effectiveRealTarget = fRealIn_.GetOffset () + getOffsetToEndOfStream (fRealIn_) + offset;
100 effectiveRealTarget = 0;
103 ValidateRealOffset_ (effectiveRealTarget);
105 ValidateRealOffset_ (result);
106 return result - fOffsetMine2Real_;
109 return fRealIn_.Seek (whence, offset + fOffsetMine2Real_) - fOffsetMine2Real_;
112 virtual optional<size_t> AvailableToRead ()
override
115 Require (IsOpenRead ());
117 if (fForcedEndInReal_ and myOffset >= *fForcedEndInReal_) {
121 return fRealIn_.AvailableToRead ();
123 virtual optional<SeekOffsetType> RemainingLength ()
override
128 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag)
override
130 Require (not intoBuffer.empty ());
132 Require (IsOpenRead ());
133 if (fForcedEndInReal_) {
138 if (maxNewReal > *fForcedEndInReal_) {
139 if (curReal == *fForcedEndInReal_) {
140 return span<ELEMENT_TYPE>{};
143 ELEMENT_TYPE* newIntoEnd{intoBuffer.data () + *fForcedEndInReal_ - curReal};
144 Assert (newIntoEnd < intoBuffer.data () + intoBuffer.size ());
145 return fRealIn_.ReadOrThrow (span{intoBuffer.data (), newIntoEnd}, blockFlag);
149 return fRealIn_.Read (intoBuffer, blockFlag);
153 nonvirtual
void ValidateRealOffset_ (SignedSeekOffsetType offset)
const
158 if (fForcedEndInReal_) {
164 typename InputStream::Ptr<ELEMENT_TYPE> fRealIn_;
166 optional<SeekOffsetType> fForcedEndInReal_;
167 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
176 template <
typename ELEMENT_TYPE>
180 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE>> (realIn, start, end)};
182 template <
typename ELEMENT_TYPE>
184 const optional<SeekOffsetType>& start,
const optional<SeekOffsetType>& end) ->
Ptr<ELEMENT_TYPE>
186 switch (internallySynchronized) {
187 case Execution::eInternallySynchronized:
188 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE>> ({}, realIn, start, end);
189 case Execution::eNotKnownInternallySynchronized:
190 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...