4#include "Stroika/Foundation/StroikaPreComp.h"
8#include "Stroika/Foundation/Execution/Common.h"
9#include "Stroika/Foundation/Execution/OperationNotSupportedException.h"
17using namespace Stroika::Foundation::IO;
20using namespace Stroika::Foundation::IO::Network::HTTP::MessageStartTextInputStreamBinaryAdapter;
21using namespace Stroika::Foundation::Streams;
25using Memory::MakeSharedPtr;
31 constexpr size_t kDefaultBufSize_ = 2 * 1024;
45 , fAllDataReadBuf_{kDefaultBufSize_}
47 , fBufferFilledUpValidBytes_{0}
52 bool AssureHeaderSectionAvailable ()
55#if USE_NOISY_TRACE_IN_THIS_MODULE_
58 this->SeekRead (eFromStart, 0);
67 while (optional<span<Character>> o = Read (span{&c, &c + 1}, NoDataAvailableHandling::eDontBlock)) {
68 if (o->size () == 0) {
71 Assert (o->size () == 1);
82 DbgTrace (
"Looks like bad HTTP header (\\r)"_f);
93 this->SeekRead (eFromStart, 0);
97 DbgTrace (
"Looks like bad HTTP header (\\n)"_f);
116 sb <<
"Offset: "sv << fOffset_;
117 sb <<
", HighWaterMark: "sv << fBufferFilledUpValidBytes_;
120 case ToStringFormat::eAsBytes: {
121 for (
size_t i = 0; i < fBufferFilledUpValidBytes_; ++i) {
122 sb <<
"x{:x}, "_f(fAllDataReadBuf_[i]);
125 case ToStringFormat::eAsString: {
127 for (
Character c :
String::FromLatin1 (span{reinterpret_cast<const char*> (begin (fAllDataReadBuf_)), fBufferFilledUpValidBytes_})) {
148 virtual bool IsSeekable ()
const override
152 virtual void CloseRead ()
override
155 if (fSource_ !=
nullptr) {
158 Assert (fSource_ ==
nullptr);
160 virtual bool IsOpenRead ()
const override
162 return fSource_ !=
nullptr;
164 virtual optional<size_t> AvailableToRead ()
override
166 Require (IsOpenRead ());
167 if (fOffset_ < fBufferFilledUpValidBytes_) {
168 return fBufferFilledUpValidBytes_ - fOffset_;
171 return inherited::AvailableToRead ();
173 virtual optional<SeekOffsetType> RemainingLength ()
override
175 Require (IsOpenRead ());
178 virtual optional<span<Character>> Read (span<Character> intoBuffer,
NoDataAvailableHandling blockFlag)
override
180 Require (not intoBuffer.empty ());
181 Require (IsOpenRead ());
183 Assert (fBufferFilledUpValidBytes_ >= fOffset_);
184 if (fBufferFilledUpValidBytes_ == fOffset_) {
185 size_t roomLeftInBuf = fAllDataReadBuf_.GetSize () - fBufferFilledUpValidBytes_;
186 if (roomLeftInBuf == 0) {
188 fAllDataReadBuf_.GrowToSize_uninitialized (fBufferFilledUpValidBytes_ + kDefaultBufSize_);
189 roomLeftInBuf = fAllDataReadBuf_.GetSize () - fBufferFilledUpValidBytes_;
191 Assert (roomLeftInBuf > 0);
196 size_t nBytesNeeded = intoBuffer.size ();
197 if (roomLeftInBuf > nBytesNeeded) {
198 roomLeftInBuf = nBytesNeeded;
202 byte* startReadAt = fAllDataReadBuf_.begin () + fBufferFilledUpValidBytes_;
203 size_t n = fSource_.ReadOrThrow (span{startReadAt, roomLeftInBuf}, blockFlag).size ();
204 Assert (n <= roomLeftInBuf);
206 fBufferFilledUpValidBytes_ += n;
211 for (
auto outChar = intoBuffer.begin (); outChar != intoBuffer.end (); ++outChar) {
212 if (fOffset_ < fBufferFilledUpValidBytes_) {
219 Ensure (outN <= intoBuffer.size ());
220 return intoBuffer.subspan (0, outN);
225 Require (IsOpenRead ());
231 Require (IsOpenRead ());
232 static const auto kException_ = range_error{
"seek"};
235 if (offset < 0) [[unlikely]] {
236 Execution::Throw (kException_);
239 if (uOffset > fBufferFilledUpValidBytes_) [[unlikely]] {
240 Execution::Throw (kException_);
243 fOffset_ =
static_cast<size_t> (offset);
248 if (newOffset < 0) [[unlikely]] {
249 Execution::Throw (kException_);
252 if (uNewOffset > fBufferFilledUpValidBytes_) [[unlikely]] {
253 Execution::Throw (kException_);
256 fOffset_ =
static_cast<size_t> (newOffset);
260 if (newOffset < 0) [[unlikely]] {
261 Execution::Throw (kException_);
264 if (uNewOffset > fBufferFilledUpValidBytes_) [[unlikely]] {
265 Execution::Throw (kException_);
268 fOffset_ =
static_cast<size_t> (newOffset);
271 Ensure ((0 <= fOffset_) and (fOffset_ <= fBufferFilledUpValidBytes_));
272 return GetReadOffset ();
280 size_t fBufferFilledUpValidBytes_;
291 return Ptr{MakeSharedPtr<Rep_> (src)};
304bool MessageStartTextInputStreamBinaryAdapter::Ptr::AssureHeaderSectionAvailable ()
306 return Debug::UncheckedDynamicCast<Rep_&> (
GetRepRWRef ()).AssureHeaderSectionAvailable ();
311 return Debug::UncheckedDynamicCast<const Rep_&> (GetRepConstRef ()).ToString (format);
#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...
NoDataAvailableHandling
If eDontBlock passed to most Stream APIs, then when the code would do a blocking read,...
int64_t SignedSeekOffsetType
constexpr char32_t GetCharacterCode() const noexcept
Return the char32_t UNICODE code-point associated with this character.
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
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...
nonvirtual Characters::String ToString(ToStringFormat format=ToStringFormat::eDEFAULT) const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...