Units and Versions

Integer Indexes, Amounts, Offsets and Ranges

Representation and Construction

Include each concrete unit type through its own public header, such as <erbsland/ArgumentIndex.hpp> or <erbsland/ArgumentCount.hpp>. ArgumentUnit.hpp declares only the shared argument-unit tag.

Positional unit tags identify the coordinate system without configuring storage. Indexes and amounts use unsigned 64-bit values; offsets use signed 64-bit values. The largest unsigned value is reserved for noIndex() or infinite(). maximum() is always the largest finite value.

Numeric constructors are consteval: ByteIndex{12} and ByteIndex(12) both validate their input at compile time. Native integer types other than bool are accepted, but floating-point inputs, negative indexes or amounts, and numeric sentinel values are rejected. Negative offsets are valid, including the signed minimum. Default construction produces zero; copying typed values remains available at runtime.

For runtime integers, fromInteger(value) saturates into the finite domain and fromIntegerOrThrow(value) throws OverflowError outside that domain. Use noIndex() and infinite() explicitly to create special states. fromSizeT() and fromSizeTOrThrow() follow the same rules. Extraction through toSizeTOrThrow() checks representability only: it does not reject a sentinel that fits.

Movement and Distances

Move indexes by matching amounts with advance() and retreat(), or by signed offsets with move(). Their copy variants are advanced(), retreated(), and moved(). Regular movement saturates and preserves an absent index; OrThrow variants require exact finite movement. wouldAdvanceSaturate(), wouldRetreatSaturate(), and wouldMoveSaturate() detect failure of that exact operation. canAdvance(step, bounds), canRetreat(step, bounds), and canMove(offset, bounds) additionally require the result to lie within the supplied length. The starting index may be outside those bounds.

distanceFromZero() and absoluteDistanceTo() return non-negative amounts, using infinity for absent indexes. offsetFromZero() and offsetTo() return signed offsets, saturating when necessary; their OrThrow variants reject absent indexes and unrepresentable differences. mirroredWithin(length) returns length - index - 1 only for positions inside a finite length, otherwise no-index.

An amount’s remainingFrom(index) returns the length or count from an inclusive index to that amount’s exclusive end. Positions at or beyond the end return zero, as does noIndex(). An infinite amount returns infinity for every valid index and zero for noIndex(). For example, ByteCount{12}.remainingFrom(ByteIndex{5}) returns ByteCount{7}. The method accepts only the matching index family.

Index::last(length) returns the final included index of a finite, nonempty sequence measured from zero. For example, ByteIndex::last(ByteCount{8}) returns ByteIndex{7}. Zero and infinite lengths return noIndex() because they have no last element. Unlike Index::end(length).decremented(), the empty case does not saturate to index zero.

Ranges

A range stores an inclusive beginIndex() and a length; endIndex() is exclusive. Construction accepts either (begin, length) or (begin, end), including compact slicing such as text.slice({begin, end}). fromBeginEnd() provides the same endpoint semantics:

  • Ordered finite endpoints produce their difference.

  • Reversed finite endpoints produce an empty range at the beginning.

  • An absent beginning produces noRange().

  • A valid beginning and absent endpoint produce an open-ended range.

fromBeginEndOrThrow() rejects reversed endpoints and an absent beginning with OutOfRangeError; it accepts an open endpoint.

fromBegin(begin) stores the beginning directly and sets an infinite length. An absent beginning produces an absent, invalid range that retains its infinite length. The factory performs no checks or conversions.

isNoRange() tests an absent beginning. isEmpty() tests zero length independently of validity. isValid() requires a valid beginning and, for finite lengths, an exclusive endpoint at most Index::maximum(). An empty range at the maximum is valid; a finite one-element range beginning there is invalid. Open-ended ranges remain valid and include the maximum index. endIndex() returns no-index for invalid or open-ended ranges. lastIndex() returns the final included index, accounting for the range’s beginning. For example, ByteRange{ByteIndex{4}, ByteCount{3}}.lastIndex() returns ByteIndex{6}. Empty, infinite, and invalid ranges return noIndex().

Invalid ranges contain nothing, produce noRange() when clamped or translated, and return LoopResult::Error from forEach(). Open-ended iteration visits representable indexes through the maximum without wrapping. Saturating movement preserves length and keeps a valid range valid by limiting its beginning to maximum() - length() for finite ranges. Throwing movement variants reject invalid input or required saturation.

toAbsolute(origin) adds an origin; relativeTo(origin) subtracts it. Both preserve length exactly and return noRange() for invalid input, overflow, or subtraction below zero. intersection(other) returns the common range, an empty range at the later beginning if disjoint or touching, or noRange() if either operand is invalid. Open endpoints are treated as unbounded. contains(otherRange) requires both ranges to be valid. An empty range is contained at either boundary; a finite range never contains an open-ended range.

remainingFrom(index) returns the suffix beginning at an absolute index in the range’s coordinate system. An index before or at the beginning returns the original range; one at or beyond a finite end returns an empty range at that end. Open-ended ranges retain their infinite length. An absent index or invalid range returns noRange(). For example, ByteRange{ByteIndex{4}, ByteCount{8}}.remainingFrom(ByteIndex{7}) represents [7, 12).

Scalar Arithmetic

Integer unit lengths and offsets support scalar multiplication, division and modulo while preserving their unit type. Lengths require unsigned scalar operands. Offsets require signed scalar operands. Scalar operands may be native integer types or SaturatingInteger values.

Unit values are not multiplied, divided or modulo-applied with other unit values. Indexes also keep their stricter domain model and can only be moved with matching lengths and offsets. Unchecked Operations and Iteration ———————————-

Use T{rawValue, T::Unchecked{}} when the native value is already proven representable. The constructor stores the raw representation directly, including the reserved sentinel representation. It does not validate narrowing or signed-to-unsigned conversion before construction. Keep runtime factories at boundaries where negative values, overflow, or numeric sentinels remain possible.

Indexes provide uncheckedAdvance(), uncheckedRetreat(), uncheckedMove(), uncheckedIncrement(), and uncheckedDecrement(), plus the copy variants ending in Advanced, Retreated, Moved, Incremented, and Decremented. Amounts provide uncheckedAdd(), uncheckedSubtract(), their copy variants uncheckedAdded() and uncheckedSubtracted(), and uncheckedIncrement() and uncheckedDecrement(). These operations require finite operands and an exactly representable finite result. Use them inside loops whose enclosing buffer or range checks already establish those bounds.

amount.forEach(function) visits indexes from zero up to the exclusive amount bound. An infinite amount returns LoopResult::Error without invoking the callback. range.forEach(function) visits the range’s indexes after validating the range once. Both capture their original bounds, use raw increments internally, and accept callbacks returning void or LoopStatus. Continue proceeds, Stop returns LoopResult::Stopped, and Error returns LoopResult::Error. An empty valid iteration returns LoopResult::Success without calling the function. Exceptions from callbacks propagate to the caller.

Scalar Limits

Finite length multiplication saturates at the largest finite length. Infinite lengths remain infinite for scalar multiplication, division and modulo. Division and modulo by zero terminate, matching the saturating integer helpers.

Integer Amounts

IntegerAmount stores a signed saturating count with a unit tag and a scale. Construction accepts signed counts; unsigned construction is deleted. Comparison, addition, and subtraction require the exact same amount type. Signed scalar multiplication, division, and remainder preserve the amount type; division and remainder by zero terminate. Arithmetic saturates, including negation of the minimum value to the maximum. Increment and decrement change the count by one and saturate at the bounds.

Compatible conversion requires a shared unit tag and a supported scale ratio. converted<T>() saturates on overflow and truncates division toward zero. wouldConvertSaturate<T>() and convertedOrThrow<T>() check overflow, without rejecting discarded remainders. toRawValue() returns the native count; toValue() returns its saturating integer wrapper. The Interface section below gives the remaining helpers for extraction, clamping, absolute values, and factories. See Working with Typed Time Amounts for practical construction, conversion, and arithmetic with the time aliases.

Version

Introduction

Version stores a four-part version as major, minor, revision, and build number. The default value is 0.0.0.0. You can construct versions from raw part values or from typed part values in any order:

auto api = el::Version{1, 2, 0};
auto selected = el::Version{el::Major{13}, el::Revision{2}}

Parsing

fromString() accepts one to four decimal parts separated by dots. Each part must contain digits only, have no leading zeros unless it is zero, and fit in an unsigned 16-bit value. Whitespace, signs, and trailing characters are invalid. The requiredPrecision argument sets the least significant part that must be present; omitted parts become zero. Invalid text returns std::nullopt. Use fromStringOrThrow() to receive an err::ParseError instead.

Precision

