Memory and Byte Data

Byte Reader, Writer, Types and Utilities

Introduction

Byte Values, Arrays, and Views

Byte represents one explicit byte and provides conversions, masking, bitwise operators, shifts, and rotations. ByteArray provides fixed-size mutable byte storage with safe indexed and bulk operations, whole-array and per-byte bit operations, and endian-aware integer access. ByteBuffer provides equivalent operations for compact, uniquely owned dynamic byte storage without copy-on-write. ByteIndex, ByteLength, and ByteRange describe all owning-container access. Range spans and mutations clamp to the owner; invalid ranges produce an empty view or a no-op, and infinite lengths extend to the end. The xorAt*() methods modify one indexed byte without a separate read, while xorWith*() combines byte ranges. ByteArray::secureErase() clears the complete fixed storage. ByteBuffer::secureErase() clears the complete allocated capacity while preserving its visible length and capacity.

ByteSpan and ConstByteSpan are dynamic-extent writable and read-only views. FixedByteSpan and FixedConstByteSpan retain an extent in the type. Spans are views rather than owning values and therefore remain bound to their source object. The toByteSpan() and toConstByteSpan() compatibility functions reinterpret compatible std::byte, uint8_t, and char spans without copying; the returned view has the same lifetime and invalidation rules as the source span. The free getInteger* and setInteger* helpers provide the same checked endian-aware access for any byte span.

Byte Block

ByteBlock is the owning read-only type for arbitrary byte sequences. It shares copy-on-write storage, and its slices retain the same storage while exposing a smaller byte range. Ordinary copies and slice() share allocations; copy() creates independent storage for the visible bytes, and kept() copies a selected clamped range directly without retaining the source allocation. It is also the scalar byte-storage type used by configuration values, hashes, signatures, and other Core APIs, so these subsystems can exchange immutable byte data without adapter wrappers.

Basic Usage

Create a block from raw byte values and read it with ByteIndex. Use ByteBlockEditor when the bytes must be changed.

const auto data = el::ByteBlock({0x01, 0x02, 0x03, 0x04});
auto header = data.slice(el::ByteIndex{0}, el::ByteLength{2});

auto editor = el::ByteBlockEditor{data};
editor.set(el::ByteIndex{1}, el::Byte{0xff});
const auto modified = el::ByteBlock{editor};
Modification

Ranges are clamped to the visible data. Invalid ranges are treated as empty for removals and replacements; keep() with an invalid range clears the editor.

Byte Block Editor

ByteBlockEditor provides mutation and capacity management. Converting an editor to ByteBlock shares the complete data without copying; later editor mutations detach and leave the read-only value unchanged. Constructing an editor from a ByteBlock copies only the visible bytes, including when the source is a slice. The editor’s copy() and kept() methods likewise create independent mutable storage and preserve the sensitive allocation mark. The editor provides the same checked little- and big-endian integer helpers as ByteArray. Failed tolerant writes validate before detaching, so both bytes and sharing remain unchanged. appendInteger() encodes and appends one integer. overwrite() is a non-resizing operation that copies the largest possible prefix of the source into a clamped target range. Invalid, outside, or empty targets and empty sources are no-ops. It validates no-op cases before detaching and differs intentionally from the clamping, resizing replace() operation. The whole-sequence xorWith() methods return false without changing the destination when lengths differ. Use xorWithOrThrow() when equal lengths are an invariant and a mismatch must raise ParameterError. Range overloads remain clamped operations that combine as many source bytes as fit.

Sensitive Storage

ByteBlock and ByteBlockEditor can mark their shared allocation with markAsSensitive(). The mark is visible to every alias and cannot be cleared. Owning-block mutations and deep copies propagate it, while raw spans carry no sensitivity metadata. Marked allocations are erased in full when reallocated or finally destroyed; ordinary formatting and conversions remain available and produce unprotected copies.

ByteBuffer instead has a reversible object mode controlled by setSensitive(). Copies duplicate the mode and storage independently, while moves transfer both. In sensitive mode, truncated and replaced bytes and old allocations are erased before release. Disabling the mode erases the complete allocation, discards visible bytes, and retains capacity. clear(), reset(), and shrinkToFit() preserve the selected mode. See About Sensitive Strings and Byte Blocks for the complete contract.

Compatibility Boundaries

ByteBuffer replaces raw dynamic byte vectors at owning Erbsland Core API boundaries. Short byte sequences can be initialized directly with ByteBlock({0x01, 0x02}). The fromSpan() and raw uint8_t /char fromVector() factories make compatibility copies explicit, while toByteBuffer(), toUInt8Vector(), and toCharVector() explicitly copy ordinary block data out. Searches and editor modifiers accept ConstByteSpan and FixedConstByteSpan for call-scoped borrowing without creating an intermediate block. If such an input overlaps the destination storage, the editor preserves only the necessary source bytes before detaching or reallocating. Raw vector parameters remain confined to the explicit compatibility factories.

Every contiguous owning byte type exposes borrowed read-only full and ranged spans. An array span remains bound through in-place mutation. A buffer span remains bound through non-resizing writes, but allocation-changing edits, reset, move, or destruction invalidate it. Treat any editor mutation as invalidating its spans because copy-on-write may detach storage; block erasure, reset, move, or destruction likewise invalidates a block span. A block slice keeps its own owning reference when selected bytes must outlive the call. Owning types expose no writable span, raw pointer, size, or iterator API. Low-level integrations keep ByteSpan as an explicit native boundary. Internal native adapters use mem::impl::UnsafeByteArrayAccess or mem::impl::UnsafeByteBufferAccess when owning scratch storage must be passed to a writable byte-span boundary.

Internally, every contiguous byte owner exposes its storage through a private mem::impl::ByteDataView. Stateful read and comparison tools bind to this raw view, which lets arrays, buffers, blocks, editors, and readers share algorithms without temporary owners or repeated shared-storage traversal. Writable owners expose a private writable span for fixed-size mutation tools. The owner still validates the operation and handles copy-on-write, allocation, sensitivity, and aliased sources before requesting writable storage. mem::impl::UnsafeByteBlockAccess marks native read-only integration boundaries and exposes the same data-view type; it does not provide editor or writable access. mem::impl::UnsafeByteBlockBuffer supports growing uncommitted storage while preserving a written prefix and then transfers the completed allocation into a byte block without a final copy. Its storage is uninitialized and can be created in sensitive mode; a low-level producer must write every byte included in take().

Byte Reader

ByteReader reads bytes and integer values sequentially from a ByteBlock or ByteBlockEditor. It can return exact byte ranges and decode structured text frames. ByteIntegerFormat fixes the signedness and wire width of a formatted integer independently from its C++ destination type. Alongside fixed widths and the compact count formats, it supports canonical most-significant-group-first unsigned base-128 integers for ASN.1 identifier and object-identifier components. ByteTextOptions defines UTF encoding, count prefix, optional validated end mark, and dynamic or padded-field framing. Structured reads parse with a local cursor over the raw data and commit the reader position only after the complete value has been validated and decoded. This includes readers positioned in the middle of a block. Strict reads leave the position unchanged on failure; optional reads report an incomplete or invalid frame without advancing.

Bit Reader

BitReader reads individual bits from a borrowed ConstByteSpan without copying or owning its input. It processes the most-significant bit first in each byte and exposes the total bit count, current position, remaining count, bounded position changes, and end checks. readBool() returns the next bit as a boolean, while readInteger<T>() returns the same bit as zero or one of a selected native integer type. Reads at the end return false or zero without advancing.

Byte Writer

ByteWriter writes bytes and integer values sequentially into an internal editor and returns the completed data as a read-only ByteBlock. Writing overwrites at the current position or appends when the position is at the end. Text and formatted-integer writes prepare the complete encoded value before modifying the writer, so encoding or validation failures leave the written data and position unchanged. Text writes use ByteTextOptions. The default is dynamic UTF-8 with an unsigned 32-bit unit count, while ByteTextOptions::compact() uses an unsigned variable-length count. An explicit end mark is always validated by the reader, including in padded fields.

Ring Buffers

RingBuffer stores bytes in fixed or bounded-growing contiguous storage. Safe methods copy data into and out of the ring. Atomic reserve and exact-write operations return Result; failure means the hard limit was exceeded and the ring was not modified. Low-level platform adapters use an internal exclusive access lease to pass the ring’s one or two contiguous sections directly to native APIs. Sensitive mode is enabled with setSensitive(true). In this mode the ring securely erases consumed bytes and old allocations after capacity changes, and erases its storage on destruction. secureErase() wipes the complete capacity and empties the ring while preserving the mode. Disabling sensitive mode also wipes the complete capacity and discards unread bytes. Owned reads from a sensitive ring return a marked ByteBlock.

ByteRingBuffer adds atomic endian-aware integer reads and writes.

For structured stream output, assemble a complete record with ByteWriter and submit its byte block with one atomic byte-stream write. This avoids checking each individual field write.

Secure Erasure

secureErase() overwrites a caller-owned writable byte span using the platform’s optimizer-resistant erasure primitive. ByteArray, ByteBuffer, ByteBlock, and ByteBlockEditor provide a member secureErase() for owned storage.

Block erasure preserves the logical length. A uniquely owned block erases its complete capacity. Erasing a shared block installs independent zero-filled storage, so aliases and slices remain unchanged. Editors also preserve their observable capacity. If allocating replacement storage fails, the invoking shared block is unchanged.

Byte Compression

The byte-compression API provides raw LZ4 blocks and a framed representation that records the algorithm and original length. Use raw blocks when another format already carries this metadata, and use the envelope for standalone stored or transmitted values.

Raw Compression

ByteCompressor always returns a valid raw block, even when the block is larger than its input. Raw ByteDecompressor calls require the exact original size and reject output-length mismatches.

Compression Envelopes

compressWithEnvelope() frames the raw payload with the ELBC header, algorithm identifier, original length, and payload length. ByteDecompressor::decompressWithEnvelope() validates the complete frame and automatically selects the encoded algorithm. The optional maximum-output limit is checked before allocating output storage.

Buffered Operation

Both codec classes accept input through update() and emit one result during finalization. The first successful finalizer selects raw or envelope output until reset() is called, and repeated calls to the same finalizer return the cached result. One-shot methods do not alter this buffered state.

Cow Storage

Introduction

Cow Storage

CowStorage is a small copy-on-write helper for ordinary C++ data types. It stores the data in a std::shared_ptr and always keeps a valid data object, so user code can work with references instead of raw pointers.

Copying the storage shares the data object. Mutable access through data() automatically detaches when the object is shared. Calling detach() before a group of write operations is optional, but can make the copy-on-write point explicit. Operations that create, replace, or detach data may throw allocation errors or exceptions from the stored type.

Separate storage objects may be copied, destroyed, and detached from different threads. Concurrent access to the same storage object, or concurrent mutation of the same detached data object, still requires external synchronization.

Example
using Storage = erbsland::mem::CowStorage<std::set<erbsland::text::Char>>;

auto storage = Storage::from(std::set<erbsland::text::Char>{ch});
auto copy = storage;

storage.detach();
storage.data().insert(otherChar);

Cow Manual Storage

CowManualStorage is a copy-on-write helper for code that wants explicit writable access. It stores the data in a std::shared_ptr and always keeps a valid data object.

Reading uses data(). Writing uses detachedData(), which detaches first when the data object is shared. This makes mutable call sites easy to find while avoiding nullable or raw pointer handling in user code. Operations that create, replace, or detach data may throw allocation errors or exceptions from the stored type.

Use sharedDefault() when many storage instances can start with the same default-constructed data object. The method keeps one shared default object for each data type and returns another owner for every call. The retained canonical owner contributes to useCount() and ensures that writable access always detaches from the default object. Ordinary default construction remains unique and constructs a separate data object for each storage instance.

Shared Array Data

SharedArrayData stores a small shared-data header and a trailing array in one allocation. The actual elements are placed in aligned storage immediately after the header, which keeps compact string-like storage types cache-friendly while still using the intrusive reference-counting model.

Use this type when you build library internals that need copy-on-write array storage. The allocation must be created, cloned, and destroyed through SharedArrayData itself, because the header and trailing elements are one memory block.

