6#include "Stroika/Foundation/Memory/Common.h"
9#include "InternallySynchronizedInputStream.h"
11namespace Stroika::Foundation::Streams::ExternallyOwnedSpanInputStream {
14 template <
typename ELEMENT_TYPE>
15 class Rep_ :
public InputStream::IRep<ELEMENT_TYPE> {
18 Rep_ (
const Rep_&) =
delete;
19 template <
size_t EXTENT_T>
20 Rep_ (span<const ELEMENT_TYPE, EXTENT_T> s)
22 , fEnd_{fStart_ + s.size ()}
28 nonvirtual Rep_& operator= (
const Rep_&) =
delete;
31 bool fIsOpenForRead_{
true};
34 virtual bool IsSeekable ()
const override
38 virtual void CloseRead ()
override
40 fIsOpenForRead_ =
false;
41 Ensure (not IsOpenRead ());
43 virtual bool IsOpenRead ()
const override
45 return fIsOpenForRead_;
47 virtual optional<size_t> AvailableToRead ()
override
50 Require (IsOpenRead ());
51 Ensure (fEnd_ >= fCursor_);
52 return static_cast<size_t> (fEnd_ - fCursor_);
54 virtual optional<SeekOffsetType> RemainingLength ()
override
57 Require (IsOpenRead ());
58 Ensure (fEnd_ >= fCursor_);
59 return static_cast<size_t> (fEnd_ - fCursor_);
61 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, [[maybe_unused]] NoDataAvailableHandling blockFlag)
override
63 Require (not intoBuffer.empty ());
64 Require (IsOpenRead ());
65 size_t nRequested = intoBuffer.size ();
67 Assert ((fStart_ <= fCursor_) and (fCursor_ <= fEnd_));
68 size_t nAvail = fEnd_ - fCursor_;
69 size_t nCopied = min (nAvail, nRequested);
70 copy (fCursor_, fCursor_ + nCopied, intoBuffer.data ());
72 return intoBuffer.subspan (0, nCopied);
77 Require (IsOpenRead ());
78 return fCursor_ - fStart_;
80 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset)
override
83 Require (IsOpenRead ());
84 static const auto kRangeException_ = range_error{
"seek"};
87 if (offset < 0) [[unlikely]] {
90 if (offset > (fEnd_ - fStart_)) [[unlikely]] {
93 fCursor_ = fStart_ + offset;
96 Streams::SeekOffsetType curOffset = fCursor_ - fStart_;
97 Streams::SignedSeekOffsetType newOffset = curOffset + offset;
98 if (newOffset < 0) [[unlikely]] {
101 if (newOffset > (fEnd_ - fStart_)) [[unlikely]] {
104 fCursor_ = fStart_ + newOffset;
107 Streams::SignedSeekOffsetType newOffset = (fEnd_ - fStart_) + offset;
108 if (newOffset < 0) [[unlikely]] {
111 if (newOffset > (fEnd_ - fStart_)) [[unlikely]] {
114 fCursor_ = fStart_ + newOffset;
117 Ensure ((fStart_ <= fCursor_) and (fCursor_ <= fEnd_));
118 return fCursor_ - fStart_;
122 const ELEMENT_TYPE* fStart_;
123 const ELEMENT_TYPE* fEnd_;
124 const ELEMENT_TYPE* fCursor_;
134 template <
typename ELEMENT_TYPE, Memory::ISpanBytesCastable<span<const ELEMENT_TYPE>> FROM_SPAN>
137 return Ptr<ELEMENT_TYPE>{Memory::MakeSharedPtr<Private_::Rep_<ELEMENT_TYPE>> (Memory::SpanBytesCast<span<const ELEMENT_TYPE>> (s))};
139 template <
typename ELEMENT_TYPE, Memory::ISpanBytesCastable<span<const ELEMENT_TYPE>> FROM_SPAN>
142 switch (internallySynchronized) {
143 case Execution::eInternallySynchronized:
144 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE>> ({}, Memory::SpanBytesCast<span<const ELEMENT_TYPE>> (s));
145 case Execution::eNotKnownInternallySynchronized:
146 return New<ELEMENT_TYPE> (s);
#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...
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
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...