compare() accepts a VersionPart as precision. The selected part is the last compared part. For example, minor precision compares major and minor, while revision and build are ignored.

Numeric Representation

toNumber() packs the four 16-bit parts into a uint64_t as major << 48 | minor << 32 | revision << 16 | build. This keeps numeric ordering identical to full version ordering.

Version Part

VersionPart identifies the part of a Version. It is also used as comparison precision: the selected part is included, and less-significant parts are ignored.

Version Range

VersionRange stores optional inclusive minimum and maximum version bounds. Missing bounds are open-ended, so a default range contains every version.

Containment uses the same precision rules as Version::compare. If both bounds are present and the minimum is greater than the maximum at the selected precision, the range is empty.

Common Ranges

Use all() for an open range, atLeast() for a lower-bounded range, atMost() for an upper-bounded range, between() for inclusive minimum and maximum bounds, and exact() for a single version.

Version Components

VersionComponent<VersionPart> represents an independent unsigned 16-bit version field. Use the distinct aliases Major, Minor, Revision, and BuildNumber. Each accepts the full range 0–65535 and has no index or infinity state.

Compile-time integer construction and runtime fromInteger() / fromIntegerOrThrow() follow the unit construction rules, with 65535 as the finite maximum. Components support comparison, hashing, formatting, saturating increment and decrement, and unsigned scalar addition and subtraction. addedOrThrow() and subtractedOrThrow() reject results outside the component range; matching mutating variants are also available.

The raw numeric Version constructor validates constants at compile time. For runtime values, construct typed components with the appropriate runtime factories and pass those to Version. Parsing and packed 64-bit representation retain their existing format.

Interface

using erbsland::unit::ArgumentCount = IntegerUnitCount<ArgumentUnit>

A non-negative number of arguments.

using erbsland::unit::ArgumentIndex = IntegerUnitIndex<ArgumentUnit>

A zero-based argument index.

struct ArgumentUnit : public erbsland::unit::IntegerUnit

The integer unit for argument types.

using erbsland::unit::BuildNumber = VersionComponent<VersionPart::Build>

The buildnumber component of a version.

using erbsland::unit::ByteCount = IntegerUnitCount<ByteUnit>

A non-negative count of bytes.

using erbsland::unit::ByteIndex = IntegerUnitIndex<ByteUnit>

A byte-based index.

using erbsland::unit::ByteOffset = IntegerUnitOffset<ByteUnit>

A byte-based offset.

using erbsland::unit::ByteRange = IntegerUnitRange<ByteUnit>

A byte-based range.

struct ByteUnit : public erbsland::unit::IntegerUnit

The integer unit for byte-based types.

struct CodeContinuousRange

A continuous source code range with an exclusive end location.

Public Members

CodeLocation begin

The inclusive begin location.

CodeLocation end

The exclusive end location.

class CodeLocation

A source code location with optional line, column and code-point position.

Public Functions

constexpr CodeLocation() noexcept = default

Create an undefined code location.

inline constexpr CodeLocation(LineIndex line, ColumnIndex column = ColumnIndex::noIndex(), CpIndex position = CpIndex::noIndex()) noexcept

Create a code location from its optional components.

inline constexpr LineIndex line() const noexcept

Get the zero-based line index.

inline constexpr CodeLocation &setLine(LineIndex line) noexcept

Set the zero-based line index.

inline constexpr ColumnIndex column() const noexcept

Get the zero-based column index.

inline constexpr CodeLocation &setColumn(ColumnIndex column) noexcept

Set the zero-based column index.

inline constexpr CpIndex position() const noexcept

Get the zero-based absolute code-point position.

inline constexpr CodeLocation &setPosition(CpIndex position) noexcept

Set the zero-based absolute code-point position.

bool operator==(const CodeLocation&) const noexcept = default

Compare two locations.

bool isUndefined() const noexcept

Test if no location component is defined.

void nextLine() noexcept

Advance to the first character of the next line.

void nextColumn() noexcept

Advance to the next character in the current line.

text::String toString() const noexcept

Format the known location in one-based, human-readable form.

using erbsland::unit::ColumnCount = IntegerUnitCount<ColumnUnit>

A source code column count.

using erbsland::unit::ColumnIndex = IntegerUnitIndex<ColumnUnit>

A zero-based source code column index.

using erbsland::unit::ColumnOffset = IntegerUnitOffset<ColumnUnit>

A signed source code column offset.

using erbsland::unit::ColumnRange = IntegerUnitRange<ColumnUnit>

A range of source code columns.

struct ColumnUnit : public erbsland::unit::IntegerUnit

The integer unit for source code column types.

using erbsland::unit::CpCount = IntegerUnitCount<CpUnit>

A non-negative count of Unicode code points.

using erbsland::unit::CpIndex = IntegerUnitIndex<CpUnit>

A Unicode code-point-based index.

using erbsland::unit::CpOffset = IntegerUnitOffset<CpUnit>

A Unicode code-point-based offset.

using erbsland::unit::CpRange = IntegerUnitRange<CpUnit>

A Unicode code-point-based range.

struct CpUnit : public erbsland::unit::IntegerUnit

The integer unit Unicode code-point-based types.

class ExitCode

Represents an exit code for a program.

Public Types

using Value = int32_t

The raw exit-code value type.

Public Functions

inline explicit constexpr ExitCode(const Value exitCode)

Create an exit code from a given generic integer value.

inline bool isSuccess() const noexcept

Test if the exit-code is zero.

inline bool isFailure() const noexcept

Test if the exit-code is not zero.

inline bool isZero() const noexcept

Test if the exit-code is zero.

inline bool isOne() const noexcept

Test if the exit-code is one.

inline bool isMinimum() const noexcept

Test if the exit-code is at its minimum value.

inline bool isMaximum() const noexcept

Test if the exit-code is at its maximum value.

inline bool isValidPosix() const noexcept

Test if the exit code is in valid POSIX range.

inline bool isRecommendedPosix() const noexcept

Test if the exit code is in the recommended POSIX range.

inline Value toRawValue() const noexcept

Access the raw underlying value.

inline ExitCode toRecommendedPosix() const noexcept

Convert the exit code to the recommended POSIX range.

Public Static Functions

static inline constexpr ExitCode success() noexcept

Get a zero exit-code, indicating success.

static inline constexpr ExitCode failure() noexcept

Get a one exit-code, indicating a generic failure.

static inline constexpr ExitCode zero() noexcept

Get a zero exit-code.

static inline constexpr ExitCode one() noexcept

Get a one exit-code.

static inline constexpr ExitCode minimum() noexcept

Get the minimum possible exit code.

static inline constexpr ExitCode maximum() noexcept

get the maximum possible exit code.

template<typename tUnit, typename tRatio, typename tValue>
class IntegerAmount

A signed integer amount in a ratio-scaled unit.

This type is intended for values such as seconds, milliseconds, meters, or kilometers where signed arithmetic, ratio conversion, and saturating integer behavior are desired.

See: Units and Versions

Template Parameters:
  • tUnit – The unit tag that prevents accidental mixing with unrelated amounts.

  • tRatio – The ratio of this amount to its base unit.

  • tValue – The signed saturating integer type used to store the amount.

Public Types

using Unit = tUnit

The unit tag.

using Ratio = tRatio

The ratio to the base unit.

using Value = tValue

The saturating integer value type.

using NativeValue = math::NativeIntegerOfT<Value>

The native signed integer type wrapped by Value.

Public Functions

constexpr IntegerAmount() noexcept = default

Create a zero amount.

inline explicit constexpr IntegerAmount(Value value) noexcept

Create an amount from a saturating integer value.

inline explicit constexpr IntegerAmount(NativeValue value) noexcept

Create an amount from a native signed integer value.

template<impl::SignedIntegerAmountOperand tOther>
inline explicit constexpr IntegerAmount(tOther value) noexcept

Create an amount from another signed integer operand, saturating if needed.

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

Compare this amount with another amount of the exact same type.

inline IntegerAmount operator+(IntegerAmount other) const noexcept

Add another amount, saturating on overflow.

inline IntegerAmount &operator+=(IntegerAmount other) noexcept

Add another amount in place, saturating on overflow.

inline IntegerAmount operator-(IntegerAmount other) const noexcept

Subtract another amount, saturating on underflow.

inline IntegerAmount &operator-=(IntegerAmount other) noexcept

Subtract another amount in place, saturating on underflow.

inline IntegerAmount operator-() const noexcept

Return the negated amount, saturating the minimum value to the maximum value.

inline IntegerAmount &operator++() noexcept

Increment this amount by one, saturating at maximum().

inline IntegerAmount operator++(int) noexcept

Increment this amount by one and return the previous value.

inline IntegerAmount &operator--() noexcept

Decrement this amount by one, saturating at minimum().