SharedArrayDataCleanupMethod selects ordinary cleanup or secure erasure for raw, trivially copyable arrays. Secure allocations are zero-initialized across their complete element capacity and securely erased through an optimizer-resistant platform backend before deallocation. The final erase covers the one-block allocation in full: reference-count metadata, size and capacity fields, alignment padding, used elements, and unused capacity. Every copy-on-write allocation is erased independently when its final owner releases it. If construction or cloning fails, already constructed elements are destroyed and the failed allocation follows the same cleanup path before the exception is rethrown.

Headers that only store or pass a SharedDataPointer to shared array data can include SharedArrayData_fwd.hpp. Constructors, destructors, copies, detach operations, and direct data access must be implemented in a source file that includes SharedArrayData.hpp. This keeps the full allocation template out of dependent headers without adding a PImpl allocation or changing the storage layout.

Shared Data

SharedData is the base class for custom data blocks that participate in Erbsland Core’s intrusive shared-data model. It places the ReferenceCounter at the start of derived data and marks the type as compatible with the shared-data traits.

Use this class only when you extend the library with a new shared storage type. For ordinary application data, prefer the public value types that already manage their storage for you.

Shared Data Pointer

SharedDataPointer is an intrusive copy-on-write pointer for supported shared data objects. It owns a pointer to data with an embedded ReferenceCounter, increments and decrements that counter as pointers are copied or destroyed, and destroys the allocation when the last reference is released.

Copying the pointer shares the same data. Mutable access automatically detaches shared data by cloning it, unless tManualDetach is enabled. Manual detach mode is useful for code that wants to control exactly when copy-on-write materialization happens.

Separate SharedDataPointer instances may be copied, destroyed, reset, and detached from different threads. Concurrent access to the same pointer object, or concurrent mutation of the same already-detached data object, still requires external synchronization.

Unsafe Pointers

Interface

class BitReader

A sequential reader for individual bits in a read-only byte span.

Bits are read most-significant bit first within each byte. The reader borrows its input; the source bytes must remain valid for the reader’s lifetime.

See: Memory and Byte Data

Public Functions

BitReader() = default

Create an empty reader.

explicit BitReader(ConstByteSpan data, std::size_t bitPosition = 0U) noexcept

Create a reader over data at bitPosition.

Positions beyond the input are clamped to bitCount().

inline std::size_t bitCount() const noexcept

Get the total number of readable bits.

inline std::size_t bitPosition() const noexcept

Get the current bit position.

void setBitPosition(std::size_t bitPosition) noexcept

Set the current bit position, clamped to bitCount().

inline std::size_t remainingBitCount() const noexcept

Get the number of bits remaining at the current position.

inline bool isAtEnd() const noexcept

Test if the reader is at the end of the input.

inline bool canRead(std::size_t count) const noexcept

Test if count bits can be read at the current position.

void advance(std::size_t count) noexcept

Advance by count bits, clamped to bitCount().

bool readBool() noexcept

Read the next bit as a boolean, or return false at end.

template<std::integral T>
inline T readInteger() noexcept

Read the next bit as zero or one of the requested integer type, or return zero at end.

Template Parameters:

T – Any native integral type except bool.

class Byte

A small wrapper around a single byte.

Provides a convenient interface for working with individual bytes and bits. Shift operations return zero when the shift is eight or greater. Rotation amounts are reduced modulo eight; negative amounts rotate in the opposite direction.

Public Types

using Value = std::byte

The raw byte value type.

Public Functions

inline constexpr Byte(const Value byte)

Create a byte from a raw byte value.

inline constexpr Byte(const uint8_t byte)

Create a byte from a uint8_t value.

inline constexpr Byte &operator|=(const Byte &other) noexcept

Apply a bitwise OR to this byte.

inline constexpr Byte &operator&=(const Byte &other) noexcept

Apply a bitwise AND to this byte.

inline constexpr Byte &operator^=(const Byte &other) noexcept

Apply a bitwise XOR to this byte.

inline constexpr Byte operator~() const noexcept

Invert every bit.

inline constexpr Byte operator<<(const std::size_t shift) const noexcept

Shift bits left and fill with zero.

inline constexpr Byte operator>>(const std::size_t shift) const noexcept

Shift bits right and fill with zero.

inline constexpr Byte &operator<<=(const std::size_t shift) noexcept

Shift this byte left and fill with zero.

inline constexpr Byte &operator>>=(const std::size_t shift) noexcept

Shift this byte right and fill with zero.

inline constexpr Byte shiftedLeft(const std::size_t shift) const noexcept

Return this byte shifted left.

Parameters:

shift – The number of bit positions.

Returns:

The shifted byte, or zero if shift is eight or greater.

inline constexpr void shiftLeft(const std::size_t shift) noexcept

Shift this byte left in place.

Parameters:

shift – The number of bit positions.

inline constexpr Byte shiftedRight(const std::size_t shift) const noexcept

Return this byte shifted right.

Parameters:

shift – The number of bit positions.

Returns:

The shifted byte, or zero if shift is eight or greater.

inline constexpr void shiftRight(const std::size_t shift) noexcept

Shift this byte right in place.

Parameters:

shift – The number of bit positions.

inline constexpr Byte rotatedLeft(const int amount) const noexcept

Return this byte rotated left.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated byte.

inline constexpr void rotateLeft(const int amount) noexcept

Rotate this byte left in place.

Parameters:

amount – The signed rotation amount.

inline constexpr Byte rotatedRight(const int amount) const noexcept

Return this byte rotated right.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated byte.

inline constexpr void rotateRight(const int amount) noexcept

Rotate this byte right in place.

Parameters:

amount – The signed rotation amount.

inline constexpr Byte masked(const Byte mask) const noexcept

Apply a bit mask to this byte.

Parameters:

mask – The bits to retain.

Returns:

The masked byte.

inline constexpr bool matches(const Byte mask, const Byte expected) const noexcept

Test if the masked bits equal the expected value.

Parameters:
  • mask – The bits to compare.

  • expected – The expected masked value.

Returns:

true if the masked bits match.

inline constexpr std::byte toStdByte() const noexcept

Get the byte as std::byte value.

inline constexpr char toChar() const noexcept

Get the byte as char value.

inline constexpr uint8_t toUInt8() const noexcept

Get the byte as an unsigned integer.

inline constexpr uint16_t toUInt16() const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline constexpr uint32_t toUInt32() const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline constexpr uint64_t toUInt64() const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline constexpr std::byte toRawValue() const noexcept

Get the underlying raw value.

Please use one of the conversion functions instead, as this leads to future proof and more readable code.

Public Static Functions

static inline constexpr Byte fromChar(const char value) noexcept

Create a byte from a char.

Parameters:

value – The character whose bit pattern is copied.

Returns:

The byte value.

static inline constexpr Byte fromUInt8(const uint8_t value) noexcept

Create a byte from the lowest bits of an integer.

Parameters:

value – The unsigned integer value.

Returns:

The byte value.

static inline constexpr Byte fromCroppedUInt16(const uint16_t value) noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

static inline constexpr Byte fromCroppedUInt32(const uint32_t value) noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

static inline constexpr Byte fromCroppedUInt64(const uint64_t value) noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Friends

inline friend constexpr friend Byte operator| (const Byte &lhs, const Byte &rhs) noexcept

Compute the bitwise OR of two bytes.

inline friend constexpr friend Byte operator& (const Byte &lhs, const Byte &rhs) noexcept

Compute the bitwise AND of two bytes.

inline friend constexpr friend Byte operator^ (const Byte &lhs, const Byte &rhs) noexcept

Compute the bitwise XOR of two bytes.

template<std::size_t N>
class ByteArray

A fixed-size array of explicit byte values.

Default construction initializes every byte to zero. Whole-array shifts and rotations treat index zero as the most-significant byte.

Template Parameters:

N – The number of bytes.

Public Types

using Value = Byte

The stored value type.

Public Functions

template<typename ...tBytes>
inline constexpr ByteArray(tBytes&&... bytes) noexcept

Create an array from exactly N byte values.

Parameters:

bytes – The byte values.

inline bool isEqualConstTime(const ByteArray &other) const noexcept

Test equality without content-dependent short-circuiting.

Both arrays always have the same length and every byte is inspected.

Parameters:

other – The byte array to compare.

Returns:

true if both arrays contain the same bytes.

inline bool isEqualConstTime(ConstByteSpan other) const noexcept

Test equality with a borrowed sequence without content-dependent short-circuiting.

Equal-length inputs always inspect every byte; a length mismatch returns immediately.

Parameters:

other – The borrowed byte sequence to compare.

Returns:

true if both sequences have the same length and contents.

inline constexpr ByteArray &operator|=(const ByteArray &other) noexcept

Apply an element-wise bitwise OR.

inline constexpr ByteArray &operator&=(const ByteArray &other) noexcept

Apply an element-wise bitwise AND.

inline constexpr ByteArray &operator^=(const ByteArray &other) noexcept

Apply an element-wise bitwise XOR.

inline constexpr ByteArray operator~() const noexcept

Invert every bit.

inline constexpr ByteArray operator<<(const std::size_t shift) const noexcept

Shift the complete bit string left.

inline constexpr ByteArray operator>>(const std::size_t shift) const noexcept

Shift the complete bit string right.

inline constexpr ByteArray &operator<<=(const std::size_t shift) noexcept

Shift the complete bit string left in place.

inline constexpr ByteArray &operator>>=(const std::size_t shift) noexcept

Shift the complete bit string right in place.

inline constexpr Byte get(const unit::ByteIndex index, const Byte defaultValue = {}) const noexcept

Get a byte or a default value if index is out of range.

Parameters:
  • index – The zero-based byte index.

  • defaultValue – The value returned for an invalid index.

Returns:

The stored byte or defaultValue.

inline Byte getOrThrow(const unit::ByteIndex index) const

Get a byte or throw if index is out of range.

Parameters:

index – The zero-based byte index.

Throws:

err::OutOfRangeError – If index is out of range.

Returns:

The stored byte.

template<typename Function>
inline util::LoopResult forEach(Function function) const

Invoke a callback for every byte and its optional index.

inline constexpr void set(const unit::ByteIndex index, const Byte value) noexcept

Set a byte, ignoring invalid indexes.

inline constexpr void setOrThrow(const unit::ByteIndex index, const Byte value)

Set a byte or throw if its index is invalid.

inline constexpr void xorAt(const unit::ByteIndex index, const Byte value) noexcept

XOR a byte value at an index, ignoring invalid indexes.

inline constexpr void xorAtOrThrow(const unit::ByteIndex index, const Byte value)

XOR a byte value at an index or throw if its index is invalid.

Throws:

err::OutOfRangeError – If index is invalid or outside this array.

inline constexpr void fill(const Byte value) noexcept

Fill the array with a byte value.

Parameters:

value – The byte value.

inline void fill(const unit::ByteRange targetRange, const Byte value) noexcept

Fill a clamped byte range.

inline void overwrite(const ConstByteSpan source) noexcept

Overwrite from the beginning with as many source bytes as fit.

inline void overwrite(const unit::ByteIndex index, const ConstByteSpan source) noexcept

Overwrite from an index with as many source bytes as fit.

inline void overwrite(const unit::ByteRange targetRange, const ConstByteSpan source) noexcept

Overwrite a clamped target range with as many source bytes as fit.

inline bool xorWith(const ConstByteSpan source) noexcept

XOR every byte with an equally sized source.

inline void xorWithOrThrow(const ConstByteSpan source)

XOR every byte with an equally sized source or throw if the lengths differ.

Throws:

err::ParameterError – If the lengths differ.

inline void xorWith(const unit::ByteRange targetRange, const ConstByteSpan source) noexcept

XOR a clamped range with as many source bytes as fit.

inline constexpr ByteArray shiftedLeft(const std::size_t shift) const noexcept

Return the complete bit string shifted left.

Parameters:

shift – The number of bit positions.

Returns:

The shifted array.

inline constexpr void shiftLeft(const std::size_t shift) noexcept

Shift the complete bit string left in place.

Parameters:

shift – The number of bit positions.

inline constexpr ByteArray shiftedRight(const std::size_t shift) const noexcept

Return the complete bit string shifted right.

Parameters:

shift – The number of bit positions.

Returns:

The shifted array.

inline constexpr void shiftRight(const std::size_t shift) noexcept

Shift the complete bit string right in place.

Parameters:

shift – The number of bit positions.

inline constexpr ByteArray rotatedLeft(const int amount) const noexcept

