6#include "Stroika/Foundation/Streams/InternallySynchronizedInputStream.h"
9namespace Stroika::Foundation::Streams::BufferedInputStream {
13 [[noreturn]]
void ThrowCannotSeekFromEnd_ ();
16 template <
typename ELEMENT_TYPE>
17 class Rep_Seekable_FromSeekable_ :
public IRep_<ELEMENT_TYPE> {
19 Rep_Seekable_FromSeekable_ (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn)
23 Require (realIn.IsSeekable ());
25 virtual bool IsSeekable ()
const override
29 virtual void CloseRead ()
override
31 if (fRealIn_ !=
nullptr) {
34 Ensure (not IsOpenRead ());
35 Assert (fRealIn_ ==
nullptr);
37 virtual bool IsOpenRead ()
const override
39 return fRealIn_ !=
nullptr;
43 Require (IsOpenRead ());
44 return fReader_.GetOffset ();
46 virtual optional<size_t> AvailableToRead ()
override
49 Require (IsOpenRead ());
50 return fReader_.AvailableToRead ();
52 virtual optional<SeekOffsetType> RemainingLength ()
override
55 Require (IsOpenRead ());
56 return fReader_.RemainingLength ();
58 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset)
override
61 Require (IsOpenRead ());
62 return fReader_.Seek (whence, offset);
64 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag)
override
67 Require (IsOpenRead ());
68 return fReader_.Read (intoBuffer, blockFlag);
72 typename InputStream::Ptr<ELEMENT_TYPE> fRealIn_;
73 StreamReader<ELEMENT_TYPE> fReader_;
78 template <
typename ELEMENT_TYPE,
size_t INLINE_BUF_SIZE>
79 class Rep_Seekable_FromUnSeekable_ :
public IRep_<ELEMENT_TYPE> {
81 Rep_Seekable_FromUnSeekable_ (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn)
85 virtual bool IsSeekable ()
const override
89 virtual void CloseRead ()
override
91 if (fRealIn_ !=
nullptr) {
94 Ensure (not IsOpenRead ());
95 Assert (fRealIn_ ==
nullptr);
97 virtual bool IsOpenRead ()
const override
99 return fRealIn_ !=
nullptr;
103 Require (IsOpenRead ());
106 virtual optional<size_t> AvailableToRead ()
override
109 Require (IsOpenRead ());
110 if (fSeekOffset_ < fBufferOfAllReadDataSoFar_.size ()) [[likely]] {
111 return fBufferOfAllReadDataSoFar_.size () -
static_cast<size_t> (fSeekOffset_);
113 return fRealIn_.AvailableToRead ();
115 virtual optional<SeekOffsetType> RemainingLength ()
override
118 Require (IsOpenRead ());
119 if (
auto rl = fRealIn_.RemainingLength ()) {
120 return MapOffsetFromReal2Mine_ (*rl);
124 virtual auto SeekRead (Whence whence, SignedSeekOffsetType offset) ->
SeekOffsetType override
127 Require (IsOpenRead ());
130 case Whence::eFromCurrent:
131 fSeekOffset_ += offset;
133 case Whence::eFromStart:
134 fSeekOffset_ = offset;
136 case Whence::eFromEnd:
137 if (
auto remaining = this->RemainingLength ()) {
142 Private_::ThrowCannotSeekFromEnd_ ();
149 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag)
override
152 Require (IsOpenRead ());
153 Assert (fSeekOffset_ <= fBufferOfAllReadDataSoFar_.size ());
154 if (fSeekOffset_ == fBufferOfAllReadDataSoFar_.size ()) [[unlikely]] {
155 ELEMENT_TYPE buf[1024];
156 if (
auto r = fRealIn_.Read (span{buf}, blockFlag)) {
157 fBufferOfAllReadDataSoFar_.push_back (*r);
163 if (fSeekOffset_ <= fBufferOfAllReadDataSoFar_.size ()) [[likely]] {
164 size_t n2Read = min<size_t> (intoBuffer.size (),
static_cast<size_t> (fBufferOfAllReadDataSoFar_.size () - fSeekOffset_));
165 auto result = Memory::CopySpanData (span{fBufferOfAllReadDataSoFar_}.subspan (
static_cast<size_t> (fSeekOffset_), n2Read), intoBuffer);
166 Assert (result.size () == n2Read);
167 fSeekOffset_ += n2Read;
174 nonvirtual
SeekOffsetType MapOffsetFromReal2Mine_ (SeekOffsetType so)
const
181 typename InputStream::Ptr<ELEMENT_TYPE> fRealIn_;
182 Memory::InlineBuffer<ELEMENT_TYPE, INLINE_BUF_SIZE> fBufferOfAllReadDataSoFar_;
188 template <
typename ELEMENT_TYPE,
size_t INLINE_BUF_SIZE>
189 class Rep_UnSeekable_ :
public IRep_<ELEMENT_TYPE> {
191 Rep_UnSeekable_ (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn)
195 virtual bool IsSeekable ()
const override
199 virtual void CloseRead ()
override
201 if (fRealIn_ !=
nullptr) {
204 Ensure (not IsOpenRead ());
205 Assert (fRealIn_ ==
nullptr);
207 virtual bool IsOpenRead ()
const override
209 return fRealIn_ !=
nullptr;
213 Require (IsOpenRead ());
216 Assert (fRealIn_.GetOffset () >= GetNEltsAlreadyBufferedFromUpstream_ ());
217 return fRealIn_.GetOffset () - GetNEltsAlreadyBufferedFromUpstream_ ();
219 virtual optional<size_t> AvailableToRead ()
override
222 Require (IsOpenRead ());
223 size_t n = GetNEltsAlreadyBufferedFromUpstream_ ();
224 if (
auto o = fRealIn_.AvailableToRead ()) {
233 virtual optional<SeekOffsetType> RemainingLength ()
override
236 Require (IsOpenRead ());
237 if (
auto o = fRealIn_.RemainingLength ()) {
238 return *o + GetNEltsAlreadyBufferedFromUpstream_ ();
242 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, NoDataAvailableHandling blockFlag)
override
245 Require (IsOpenRead ());
246 auto n = GetNEltsAlreadyBufferedFromUpstream_ ();
247 if (n == 0) [[unlikely]] {
255 ELEMENT_TYPE buf[INLINE_BUF_SIZE];
256 if (
auto bufR = fRealIn_.Read (span{buf}, blockFlag)) {
258 fIntermediateBuffer_.resize_uninitialized (0);
259 fIntermediateBuffer_.push_back (*bufR);
260 fReadOffsetIntoIntermediateBuf_ = 0;
270 Assert (n != 0 or not fRealIn_.IsSeekable () or fRealIn_.IsAtEOF ());
271 size_t n2Read = Math::AtMost (n, intoBuffer.size ());
272 auto t = Memory::CopySpanData (span{fIntermediateBuffer_}.subspan (fReadOffsetIntoIntermediateBuf_, n2Read), intoBuffer);
273 Assert (t.size () == n2Read);
274 fReadOffsetIntoIntermediateBuf_ += n2Read;
279 nonvirtual
size_t GetNEltsAlreadyBufferedFromUpstream_ ()
const
281 Assert (fReadOffsetIntoIntermediateBuf_ <= fIntermediateBuffer_.size ());
282 return fIntermediateBuffer_.size () - fReadOffsetIntoIntermediateBuf_;
286 typename InputStream::Ptr<ELEMENT_TYPE> fRealIn_;
287 Memory::InlineBuffer<ELEMENT_TYPE, INLINE_BUF_SIZE> fIntermediateBuffer_;
288 size_t fReadOffsetIntoIntermediateBuf_{0};
298 template <
typename ELEMENT_TYPE>
299 inline auto New (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn, optional<SeekableFlag> seekable) -> Ptr<ELEMENT_TYPE>
301 using PTR = Ptr<ELEMENT_TYPE>;
303 SeekableFlag useSeekable = seekable.value_or (srcSeekable);
304 constexpr size_t INLINE_BUF_SIZE = 4 * 1024;
305 if (useSeekable == SeekableFlag::eSeekable) {
306 return (srcSeekable == SeekableFlag::eSeekable)
307 ? PTR{Memory::MakeSharedPtr<Private_::Rep_Seekable_FromSeekable_<ELEMENT_TYPE>> (realIn)}
308 : PTR{Memory::MakeSharedPtr<Private_::Rep_Seekable_FromUnSeekable_<ELEMENT_TYPE, INLINE_BUF_SIZE>> (realIn)};
311 return PTR{Memory::MakeSharedPtr<Private_::Rep_UnSeekable_<ELEMENT_TYPE, INLINE_BUF_SIZE>> (realIn)};
314 template <
typename ELEMENT_TYPE>
316 optional<SeekableFlag> seekable) -> Ptr<ELEMENT_TYPE>
318 constexpr size_t INLINE_BUF_SIZE = 4 * 1024;
319 switch (internallySynchronized) {
320 case Execution::eInternallySynchronized: {
322 SeekableFlag useSeekable = seekable.value_or (srcSeekable);
323 if (useSeekable == SeekableFlag::eSeekable) {
324 return (srcSeekable == SeekableFlag::eSeekable)
325 ? InternallySynchronizedInputStream::New<Private_::Rep_Seekable_FromSeekable_<ELEMENT_TYPE>> ({}, realIn)
326 : InternallySynchronizedInputStream::New<Private_::Rep_Seekable_FromUnSeekable_<ELEMENT_TYPE, INLINE_BUF_SIZE>> ({}, realIn);
329 return InternallySynchronizedInputStream::New<Private_::Rep_UnSeekable_<ELEMENT_TYPE, INLINE_BUF_SIZE>> ({}, realIn);
332 case Execution::eNotKnownInternallySynchronized:
333 return New<ELEMENT_TYPE> (realIn, seekable);
345 template <
typename ELEMENT_TYPE>
346 inline Ptr<ELEMENT_TYPE>::Ptr (
const shared_ptr<Private_::IRep_<ELEMENT_TYPE>>& from)
351 template <
typename ELEMENT_TYPE>
352 [[deprecated (
"Since Stroika v3.0d19 use Seekability overload")]] Ptr<ELEMENT_TYPE> New (
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn,
353 optional<bool> seekable)
355 optional<SeekableFlag> sf;
357 sf = *seekable ? SeekableFlag::eSeekable : SeekableFlag::eNotSeekable;
359 return New (realIn, sf);
361 template <
typename ELEMENT_TYPE>
362 [[deprecated (
"Since Stroika v3.0d19 use Seekability overload")]] Ptr<ELEMENT_TYPE>
363 New (Execution::InternallySynchronized internallySynchronized,
const typename InputStream::Ptr<ELEMENT_TYPE>& realIn, optional<bool> seekable = {})
365 optional<SeekableFlag> sf;
367 sf = *seekable ? SeekableFlag::eSeekable : SeekableFlag::eNotSeekable;
369 return New (internallySynchronized, realIn, sf);
#define RequireNotReached()
#define qStroika_ATTRIBUTE_NO_UNIQUE_ADDRESS_VCFORCE
[[msvc::no_unique_address]] isn't always broken in MSVC. Annotate with this on things where its not b...
int64_t SignedSeekOffsetType
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...