inline IntegerAmount operator--(int) noexcept

Decrement this amount by one and return the previous value.

template<impl::SignedIntegerAmountOperand tFactor>
inline IntegerAmount operator*(tFactor factor) const noexcept

Multiply this amount by a signed integer factor.

template<impl::SignedIntegerAmountOperand tFactor>
inline IntegerAmount &operator*=(tFactor factor) noexcept

Multiply this amount in place by a signed integer factor.

template<impl::SignedIntegerAmountOperand tDivisor>
inline IntegerAmount operator/(tDivisor divisor) const noexcept

Divide this amount by a signed integer divisor.

template<impl::SignedIntegerAmountOperand tDivisor>
inline IntegerAmount &operator/=(tDivisor divisor) noexcept

Divide this amount in place by a signed integer divisor.

template<impl::SignedIntegerAmountOperand tModulus>
inline IntegerAmount operator%(tModulus modulus) const noexcept

Modulo this amount by a signed integer factor.

template<impl::SignedIntegerAmountOperand tModulus>
inline IntegerAmount &operator%=(tModulus modulus) noexcept

Modulo an amount by another amount.

inline constexpr bool isZero() const noexcept

Test if this amount is zero.

inline constexpr bool isOne() const noexcept

Test if this amount is one.

inline constexpr bool isMinusOne() const noexcept

Test if this amount is minus one.

inline constexpr bool isPositive() const noexcept

Test if this amount is positive.

inline constexpr bool isNegative() const noexcept

Test if this amount is negative.

inline constexpr bool isMinimum() const noexcept

Test if this amount has the minimum representable value.

inline constexpr bool isMaximum() const noexcept

Test if this amount has the maximum representable value.

inline constexpr bool wouldAddSaturate(const IntegerAmount &other) const noexcept

Test if adding would saturate.

inline constexpr bool wouldSubtractSaturate(const IntegerAmount &other) const noexcept

Test if subtracting would saturate.

template<impl::SignedIntegerAmountOperand tFactor>
inline constexpr bool wouldMultiplySaturate(const tFactor &other) const noexcept

Test if multiplying would saturate.

inline constexpr NativeValue toRawValue() const noexcept

Access the raw native signed integer value.

inline constexpr Value toValue() const noexcept

Access the saturating integer value.

inline constexpr std::strong_ordering compare(const IntegerAmount &other) const noexcept

Compare this amount with another amount of the exact same type.

inline IntegerAmount<Unit, std::ratio<1>, Value> toBaseUnit() const noexcept

Convert this amount to the base unit for its unit tag.

inline IntegerAmount<Unit, std::ratio<1>, Value> toBaseUnitOrThrow() const

Convert this amount to the base unit for its unit tag.

Throws:

err::OverflowError – if the conversion would saturate.

template<typename tTarget>
inline bool wouldConvertSaturate() const noexcept

Test if conversion to another ratio with the same unit tag would saturate.

template<typename tTarget>
inline tTarget converted() const noexcept

Convert this amount to another ratio with the same unit tag.

template<typename tTarget>
inline tTarget convertedOrThrow() const

Convert this amount to another ratio with the same unit tag.

Throws:

err::OverflowError – if the conversion would saturate.

template<typename tTarget>
inline tTarget convert() const noexcept

Compatibility alias for converted.

template<typename tTarget>
inline tTarget convertOrThrow() const

Compatibility alias for convertedOrThrow.

Throws:

err::OverflowError – if the conversion would saturate.

template<typename tTarget>
inline tTarget extract() noexcept

Extract a larger whole unit and keep the signed remainder in this amount.

inline IntegerAmount negated() const noexcept

Return the negated amount, saturating the minimum value to the maximum value.

inline void negate() noexcept

Negate this amount in place, saturating the minimum value to the maximum value.

inline IntegerAmount clamped(IntegerAmount first, IntegerAmount last) const noexcept

Return this amount clamped to the given inclusive range.

inline void clamp(IntegerAmount first, IntegerAmount last) noexcept

Clamp this amount to the given inclusive range.

inline IntegerAmount toAbsolute() const noexcept

Return the absolute value of this amount.

Public Static Functions

static inline constexpr IntegerAmount zero() noexcept

Return the zero amount.

static inline constexpr IntegerAmount one() noexcept

Return the amount one.

static inline constexpr IntegerAmount minusOne() noexcept

Return the amount minus one.

static inline constexpr IntegerAmount minimum() noexcept

Return the smallest representable amount.

static inline constexpr IntegerAmount maximum() noexcept

Return the largest representable amount.

static inline constexpr std::intmax_t ratioNumerator() noexcept

Return the ratio numerator.

static inline constexpr std::intmax_t ratioDenominator() noexcept

Return the ratio denominator.

static inline constexpr bool isBaseUnit() noexcept

Test if this amount is measured in the base unit.

Public Static Attributes

static constexpr auto cIsIntegerAmount = true

Marker used by concepts to identify integer amount types.

Friends

template<impl::SignedIntegerAmountOperand tFactor>
inline friend IntegerAmount operator*(tFactor factor, IntegerAmount amount) noexcept

Multiply a signed integer factor by an amount.

struct IntegerUnit

The tag base for positional integer units.

Subclassed by erbsland::cterm::BlockUnit, erbsland::unit::ArgumentUnit, erbsland::unit::ByteUnit, erbsland::unit::ColumnUnit, erbsland::unit::CpUnit, erbsland::unit::ItemUnit, erbsland::unit::LineUnit, erbsland::unit::U16Unit

template<impl::ValidIntegerUnit tIntegerUnit>
class IntegerUnitCount

A non-negative count with an integer unit.

See: Units and Versions

Template Parameters:

tIntegerUnit – The integer unit for this count.

Public Types

using Value = uint64_t

The raw unsigned integer type.

using Unit = tIntegerUnit

The unit type.

Public Functions

constexpr IntegerUnitCount() noexcept = default

Create a zero length.

template<math::NativeInteger T>
inline explicit consteval IntegerUnitCount(T value)

Construct a finite value from a compile-time integer.

Parameters:

value – An integer within the finite domain; invalid values fail compilation.

inline constexpr IntegerUnitCount(const Value value, Unchecked) noexcept

Construct directly from a raw representation without conversion or range checks.

The caller must ensure the input fits Value before conversion and represents the intended finite or special state.

Parameters:

value – The raw unsigned integer value.

inline constexpr IntegerUnitCount operator+(const IntegerUnitCount other) const noexcept

Add another length and return the saturated result.

inline constexpr IntegerUnitCount &operator+=(const IntegerUnitCount other) noexcept

Add another length to this length with saturation.

inline constexpr IntegerUnitCount operator-(const IntegerUnitCount other) const noexcept

Subtract another length and return the saturated result.

inline constexpr IntegerUnitCount &operator-=(const IntegerUnitCount other) noexcept

Subtract another length from this length with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount operator*(T scalar) const noexcept

Multiply this length by an unsigned scalar and return the saturated result.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &operator*=(T scalar) noexcept

Multiply this length by an unsigned scalar with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount operator/(T scalar) const noexcept

Divide this length by an unsigned scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &operator/=(T scalar) noexcept

Divide this length by an unsigned scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount operator%(T scalar) const noexcept

Calculate the modulo of this length and an unsigned scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &operator%=(T scalar) noexcept

Apply modulo with an unsigned scalar.

inline constexpr IntegerUnitCount &operator++() noexcept

Increment this length by one with saturation.

inline constexpr IntegerUnitCount operator++(int) noexcept

Increment this length by one with saturation and return the previous value.

inline constexpr IntegerUnitCount &operator--() noexcept

Decrement this length by one with saturation.

inline constexpr IntegerUnitCount operator--(int) noexcept

Decrement this length by one with saturation and return the previous value.

inline constexpr bool isZero() const noexcept

Test if this length is zero.

inline constexpr bool isOne() const noexcept

Test if this length is one.

inline constexpr bool isMinimum() const noexcept

Test if this length has the minimum value.

inline constexpr bool isMaximum() const noexcept

Test if this length has the largest finite value.

inline constexpr bool isInfinite() const noexcept

Test if this length has the infinite value.

inline constexpr bool isFinite() const noexcept

Test if this length has a finite value.

inline constexpr Value toRawValue() const noexcept

Access the raw value of this length.

inline constexpr auto remainingFrom(const IntegerUnitIndex<tIntegerUnit> index) const noexcept -> IntegerUnitCount

Return the amount remaining from an index measured from zero.

An absent index or a position at or beyond the end returns zero, including noIndex() for infinite amounts.

Parameters:

index – The inclusive beginning of the remaining amount.

Returns:

The remaining amount, or infinite for a valid index within an infinite amount.