Return the complete bit string rotated left.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated array.

inline constexpr void rotateLeft(const int amount) noexcept

Rotate the complete bit string left in place.

Parameters:

amount – The signed rotation amount.

inline constexpr ByteArray rotatedRight(const int amount) const noexcept

Return the complete bit string rotated right.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated array.

inline constexpr void rotateRight(const int amount) noexcept

Rotate the complete bit string right in place.

Parameters:

amount – The signed rotation amount.

inline constexpr ByteArray eachByteShiftedLeft(const std::size_t shift) const noexcept

Return an array with every byte shifted left independently.

Parameters:

shift – The number of bit positions.

Returns:

The shifted bytes.

inline constexpr void shiftEachByteLeft(const std::size_t shift) noexcept

Shift every byte left independently in place.

Parameters:

shift – The number of bit positions.

inline constexpr ByteArray eachByteShiftedRight(const std::size_t shift) const noexcept

Return an array with every byte shifted right independently.

Parameters:

shift – The number of bit positions.

Returns:

The shifted bytes.

inline constexpr void shiftEachByteRight(const std::size_t shift) noexcept

Shift every byte right independently in place.

Parameters:

shift – The number of bit positions.

inline constexpr ByteArray eachByteRotatedLeft(const int amount) const noexcept

Return an array with every byte rotated left independently.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated bytes.

inline constexpr void rotateEachByteLeft(const int amount) noexcept

Rotate every byte left independently in place.

Parameters:

amount – The signed rotation amount.

inline constexpr ByteArray eachByteRotatedRight(const int amount) const noexcept

Return an array with every byte rotated right independently.

Parameters:

amount – The signed rotation amount.

Returns:

The rotated bytes.

inline constexpr void rotateEachByteRight(const int amount) noexcept

Rotate every byte right independently in place.

Parameters:

amount – The signed rotation amount.

template<typename T>
inline constexpr auto getInteger(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little, const T defaultOnError = T{}) const noexcept -> T

Get an integer or return a default value if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

  • defaultOnError – The value returned for an invalid range.

Returns:

The decoded value or defaultOnError.

