4#include "Stroika/Foundation/Containers/Common.h"
7#include "Stroika/Foundation/Memory/Common.h"
11namespace Stroika::Foundation::Memory {
18 struct BLOB::BasicRep_ final :
public _IRep,
public Memory::UseBlockAllocationIfAppropriate<BasicRep_> {
23 InlineBuffer<byte, 64> fData;
25 BasicRep_ (span<const byte> s)
26 : fData{Memory::eUninitialized, s.
size ()}
28 CopyBytes (s, span{fData});
31 BasicRep_ (
const initializer_list<pair<const byte*, const byte*>>& startEndPairs);
32 BasicRep_ (
const initializer_list<BLOB>& list2Concatenate);
33 BasicRep_ (
const BasicRep_&) =
delete;
34 BasicRep_& operator= (
const BasicRep_&) =
delete;
36 virtual span<const byte> GetBounds ()
const override;
39 struct BLOB::ZeroRep_ final :
public _IRep,
public Memory::UseBlockAllocationIfAppropriate<ZeroRep_> {
40 virtual span<const byte> GetBounds ()
const override;
41 ZeroRep_ () =
default;
42 ZeroRep_ (
const ZeroRep_&) =
delete;
43 ZeroRep_& operator= (
const ZeroRep_&) =
delete;
46 struct BLOB::AdoptRep_ final :
public _IRep,
public Memory::UseBlockAllocationIfAppropriate<AdoptRep_> {
50 AdoptRep_ (
const AdoptRep_&) =
delete;
51 AdoptRep_ (
const byte* start,
const byte*
end);
52 ~AdoptRep_ () =
default;
53 AdoptRep_& operator= (
const AdoptRep_&) =
delete;
54 virtual span<const byte> GetBounds ()
const override;
57 struct BLOB::AdoptAndDeleteRep_ final :
public _IRep,
public Memory::UseBlockAllocationIfAppropriate<AdoptAndDeleteRep_> {
61 AdoptAndDeleteRep_ (
const AdoptAndDeleteRep_&) =
delete;
62 AdoptAndDeleteRep_ (
const byte* start,
const byte*
end);
63 ~AdoptAndDeleteRep_ ();
64 AdoptAndDeleteRep_& operator= (
const AdoptAndDeleteRep_&) =
delete;
65 virtual span<const byte> GetBounds ()
const override;
77 template <ranges::range CONTAINER_OF_BYTE>
78 inline BLOB::BLOB (
const CONTAINER_OF_BYTE& data)
79 requires (is_convertible_v<typename CONTAINER_OF_BYTE::value_type, byte> or is_convertible_v<typename CONTAINER_OF_BYTE::value_type, uint8_t>)
80 :
BLOB{as_bytes (span{data.data (), data.size ()})}
83 inline BLOB::BLOB (
const initializer_list<byte>& bytes)
87 inline BLOB::BLOB (
const initializer_list<uint8_t>& bytes)
88 : BLOB{as_bytes (span{bytes})}
92 : fRep_{s.empty () ? shared_ptr<_IRep>{MakeSharedPtr<ZeroRep_> ()} : shared_ptr<_IRep>{MakeSharedPtr<BasicRep_> (s)}}
94 Ensure (s.size () == size ());
96 inline BLOB::BLOB (
const byte* start,
const byte* end)
97 : BLOB{span{start, end}}
99 Ensure (
static_cast<size_t> (
end - start) ==
size ());
101 inline BLOB::BLOB (
const uint8_t* start,
const uint8_t* end)
102 : BLOB{as_bytes (span{start, end})}
104 Ensure (
static_cast<size_t> (
end - start) ==
size ());
106 inline BLOB::BLOB (
const initializer_list<pair<const byte*, const byte*>>& startEndPairs)
110 inline BLOB::BLOB (
const initializer_list<BLOB>& list2Concatenate)
125 return FromHex (span<const char>{b, ::strlen (b)});
129 return FromHex (span<const char>{s, e});
133 return FromHex (span<const char>{s});
138 return FromBase64 (span<const char>{b, ::strlen (b)});
144 template <Common::trivially_copyable T>
147 return BLOB{span{
reinterpret_cast<const byte*
> (s),
reinterpret_cast<const byte*
> (e)}};
149 template <Common::trivially_copyable T>
152 return BLOB{span{
reinterpret_cast<const byte*
> (s), sz}};
154 template <Common::trivially_copyable T>
156 requires (same_as<typename char_traits<T>::char_type, T>)
159 return FromRaw (s, s + char_traits<T>::length (s));
161 template <Common::trivially_copyable T>
163 requires (same_as<typename char_traits<T>::char_type, T>)
165 return FromRaw (s.c_str (), s.c_str () + s.length ());
167 template <Common::trivially_copyable T>
172 template <
typename BYTEISH,
size_t EXTENT>
173 inline BLOB BLOB::Attach (span<BYTEISH, EXTENT> s)
174 requires (convertible_to<BYTEISH, const byte> or convertible_to<BYTEISH, const uint8_t>)
176 const byte* b =
reinterpret_cast<const byte*
> (s.data ());
177 return BLOB{MakeSharedPtr<AdoptRep_> (b, b + s.size ())};
179 template <
typename BYTEISH,
size_t EXTENT>
180 inline BLOB BLOB::Attach (BYTEISH (&data)[EXTENT])
181 requires (convertible_to<BYTEISH, const byte> or convertible_to<BYTEISH, const uint8_t>)
183 return Attach (span<const BYTEISH>{data, EXTENT});
185 inline BLOB BLOB::AttachAndDelete (
const byte* b,
size_t arrayLen)
187 return BLOB{MakeSharedPtr<AdoptAndDeleteRep_> (b, b + arrayLen)};
190 Streams::InputStream::Ptr<byte>
BLOB::As ()
const;
191 template <
typename T>
193#if !qCompilerAndStdLib_template_requires_doesnt_work_with_specialization_Buggy
196 Common::IAnyOf<T,span<const byte>,span<const uint8_t>, pair<const byte*, const byte*>, pair<const uint8_t*, const uint8_t*>, vector<byte> ,vector<uint8_t>, Streams::InputStream::Ptr<byte>,
string>
197 or is_trivially_copyable_v<T>
203 if constexpr (same_as<T, span<const byte>>) {
204 return fRep_->GetBounds ();
206 else if constexpr (same_as<T, span<const uint8_t>>) {
207 return T{
reinterpret_cast<const uint8_t*
> (this->data ()), this->size ()};
209 else if constexpr (same_as<T, pair<const byte*, const byte*>>) {
210 return make_pair (this->data (), this->data () + this->size ());
212 else if constexpr (same_as<T, pair<const uint8_t*, const uint8_t*>>) {
213 auto s = this->As<span<const uint8_t>> ();
214 return make_pair (s.data (), s.data () + s.size ());
216 else if constexpr (same_as<T, vector<byte>>) {
217 return T{this->begin (), this->end ()};
219 else if constexpr (same_as<T, vector<uint8_t>>) {
220 auto s = this->As<span<const uint8_t>> ();
221 return T{s.begin (), s.end ()};
223 else if constexpr (same_as<T, Streams::InputStream::Ptr<byte>>) {
226 else if constexpr (same_as<T, string>) {
227 span<const byte> tmp = fRep_->GetBounds ();
228 return string{
reinterpret_cast<const char*
> (tmp.data ()),
reinterpret_cast<const char*
> (tmp.data () + tmp.size ())};
230 else if constexpr (is_trivially_copyable_v<T>) {
231 Require (size () >=
sizeof (T));
232 return *(
reinterpret_cast<const T*
> (begin ()));
237 return As<Streams::InputStream::Ptr<byte>> ();
242 span<const byte> tmp = fRep_->GetBounds ();
243 Assert (i < tmp.size ());
249 span<const byte> tmp = fRep_->GetBounds ();
250 Assert (tmp.begin () <= tmp.end ());
256 return fRep_->GetBounds ().data ();
261 auto b = fRep_->GetBounds ();
262 return b.data () + b.size ();
267 span<const byte> tmp = fRep_->GetBounds ();
268 Assert (tmp.begin () <= tmp.end ());
286 inline strong_ordering BLOB::operator<=> (
const BLOB& rhs)
const
288 return TWC_ (*
this, rhs);
290 inline bool BLOB::operator== (
const BLOB& rhs)
const
294 if (fRep_ == rhs.fRep_) {
297 span<const byte> l = fRep_->GetBounds ();
298 span<const byte> r = rhs.fRep_->GetBounds ();
299 size_t lSize = l.size ();
300 size_t rSize = r.size ();
301 if (lSize != rSize) {
304 return CompareBytes (l, r) == 0;
309 return BLOB ({*
this, rhs});
311 inline strong_ordering BLOB::TWC_ (
const BLOB& lhs,
const BLOB& rhs)
315 span<const byte> l = lhs.fRep_->GetBounds ();
316 span<const byte> r = rhs.fRep_->GetBounds ();
317 size_t lSize = l.size ();
318 size_t rSize = r.size ();
319 size_t nCommonBytes = min (lSize, rSize);
320 if (nCommonBytes != 0) {
322 if (strong_ordering tmp = CompareBytes (l.subspan (0, nCommonBytes), r.subspan (0, nCommonBytes)); tmp != strong_ordering::equal) {
327 if (lSize == rSize) {
328 return strong_ordering::equal;
330 return (lSize < rSize) ? strong_ordering::less : strong_ordering::greater;
333 inline namespace Literals {
334 inline BLOB operator"" _blob (
const char* str,
size_t len)
336 return BLOB::Attach (span<const byte>{
reinterpret_cast<const byte*
> (str), len});
#define RequireNotNull(p)
#define AssertNotReached()
auto MakeSharedPtr(ARGS_TYPE &&... args) -> shared_ptr< T >
same as make_shared, but if type T has block allocation, then use block allocation for the 'shared pa...
shared_lock< const AssertExternallySynchronizedMutex > ReadContext
Instantiate AssertExternallySynchronizedMutex::ReadContext to designate an area of code where protect...
nonvirtual size_t length() const
nonvirtual const byte * end() const
nonvirtual STRING_TYPE AsBase64() const
static BLOB FromHex(const char *b)
Convert string of hex bytes to BLOB.
nonvirtual byte operator[](const size_t i) const
nonvirtual BLOB operator+(const BLOB &rhs) const
nonvirtual bool empty() const
nonvirtual const byte * begin() const
nonvirtual size_t GetSize() const
static BLOB FromBase64(const char *b)
Convert string of base64 bytes to BLOB.
static BLOB FromRaw(const T *s, const T *e)
Convert pointed to/referenced data to BLOB (treating the argument as raw bytes).
nonvirtual size_t size() const
nonvirtual const byte * data() const
Ptr Attach(PlatformNativeHandle sd)