inline constexpr IntegerUnitCount &add(const IntegerUnitCount other) noexcept

Add another length, saturating at the largest finite length or infinite length.

If either operand is infinite, the result is infinite.

inline constexpr IntegerUnitCount added(const IntegerUnitCount other) const noexcept

Create a new length by adding another length to it.

If either operand is infinite, the result is infinite.

inline constexpr IntegerUnitCount &addOrThrow(const IntegerUnitCount other)

Add another length.

Throws:

OverflowError – if either operand is infinite or the finite result exceeds maximum().

inline constexpr IntegerUnitCount addedOrThrow(const IntegerUnitCount other) const

Create a new length by adding another length to it.

Throws:

OverflowError – if either operand is infinite or the finite result exceeds maximum().

inline constexpr IntegerUnitCount &subtract(const IntegerUnitCount other) noexcept

Subtract another length, saturating at zero.

If this length is infinite, it remains infinite. Subtracting infinite from a finite length produces zero.

inline constexpr IntegerUnitCount subtracted(const IntegerUnitCount other) const noexcept

Create a new length by subtracting another length from it.

If this length is infinite, the result is infinite. Subtracting infinite from a finite length produces zero.

inline constexpr IntegerUnitCount &subtractOrThrow(const IntegerUnitCount other)

Subtract another length.

Throws:

OverflowError – if either operand is infinite or the finite result would be below zero.

inline constexpr IntegerUnitCount subtractedOrThrow(const IntegerUnitCount other) const

Create a new length by subtracting another length from it.

Throws:

OverflowError – if either operand is infinite or the finite result would be below zero.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &multiply(T scalar) noexcept

Multiply this length by an unsigned scalar with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount multiplied(T scalar) const noexcept

Create a new length by multiplying this length with an unsigned scalar.

Infinite lengths stay infinite.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &divide(T scalar) noexcept

Divide this length by an unsigned scalar.

Infinite lengths stay infinite.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount divided(T scalar) const noexcept

Create a new length by dividing this length by an unsigned scalar.

Infinite lengths stay infinite.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount &applyModulo(T scalar) noexcept

Apply modulo with an unsigned scalar.

Infinite lengths stay infinite.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitCount modulo(T scalar) const noexcept

Calculate the modulo of this length and an unsigned scalar.

Infinite lengths stay infinite.

inline constexpr IntegerUnitCount &increment() noexcept

Increment this length by one, preserving infinity and saturating at the finite bounds.

inline constexpr IntegerUnitCount &decrement() noexcept

Decrement this length by one, preserving infinity and saturating at the finite bounds.

inline constexpr IntegerUnitCount &uncheckedAdd(const IntegerUnitCount other) noexcept

Add a length without checks; both operands and the result must be finite and representable.

Parameters:

other – The length to add.

inline constexpr IntegerUnitCount uncheckedAdded(const IntegerUnitCount other) const noexcept

Return the exact result without checks; both operands and the result must be finite and representable.

Parameters:

other – The length to add.

Returns:

The exact result.

inline constexpr IntegerUnitCount &uncheckedSubtract(const IntegerUnitCount other) noexcept

Subtract a length without checks; both operands and the result must be finite and representable.

Parameters:

other – The length to subtract.

inline constexpr IntegerUnitCount uncheckedSubtracted(const IntegerUnitCount other) const noexcept

Return the exact result without checks; both operands and the result must be finite and representable.

Parameters:

other – The length to subtract.

Returns:

The exact result.

inline constexpr IntegerUnitCount &uncheckedIncrement() noexcept

Increment without checks; this length and the result must be finite and representable.

inline constexpr IntegerUnitCount &uncheckedDecrement() noexcept

Decrement without checks; this length and the result must be finite and representable.

inline constexpr std::size_t toSizeT() const noexcept

Convert this length to std::size_t, saturating if the raw value is too large.

inline constexpr std::size_t toSizeTOrThrow() const

Convert this length to std::size_t.

Throws:

OverflowError – if the raw value does not fit into std::size_t.

template<typename Fn>
inline util::LoopResult forEach(Fn &&loopFn) const

Call a function for each index in this range.

Raw index values are incremented internally, avoiding saturation checks for every step.

Parameters:

loopFn – The function to call with each index. It may return void or util::LoopStatus.

Returns:

The result of the loop.

Public Static Functions

static inline constexpr IntegerUnitCount zero() noexcept

Return the zero length.

static inline constexpr IntegerUnitCount one() noexcept

Return the length one.

static inline constexpr IntegerUnitCount minimum() noexcept

Return the smallest finite length.

static inline constexpr IntegerUnitCount maximum() noexcept

Return the largest finite length.

static inline constexpr IntegerUnitCount infinite() noexcept

Return the special infinite length.

static inline constexpr IntegerUnitCount fromSizeT(std::size_t value) noexcept

Create a finite value from a native size, saturating at maximum().

static inline constexpr IntegerUnitCount fromSizeTOrThrow(std::size_t value)

Create a finite value from a native size.

Throws:

err::OverflowError – if the value exceeds maximum().

template<math::NativeInteger T>
static inline constexpr IntegerUnitCount fromInteger(T value) noexcept

Convert an integer, saturating into the finite domain.

Parameters:

value – The integer to convert.

Returns:

The bounded finite value.

template<math::NativeInteger T>
static inline constexpr IntegerUnitCount fromIntegerOrThrow(T value)

Convert an integer exactly into the finite domain.

Parameters:

value – The integer to convert.

Throws:

err::OverflowError – if value is outside the finite domain.

Returns:

The finite value.

Public Static Attributes

static constexpr Value cRawInfinite = std::numeric_limits<Value>::max()

The raw value used for the special infinite length.

static constexpr Value cRawMaximum = cRawInfinite - 1U

The largest finite raw value.

struct Unchecked

Tag for unchecked construction.

template<impl::ValidIntegerUnit tIntegerUnit>
class IntegerUnitIndex

An integer index with a unit.

See: Units and Versions

Template Parameters:

tIntegerUnit – The integer unit for this index.

Public Types

using Value = uint64_t

The raw unsigned integer type.

using Unit = tIntegerUnit

The unit type.

using Count = IntegerUnitCount<tIntegerUnit>

The matching count type.

using Offset = IntegerUnitOffset<tIntegerUnit>

The matching offset type.

Public Functions

constexpr IntegerUnitIndex() noexcept = default

Create a zero index.

template<math::NativeInteger T>
inline explicit consteval IntegerUnitIndex(T value)

Construct a finite value from a compile-time integer.

Parameters:

value – An integer within the finite domain; invalid values fail compilation.

inline constexpr IntegerUnitIndex(const Value value, Unchecked) noexcept

Construct directly from a raw representation without conversion or range checks.

The caller must ensure the input fits Value before conversion and represents the intended finite or special state.

Parameters:

value – The raw unsigned integer value.

inline constexpr IntegerUnitIndex operator+(const Count length) const noexcept

Advance this index by a length and return the saturated result.

inline constexpr IntegerUnitIndex &operator+=(const Count length) noexcept

Advance this index by a length with saturation.

inline constexpr IntegerUnitIndex operator-(const Count length) const noexcept

Retreat this index by a length and return the saturated result.

inline constexpr IntegerUnitIndex &operator-=(const Count length) noexcept

Retreat this index by a length with saturation.

inline constexpr IntegerUnitIndex operator+(const Offset offset) const noexcept

Move this index by an offset and return the saturated result.

inline constexpr IntegerUnitIndex &operator+=(const Offset offset) noexcept

Move this index by an offset with saturation.

inline constexpr IntegerUnitIndex operator-(const Offset offset) const noexcept

Move this index by the negated offset and return the saturated result.

inline constexpr IntegerUnitIndex &operator-=(const Offset offset) noexcept

Move this index by the negated offset with saturation.

inline constexpr IntegerUnitIndex &operator++() noexcept

Increment this index by one with saturation.

inline constexpr IntegerUnitIndex operator++(int) noexcept

Increment this index by one with saturation and return the previous value.

inline constexpr IntegerUnitIndex &operator--() noexcept

Decrement this index by one with saturation.

inline constexpr IntegerUnitIndex operator--(int) noexcept

Decrement this index by one with saturation and return the previous value.

inline constexpr bool isZero() const noexcept

Test if this index is zero.

inline constexpr bool isOne() const noexcept

Test if this index is one.

inline constexpr bool isMinimum() const noexcept

Test if this index is at its minimum.

inline constexpr bool isMaximum() const noexcept

Test if this index is at its largest valid value.

inline constexpr bool isNoIndex() const noexcept

Test if this index is the special no-index value.

inline constexpr bool isValid() const noexcept

Test if this index is a valid position.