template<typename T>
inline auto getIntegerOrThrow(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const -> T

Get an integer or throw if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

Returns:

The decoded value.

template<typename T>
inline constexpr auto getIntegerInto(T &value, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const noexcept -> bool

Decode an integer into an existing value.

The output remains unchanged if the byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • value – The destination value.

  • offset – The first byte index.

  • endianness – The byte order.

Returns:

true on success.

template<typename T>
inline constexpr auto setInteger(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little) noexcept -> bool

Store an integer in this array.

The array remains unchanged if the byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Returns:

true on success.

template<typename T>
inline constexpr void setIntegerOrThrow(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little)

Store an integer in this array or throw if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

inline void secureErase() noexcept

Securely erase all bytes in this array.

inline constexpr FixedConstByteSpan<N> span() const noexcept

Access the bytes as a read-only fixed-extent span.

inline constexpr ConstByteSpan span(const unit::ByteRange range) const noexcept

Access a clamped range as a read-only byte span.

Parameters:

range – The byte range to access.

Returns:

The clamped span, or an empty span for an invalid range.

inline constexpr ConstByteSpan span(const unit::ByteIndex begin, const unit::ByteLength lengthValue) const noexcept

Access a clamped range as a read-only byte span.

Parameters:
  • begin – The first byte index.

  • lengthValue – The requested byte length.

Returns:

The clamped span, or an empty span for an invalid index.

inline ByteBuffer toByteBuffer() const

Copy the bytes into a dynamic byte buffer.

Public Static Functions

static inline constexpr unit::ByteLength length() noexcept

Get the number of bytes as a byte length.

static inline constexpr unit::ByteIndex endIndex() noexcept

Get the index after the last byte.

static inline constexpr bool isEmpty() noexcept

Test if this array contains no bytes.

static inline std::optional<ByteArray> fromSpan(const ConstByteSpan bytes) noexcept

Create an array by copying a borrowed span with exactly the required size.

A length mismatch is rejected without copying any bytes.

Parameters:

bytes – The bytes to copy.

Returns:

The copied array, or no value if bytes does not contain exactly N bytes.

static inline ByteArray fromSpanOrThrow(const ConstByteSpan bytes)

Create an array by copying a borrowed span with exactly the required size.

Parameters:

bytes – The bytes to copy.

Throws:

err::ParameterError – If bytes does not contain exactly N bytes.

Returns:

The copied array.

Friends

inline friend constexpr friend ByteArray operator| (const ByteArray &lhs, const ByteArray &rhs) noexcept

Compute the element-wise bitwise OR.

inline friend constexpr friend ByteArray operator& (const ByteArray &lhs, const ByteArray &rhs) noexcept

Compute the element-wise bitwise AND.

inline friend constexpr friend ByteArray operator^ (const ByteArray &lhs, const ByteArray &rhs) noexcept

Compute the element-wise bitwise XOR.

class ByteBlock

An owning read-only byte block with shared copy-on-write storage.

Use this type to store, read and pass byte sequences. A ByteBlockEditor is implicitly convertible to a ByteBlock without copying data. Copying, moving and slicing are fast and copy-free operations.

Public Functions

explicit ByteBlock(unit::ByteLength length, Byte value = Byte{})

Create a byte block filled with the given byte value.

Parameters:
  • length – The number of bytes.

  • value – The byte value used to fill the block.

explicit ByteBlock(std::initializer_list<Byte> bytes)

Create a byte block by copying explicit byte values.

template<std::size_t N>
inline explicit ByteBlock(const ByteArray<N> &bytes)

Create a byte block by copying a fixed byte array.

Template Parameters:

N – The number of bytes.

Parameters:

bytes – The fixed byte array.

ByteBlock(const ByteBlockEditor &editor) noexcept

Create a read-only byte block sharing the editor’s data.

Parameters:

editor – The byte block editor whose complete data is shared.

ByteBlock copy() const

Create an independent copy containing only the visible bytes.

bool isSensitive() const noexcept

Test if this block is marked as sensitive.

void markAsSensitive() noexcept

Permanently mark this block as sensitive.

Marking empty blocks as sensitive does nothing.

ByteBlock slice(unit::ByteRange range) const noexcept

Return a shared read-only slice of this block.

ByteBlock slice(unit::ByteIndex begin, unit::ByteIndex end) const noexcept

Return a slice from the given start to the given end.

ByteBlock slice(unit::ByteIndex begin, unit::ByteLength length) const noexcept

Return a slice from the given start with the given length.

ByteBlock kept(unit::ByteRange range) const

Create an independent block containing a clamped range of visible bytes.

void secureErase()

Securely erase this block while preserving its length.

std::strong_ordering operator<=>(const ByteBlockEditor &other) const noexcept

Compare this block with an editable byte block.

std::strong_ordering operator<=>(const ByteBlock &other) const noexcept

Compare this block with another read-only byte block.

bool isEqualConstTime(const ByteBlock &other) const noexcept

Test equality without content-dependent short-circuiting.

Equal-length inputs always inspect every byte; a length mismatch returns immediately.

Parameters:

other – The byte block to compare.

Returns:

true if both blocks have the same length and contents.

bool isEqualConstTime(ConstByteSpan other) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters:

other – The borrowed byte sequence to compare.

Returns:

true if both sequences have the same length and contents.

bool isEmpty() const noexcept

Test if this block contains no bytes.

bool startsWith(const ByteBlock &other) const noexcept

Test if this block starts with another byte sequence.

bool startsWith(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool startsWith(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool startsWith(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool endsWith(const ByteBlock &other) const noexcept

Test if this block ends with another byte sequence.

bool endsWith(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool endsWith(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool endsWith(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool contains(const ByteBlock &other) const noexcept

Test if this block contains another byte sequence.

bool contains(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool contains(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool contains(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteLength length() const noexcept

Get the length of this block.

inline unit::ByteIndex endIndex() const noexcept

Get the index after the last byte.

Byte get(unit::ByteIndex index, Byte defaultValue = Byte{}) const noexcept

Get a byte or return a default value when the index is out of range.

Byte getOrThrow(unit::ByteIndex index) const

Get a byte or throw when the index is out of range.

Throws:

err::OutOfRangeError – If the index is out of range.

inline ConstByteSpan span() const noexcept

Access all visible bytes through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteRange range) const noexcept

Access a clamped visible range through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteIndex index, unit::ByteLength lengthValue) const noexcept

Access a clamped visible range through a read-only borrowed span.

template<typename Function>
inline util::LoopResult forEach(Function function) const

Invoke a callback for every visible byte and its optional index.

template<typename T>
inline auto getInteger(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little, const T defaultOnError = T{}) const noexcept -> T

Get an integer or return a default value if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

  • defaultOnError – The value returned for an invalid range.

Returns:

The decoded value, or defaultOnError.

template<typename T>
inline auto getIntegerOrThrow(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const -> T

Get an integer or throw if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

Returns:

The decoded value.

template<typename T>
inline auto getIntegerInto(T &value, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const noexcept -> bool

Decode an integer into an existing value, leaving it unchanged for an invalid range.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • value – The destination value.

  • offset – The first byte index.

  • endianness – The byte order.

Returns:

true on success.

unit::ByteIndex find(const ByteBlock &bytes) const noexcept

Find the first occurrence of a byte sequence.

unit::ByteIndex find(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex find(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(const ByteBlock &bytes, unit::ByteIndex start) const noexcept

Find the first occurrence of a byte sequence at or after start.

unit::ByteIndex find(std::initializer_list<Byte> byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(ConstByteSpan byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex find(FixedConstByteSpan<N> byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex findLast(const ByteBlock &bytes) const noexcept

Find the last occurrence of a byte sequence.

unit::ByteIndex findLast(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex findLast(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex findLast(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

ByteBuffer toByteBuffer() const

Create a deep-copying byte buffer with the visible values.

std::vector<uint8_t> toUInt8Vector() const

Create a vector with raw unsigned byte values.

std::vector<char> toCharVector() const

Create a vector with raw char values.

Public Static Functions

static ByteBlock fromSpan(ConstByteSpan bytes)

Create a block by copying an Erbsland Core byte span.

static ByteBlock fromSpan(std::span<const std::byte> bytes)

Create a block by copying standard byte values.

static ByteBlock fromSpan(std::span<const uint8_t> bytes)

Create a block by copying unsigned byte values.

static ByteBlock fromSpan(std::span<const char> bytes)

Create a block by copying character byte values.

static ByteBlock fromVector(const std::vector<uint8_t> &bytes)

Create a block by copying unsigned byte values.

static ByteBlock fromVector(const std::vector<char> &bytes)

Create a block by copying character byte values.

class ByteBlockEditor

An owning mutable byte block editor with copy-on-write storage.

Use this type to create and modify byte sequences. Constructing an editor from a read-only ByteBlock always copies its visible bytes.

Public Functions

explicit ByteBlockEditor(unit::ByteLength length, Byte value = Byte{})

Create a byte block filled with the given byte value.

Parameters:
  • length – The number of bytes.

  • value – The byte value used to fill the block.

explicit ByteBlockEditor(std::initializer_list<Byte> bytes)

Create a byte block by copying explicit byte values.

template<std::size_t N>
inline explicit ByteBlockEditor(const ByteArray<N> &bytes)

Create a byte block from a fixed byte array.

Template Parameters:

N – The number of bytes.

Parameters:

bytes – The fixed byte array.

explicit ByteBlockEditor(const ByteBlock &block)

Create an editable copy of a read-only byte block.

Parameters:

block – The visible byte sequence to copy.

ByteBlockEditor copy() const

Create an independent copy containing the visible bytes.

bool isSensitive() const noexcept

Test if this allocation is marked as sensitive.

void markAsSensitive() noexcept

Permanently mark this allocation as sensitive.

Marking a storage-less empty editor is a no-op.

ByteBlock slice(unit::ByteRange range) const noexcept

Return a read-only slice of this editor.

ByteBlock slice(unit::ByteIndex begin, unit::ByteIndex end) const noexcept

Return a slice from the given start to the given end.

ByteBlock slice(unit::ByteIndex begin, unit::ByteLength length) const noexcept

Return a slice from the given start with the given length.

ByteBlockEditor &clear() noexcept

Remove all bytes while preserving capacity.

void reset() noexcept

Reset this byte block and release all storage.

void secureErase()

Securely erase this editor while preserving length and capacity.

ByteBlockEditor &resize(unit::ByteLength length)

Resize the block, zero-filling growth.

ByteBlockEditor &remove(unit::ByteRange range)

Remove a range of bytes.

ByteBlockEditor &keep(unit::ByteRange range)

Keep only a range of bytes.

ByteBlockEditor &replace(unit::ByteRange range, const ByteBlock &replacement)

Replace a range of bytes with another byte sequence.

ByteBlockEditor &replace(unit::ByteRange range, ConstByteSpan replacement)

Replace a range by copying a borrowed byte span.

template<std::size_t N>
inline ByteBlockEditor &replace(unit::ByteRange range, FixedConstByteSpan<N> replacement)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

ByteBlockEditor &insert(unit::ByteIndex index, const ByteBlock &bytes)

Insert a byte sequence at an index. Out-of-range indexes append at the end.

ByteBlockEditor &insert(unit::ByteIndex index, ConstByteSpan bytes)

Insert a borrowed byte span at an index.

template<std::size_t N>
inline ByteBlockEditor &insert(unit::ByteIndex index, FixedConstByteSpan<N> bytes)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

ByteBlockEditor &append(Byte value, unit::ByteLength length = unit::ByteLength::one())

Append one or more bytes.

Parameters:
  • value – The byte value to append.

  • length – The number of times to append the value.

ByteBlockEditor &append(const ByteBlock &bytes)

Append a byte sequence.

ByteBlockEditor &append(ConstByteSpan bytes)

Append a borrowed byte span.

template<std::size_t N>
inline ByteBlockEditor &append(FixedConstByteSpan<N> bytes)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<typename T>
inline ByteBlockEditor &appendInteger(const T value, const Endianness endianness = Endianness::Little)

Append an integer using the selected byte order.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • value – The integer value.

  • endianness – The byte order.

Returns:

This editor.

ByteBlockEditor &overwrite(unit::ByteRange range, const ByteBlock &bytes)

Overwrite a clamped destination range with as many block bytes as fit.

ByteBlockEditor &overwrite(ConstByteSpan bytes)

Overwrite from the beginning with as many source bytes as fit.

ByteBlockEditor &overwrite(unit::ByteIndex index, ConstByteSpan bytes)

Overwrite from an index with as many source bytes as fit.

ByteBlockEditor &overwrite(unit::ByteRange range, ConstByteSpan bytes)

Overwrite a clamped destination range with as many source bytes as fit.

ByteBlockEditor &fill(Byte value)

Fill all visible bytes.

ByteBlockEditor &fill(unit::ByteRange range, Byte value)

Fill a clamped byte range.

bool xorWith(const ByteBlock &bytes)

XOR every byte with an equally sized block.

Returns:

false without changing this editor if the lengths differ.

ByteBlockEditor &xorWithOrThrow(const ByteBlock &bytes)

XOR every byte with an equally sized block.

Throws:

err::ParameterError – If the lengths differ.

bool xorWith(ConstByteSpan bytes)

XOR every byte with an equally sized borrowed source.

ByteBlockEditor &xorWithOrThrow(ConstByteSpan bytes)

XOR every byte with an equally sized borrowed source.

Throws:

err::ParameterError – If the lengths differ.

ByteBlockEditor &xorWith(unit::ByteRange range, ConstByteSpan bytes)

XOR a clamped destination range with as many source bytes as fit.

ByteBlockEditor removed(unit::ByteRange range) const

Return a copy with a range removed.

ByteBlockEditor kept(unit::ByteRange range) const

Return an independent copy containing a clamped range of bytes.

ByteBlockEditor replaced(unit::ByteRange range, const ByteBlock &replacement) const

Return a copy with a range replaced.

ByteBlockEditor join(std::initializer_list<ByteBlock> parts) const

Join byte sequences with this block as separator.

std::strong_ordering operator<=>(const ByteBlockEditor &other) const noexcept

Compare this editor with another editor.

std::strong_ordering operator<=>(const ByteBlock &other) const noexcept

Compare this editor with an immutable byte block.

bool isEqualConstTime(const ByteBlock &other) const noexcept

Test equality without content-dependent short-circuiting.

Equal-length inputs always inspect every byte; a length mismatch returns immediately.

Parameters:

other – The byte block to compare.

Returns:

true if both blocks have the same length and contents.

bool isEqualConstTime(ConstByteSpan other) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters:

other – The borrowed byte sequence to compare.

Returns:

true if both sequences have the same length and contents.

inline bool isEmpty() const noexcept

Test if this block contains no bytes.

bool startsWith(const ByteBlock &other) const noexcept

Test if this block starts with another byte sequence.

bool startsWith(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool startsWith(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool startsWith(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool endsWith(const ByteBlock &other) const noexcept

Test if this block ends with another byte sequence.

bool endsWith(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool endsWith(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool endsWith(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool contains(const ByteBlock &other) const noexcept

Test if this block contains another byte sequence.

bool contains(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

bool contains(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline bool contains(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteLength length() const noexcept

Get the length of this byte block.

inline unit::ByteIndex endIndex() const noexcept

Get the index after the last byte.

Byte get(unit::ByteIndex index, Byte defaultValue = Byte{}) const noexcept

Get a byte or return a default value when the index is out of range.

Byte getOrThrow(unit::ByteIndex index) const

Get a byte or throw when the index is out of range.

Throws:

err::OutOfRangeError – If the index is out of range.

inline ConstByteSpan span() const noexcept

Access all visible bytes through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteRange range) const noexcept

Access a clamped visible range through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteIndex index, unit::ByteLength lengthValue) const noexcept

Access a clamped visible range through a read-only borrowed span.

template<typename Function>
inline util::LoopResult forEach(Function function) const

Invoke a callback for every visible byte and its optional index.

template<typename T>
inline auto getInteger(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little, const T defaultOnError = T{}) const noexcept -> T

Get an integer or return a default value if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

  • defaultOnError – The value returned for an invalid range.

Returns:

The decoded value, or defaultOnError.

template<typename T>
inline auto getIntegerOrThrow(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const -> T

Get an integer or throw if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

Returns:

The decoded value.

template<typename T>
inline auto getIntegerInto(T &value, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const noexcept -> bool

Decode an integer into an existing value, leaving it unchanged for an invalid range.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • value – The destination value.

  • offset – The first byte index.

  • endianness – The byte order.

Returns:

true on success.

void set(unit::ByteIndex index, Byte value)

Set a byte value, ignoring out-of-range indexes.

void setOrThrow(unit::ByteIndex index, Byte value)

Set a byte value or throw when the index is out of range.

Throws:

err::OutOfRangeError – If the index is out of range.

void xorAt(unit::ByteIndex index, Byte value)

XOR a byte value at an index, ignoring out-of-range indexes.

void xorAtOrThrow(unit::ByteIndex index, Byte value)

XOR a byte value at an index or throw when the index is out of range.

Throws:

err::OutOfRangeError – If the index is out of range.

template<typename T>
inline auto setInteger(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little) -> bool

Store an integer, leaving the block unchanged if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Returns:

true on success.

template<typename T>
inline void setIntegerOrThrow(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little)

Store an integer or throw if its byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

unit::ByteIndex find(const ByteBlock &bytes) const noexcept

Find the first occurrence of a byte sequence.

unit::ByteIndex find(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex find(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(const ByteBlock &bytes, unit::ByteIndex start) const noexcept

Find the first occurrence of a byte sequence at or after start.

unit::ByteIndex find(std::initializer_list<Byte> byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex find(ConstByteSpan byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex find(FixedConstByteSpan<N> byteSequence, unit::ByteIndex start) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex findLast(const ByteBlock &bytes) const noexcept

Find the last occurrence of a byte sequence.

unit::ByteIndex findLast(std::initializer_list<Byte> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

unit::ByteIndex findLast(ConstByteSpan byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
inline unit::ByteIndex findLast(FixedConstByteSpan<N> byteSequence) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

void detach()

Detach shared storage.

unit::ByteLength capacity() const noexcept

Get the current capacity.

void reserve(unit::ByteLength capacity)

Reserve capacity.

void shrinkToFit()

Shrink storage to the current length.

ByteBuffer toByteBuffer() const

Create a deep-copying byte buffer with the visible values.

std::vector<uint8_t> toUInt8Vector() const

Create a vector with raw unsigned byte values.

std::vector<char> toCharVector() const

Create a vector with raw char values.

Public Static Functions

static ByteBlockEditor fromSpan(ConstByteSpan bytes)

Create an editor by copying an Erbsland Core byte span.

static ByteBlockEditor fromSpan(std::span<const std::byte> bytes)

Create an editor by copying standard byte values.

static ByteBlockEditor fromSpan(std::span<const uint8_t> bytes)

Create an editor by copying unsigned byte values.

static ByteBlockEditor fromSpan(std::span<const char> bytes)

Create an editor by copying character byte values.

static ByteBlockEditor fromVector(const std::vector<uint8_t> &bytes)

Create an editor by copying unsigned byte values.

static ByteBlockEditor fromVector(const std::vector<char> &bytes)

Create an editor by copying character byte values.

static ByteBlockEditor fromJoined(std::initializer_list<ByteBlock> parts)

Join byte sequences without a separator.

class ByteBuffer

A dynamic, deep-copying buffer of explicit byte values.

The object uniquely owns a compact byte allocation and never shares storage through copy-on-write.

See: Memory and Byte Data

Public Functions

ByteBuffer() = default

Create an empty buffer.

explicit ByteBuffer(unit::ByteLength length, Byte value = Byte{})

Create a buffer filled with a byte value.

ByteBuffer(std::initializer_list<Byte> bytes)

Create a buffer by copying explicit byte values.

explicit ByteBuffer(ConstByteSpan bytes)

Create a buffer by copying a borrowed byte span.

ByteBuffer &operator=(const ByteBuffer &other)

Copy another buffer’s contents and storage mode.

ByteBuffer &operator=(ByteBuffer &&other) noexcept

Move another buffer’s contents and storage mode.

std::strong_ordering operator<=>(const ByteBuffer &other) const noexcept

Compare the visible byte contents lexicographically.

bool isEqualConstTime(const ByteBuffer &other) const noexcept

Test equality without content-dependent short-circuiting.

Equal-length inputs always inspect every byte; a length mismatch returns immediately.

Parameters:

other – The byte buffer to compare.

Returns:

true if both buffers have the same length and contents.

bool isEqualConstTime(ConstByteSpan other) const noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

Parameters:

other – The borrowed byte sequence to compare.

Returns:

true if both sequences have the same length and contents.

bool isEmpty() const noexcept

Test if this buffer contains no bytes.

unit::ByteLength length() const noexcept

Get the visible byte length.

inline unit::ByteIndex endIndex() const noexcept

Get the index after the final byte.

unit::ByteLength capacity() const noexcept

Get the allocated capacity.

inline bool isSensitive() const noexcept

Test if discarded storage is securely erased.

void setSensitive(bool sensitive) noexcept

Enable or disable secure erasure for discarded storage.

Disabling this mode securely erases the complete allocation and discards all visible bytes.

ConstByteSpan span() const noexcept

Access all bytes through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteRange range) const noexcept

Access a clamped range through a read-only borrowed span.

inline ConstByteSpan span(unit::ByteIndex index, unit::ByteLength lengthValue) const noexcept

Access a clamped range through a read-only borrowed span.

Byte get(unit::ByteIndex index, Byte defaultValue = Byte{}) const noexcept

Get a byte or a default value if its index is invalid.

Byte getOrThrow(unit::ByteIndex index) const

Get a byte or throw if its index is invalid.

Throws:

err::OutOfRangeError – If index is invalid or outside this buffer.

template<typename Function>
inline util::LoopResult forEach(Function function) const

Invoke a callback for every byte and its optional index.

template<typename T>
inline auto getInteger(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little, const T defaultOnError = T{}) const noexcept -> T

Read an integer or return a default value if its range is invalid.

template<typename T>
inline auto getIntegerOrThrow(const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const -> T

Read an integer or throw if its range is invalid.

template<typename T>
inline auto getIntegerInto(T &value, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) const noexcept -> bool

Decode an integer into an existing value.

void set(unit::ByteIndex index, Byte value) noexcept

Set a byte, ignoring invalid indexes.

void setOrThrow(unit::ByteIndex index, Byte value)

Set a byte or throw for an invalid index.

void xorAt(unit::ByteIndex index, Byte value) noexcept

XOR a byte value at an index, ignoring invalid indexes.

void xorAtOrThrow(unit::ByteIndex index, Byte value)

XOR a byte value at an index or throw if its index is invalid.

Throws:

err::OutOfRangeError – If index is invalid or outside this buffer.

template<typename T>
inline auto setInteger(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little) noexcept -> bool

Store an integer, leaving this buffer unchanged if its range is invalid.

template<typename T>
inline void setIntegerOrThrow(const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little)

Store an integer or throw if its range is invalid.

inline void fill(Byte value) noexcept

Fill all visible bytes.

inline void fill(unit::ByteRange targetRange, Byte value) noexcept

Fill a clamped byte range.

void overwrite(ConstByteSpan source)

Overwrite from the beginning with as many source bytes as fit.

void overwrite(unit::ByteIndex index, ConstByteSpan source)

Overwrite from an index with as many source bytes as fit.

void overwrite(unit::ByteRange targetRange, ConstByteSpan source)

Overwrite a clamped target range with as many source bytes as fit.

bool xorWith(ConstByteSpan source)

XOR every byte with an equally sized source.

Returns:

false without changing the buffer if the lengths differ.

void xorWithOrThrow(ConstByteSpan source)

XOR every byte with an equally sized source or throw if the lengths differ.

Throws:

err::ParameterError – If the lengths differ.

void xorWith(unit::ByteRange targetRange, ConstByteSpan source)

XOR a clamped target range with as many source bytes as fit.

void secureErase() noexcept

Securely erase the complete allocated capacity while preserving length and capacity.

ByteBuffer &resize(unit::ByteLength lengthValue)

Resize visible storage, zero-filling growth.

void reserve(unit::ByteLength capacityValue)

Reserve at least the requested capacity.

void shrinkToFit()

Reduce capacity to the visible length.

ByteBuffer &clear() noexcept

Remove all visible bytes while preserving capacity.

void reset() noexcept

Remove all bytes and release storage.

ByteBuffer &append(Byte value, unit::ByteLength length = unit::ByteLength::one())

Append one or more bytes.

Parameters:
  • value – The byte value to append.

  • length – The number of times to append the value.

ByteBuffer &append(ConstByteSpan bytes)

Append borrowed bytes.

ByteBuffer &insert(unit::ByteIndex index, ConstByteSpan bytes)

Insert borrowed bytes, clamping out-of-range indexes to the end.

ByteBuffer &replace(unit::ByteRange range, ConstByteSpan replacement)

Replace a clamped range with borrowed bytes.

ByteBuffer &remove(unit::ByteRange range)

Remove a clamped range.

ByteBuffer &keep(unit::ByteRange range)

Keep only a clamped range.

std::vector<uint8_t> toUInt8Vector() const

Copy into raw unsigned-byte storage.

std::vector<char> toCharVector() const

Copy into raw character storage.

Public Static Functions

static ByteBuffer fromSpan(std::span<const std::byte> bytes)

Copy standard byte values.

static ByteBuffer fromSpan(std::span<const uint8_t> bytes)

Copy raw unsigned-byte values.

static ByteBuffer fromSpan(std::span<const char> bytes)

Copy raw character values.

class ByteCompressionAlgorithm

A byte-compression algorithm supported by the library.

Raw algorithm values are stable because they are stored in compression envelopes.

See: Memory and Byte Data

Public Types

enum Value

The raw compression algorithm value.

Values:

enumerator Lz4Block

Standard raw LZ4 block compression.

Public Functions

constexpr ByteCompressionAlgorithm() noexcept = default

Create the default LZ4 block algorithm.

inline constexpr ByteCompressionAlgorithm(const Value value) noexcept

Create an algorithm from its raw value.

inline constexpr Value toRawValue() const noexcept

Get the stable raw algorithm value.

unit::ByteLength maximumCompressedLength(unit::ByteLength length) const

Calculate an upper bound for a raw compressed block.

Throws:

err::OutOfRangeError – If length is infinite or the bound is not representable.

text::String toString() const

Convert the algorithm to its stable lowercase identifier.

Public Static Functions

static std::optional<ByteCompressionAlgorithm> fromString(const text::String &text) noexcept

Parse an exact lowercase algorithm identifier.

static ByteCompressionAlgorithm fromStringOrThrow(const text::String &text)

Parse an exact lowercase algorithm identifier.

Throws:

err::ParseError – If the identifier is unsupported.

static std::span<const ByteCompressionAlgorithm> all() noexcept

Get all supported algorithms in stable order.

class ByteCompressionError : public erbsland::err::RuntimeError

A malformed or unsupported byte-compression representation.

Public Functions

ByteCompressionError(ByteCompressionErrorReason reason, text::String message) noexcept

Create a byte-compression error.

ByteCompressionError(ByteCompressionErrorReason reason, std::string_view message) noexcept

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline ByteCompressionErrorReason reasonCode() const noexcept

Get the machine-readable failure reason.

enum class erbsland::mem::ByteCompressionErrorReason : uint8_t

A machine-readable byte-compression failure reason.

Values:

enumerator MalformedData

The compressed payload is malformed or truncated.

enumerator LengthMismatch

Encoded and expected lengths do not match.

enumerator UnsupportedAlgorithm

The selected or encoded algorithm is unsupported.

enumerator UnsupportedEnvelopeVersion

The envelope version is unsupported.

class ByteCompressor

Compress complete byte values as raw blocks or self-describing envelopes.

Incremental input is buffered until either finalization method is called. One-shot calls are independent of the incremental state. After finalization, call reset() before adding more input or choosing another output format.

See: Memory and Byte Data

Public Functions

explicit ByteCompressor(ByteCompressionAlgorithm algorithm)

Create a compressor for an algorithm.

ByteBlock compress(ConstByteSpan data) const

Compress borrowed bytes into one raw algorithm block.

ByteBlock compress(const ByteBlock &data) const

Compress an owning byte block and propagate its sensitivity mark.

ByteBlock compressWithEnvelope(ConstByteSpan data) const

Compress borrowed bytes into a self-describing Erbsland Core envelope.

ByteBlock compressWithEnvelope(const ByteBlock &data) const

Compress an owning byte block into an envelope and propagate sensitivity.

void update(ConstByteSpan data)

Append borrowed input to the incremental buffer.

Throws:

err::LogicError – If this compressor is finalized.

void update(const ByteBlock &data)

Append an owning input and propagate its sensitivity mark.

Throws:

err::LogicError – If this compressor is finalized.

ByteBlock finalize()

Finalize incremental input as one raw block.

Repeated calls return the cached result.

Throws:

err::LogicError – If envelope finalization was selected.

ByteBlock finalizeWithEnvelope()

Finalize incremental input as a self-describing envelope.

Repeated calls return the cached result.

Throws:

err::LogicError – If raw finalization was selected.

void reset() noexcept

Clear buffered input and cached output for reuse.

inline ByteCompressionAlgorithm algorithm() const noexcept

Get the selected compression algorithm.

inline bool isFinalized() const noexcept

Test whether incremental input was finalized.

inline unit::ByteLength bufferedLength() const noexcept

Get the buffered incremental input length.

class ByteDecompressor

Decompress raw algorithm blocks and self-describing Erbsland Core envelopes.

A default instance can incrementally decode envelopes. Configure an algorithm to decode raw blocks.

See: Memory and Byte Data

Public Functions

ByteDecompressor() noexcept = default

Create an automatic decompressor for buffered envelopes.

explicit ByteDecompressor(ByteCompressionAlgorithm algorithm)

Create a decompressor for raw blocks using an algorithm.

ByteBlock decompress(ConstByteSpan data, unit::ByteLength originalLength) const

Decompress a borrowed raw block to its exact original length.

Throws:
ByteBlock decompress(const ByteBlock &data, unit::ByteLength originalLength) const

Decompress an owning raw block and propagate sensitivity.

void update(ConstByteSpan data)

Append borrowed compressed input to the incremental buffer.

Throws:

err::LogicError – If this decompressor is finalized.

void update(const ByteBlock &data)

Append owning compressed input and propagate its sensitivity mark.

Throws:

err::LogicError – If this decompressor is finalized.

ByteBlock finalize(unit::ByteLength originalLength)

Finalize buffered data as a raw block.

Throws:

err::LogicError – If no algorithm is configured or envelope finalization was selected.

ByteBlock finalizeWithEnvelope(unit::ByteLength maximumOutputSize = unit::ByteLength::infinite())

Finalize buffered data as a self-describing envelope.

Throws:

err::LogicError – If raw finalization was selected.

void reset() noexcept

Clear buffered input and cached output for reuse.

inline const std::optional<ByteCompressionAlgorithm> &algorithm() const noexcept

Get the configured raw algorithm, or no value for automatic envelope-only instances.

inline bool isFinalized() const noexcept

Test whether incremental input was finalized.

inline unit::ByteLength bufferedLength() const noexcept

Get the buffered incremental input length.

Public Static Functions

static auto decompressWithEnvelope(ConstByteSpan data, unit::ByteLength maximumOutputSize = unit::ByteLength::infinite()) -> ByteBlock

Automatically decode a self-describing envelope.

Parameters:
  • data – The complete envelope.

  • maximumOutputSize – The largest accepted original length.

Throws:
static auto decompressWithEnvelope(const ByteBlock &data, unit::ByteLength maximumOutputSize = unit::ByteLength::infinite()) -> ByteBlock

Automatically decode an owning envelope and propagate sensitivity.

template<typename T>
constexpr auto erbsland::mem::getInteger(const ConstByteSpan bytes, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little, const T defaultOnError = T()) noexcept -> T

Get an integer from a byte span or return a default value for an invalid range.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • bytes – The source bytes.

  • offset – The first byte index.

  • endianness – The byte order.

  • defaultOnError – The value returned for an invalid range.

Returns:

The decoded value, or defaultOnError.

template<typename T>
constexpr auto erbsland::mem::getIntegerOrThrow(const ConstByteSpan bytes, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) -> T

Get an integer from a byte span or throw for an invalid range.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • bytes – The source bytes.

  • offset – The first byte index.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

Returns:

The decoded value.

template<typename T>
constexpr auto erbsland::mem::getIntegerInto(const ConstByteSpan bytes, T &value, const unit::ByteIndex offset, const Endianness endianness = Endianness::Little) noexcept -> bool

Decode an integer from a byte span into an existing value.

The output remains unchanged if the byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • bytes – The source bytes.

  • value – The destination value.

  • offset – The first byte index.

  • endianness – The byte order.

Returns:

true on success.

template<typename T>
constexpr auto erbsland::mem::setInteger(const ByteSpan bytes, const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little) noexcept -> bool

Store an integer in a byte span.

The bytes remain unchanged if the byte range is invalid.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • bytes – The destination bytes.

  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Returns:

true on success.

template<typename T>
constexpr void erbsland::mem::setIntegerOrThrow(const ByteSpan bytes, const unit::ByteIndex offset, const T value, const Endianness endianness = Endianness::Little)

Store an integer in a byte span or throw for an invalid range.

Template Parameters:

T – A non-boolean native integer type.

Parameters:
  • bytes – The destination bytes.

  • offset – The first byte index.

  • value – The integer value.

  • endianness – The byte order.

Throws:

err::OutOfRangeError – If the integer does not fit at offset.

class ByteIntegerFormat

The exact wire representation of an integer.

Public Types

enum Value

The raw integer wire-format value.

Values:

enumerator UnsignedFixed8Bit

An unsigned fixed-width 8-bit integer.

enumerator SignedFixed8Bit

A signed two’s-complement fixed-width 8-bit integer.

enumerator UnsignedFixed16Bit

An unsigned fixed-width 16-bit integer.

enumerator SignedFixed16Bit

A signed two’s-complement fixed-width 16-bit integer.

enumerator UnsignedFixed24Bit

An unsigned fixed-width 24-bit integer.

enumerator UnsignedFixed32Bit

An unsigned fixed-width 32-bit integer.

enumerator SignedFixed32Bit

A signed two’s-complement fixed-width 32-bit integer.

enumerator UnsignedFixed40Bit

An unsigned fixed-width 40-bit integer.

enumerator UnsignedFixed48Bit

An unsigned fixed-width 48-bit integer.

enumerator UnsignedFixed56Bit

An unsigned fixed-width 56-bit integer.

enumerator UnsignedFixed64Bit

An unsigned fixed-width 64-bit integer.

enumerator SignedFixed64Bit

A signed two’s-complement fixed-width 64-bit integer.

enumerator UnsignedVariableLength

An unsigned prefix-coded variable-length integer.

enumerator SignedVariableLength

A ZigZag-mapped prefix-coded variable-length integer.

enumerator UnsignedBase128

A canonical unsigned big-endian base-128 integer with continuation bits.

enumerator _valueCount

The number of wire-format values.

Public Functions

inline constexpr ByteIntegerFormat(Value value) noexcept

Create a format from its raw value.

Parameters:

value – The raw wire-format value.

inline constexpr Value toRawValue() const noexcept

Get the raw wire-format value.

inline constexpr unit::ByteLength byteCount() const noexcept

Get the fixed byte width, or infinite for variable-length formats.

inline constexpr bool isSigned() const noexcept

Test if the wire representation is signed.

inline constexpr bool isVariableLength() const noexcept

Test if the wire representation has a variable byte width.

class ByteReader

A sequential byte reader for read-only or editable byte blocks.

Public Functions

ByteReader(const ByteBlockEditor &editor) noexcept

Create a reader sharing the data from a byte block editor.

ByteReader(const ByteBlock &block) noexcept

Create a reader sharing the data from a read-only byte block.

unit::ByteLength length() const noexcept

Get the readable byte length.

inline unit::ByteIndex position() const noexcept

Get the current read position.

void setPosition(unit::ByteIndex position) noexcept

Set the read position, clamped to length().

inline Endianness endianness() const noexcept

Get the byte order for multi-byte integers.

inline void setEndianness(Endianness endianness) noexcept

Set the byte order for multi-byte integers.

inline bool isAtEnd() const noexcept

Test if the reader is at the end of the data.

bool canRead(unit::ByteLength byteCount) const noexcept

Test if byteCount bytes can be read at the current position.

inline bool canRead(std::size_t byteCount) const noexcept

Compatibility overload using a native byte count.

void advance(unit::ByteLength byteCount) noexcept

Advance the current position by byteCount, clamped to length().

inline void advance(std::size_t byteCount) noexcept

Compatibility overload using a native byte count.

Byte readByte() noexcept

Read one byte or return zero at end.

Byte peekByte() const noexcept

Read one byte without advancing, or return zero at end.

Byte peekByte(unit::ByteIndex index, Byte defaultValue = Byte{}) const noexcept

Read one byte at an absolute position without advancing, or return a default value.

Byte peekByte(std::size_t offset, Byte defaultValue = Byte{}) const noexcept

Read one byte at an offset from the current position without advancing, or return a default value.

Byte readByteOrThrow()

Read one byte or throw at end.

Throws:

err::OutOfRangeError – If there is no byte at the current position.

Byte peekByteOrThrow() const

Read one byte without advancing, or throw at end.

Throws:

err::OutOfRangeError – If there is no byte at the current position.

std::optional<ByteBlock> readBytes(unit::ByteLength length) noexcept

Read exactly length bytes into a byte block.

Returns no value without advancing if there are not enough bytes.

Parameters:

length – The number of bytes to read.

ByteBlock readBytesOrThrow(unit::ByteLength length)

Read exactly length bytes into a byte block.

Parameters:

length – The number of bytes to read.

Throws:

err::OutOfRangeError – If there are not enough bytes.

Returns:

A shared block containing the requested bytes.

std::optional<text::String> readText(const ByteTextOptions &options = {})

Read text using the given framing, or no value if it is incomplete or invalid.

Parameters:

options – The encoding and framing options.

Returns:

The decoded text, or no value if the complete valid frame is unavailable.

text::String readTextOrThrow(const ByteTextOptions &options = {})

Read text using the given framing.

Parameters:

options – The encoding and framing options.

Throws:
  • err::OutOfRangeError – If the complete field is unavailable.

  • err::ParseError – If an end mark is missing or mismatched.

Returns:

The decoded text.

template<impl::NativeByteInteger T>
T readInteger(T defaultOnError = T{0}) noexcept

Read an integer value or return defaultOnError if there are not enough bytes.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:

defaultOnError – The value returned when the complete integer is unavailable.

Returns:

The decoded integer, or defaultOnError.

template<impl::NativeByteInteger T>
T readIntegerOrThrow()

Read an integer value or throw if there are not enough bytes.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Throws:

err::OutOfRangeError – If there are not enough bytes.

Returns:

The decoded integer.

template<impl::NativeByteInteger T>
std::optional<T> readInteger(ByteIntegerFormat format)

Read an explicitly formatted integer, or no value if it is incomplete or does not fit T.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:

format – The integer wire format.

Returns:

The decoded integer, or no value if decoding fails.

template<impl::NativeByteInteger T>
std::optional<T> readInteger(ByteIntegerFormat::Value format)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<impl::NativeByteInteger T>
T readIntegerOrThrow(ByteIntegerFormat format)

Read an explicitly formatted integer.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:

format – The integer wire format.

Throws:
Returns:

The decoded integer.

template<impl::NativeByteInteger T>
T readIntegerOrThrow(ByteIntegerFormat::Value format)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<impl::NativeByteInteger T>
bool readIntegerInto(T &value) noexcept

Read an integer into value.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:

value – The destination, which remains unchanged if the complete integer is unavailable.

Returns:

true on success, false when there are not enough bytes.

inline int8_t readInt8(int8_t defaultOnError = 0) noexcept

Read a signed 8-bit integer or return defaultOnError.

inline uint8_t readUInt8(uint8_t defaultOnError = 0U) noexcept

Read an unsigned 8-bit integer or return defaultOnError.

inline int16_t readInt16(int16_t defaultOnError = 0) noexcept

Read a signed 16-bit integer or return defaultOnError.

inline uint16_t readUInt16(uint16_t defaultOnError = 0U) noexcept

Read an unsigned 16-bit integer or return defaultOnError.

inline int32_t readInt32(int32_t defaultOnError = 0) noexcept

Read a signed 32-bit integer or return defaultOnError.

inline uint32_t readUInt32(uint32_t defaultOnError = 0U) noexcept

Read an unsigned 32-bit integer or return defaultOnError.

inline int64_t readInt64(int64_t defaultOnError = 0) noexcept

Read a signed 64-bit integer or return defaultOnError.

inline uint64_t readUInt64(uint64_t defaultOnError = 0U) noexcept

Read an unsigned 64-bit integer or return defaultOnError.

inline int8_t readInt8OrThrow()

Read a signed 8-bit integer or throw if there are not enough bytes.

inline uint8_t readUInt8OrThrow()

Read an unsigned 8-bit integer or throw if there are not enough bytes.

inline int16_t readInt16OrThrow()

Read a signed 16-bit integer or throw if there are not enough bytes.

inline uint16_t readUInt16OrThrow()

Read an unsigned 16-bit integer or throw if there are not enough bytes.

inline int32_t readInt32OrThrow()

Read a signed 32-bit integer or throw if there are not enough bytes.

inline uint32_t readUInt32OrThrow()

Read an unsigned 32-bit integer or throw if there are not enough bytes.

inline int64_t readInt64OrThrow()

Read a signed 64-bit integer or throw if there are not enough bytes.

inline uint64_t readUInt64OrThrow()

Read an unsigned 64-bit integer or throw if there are not enough bytes.

class ByteRingBuffer : public erbsland::mem::RingBuffer

A byte ring with atomic endian-aware integer operations.

Public Functions

inline Endianness endianness() const noexcept

Get the byte order used by integer operations.

inline void setEndianness(const Endianness value) noexcept

Set the byte order used by integer operations.

template<std::integral T>
inline std::optional<T> readInteger()

Atomically read an integer.

Returns:

The value, or an empty optional if there are not enough readable bytes.

template<std::integral T>
inline util::Result writeInteger(const T value)

Atomically write an integer.

Returns:

Failure without modification if the hard storage limit would be exceeded.

explicit RingBuffer(unit::ByteLength capacity)

Create a fixed-capacity ring.

RingBuffer(unit::ByteLength initialCapacity, unit::ByteLength maximumCapacity)

Create a growable ring.

using erbsland::mem::ByteSpan = std::span<Byte>

A writable dynamic-extent span of bytes.

using erbsland::mem::ConstByteSpan = std::span<const Byte>

A read-only dynamic-extent span of bytes.

template<std::size_t Extent>
using erbsland::mem::FixedByteSpan = std::span<Byte, Extent>

A writable fixed-extent span of bytes.

Template Parameters:

Extent – The number of bytes in the span.

template<std::size_t Extent>
using erbsland::mem::FixedConstByteSpan = std::span<const Byte, Extent>

A read-only fixed-extent span of bytes.

Template Parameters:

Extent – The number of bytes in the span.

ByteSpan erbsland::mem::toByteSpan(std::span<std::byte> span) noexcept

Create a zero-copy byte view of mutable standard-byte storage.

ByteSpan erbsland::mem::toByteSpan(std::span<uint8_t> span) noexcept

Create a zero-copy byte view of mutable unsigned-byte storage.

ByteSpan erbsland::mem::toByteSpan(std::span<char> span) noexcept

Create a zero-copy byte view of mutable character storage.

ConstByteSpan erbsland::mem::toConstByteSpan(std::span<const std::byte> span) noexcept

Create a zero-copy read-only byte view of standard-byte storage.

ConstByteSpan erbsland::mem::toConstByteSpan(std::span<const uint8_t> span) noexcept

Create a zero-copy read-only byte view of unsigned-byte storage.

ConstByteSpan erbsland::mem::toConstByteSpan(std::span<const char> span) noexcept

Create a zero-copy read-only byte view of character storage.

enum class erbsland::mem::ByteTextFormat : uint8_t

The byte-level framing mode for text values.

Values:

enumerator Dynamic

A dynamically-sized text value.

enumerator PaddedField

A fixed-size field with optional trailing padding.

class ByteTextOptions

Options that define the byte framing of a text value.

Public Functions

constexpr ByteTextOptions() noexcept = default

Create default dynamic UTF-8 framing with an unsigned 32-bit count.

inline constexpr ByteTextOptions(text::StringEncoding encoding) noexcept

Create default dynamic framing for an encoding.

Parameters:

encoding – The text encoding.

inline constexpr ByteTextOptions(ByteTextFormat format, text::StringEncoding encoding = text::StringEncoding::Utf8) noexcept

Create framing with a format and encoding.

Parameters:
  • format – The byte-level framing mode.

  • encoding – The text encoding.

inline constexpr ByteTextFormat format() const noexcept

Get the byte-level framing mode.

inline constexpr ByteTextOptions &setFormat(ByteTextFormat value) noexcept

Set the byte-level framing mode.

inline constexpr text::StringEncoding encoding() const noexcept

Get the text encoding.

inline constexpr ByteTextOptions &setEncoding(text::StringEncoding value) noexcept

Set the text encoding.

inline constexpr unit::ByteLength length() const noexcept

Get the maximum payload length or fixed field length.

inline constexpr ByteTextOptions &setLength(unit::ByteLength value) noexcept

Set the maximum payload length or fixed field length.

inline constexpr const std::optional<text::Char> &endMark() const noexcept

Get the optional end-mark character.

inline constexpr ByteTextOptions &setEndMark(text::Char value) noexcept

Set the end-mark character.

inline constexpr ByteTextOptions &clearEndMark() noexcept

Clear the end-mark character.

inline constexpr const std::optional<ByteIntegerFormat> &countFormat() const noexcept

Get the optional code-unit count format.

inline constexpr ByteTextOptions &setCountFormat(ByteIntegerFormat value) noexcept

Set the code-unit count format.

inline constexpr ByteTextOptions &clearCountFormat() noexcept

Clear the code-unit count format.

inline constexpr Byte padding() const noexcept

Get the byte used to pad fixed fields.

inline constexpr ByteTextOptions &setPadding(Byte value) noexcept

Set the byte used to pad fixed fields.

Public Static Functions

static inline constexpr ByteTextOptions compact() noexcept

Create the default compact dynamic framing with a variable-length count.

class ByteWriter

A sequential byte writer that produces a ByteBlock or ByteBlockEditor.

It is the best choice to write multi-field binary data for protocols and byte based formats. Make sure to set the correct endianness for multi-byte integers, default is Endianness::Little. The various overloads for Erbsland Core types, allow to write compact binary representations that can be read back with the corresponding ByteReader overloads.

Public Functions

inline unit::ByteLength length() const noexcept

Get the current byte length.

inline unit::ByteIndex position() const noexcept

Get the current write position.

void setPosition(unit::ByteIndex position) noexcept

Set the write position, clamped to length().

void reset() noexcept

Reset the writer.

This discards all written bytes and resets the write position.

inline Endianness endianness() const noexcept

Get the byte order for multi-byte integers.

inline void setEndianness(const Endianness endianness) noexcept

Set the byte order for multi-byte integers.

inline ByteBlock toByteBlock() const noexcept

Return the written bytes as a byte block.

ByteBlockEditor takeByteBlockEditor() noexcept

Take the written bytes as a byte block editor.

This resets the write position of the writer.

ByteWriter &reserve(unit::ByteLength capacity)

Reserve capacity for at least capacity bytes.

Parameters:

capacity – The minimum byte capacity to reserve.

Returns:

A reference to this writer.

ByteWriter &writeByte(Byte value)

Write a byte at the current position and advance.

Parameters:

value – The byte value.

Returns:

A reference to this writer.

ByteWriter &writeBytes(const ConstByteSpan &data)

Write a block of data at the current position and advance.

Parameters:

data – The data to write.

ByteWriter &writeBytes(const std::span<const std::byte> &data)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

ByteWriter &writeBytes(const ByteBlock &data)

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<impl::NativeByteInteger T>
ByteWriter &writeInteger(T value)

Write an integer at the current position and advance.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:

value – The integer value.

Returns:

A reference to this writer.

template<impl::NativeByteInteger T>
ByteWriter &writeIntegerOrThrow(T value, ByteIntegerFormat format)

Write an integer using an explicit wire format.

Template Parameters:

T – One of the fixed-width native integer types from int8_t through uint64_t.

Parameters:
  • value – The integer value.

  • format – The integer wire format.

Throws:

err::OutOfRangeError – If the value cannot be represented by format.

Returns:

A reference to this writer.

ByteWriter &writeText(const text::String &text, const ByteTextOptions &options = {})

Write text, truncating it at character boundaries when necessary.

Parameters:
  • text – The text to write.

  • options – The encoding and framing options.

Throws:

err::OutOfRangeError – If even an empty text frame cannot fit.

Returns:

A reference to this writer.

ByteWriter &writeTextOrThrow(const text::String &text, const ByteTextOptions &options = {})

Write text using exactly the framing specified by options.

Parameters:
  • text – The text to write.

  • options – The encoding and framing options.

Throws:

err::OutOfRangeError – If the text cannot fit in the specified framing.

Returns:

A reference to this writer.

inline ByteWriter &writeInt8(int8_t value)

Write a signed 8-bit integer.

inline ByteWriter &writeUInt8(uint8_t value)

Write an unsigned 8-bit integer.

inline ByteWriter &writeInt16(int16_t value)

Write a signed 16-bit integer.

inline ByteWriter &writeUInt16(uint16_t value)

Write an unsigned 16-bit integer.

inline ByteWriter &writeInt32(int32_t value)

Write a signed 32-bit integer.

inline ByteWriter &writeUInt32(uint32_t value)

Write an unsigned 32-bit integer.

inline ByteWriter &writeInt64(int64_t value)

Write a signed 64-bit integer.

inline ByteWriter &writeUInt64(uint64_t value)

Write an unsigned 64-bit integer.

template<std::copy_constructible tDataType>
class CowManualStorage

Shared copy-on-write storage with explicit writable access.

See: Memory and Byte Data

CowManualStorage always owns a valid data object. Copying the storage shares that object. Reading uses data(); writing uses detachedData(), which detaches before returning a mutable reference. Methods that create, replace, or detach data may throw allocation errors or exceptions from tDataType.

Template Parameters:

tDataType – The copy-constructible data type to store.

Public Types

using Type = tDataType

The stored data type.

Public Functions

inline CowManualStorage()

Create storage with a default-constructed data object.

inline const tDataType &data() const noexcept

Access the data for reading.

Returns:

A const reference to the stored data object.

inline tDataType &detachedData()

Access the data for writing.

If the data object is shared, this method creates a private copy first.

Returns:

A mutable reference to the stored data object.

inline void setData(tDataType data)

Replace the stored data object with a new unique object.

Parameters:

data – The data object to move into the storage.

template<typename ...tArgs>
inline void emplaceData(tArgs&&... args)

Replace the stored data object by constructing a new unique object in place.

Parameters:

args – The arguments forwarded to the data type constructor.

inline void detach()

Ensure this storage uniquely owns its data object.

inline bool isShared() const noexcept

Test if this storage shares its data object with another storage.

Returns:

true if there is more than one owner for the data object.

inline long useCount() const noexcept

Get the current use count of the shared data object.

Returns:

The number of storages currently sharing the data object.

inline std::size_t storageId() const noexcept

Get a unique identifier for the currently stored data object.

Returns:

The address of the data object as an integer.

inline void swap(CowManualStorage &other) noexcept

Swap two storage objects.

Parameters:

other – The storage to swap with.

Public Static Functions

static inline CowManualStorage from(tDataType data)

Create storage from an existing data object.

Parameters:

data – The data object to move into the storage.

Returns:

New unique storage containing data.

template<typename ...tArgs>
static inline CowManualStorage create(tArgs&&... args)

Create storage by constructing the data object in place.

Parameters:

args – The arguments forwarded to the data type constructor.

Returns:

New unique storage containing the constructed data object.

static inline auto sharedDefault() -> CowManualStorage

Create storage that shares one default-constructed data object.

The shared default object is retained for the lifetime of the program and contributes one owner to useCount(). Mutable access detaches before returning the data object.

Returns:

Storage sharing the default data object for this specialization.

Friends

inline friend void swap(CowManualStorage &a, CowManualStorage &b) noexcept

Swap two storage objects.

Parameters:
  • a – The first storage.

  • b – The second storage.

template<std::copy_constructible tDataType>
class CowStorage

Shared copy-on-write storage for regular C++ data types.

See: Memory and Byte Data

CowStorage always owns a valid data object. Copying the storage shares that object, while mutable access through data() detaches first when the object is shared. Methods that create, replace, or detach data may throw allocation errors or exceptions from tDataType.

Template Parameters:

tDataType – The copy-constructible data type to store.

Public Types

using Type = tDataType

The stored data type.

Public Functions

inline CowStorage()

Create storage with a default-constructed data object.

inline CowStorage(CowStorage &&other) noexcept

Move storage while keeping the source object valid.

inline CowStorage &operator=(CowStorage &&other) noexcept

Move storage while keeping the source object valid.

inline const tDataType &data() const noexcept

Access the data for reading.

Returns:

A const reference to the stored data object.

inline tDataType &data()

Access the data for writing.

If the data object is shared, this method creates a private copy first.

Returns:

A mutable reference to the stored data object.

inline void setData(tDataType data)

Replace the stored data object with a new unique object.

Parameters:

data – The data object to move into the storage.

template<typename ...tArgs>
inline void emplaceData(tArgs&&... args)

Replace the stored data object by constructing a new unique object in place.

Parameters:

args – The arguments forwarded to the data type constructor.

inline void detach()

Ensure this storage uniquely owns its data object.

inline bool isShared() const noexcept

Test if this storage shares its data object with another storage.

Returns:

true if there is more than one owner for the data object.

inline long useCount() const noexcept

Get the current use count of the shared data object.

Returns:

The number of storages currently sharing the data object.

inline std::size_t storageId() const noexcept

Get a unique identifier for the currently stored data object.

Returns:

The address of the data object as an integer.

inline void swap(CowStorage &other) noexcept

Swap two storage objects.

Parameters:

other – The storage to swap with.

Public Static Functions

static inline CowStorage from(tDataType data)

Create storage from an existing data object.

Parameters:

data – The data object to move into the storage.

Returns:

New unique storage containing data.

template<typename ...tArgs>
static inline CowStorage create(tArgs&&... args)

Create storage by constructing the data object in place.

Parameters:

args – The arguments forwarded to the data type constructor.

Returns:

New unique storage containing the constructed data object.

Friends

inline friend void swap(CowStorage &a, CowStorage &b) noexcept

Swap two storage objects.

Parameters:
  • a – The first storage.

  • b – The second storage.

enum class erbsland::mem::Endianness : uint8_t

The byte order used to read or write multi-byte integer values.

Values:

enumerator Little

Lowest bytes first.

enumerator Big

Highest bytes first.

class ReferenceCounter

An atomic reference counter.

Warning

This is an advanced data type, meant for people extending the library. Do not use it unless you understand the implications and have a specific need.

Public Types

enum ReferenceStatus

The reference status for humans.

Values:

enumerator NoReferences
enumerator HasReferences

Public Functions

inline ReferenceStatus addReference() noexcept

Add a reference.

Returns:

The referencing status of the counter.

inline ReferenceStatus removeReference() noexcept

Remove a reference.

Returns:

The referencing status of the counter.

inline bool isReferenced() const noexcept

Checks if the object is referenced.

inline ReferenceStatus status() const noexcept

Get the referencing status of the counter.

inline bool isShared() const noexcept

Checks if the object is shared with multiple instances.

inline uint32_t useCount() const noexcept

Get the current number of references.

class RingBuffer

A contiguous-storage byte ring with checked safe access.

The storage can optionally grow up to a fixed hard limit. Native APIs use impl::UnsafeRingBufferAccess to access the two contiguous sections around the wrap point without copying.

Subclassed by erbsland::mem::ByteRingBuffer

Public Functions

explicit RingBuffer(unit::ByteLength capacity)

Create a fixed-capacity ring.

RingBuffer(unit::ByteLength initialCapacity, unit::ByteLength maximumCapacity)

Create a growable ring.

virtual ~RingBuffer()

Destroy this ring buffer.

unit::ByteLength capacity() const noexcept

Get the current storage capacity.

unit::ByteLength maximumCapacity() const noexcept

Get the hard storage limit.

unit::ByteLength length() const noexcept

Get the number of readable bytes.

unit::ByteLength available() const noexcept

Get the writable space in the current storage.

inline bool isEmpty() const noexcept

Test if the ring contains no readable bytes.

inline bool isFull() const noexcept

Test if the current storage has no writable space.

bool canWrite(unit::ByteLength length) const noexcept

Test if an atomic write can fit within the hard storage limit.

inline bool isSensitive() const noexcept

Test if discarded storage is securely erased.

void setSensitive(bool sensitive) noexcept

Enable or disable secure erasure for discarded storage.

Disabling this mode securely erases the complete allocation and discards all buffered bytes.

util::Result reserveAdditional(unit::ByteLength length)

Reserve space for additional bytes without changing the visible data.

Returns:

Success if the requested space is available, Failure if it exceeds the hard limit.

unit::ByteLength write(ConstByteSpan bytes)

Copy as many bytes as possible into the ring.

Returns:

The number of copied bytes.

util::Result writeExact(ConstByteSpan bytes)

Atomically copy all bytes into the ring.

Returns:

Failure without modification if the bytes exceed the hard limit.

unit::ByteLength read(ByteSpan destination)

Copy as many buffered bytes as possible to the destination.

Returns:

The number of copied bytes.

ByteBlock read(unit::ByteLength maximum)

Read up to the requested number of bytes.

void clear() noexcept

Discard all buffered bytes.

void secureErase() noexcept

Securely erase the complete allocation and discard all buffered bytes.

void shrinkToInitial()

Shrink empty storage back to its initial capacity.

void swap(RingBuffer &other) noexcept

Swap complete ring state with another ring.

void erbsland::mem::secureErase(ByteSpan span) noexcept

Secure erase the memory from a byte span.

The platform implementation prevents the erase from being optimized away.

Parameters:

span – The writable bytes to erase.

template<typename T, std::size_t Extent>
void erbsland::mem::secureErase(const std::span<T, Extent> span) noexcept

Securely erase writable storage represented by native trivially-copyable objects.

This overload is intended for mathematical word state whose representation is not byte-addressed at the API level.

Template Parameters:
  • T – The writable trivially-copyable element type.

  • Extent – The span extent.

Parameters:

span – The native object storage to erase.

template<typename tDataType, impl::SharedArrayDataSizeType tSizeType, SharedArrayDataConstructMethod tConstructMethod, SharedArrayDataCleanupMethod tCleanupMethod>
class SharedArrayData

A one-allocation intrusive shared header with aligned trailing array storage.

See: Memory and Byte Data

Warning

This is an advanced data type, meant for people extending the library. Do not use it unless you understand the implications and have a specific need.

Template Parameters:
  • tDataType – The element type stored in the trailing array.

  • tSizeType – The size type, either uint32_t or uint64_t.

  • tConstructMethod – Controls if and how array elements are constructed.

  • tCleanupMethod – Controls whether the complete allocation is securely erased before deallocation.

Public Types

using SizeType = tSizeType

The integer type used for size and capacity values.

using DataType = tDataType

The element type stored in the trailing array.

Public Functions

inline SizeType size() const noexcept

Get the current size of the data.

Returns:

The number of elements currently used.

inline void setSize(SizeType newSize) noexcept

Set the size of the data.

The size must not exceed the capacity. Violating this invariant terminates the program.

Parameters:

newSize – The new number of used elements.

inline SizeType capacity() const noexcept

Get the current capacity of the data.

Returns:

The number of elements allocated in the trailing storage.

inline DataType *data() noexcept

Access the data as a pointer to the first element.

Returns:

A mutable pointer to the first element in trailing storage.

inline const DataType *data() const noexcept

Access the data as a pointer to the first element.

Returns:

A const pointer to the first element in trailing storage.

inline SharedArrayData *clone() const

Create a detached copy of this shared array data.

For trivially copied raw storage, only the used range is copied. For constructed element storage, the used range is copied and the remaining capacity is default/value constructed according to tConstructMethod. If copying or construction throws, all successfully constructed destination elements are destroyed and the destination allocation is cleaned up before the exception is rethrown. Secure allocations are erased in full.

Returns:

A newly allocated, unreferenced copy of this array data block.

Public Static Functions

static inline SharedArrayData *create(SizeType size, SizeType capacity)

Create a new shared array data block.

If tConstructMethod requests element construction, this function constructs all capacity elements. If construction throws, already constructed elements and the allocation are cleaned up before the exception is rethrown. Invalid sizes terminate the program.

Parameters:
  • size – The initial number of used elements.

  • capacity – The number of elements to allocate.

Returns:

A newly allocated, unreferenced array data block.

static inline void destroy(SharedArrayData *data) noexcept

Destroy data created by create or clone.

Constructed elements and the header end their lifetimes first. In secure mode, the complete allocation, including metadata, alignment padding, used storage, and unused capacity, is then erased before deallocation.

Parameters:

data – The array data block to destroy, or nullptr.

template<std::integral T>
static inline constexpr bool canAllocateWithCapacity(const T capacity) noexcept

Test if an array with the given capacity can be allocated.

This function checks the numeric range and allocation size arithmetic. A later allocation can still throw std::bad_alloc if the system cannot provide the requested memory.

Parameters:

capacity – The requested allocated element count.

Returns:

true if the capacity can be passed to create() without violating range or overflow preconditions.

static inline constexpr std::size_t allocationOverhead() noexcept

Calculate the fixed allocation overhead before element storage.

Returns:

The header size plus the maximum padding needed to align element storage.

template<std::integral T>
static inline constexpr std::size_t allocationSizeForCapacity(const T capacity) noexcept

Calculate the allocation size for the given capacity.

Parameters:

capacity – The element capacity to allocate.

Returns:

The total allocation size in bytes, including header and alignment overhead.

enum class erbsland::mem::SharedArrayDataCleanupMethod : uint8_t

The method used to clean up a shared array allocation before deallocation.

Values:

enumerator None

Deallocate storage after normal element and header destruction.

enumerator SecureErase

Securely erase the complete allocation after destruction and before deallocation.

enum class erbsland::mem::SharedArrayDataConstructMethod : uint8_t

The method used to construct elements in shared array storage.

Values:

enumerator None

Leave raw trivially copyable element storage unconstructed.

enumerator DefaultConstruct

Default-construct every capacity element.

enumerator ValueConstruct

Value-construct every capacity element.

class SharedData

The base class for custom implicitly/explicitly shared data.

See: Memory and Byte Data

Warning

This is an advanced data type, meant for people extending the library. Do not use it unless you understand the implications and have a specific need.

Subclassed by erbsland::cterm::impl::BlockStringData, erbsland::cterm::impl::TerminalDocumentStyleData, erbsland::mem::SharedVirtualData, erbsland::mem::impl::SharedByteDataWithFlag< tDataType >, erbsland::path::impl::PathData, erbsland::text::impl::FormatData

Public Functions

SharedData() = default

Create a shared-data base with a zero reference count.

inline SharedData(const SharedData&) noexcept

Copy shared-data state without copying its reference counter.

Parameters:

other – The source shared-data base.

inline SharedData(SharedData&&) noexcept

Move shared-data state without moving its reference counter.

Parameters:

other – The source shared-data base.

inline SharedData &operator=(const SharedData&) noexcept

Assign shared-data state without assigning its reference counter.

Parameters:

other – The source shared-data base.

inline SharedData &operator=(SharedData&&) noexcept

Move-assign shared-data state without assigning its reference counter.

Parameters:

other – The source shared-data base.

template<typename tDataType, bool tManualDetach = false>
class SharedDataPointer

An intrusive copy-on-write pointer for shared data objects.

See: Memory and Byte Data

Warning

This is an advanced data type, meant for people extending the library. Do not use it unless you understand the implications and have a specific need.

Template Parameters:
  • tDataType – A type supported by impl::SharedDataPointerTraits.

  • tManualDetach – If true, mutable access does not detach automatically.

Public Types

using Type = tDataType

The managed shared data type.

using Pointer = tDataType*

The raw pointer type used for the managed data.

Public Functions

inline constexpr SharedDataPointer() noexcept

Create a null pointer that does not own any data.

inline SharedDataPointer(const SharedDataPointer &copy) noexcept

Create a copy and increase the reference count.

Parameters:

copy – The pointer to copy.

inline SharedDataPointer(SharedDataPointer &&other) noexcept

Move, without changing the reference count.

Parameters:

other – The pointer to move from.

inline explicit SharedDataPointer(tDataType *data) noexcept

Initialize the pointer with a new data object.

The pointer takes shared ownership by adding one reference. The object must not already be managed by another ownership mechanism.

Parameters:

data – A newly allocated data object, or nullptr.

inline ~SharedDataPointer()

Destroy the pointer and release the shared data if no references remain.

inline SharedDataPointer &operator=(const SharedDataPointer &other) noexcept

Assign another pointer to this one.

Parameters:

other – The pointer to copy.

Returns:

A reference to this pointer.

inline SharedDataPointer &operator=(SharedDataPointer &&other) noexcept

Move another pointer to this one.

Parameters:

other – The pointer to move from.

Returns:

A reference to this pointer.

inline void operator=(tDataType *data) noexcept

Assign shared data.

Parameters:

data – A newly allocated data object, or nullptr.

inline bool operator==(const SharedDataPointer &other) const noexcept

Compare if two pointers reference the same data object.

Parameters:

other – The pointer to compare with.

Returns:

true if both pointers reference the same data object.

inline bool operator!=(const SharedDataPointer &other) const noexcept

Compare if two pointers reference different data objects.

Parameters:

other – The pointer to compare with.

Returns:

true if the pointers reference different data objects.

inline void detach()

Detach the data from the shared instance.

If this pointer is null or already uniquely owns its data, this function does nothing. Otherwise, it clones the current data object, references the clone, and releases the old data.

inline tDataType *get()

Get the pointer to the data.

Automatically detaches shared data unless manual detach mode is enabled.

Returns:

A mutable pointer to the managed data, or nullptr.

inline const tDataType *get() const noexcept

Get a const pointer to the data.

Returns:

A const pointer to the managed data, or nullptr.

inline const tDataType *constGet() const noexcept

Get the pointer to the data, always const.

Returns:

A const pointer to the managed data, or nullptr.

inline void reset(tDataType *data = nullptr) noexcept

Set the shared data to another instance.

The new data receives one reference. The previously managed data is released and destroyed if this pointer held the last reference.

Parameters:

data – A newly allocated data object, or nullptr.

inline void swap(SharedDataPointer &other) noexcept

Swap two shared data pointers.

Parameters:

other – The pointer to swap with.

inline bool isNull() const noexcept

Check if this is a null pointer.

Returns:

true if this pointer does not manage data.

inline bool isShared() const noexcept

Check if the referenced data is shared with other pointers.

Returns:

true if the managed data has more than one reference.

inline uint32_t useCount() const noexcept

Get the current reference count for the referenced data.

Returns:

The reference count, or zero for a null pointer.

inline std::size_t storageId() const noexcept

Get a unique ID for the shared data.

inline tDataType &operator*()

Access the managed data as a mutable reference.

Automatically detaches shared data unless manual detach mode is enabled.

Returns:

A mutable reference to the managed data.

inline const tDataType &operator*() const noexcept

Access the managed data as a const reference.

Returns:

A const reference to the managed data.

inline tDataType *operator->()

Access the managed data as a mutable pointer.

Automatically detaches shared data unless manual detach mode is enabled.

Returns:

A mutable pointer to the managed data.

inline const tDataType *operator->() const noexcept

Access the managed data as a const pointer.

Returns:

A const pointer to the managed data.

inline explicit operator tDataType*()

Convert to a mutable raw pointer.

Automatically detaches shared data unless manual detach mode is enabled.

Returns:

A mutable pointer to the managed data, or nullptr.

inline explicit operator const tDataType*() const noexcept

Convert to a const raw pointer.

Returns:

A const pointer to the managed data, or nullptr.

Friends

inline friend void swap(SharedDataPointer &a, SharedDataPointer &b) noexcept

Swap two shared data pointers.

Parameters:
  • a – The first pointer.

  • b – The second pointer.

class SharedVirtualData : public erbsland::mem::SharedData

Base class for polymorphic shared data.

Derive from this class when a SharedDataPointer shall manage an abstract base type and detach by virtual clone. Implementations must return a newly allocated copy of the same dynamic type from clone().

See: Memory and Byte Data

Subclassed by erbsland::cryptology::impl::X509CertificateData, erbsland::text::impl::AnyStringBuilderBase, erbsland::text::impl::StringReaderBase

Public Functions

virtual ~SharedVirtualData() = default

Destroy this virtual shared data.

virtual SharedVirtualData *clone() const = 0

Create an unreferenced polymorphic copy of this data.

class StorageIdentifier

A stable identifier for a backend storage range.

This identifier is meant for identity checks, not for ordering by content. It identifies a backend storage range without exposing the memory addresses used to derive it.

See: Memory and Byte Data

Public Functions

constexpr StorageIdentifier() noexcept = default

Create an empty identifier.

inline constexpr std::strong_ordering operator<=>(const StorageIdentifier &other) const noexcept

Compare two identifiers.

inline constexpr bool operator==(const StorageIdentifier &other) const noexcept

Test if two identifiers are equal.

inline constexpr bool operator!=(const StorageIdentifier &other) const noexcept

Test if two identifiers differ.

inline constexpr bool isEmpty() const noexcept

Test if this identifier is empty.

inline constexpr std::array<uint64_t, 2> toRawValues() const noexcept

Return the mixed identity values.

Public Static Functions

static inline StorageIdentifier fromMemoryRange(const void *begin, const void *end) noexcept

Create an identifier from the first and one-past-last address of a visible storage range.

using erbsland::mem::UnsafeConstCharPtr = const char*

An unsafe pointer to a character segment.

using erbsland::mem::UnsafeCharPtr = char*

An unsafe pointer to a character segment.

using erbsland::mem::UnsafeConstChar8Ptr = const char8_t*

An unsafe pointer to a character segment.

using erbsland::mem::UnsafeChar8Ptr = char8_t*

An unsafe pointer to a character segment.

using erbsland::mem::UnsafeConstMemoryPtr = const void*

Marks an unsafe pointer to a memory segment.

Note

If you see one of those, … run!

using erbsland::mem::UnsafeMemoryPtr = void*

Marks an unsafe pointer to a memory segment.

Note

If you see one of those, … run!