4#include "Stroika/Foundation/StroikaPreComp.h"
11#include "Stroika/Foundation/Execution/Exceptions.h"
12#include "Stroika/Foundation/Execution/Throw.h"
21using namespace Stroika::Foundation::Debug;
22using namespace Stroika::Foundation::Memory;
23using namespace Stroika::Foundation::Streams;
34 size_t len_ (
const initializer_list<pair<const byte*, const byte*>>& startEndPairs)
37 for (
auto i : startEndPairs) {
38 sz += (i.second - i.first);
42 size_t len_ (
const initializer_list<BLOB>& list2Concatenate)
45 for (
const auto& i : list2Concatenate) {
52BLOB::BasicRep_::BasicRep_ (
const initializer_list<pair<const byte*, const byte*>>& startEndPairs)
53 : fData{len_ (startEndPairs)}
55 byte* pb = fData.begin ();
56 for (
auto i : startEndPairs) {
57 auto itemSize{i.second - i.first};
59 (void)::memcpy (pb, i.first, itemSize);
63 Ensure (pb == fData.end ());
66BLOB::BasicRep_::BasicRep_ (
const initializer_list<BLOB>& list2Concatenate)
67 : fData{len_ (list2Concatenate)}
69 byte* pb = fData.begin ();
70 for (
const auto& i : list2Concatenate) {
71 auto itemSize{i.GetSize ()};
73 (void)::memcpy (pb, i.begin (), itemSize);
77 Ensure (pb == fData.end ());
80span<const byte> BLOB::BasicRep_::GetBounds ()
const
82 Ensure (fData.begin () <= fData.end ());
83#if qCompilerAndStdLib_span_requires_explicit_type_for_BLOBCVT_Buggy
84 return span<const byte>{fData.begin (), fData.end ()};
86 return span{fData.begin (), fData.end ()};
95span<const byte> BLOB::ZeroRep_::GetBounds ()
const
97 return span<const byte>{};
105BLOB::AdoptRep_::AdoptRep_ (
const byte* start,
const byte* end)
109 Require (start <= end);
112span<const byte> BLOB::AdoptRep_::GetBounds ()
const
114 Ensure (fStart <= fEnd);
115 return span<const byte>{fStart, fEnd};
123BLOB::AdoptAndDeleteRep_::AdoptAndDeleteRep_ (
const byte* start,
const byte* end)
127 Require (start <= end);
130BLOB::AdoptAndDeleteRep_::~AdoptAndDeleteRep_ ()
135span<const byte> BLOB::AdoptAndDeleteRep_::GetBounds ()
const
137 Ensure (fStart <= fEnd);
138 return span<const byte>{fStart, fEnd};
158 return Cryptography::Encoding::Algorithm::Base64::Decode (
s);
170 using namespace Streams;
172 BLOBBINSTREAM_ (
const BLOB& b)
173 : InputStream::
Ptr<byte>{Memory::MakeSharedPtr<REP> (b)}
177 bool fIsOpenForRead_{
true};
182 , fCur{fSavedBLOB_.begin ()}
183 , fStart{fSavedBLOB_.begin ()}
184 , fEnd{fSavedBLOB_.end ()}
187 virtual bool IsSeekable ()
const override
191 virtual void CloseRead ()
override
193 fIsOpenForRead_ =
false;
194 Require (not IsOpenRead ());
196 virtual bool IsOpenRead ()
const override
198 return fIsOpenForRead_;
200 virtual optional<size_t> AvailableToRead ()
override
202 Require (IsOpenRead ());
206 virtual optional<SeekOffsetType> RemainingLength ()
override
209 Require (IsOpenRead ());
212 virtual optional<span<byte>> Read (span<byte> intoBuffer, [[maybe_unused]]
NoDataAvailableHandling blockFlag)
override
214 Require (not intoBuffer.empty ());
216 size_t bytesToRead = intoBuffer.size ();
217 size_t bytesLeft = fEnd - fCur;
218 bytesToRead = min (bytesLeft, bytesToRead);
219 CopyBytes (span{fCur, bytesToRead}, intoBuffer);
221 return intoBuffer.subspan (0, bytesToRead);
225 Require (IsOpenRead ());
227 return fCur - fStart;
231 static const auto kException_ = range_error{
"seek"};
233 Require (IsOpenRead ());
236 if (offset < 0) [[unlikely]] {
237 Execution::Throw (kException_);
239 if (offset > (fEnd - fStart)) [[unlikely]] {
240 Execution::Throw (kException_);
242 fCur = fStart + offset;
247 if (newOffset < 0) [[unlikely]] {
248 Execution::Throw (kException_);
250 if (newOffset > (fEnd - fStart)) [[unlikely]] {
251 Execution::Throw (kException_);
253 fCur = fStart + newOffset;
257 if (newOffset < 0) [[unlikely]] {
258 Execution::Throw (kException_);
260 if (newOffset > (fEnd - fStart)) [[unlikely]] {
261 Execution::Throw (kException_);
263 fCur = fStart + newOffset;
266 Ensure ((fStart <= fCur) and (fCur <= fEnd));
267 return GetReadOffset ();
280 return BLOBBINSTREAM_{*
this};
287 span<const byte> bytes = As<span<const byte>> ();
294 return AsBase64 ({});
308 else if (count <= 2) {
310 for (
unsigned int i = 1; i < count; ++i) {
320 for (
unsigned int i = 0; i < count; ++i) {
340 return s.ReplaceAll (
"\n"sv,
"\\n"sv).ReplaceAll (
"\r"sv,
"\\r"sv);
conditional_t< qStroika_Foundation_Memory_PreferBlockAllocation and andTrueCheck, BlockAllocationUseHelper< T >, Common::Empty > UseBlockAllocationIfAppropriate
Use this to enable block allocation for a particular class. Beware of subclassing.
#define Stroika_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
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...
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...
shared_lock< const AssertExternallySynchronizedChecker > ReadContext
Instantiate AssertExternallySynchronizedChecker::ReadContext to designate an area of code where prote...
nonvirtual STRING_TYPE AsBase64() const
nonvirtual Characters::String ToString(size_t maxBytesToShow=80) const
nonvirtual BLOB Repeat(unsigned int count) const
static BLOB FromHex(const char *b)
Convert string of hex bytes to BLOB.
nonvirtual BLOB Slice(size_t startAt, size_t endAt) const
nonvirtual const byte * begin() const
nonvirtual STRING_TYPE AsHex(size_t maxBytesToShow=numeric_limits< size_t >::max()) const
nonvirtual size_t GetSize() const
static BLOB FromBase64(const char *b)
Convert string of base64 bytes to BLOB.
nonvirtual size_t size() const
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual void reserve(size_t newCapacity, bool atLeast=true)
A Streams::Ptr<ELEMENT_TYPE> is a smart-pointer to a stream of elements of type T.
char ASCII
Stroika's string/character classes treat 'char' as being an ASCII character.
string Encode(const Streams::InputStream::Ptr< byte > &from, const Options &o={})
string Encode(span< const byte > from)
The bytes as hex: two digits a byte, lower case - {0x29, 0x14} as "2914".
Memory::BLOB Decode(span< const char > s)
Hex read back into bytes: digits of either case; spaces before a byte's two digits skipped (so "29 14...