inline constexpr bool isWithin(const Count length) const noexcept

Test if this index is a valid position within the given length.

inline constexpr bool wouldAdvanceSaturate(Count length) const noexcept

Test whether exact finite advance is impossible.

inline constexpr bool canAdvance(Count length, Count bounds) const noexcept

Test whether exact movement lands within bounds without saturation.

inline constexpr bool wouldRetreatSaturate(Count length) const noexcept

Test whether exact finite retreat is impossible.

inline constexpr bool canRetreat(Count length, Count bounds) const noexcept

Test whether exact movement lands within bounds without saturation.

inline constexpr bool wouldMoveSaturate(Offset offset) const noexcept

Test whether exact finite move is impossible.

inline constexpr bool canMove(Offset offset, Count bounds) const noexcept

Test whether exact movement lands within bounds without saturation.

inline constexpr Value toRawValue() const noexcept

Access the raw value of this index.

inline constexpr IntegerUnitIndex &advance(const Count length) noexcept

Advance this index by a non-negative length.

Saturates at maximum() and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex &advanceOrThrow(const Count length)

Advance this index by a non-negative length.

Throws:

OverflowError – if this index is noIndex() or the result would exceed maximum().

inline constexpr IntegerUnitIndex advanced(const Count length) const noexcept

Create a new index advanced by a non-negative length.

Saturates at maximum() and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex advancedOrThrow(const Count length) const

Create a new index advanced by a non-negative length.

Throws:

OverflowError – if this index is noIndex() or the result would exceed maximum().

inline constexpr IntegerUnitIndex &retreat(const Count length) noexcept

Retreat this index by a non-negative length.

Saturates at zero and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex &retreatOrThrow(const Count length)

Retreat this index by a non-negative length.

Throws:

OverflowError – if this index is noIndex() or the result would be before zero.

inline constexpr IntegerUnitIndex retreated(const Count length) const noexcept

Create a new index retreated by a non-negative length.

Saturates at zero and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex retreatedOrThrow(const Count length) const

Create a new index retreated by a non-negative length.

Throws:

OverflowError – if this index is noIndex() or the result would be before zero.

inline constexpr IntegerUnitIndex &move(const Offset offset) noexcept

Move this index by a signed offset.

Saturates at zero or maximum() and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex &moveOrThrow(const Offset offset)

Move this index by a signed offset.

Throws:

OverflowError – if this index is noIndex() or the result would be outside zero to maximum().

inline constexpr IntegerUnitIndex moved(const Offset offset) const noexcept

Create a new index moved by a signed offset.

Saturates at zero or maximum() and keeps noIndex() unchanged.

inline constexpr IntegerUnitIndex movedOrThrow(const Offset offset) const

Create a new index moved by a signed offset.

Throws:

OverflowError – if this index is noIndex() or the result would be outside zero to maximum().

inline constexpr IntegerUnitIndex &increment() noexcept

Increment this index by one.

inline constexpr IntegerUnitIndex &decrement() noexcept

Decrement this index by one.

inline constexpr IntegerUnitIndex incremented() const noexcept

Create a new index incremented by one.

inline constexpr IntegerUnitIndex decremented() const noexcept

Create a new index decremented by one.

inline constexpr IntegerUnitIndex &uncheckedAdvance(const Count length) noexcept

Advance this index without saturation; inputs must be finite and the result a valid index.

Parameters:

length – The exact movement, already checked by the caller.

inline constexpr IntegerUnitIndex uncheckedAdvanced(const Count length) const noexcept

Return an index moved without saturation; inputs must be finite and the result a valid index.

Parameters:

length – The exact movement, already checked by the caller.

Returns:

The exactly moved index.

inline constexpr IntegerUnitIndex &uncheckedRetreat(const Count length) noexcept

Retreat this index without saturation; inputs must be finite and the result a valid index.

Parameters:

length – The exact movement, already checked by the caller.

inline constexpr IntegerUnitIndex uncheckedRetreated(const Count length) const noexcept

Return an index moved without saturation; inputs must be finite and the result a valid index.

Parameters:

length – The exact movement, already checked by the caller.

Returns:

The exactly moved index.

inline constexpr IntegerUnitIndex &uncheckedMove(const Offset offset) noexcept

Move this index without saturation; inputs must be finite and the result a valid index.

Parameters:

offset – The exact movement, already checked by the caller.

inline constexpr IntegerUnitIndex uncheckedMoved(const Offset offset) const noexcept

Return an index moved without saturation; inputs must be finite and the result a valid index.

Parameters:

offset – The exact movement, already checked by the caller.

Returns:

The exactly moved index.

inline constexpr IntegerUnitIndex &uncheckedIncrement() noexcept

Increment this index without checks; this index and the result must be valid.

inline constexpr IntegerUnitIndex uncheckedIncremented() const noexcept

Return the adjacent index without checks; this index and the result must be valid.

Returns:

The exactly moved index.

inline constexpr IntegerUnitIndex &uncheckedDecrement() noexcept

Decrement this index without checks; this index and the result must be valid.

inline constexpr IntegerUnitIndex uncheckedDecremented() const noexcept

Return the adjacent index without checks; this index and the result must be valid.

Returns:

The exactly moved index.

inline constexpr IntegerUnitIndex mirroredWithin(Count length) const noexcept

Mirror a position within a finite length, or return noIndex() if outside it.

inline constexpr Count distanceFromZero() const noexcept

Get the distance from zero to this index.

Returns:

The distance from zero, or infinite if this index is noIndex().

inline constexpr Count absoluteDistanceTo(const IntegerUnitIndex &other) const noexcept

Get the absolute distance from this index to another index.

Returns:

The absolute distance, or infinite if either index is noIndex().

inline constexpr Offset offsetFromZero() const noexcept

Get the signed offset from zero to this index.

Returns:

The offset from zero, saturated to Offset::maximum() if this index is noIndex() or too large.

inline constexpr Offset offsetFromZeroOrThrow() const

Get the signed offset from zero to this index.

Throws:

OverflowError – if this index is noIndex() or the result does not fit into Offset.

inline constexpr Offset offsetTo(const IntegerUnitIndex &other) const noexcept

Get the signed offset from this index to another index.

Returns:

The directional offset, saturated to Offset::minimum() or Offset::maximum() if necessary. If either index is noIndex(), this returns Offset::maximum().

inline constexpr Offset offsetToOrThrow(const IntegerUnitIndex &other) const

Get the signed offset from this index to another index.

Throws:

OverflowError – if either index is noIndex() or the result does not fit into Offset.

inline constexpr std::size_t toSizeT() const noexcept

Convert this index to std::size_t, saturating if the raw value is too large.

inline constexpr std::size_t toSizeTOrThrow() const

Convert this index to std::size_t.

Throws:

OverflowError – if the raw value does not fit into std::size_t.

Public Static Functions

static inline auto fromGrid(const IntegerUnitIndex x, const IntegerUnitIndex y, const Count width, const Count height) noexcept -> IntegerUnitIndex

Create a grid index from row and column indices, bound to with and height of a grid.

A grid index is a sequential index that represents a position in a grid. If x or y are out of bounds, or any of the parameters is infinite or no index, returns noIndex.

Parameters:
  • x – The index in the x position.

  • y – The index in the y position.

  • width – The width of the grid.

  • height – The height of the grid.

Returns:

The grid index or noIndex if any parameter is invalid.

static inline constexpr IntegerUnitIndex minimum() noexcept

Return the smallest valid index.

static inline constexpr IntegerUnitIndex maximum() noexcept

Return the largest valid index.

static inline constexpr IntegerUnitIndex zero() noexcept

Return the zero index.

static inline constexpr IntegerUnitIndex one() noexcept

Return the index one.

static inline constexpr IntegerUnitIndex noIndex() noexcept

Return the special no-index value.

static inline constexpr IntegerUnitIndex end(const Count length) noexcept

Return the end index for a length measured from zero.

Infinite length is converted into noIndex().

static inline constexpr IntegerUnitIndex last(const Count length) noexcept

Return the last index within a length measured from zero.

Parameters:

length – The sequence length in the matching unit family.

Returns:

The final included index, or noIndex() for a zero or infinite length.

static inline constexpr IntegerUnitIndex fromSizeT(std::size_t value) noexcept

Create a finite value from a native size, saturating at maximum().

static inline constexpr IntegerUnitIndex fromSizeTOrThrow(std::size_t value)

Create a finite value from a native size.

Throws:

err::OverflowError – if the value exceeds maximum().

template<math::NativeInteger T>
static inline constexpr IntegerUnitIndex fromInteger(T value) noexcept

Convert an integer, saturating into the finite domain.

Parameters:

value – The integer to convert.

Returns:

The bounded finite value.

