5#include "Stroika/Foundation/Memory/Common.h"
8#include "InternallySynchronizedInputStream.h"
10namespace Stroika::Foundation::Streams::ExternallyOwnedSpanInputStream {
13 template <
typename ELEMENT_TYPE>
14 class Rep_ :
public InputStream::IRep<ELEMENT_TYPE> {
17 Rep_ (
const Rep_&) =
delete;
18 template <
size_t EXTENT_T>
19 Rep_ (span<const ELEMENT_TYPE, EXTENT_T> s)
21 , fEnd_{fStart_ + s.size ()}
27 nonvirtual Rep_& operator= (
const Rep_&) =
delete;
30 bool fIsOpenForRead_{
true};
33 virtual bool IsSeekable ()
const override
37 virtual void CloseRead ()
override
39 fIsOpenForRead_ =
false;
40 Ensure (not IsOpenRead ());
42 virtual bool IsOpenRead ()
const override
44 return fIsOpenForRead_;
46 virtual optional<size_t> AvailableToRead ()
override
49 Require (IsOpenRead ());
50 Ensure (fEnd_ >= fCursor_);
51 return static_cast<size_t> (fEnd_ - fCursor_);
53 virtual optional<SeekOffsetType> RemainingLength ()
override
56 Require (IsOpenRead ());
57 Ensure (fEnd_ >= fCursor_);
58 return static_cast<size_t> (fEnd_ - fCursor_);
60 virtual optional<span<ELEMENT_TYPE>> Read (span<ELEMENT_TYPE> intoBuffer, [[maybe_unused]] NoDataAvailableHandling blockFlag)
override
62 Require (not intoBuffer.empty ());
63 Require (IsOpenRead ());
64 size_t nRequested = intoBuffer.size ();
66 Assert ((fStart_ <= fCursor_) and (fCursor_ <= fEnd_));
67 size_t nAvail = fEnd_ - fCursor_;
68 size_t nCopied = min (nAvail, nRequested);
69 copy (fCursor_, fCursor_ + nCopied, intoBuffer.data ());
71 return intoBuffer.subspan (0, nCopied);
76 Require (IsOpenRead ());
77 return fCursor_ - fStart_;
79 virtual SeekOffsetType SeekRead (Whence whence, SignedSeekOffsetType offset)
override
82 Require (IsOpenRead ());
83 static const auto kRangeException_ = range_error{
"seek"};
86 if (offset < 0) [[unlikely]] {
89 if (offset > (fEnd_ - fStart_)) [[unlikely]] {
92 fCursor_ = fStart_ + offset;
95 Streams::SeekOffsetType curOffset = fCursor_ - fStart_;
96 Streams::SignedSeekOffsetType newOffset = curOffset + offset;
97 if (newOffset < 0) [[unlikely]] {
100 if (newOffset > (fEnd_ - fStart_)) [[unlikely]] {
103 fCursor_ = fStart_ + newOffset;
106 Streams::SignedSeekOffsetType newOffset = (fEnd_ - fStart_) + offset;
107 if (newOffset < 0) [[unlikely]] {
110 if (newOffset > (fEnd_ - fStart_)) [[unlikely]] {
113 fCursor_ = fStart_ + newOffset;
116 Ensure ((fStart_ <= fCursor_) and (fCursor_ <= fEnd_));
117 return fCursor_ - fStart_;
121 const ELEMENT_TYPE* fStart_;
122 const ELEMENT_TYPE* fEnd_;
123 const ELEMENT_TYPE* fCursor_;
124 [[no_unique_address]] Debug::AssertExternallySynchronizedMutex fThisAssertExternallySynchronized_;
133 template <
typename ELEMENT_TYPE, Memory::ISpanBytesCastable<span<const ELEMENT_TYPE>> FROM_SPAN>
136 return Ptr<ELEMENT_TYPE>{make_shared<Private_::Rep_<ELEMENT_TYPE>> (Memory::SpanBytesCast<span<const ELEMENT_TYPE>> (s))};
138 template <
typename ELEMENT_TYPE, Memory::ISpanBytesCastable<span<const ELEMENT_TYPE>> FROM_SPAN>
141 switch (internallySynchronized) {
142 case Execution::eInternallySynchronized:
143 return InternallySynchronizedInputStream::New<Private_::Rep_<ELEMENT_TYPE>> ({}, Memory::SpanBytesCast<span<const ELEMENT_TYPE>> (s));
144 case Execution::eNotKnownInternallySynchronized:
145 return New<ELEMENT_TYPE> (s);
#define RequireNotReached()
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...