template<math::NativeInteger T>
static inline constexpr IntegerUnitIndex fromIntegerOrThrow(T value)

Convert an integer exactly into the finite domain.

Parameters:

value – The integer to convert.

Throws:

err::OverflowError – if value is outside the finite domain.

Returns:

The finite value.

Public Static Attributes

static constexpr Value cRawNoIndex = std::numeric_limits<Value>::max()

The raw value used for the special no-index state.

static constexpr Value cRawMaximum = cRawNoIndex - 1U

The largest valid raw index value.

Friends

inline friend void swap(IntegerUnitIndex &first, IntegerUnitIndex &second) noexcept

Swap two indexes.

struct Unchecked

Tag for unchecked construction.

template<impl::ValidIntegerUnit tIntegerUnit>
class IntegerUnitOffset

A signed offset with a unit tag.

An offset describes movement relative to an index. Positive offsets move forward, negative offsets move backward. Use IntegerUnitCount for non-negative spans and counts.

Template Parameters:

tIntegerUnit – The unit tag for this offset.

Public Types

using Value = int64_t

The raw signed integer type.

using Unit = tIntegerUnit

The unit type.

using Count = IntegerUnitCount<tIntegerUnit>

The matching count type.

Public Functions

constexpr IntegerUnitOffset() noexcept = default

Create a zero offset.

template<math::NativeInteger T>
inline explicit consteval IntegerUnitOffset(T value)

Construct a finite value from a compile-time integer.

Parameters:

value – An integer within the finite domain; invalid values fail compilation.

inline constexpr IntegerUnitOffset(const Value value, Unchecked) noexcept

Construct directly from a raw representation without conversion or range checks.

The caller must ensure the input fits Value before conversion and represents the intended finite or special state.

Parameters:

value – The raw signed integer value.

inline constexpr IntegerUnitOffset operator+(const IntegerUnitOffset other) const noexcept

Add another offset and return the saturated result.

inline constexpr IntegerUnitOffset &operator+=(const IntegerUnitOffset other) noexcept

Add another offset to this offset with saturation.

inline constexpr IntegerUnitOffset operator-(const IntegerUnitOffset other) const noexcept

Subtract another offset and return the saturated result.

inline constexpr IntegerUnitOffset &operator-=(const IntegerUnitOffset other) noexcept

Subtract another offset from this offset with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset operator*(T scalar) const noexcept

Multiply this offset by a signed scalar and return the saturated result.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &operator*=(T scalar) noexcept

Multiply this offset by a signed scalar with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset operator/(T scalar) const noexcept

Divide this offset by a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &operator/=(T scalar) noexcept

Divide this offset by a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset operator%(T scalar) const noexcept

Calculate the modulo of this offset and a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &operator%=(T scalar) noexcept

Apply modulo with a signed scalar.

inline constexpr IntegerUnitOffset operator-() const noexcept

Return this offset with the sign inverted, saturating minimum() to maximum().

inline constexpr IntegerUnitOffset &operator++() noexcept

Increment this offset by one with saturation.

inline constexpr IntegerUnitOffset operator++(int) noexcept

Increment this offset by one with saturation and return the previous value.

inline constexpr IntegerUnitOffset &operator--() noexcept

Decrement this offset by one with saturation.

inline constexpr IntegerUnitOffset operator--(int) noexcept

Decrement this offset by one with saturation and return the previous value.

inline constexpr bool isZero() const noexcept

Test if this offset is zero.

inline constexpr bool isOne() const noexcept

Test if this offset is one.

inline constexpr bool isMinusOne() const noexcept

Test if this offset is negative one.

inline constexpr bool isNegative() const noexcept

Test if this offset is less than zero.

inline constexpr bool isPositive() const noexcept

Test if this offset is greater than zero.

inline constexpr bool isMinimum() const noexcept

Test if this offset has the minimum value.

inline constexpr bool isMaximum() const noexcept

Test if this offset has the maximum value.

inline constexpr Value toRawValue() const noexcept

Access the raw value of this offset.

inline constexpr Count absoluteLength() const noexcept

Convert this offset into the matching non-negative length.

inline constexpr IntegerUnitOffset &add(const IntegerUnitOffset other) noexcept

Add another offset, saturating at minimum() or maximum().

inline constexpr IntegerUnitOffset added(const IntegerUnitOffset other) const noexcept

Create a new offset by adding another offset to it.

inline constexpr IntegerUnitOffset &addOrThrow(const IntegerUnitOffset other)

Add another offset.

Throws:

OverflowError – if the result would exceed minimum() or maximum().

inline constexpr IntegerUnitOffset addedOrThrow(const IntegerUnitOffset other) const

Create a new offset by adding another offset to it.

Throws:

OverflowError – if the result would exceed minimum() or maximum().

inline constexpr IntegerUnitOffset &subtract(const IntegerUnitOffset other) noexcept

Subtract another offset, saturating at minimum() or maximum().

inline constexpr IntegerUnitOffset subtracted(const IntegerUnitOffset other) const noexcept

Create a new offset by subtracting another offset from it.

inline constexpr IntegerUnitOffset &subtractOrThrow(const IntegerUnitOffset other)

Subtract another offset.

Throws:

OverflowError – if the result would exceed minimum() or maximum().

inline constexpr IntegerUnitOffset subtractedOrThrow(const IntegerUnitOffset other) const

Create a new offset by subtracting another offset from it.

Throws:

OverflowError – if the result would exceed minimum() or maximum().

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &multiply(T scalar) noexcept

Multiply this offset by a signed scalar with saturation.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset multiplied(T scalar) const noexcept

Create a new offset by multiplying this offset with a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &divide(T scalar) noexcept

Divide this offset by a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset divided(T scalar) const noexcept

Create a new offset by dividing this offset by a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset &applyModulo(T scalar) noexcept

Apply modulo with a signed scalar.

template<math::AnyIntegerType T>
inline constexpr IntegerUnitOffset modulo(T scalar) const noexcept

Calculate the modulo of this offset and a signed scalar.

inline constexpr IntegerUnitOffset negated() const noexcept

Create a new offset with the sign inverted, saturating the minimum value to maximum().

Public Static Functions

static inline constexpr IntegerUnitOffset zero() noexcept

Return the zero offset.

static inline constexpr IntegerUnitOffset one() noexcept

Return the offset one.

static inline constexpr IntegerUnitOffset minusOne() noexcept

Return the offset negative one.

static inline constexpr IntegerUnitOffset minimum() noexcept

Return the smallest offset.

static inline constexpr IntegerUnitOffset maximum() noexcept

Return the largest offset.

template<math::NativeInteger T>
static inline constexpr IntegerUnitOffset fromInteger(T value) noexcept

Convert an integer, saturating into the finite domain.

Parameters:

value – The integer to convert.

Returns:

The bounded finite value.

template<math::NativeInteger T>
static inline constexpr IntegerUnitOffset fromIntegerOrThrow(T value)

Convert an integer exactly into the finite domain.

Parameters:

value – The integer to convert.

Throws:

err::OverflowError – if value is outside the finite domain.

Returns:

The finite value.

Public Static Attributes

static constexpr Value cRawMinimum = std::numeric_limits<Value>::min()

The smallest raw offset value.

static constexpr Value cRawMaximum = std::numeric_limits<Value>::max()

The largest raw offset value.

struct Unchecked

Tag for unchecked construction.

template<impl::ValidIntegerUnit tIntegerUnit>
class IntegerUnitRange

A range with a unit tag.

See: Units and Versions

Template Parameters:

tIntegerUnit – The unit tag for this range.

Public Types

using Unit = tIntegerUnit

The unit type.

using Index = IntegerUnitIndex<tIntegerUnit>

The matching index type.

using Count = IntegerUnitCount<tIntegerUnit>

The matching count type.

using Offset = IntegerUnitOffset<tIntegerUnit>

The matching offset type.

Public Functions

constexpr IntegerUnitRange() noexcept = default

Create an empty range starting at zero.

inline constexpr IntegerUnitRange(Index index, Count length) noexcept

Create a range from a start index and length.

inline constexpr IntegerUnitRange(Index begin, Index end) noexcept

Create a range from a beginning and end index.

Reversed finite endpoints produce an empty range at begin. An absent begin produces noRange(). If the end index is “no index”, the length of the range is infinite. The end index is considered one after the last unit.

Parameters:
  • begin – The index that marks the first element.

  • end – The index after the last element, or no-index for infinite length.

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

Compare this range with another range.

inline constexpr IntegerUnitRange operator+(const Offset offset) const noexcept

Move this range by an offset and return the saturated result.

inline IntegerUnitRange &operator+=(const Offset offset) noexcept

Move this range by an offset with saturation.

inline constexpr IntegerUnitRange operator-(const Offset offset) const noexcept

Move this range by the negated offset and return the saturated result.

inline IntegerUnitRange &operator-=(const Offset offset) noexcept

Move this range by the negated offset with saturation.

inline constexpr bool isValid() const noexcept

Test whether this range is present and its finite exclusive endpoint is representable.

inline constexpr bool isNoRange() const noexcept

Test whether the beginning is absent.

inline constexpr bool isEmpty() const noexcept

Test if this range is empty.

inline constexpr bool isInfinite() const noexcept

Test if this range has an infinite length.

inline constexpr bool contains(const Index index) const noexcept

Test if this range contains the given index.

inline constexpr bool contains(const IntegerUnitRange other) const noexcept

Test whether another valid range lies wholly within this range, including empty endpoints.

inline constexpr IntegerUnitRange intersection(const IntegerUnitRange other) const noexcept

Return the common range, empty at the later beginning if disjoint, or noRange() for invalid input.

inline constexpr bool isWithin(const Count bounds) const noexcept

Test if this whole range fits within the given bounds length.

inline constexpr IntegerUnitRange clampedTo(const Count bounds) const noexcept

Return this range clamped to a sequence with the given bounds length.

Invalid ranges stay invalid. Ranges starting beyond the bounds become empty at the end of the bounds.

inline constexpr Index beginIndex() const noexcept

Get the start index of this range.

inline constexpr Count length() const noexcept

Get the length of this range.

inline constexpr void setBeginIndex(Index index) noexcept

Set the start index of this range.

inline constexpr void setLength(Count length) noexcept

Set the length of this range.

inline constexpr Index endIndex() const noexcept

Get the first index after this range.

If the range is invalid, infinite, or exceeds the representable index space, this returns Index::noIndex().

inline constexpr Index lastIndex() const noexcept

Get the final included index in this range’s coordinate system.

Returns:

The last index, or noIndex() if the range is empty, infinite, or invalid.

inline constexpr IntegerUnitRange remainingFrom(const Index index) const noexcept

Return the suffix beginning at an absolute index, clamped to this range.

Invalid ranges or an absent index produce noRange(); positions beyond a finite end produce emptyAt(end).

Parameters:

index – The inclusive beginning of the remaining range, in this range’s coordinate system.

Returns:

This range before its beginning, its suffix within it, or an empty range at its end.

inline constexpr IntegerUnitRange &advance(Count length) noexcept

Advance the whole range with saturation, preserving its length.

inline constexpr IntegerUnitRange advanced(Count length) const noexcept

Return a translated range with saturation, or noRange() for invalid input.

inline constexpr IntegerUnitRange &advanceOrThrow(Count length)

Advance the range without saturation.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange advancedOrThrow(Count length) const

Return an exactly translated range.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange &retreat(Count length) noexcept

Retreat the whole range with saturation, preserving its length.

inline constexpr IntegerUnitRange retreated(Count length) const noexcept

Return a translated range with saturation, or noRange() for invalid input.

inline constexpr IntegerUnitRange &retreatOrThrow(Count length)

Retreat the range without saturation.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange retreatedOrThrow(Count length) const

Return an exactly translated range.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange &move(Offset offset) noexcept

Move the whole range with saturation, preserving its length.

inline constexpr IntegerUnitRange moved(Offset offset) const noexcept

Return a translated range with saturation, or noRange() for invalid input.

inline constexpr IntegerUnitRange &moveOrThrow(Offset offset)

Move the range without saturation.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange movedOrThrow(Offset offset) const

Return an exactly translated range.

Throws:

err::OverflowError – for invalid input or an unrepresentable translation.

inline constexpr IntegerUnitRange toAbsolute(Index origin) const noexcept

Resolve relative coordinates at origin exactly, or return noRange() on failure.

inline constexpr IntegerUnitRange relativeTo(Index origin) const noexcept

Express absolute coordinates relative to origin exactly, or return noRange() on failure.

template<typename Fn>
inline util::LoopResult forEach(Fn &&loopFn) const

Call a function for each index in this range.

Raw index values are incremented internally, avoiding saturation checks for every step.

Parameters:

loopFn – The function to call with each index. It may return void or util::LoopStatus.

Returns:

The result of the loop.

Public Static Functions

static inline constexpr IntegerUnitRange fromBegin(const Index begin) noexcept

Construct an open-ended range by preserving the beginning and setting an infinite length.

Parameters:

begin – The inclusive beginning of the range.

Returns:

The range from begin to infinity; an absent beginning produces an absent range with infinite length.

static inline constexpr IntegerUnitRange fromBeginEnd(Index begin, Index end) noexcept

Construct a range from inclusive begin and exclusive end, using constructor semantics.

static inline constexpr IntegerUnitRange fromBeginEndOrThrow(Index begin, Index end)

Construct a range from ordered endpoints, accepting noIndex() only as an open endpoint.

Throws:

err::OutOfRangeError – if begin is absent or finite endpoints are reversed.

static inline constexpr IntegerUnitRange empty() noexcept

Return an empty range starting at zero.

static inline constexpr IntegerUnitRange emptyAt(Index index) noexcept

Return an empty range starting at the given index.

static inline constexpr IntegerUnitRange all() noexcept

Return a range starting at zero with infinite length.

static inline constexpr IntegerUnitRange noRange() noexcept

Return an invalid or absent range.

static inline constexpr IntegerUnitRange fromLength(const Count length) noexcept

Return a range starting at zero with a given length.

Parameters:

length – The length to use for the range.

static inline constexpr IntegerUnitRange fromSizeT(const std::size_t length) noexcept

Return a range starting at zero with a length from std::size_t.

The length saturates at the maximum value of Count.

Parameters:

length – The length to use for the range.

static inline constexpr IntegerUnitRange fromSizeTOrThrow(const std::size_t length)

Return a range starting at zero with a length from std::size_t.

Parameters:

length – The length to use for the range.

Throws:

err::OverflowError – if the length is too large to represent.

Friends

inline friend void swap(IntegerUnitRange &first, IntegerUnitRange &second) noexcept

Swap two ranges.

using erbsland::unit::ItemCount = IntegerUnitCount<ItemUnit>

A non-negative number of items.

using erbsland::unit::ItemIndex = IntegerUnitIndex<ItemUnit>

A zero-based item index.

using erbsland::unit::ItemOffset = IntegerUnitOffset<ItemUnit>

A signed offset in item units.

using erbsland::unit::ItemRange = IntegerUnitRange<ItemUnit>

A half-open range of items.

struct ItemUnit : public erbsland::unit::IntegerUnit

The integer unit for list item positions and counts.

using erbsland::unit::LineCount = IntegerUnitCount<LineUnit>

A source code line count.

using erbsland::unit::LineIndex = IntegerUnitIndex<LineUnit>

A zero-based source code line index.

using erbsland::unit::LineOffset = IntegerUnitOffset<LineUnit>

A signed source code line offset.

using erbsland::unit::LineRange = IntegerUnitRange<LineUnit>

A range of source code lines.

struct LineUnit : public erbsland::unit::IntegerUnit

The integer unit for source code line types.

using erbsland::unit::Major = VersionComponent<VersionPart::Major>

The major component of a version.

using erbsland::unit::Minor = VersionComponent<VersionPart::Minor>

The minor component of a version.

using erbsland::unit::Revision = VersionComponent<VersionPart::Revision>

The revision component of a version.

using erbsland::unit::U16Count = IntegerUnitCount<U16Unit>

A non-negative count of unsigned 16-bit values.

using erbsland::unit::U16Index = IntegerUnitIndex<U16Unit>

An index for unsigned 16-bit values.

using erbsland::unit::U16Offset = IntegerUnitOffset<U16Unit>

An offset for unsigned 16-bit values.

using erbsland::unit::U16Range = IntegerUnitRange<U16Unit>

A range of unsigned 16-bit values.

struct U16Unit : public erbsland::unit::IntegerUnit

The integer unit for unsigned 16-bit values.

class Version

A version consisting of major, minor, revision, and build number.

The default version is 0.0.0.0. Version comparison is lexicographic by all four parts unless a precision is supplied. With a precision, all less-significant parts are ignored.

Public Types

using Value = uint16_t

The raw unsigned integer type used for each version part.

Public Functions

constexpr Version() noexcept = default

Create version 0.0.0.0.

template<math::NativeInteger tMajor, math::NativeInteger tMinor = unsigned, math::NativeInteger tRevision = unsigned, math::NativeInteger tBuild = unsigned>
inline explicit consteval Version(tMajor major, tMinor minor = 0U, tRevision revision = 0U, tBuild build = 0U)

Create a version from compile-time integer components in 0…65535.

Parameters:
  • major – The major component.

  • minor – The minor component, defaulting to zero.

  • revision – The revision component, defaulting to zero.

  • build – The build component, defaulting to zero.

template<impl::VersionComponentArgument... tArguments>
inline explicit constexpr Version(tArguments... arguments) noexcept

Create a version from typed version parts in any order.

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

Compare this version with another version at full precision.

constexpr auto inRange(const VersionRange &range, VersionPart precision = VersionPart::Build) const noexcept -> bool

Test if this version is in the given range using the selected precision.

inline constexpr Major major() const noexcept

Get the major version number.

inline constexpr void setMajor(Major major) noexcept

Set the major version number.

inline constexpr Minor minor() const noexcept

Get the minor version number.

inline constexpr void setMinor(Minor minor) noexcept

Set the minor version number.

inline constexpr Revision revision() const noexcept

Get the revision version number.

inline constexpr void setRevision(Revision revision) noexcept

Set the revision version number.

inline constexpr BuildNumber build() const noexcept

Get the build version number.

inline constexpr void setBuild(BuildNumber build) noexcept

Set the build version number.

inline constexpr auto compare(const Version &other, VersionPart precision) const noexcept -> std::strong_ordering

Compare this version with another version using the given precision.

text::String toString(VersionPart precision = VersionPart::Revision) const

Convert this version into dotted decimal text.

Parameters:

precision – The least significant version part to include.

Returns:

The version text.

inline constexpr uint64_t toNumber() const noexcept

Convert this version into a packed 64-bit number.

Public Static Functions

static auto fromString(const text::String &text, VersionPart requiredPrecision = VersionPart::Major) noexcept -> std::optional<Version>

Parse a dotted decimal version number.

Each part must be an unsigned, unpadded decimal integer in the range 0–65535.

Parameters:
  • text – One to four version parts separated by .; whitespace and trailing text are invalid.

  • requiredPrecision – The least significant part that must be present; omitted parts become zero.

Returns:

The parsed version, or std::nullopt if the text is invalid.

static auto fromStringOrThrow(const text::String &text, VersionPart requiredPrecision = VersionPart::Major) -> Version

Parse a dotted decimal version number or report an error.

Each part must be an unsigned, unpadded decimal integer in the range 0–65535.

Parameters:
  • text – One to four version parts separated by .; whitespace and trailing text are invalid.

  • requiredPrecision – The least significant part that must be present; omitted parts become zero.

Throws:

err::ParseError – If the text is invalid.

Returns:

The parsed version.

static inline constexpr Version fromNumber(uint64_t value) noexcept

Create a version from a packed 64-bit number.

Friends

inline friend constexpr void swap(Version &first, Version &second) noexcept

Swap two versions.

template<VersionPart tPart>
class VersionComponent

A distinct unsigned 16-bit version component with saturating count arithmetic.

Template Parameters:

tPart – The version field represented by this type.

See: Units and Versions

Public Types

using Value = uint16_t

The raw component representation.

Public Functions

constexpr VersionComponent() noexcept = default

Create a zero version component.

template<math::NativeInteger T>
inline explicit consteval VersionComponent(T value)

Construct a component from a compile-time integer in 0…65535.

Parameters:

value – The component value; invalid values fail compilation.

inline constexpr VersionComponent(const Value value, Unchecked) noexcept

Construct a component unchecked.

template<math::AnyIntegerType T>
inline constexpr VersionComponent operator+(T count) const noexcept

Add an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &operator+=(T count) noexcept

Add an unsigned count in place with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent operator-(T count) const noexcept

Subtract an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &operator-=(T count) noexcept

Subtract an unsigned count in place with saturation.

inline constexpr VersionComponent &operator++() noexcept

Increment with saturation.

inline constexpr VersionComponent operator++(int) noexcept

Increment with saturation and return the previous component.

inline constexpr VersionComponent &operator--() noexcept

Decrement with saturation.

inline constexpr VersionComponent operator--(int) noexcept

Decrement with saturation and return the previous component.

inline constexpr bool isZero() const noexcept

Test whether the component is zero.

inline constexpr bool isOne() const noexcept

Test whether the component is one.

inline constexpr bool isMinimum() const noexcept

Test whether the component is minimum.

inline constexpr bool isMaximum() const noexcept

Test whether the component is maximum.

inline constexpr Value toRawValue() const noexcept

Get the native component value.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &add(T count) noexcept

Add an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent added(T count) const noexcept

Return the component after adding an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &addOrThrow(T count)

Add an unsigned count exactly.

Throws:

err::OverflowError – if the result is outside 0…65535.

template<math::AnyIntegerType T>
inline constexpr VersionComponent addedOrThrow(T count) const

Return the component after exact count arithmetic.

Throws:

err::OverflowError – if the result is outside 0…65535.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &subtract(T count) noexcept

Subtract an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent subtracted(T count) const noexcept

Return the component after subtracting an unsigned count with saturation.

template<math::AnyIntegerType T>
inline constexpr VersionComponent &subtractOrThrow(T count)

Subtract an unsigned count exactly.

Throws:

err::OverflowError – if the result is outside 0…65535.

template<math::AnyIntegerType T>
inline constexpr VersionComponent subtractedOrThrow(T count) const

Return the component after exact count arithmetic.

Throws:

err::OverflowError – if the result is outside 0…65535.

inline constexpr VersionComponent &increment() noexcept

Increment with saturation.

inline constexpr VersionComponent incremented() const noexcept

Return the component incremented with saturation.

inline constexpr VersionComponent &decrement() noexcept

Decrement with saturation.

inline constexpr VersionComponent decremented() const noexcept

Return the component decremented with saturation.

Public Static Functions

static inline constexpr VersionComponent zero() noexcept

Return the zero component.

static inline constexpr VersionComponent one() noexcept

Return the one component.

static inline constexpr VersionComponent minimum() noexcept

Return the minimum component.

static inline constexpr VersionComponent maximum() noexcept

Return the maximum component.

template<math::NativeInteger T>
static inline constexpr VersionComponent fromInteger(T value) noexcept

Convert a runtime integer with saturation to 0…65535.

template<math::NativeInteger T>
static inline constexpr VersionComponent fromIntegerOrThrow(T value)

Convert a runtime integer exactly.

Throws:

err::OverflowError – if value is outside 0…65535.

Public Static Attributes

static constexpr auto cPart = tPart

The version field.

static constexpr Value cRawMaximum = std::numeric_limits<Value>::max()

The greatest component value.

struct Unchecked

Tag for unchecked construction.

enum class erbsland::unit::VersionPart : uint8_t

The part of a version number.

The order of the values follows their significance in a version.

Values:

enumerator Major

The major version part.

enumerator Minor

The minor version part.

enumerator Revision

The revision version part.

enumerator Build

The build version part.

class VersionRange

An inclusive range of versions.

A version range may have no minimum, no maximum, or neither bound. Existing bounds are inclusive. Precision-limited containment uses the same comparison rules as Version::compare().

Public Functions

constexpr VersionRange() noexcept = default

Create an open-ended range.

inline constexpr VersionRange(std::optional<Version> minimum, std::optional<Version> maximum) noexcept

Create a range from optional inclusive bounds.

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

Compare this range with another range.

inline constexpr bool hasMinimum() const noexcept

Test if this range has a minimum bound.

inline constexpr bool hasMaximum() const noexcept

Test if this range has a maximum bound.

inline constexpr bool isEmpty(VersionPart precision = VersionPart::Build) const noexcept

Test if this range is empty using the selected precision.

inline constexpr auto contains(const Version &version, VersionPart precision = VersionPart::Build) const noexcept -> bool

Test if this range contains the given version using the selected precision.

inline constexpr std::optional<Version> minimum() const noexcept

Get the inclusive minimum bound.

inline constexpr void setMinimum(const std::optional<Version> minimum) noexcept

Set the inclusive minimum bound.

inline constexpr std::optional<Version> maximum() const noexcept

Get the inclusive maximum bound.

inline constexpr void setMaximum(const std::optional<Version> maximum) noexcept

Set the inclusive maximum bound.

Public Static Functions

static inline constexpr VersionRange all() noexcept

Return a range without bounds.

static inline constexpr VersionRange atLeast(Version minimum) noexcept

Return a range with only an inclusive minimum bound.

static inline constexpr VersionRange atMost(Version maximum) noexcept

Return a range with only an inclusive maximum bound.

static inline constexpr VersionRange between(Version minimum, Version maximum) noexcept

Return a range with inclusive minimum and maximum bounds.

static inline constexpr VersionRange exact(Version version) noexcept

Return a range that contains exactly one version.

Friends

inline friend constexpr void swap(VersionRange &first, VersionRange &second) noexcept

Swap two version ranges.