Text Formatting and Parsing

String Format Definitions

Introduction

Boolean Format

BooleanFormat describes how boolean values are written to Erbsland Core strings and stream print helpers. The default format writes lowercase true and false. Use the style factories to select true /false, yes /no, on /off, or enabled /disabled output. Use Capitalization to switch between lowercase, uppercase, and titlecase words.

Use a BooleanFormat object in a print argument list to change the format for following boolean values:

el::io::printLine(el::BooleanFormat::yesNo(), "available: "_el, ready);

Byte Format

ByteFormat describes how byte blocks are written as hexadecimal text. The default format is compact lowercase output without separators, suitable for hashes and other identifiers.

Use the convenience factories for readable call sites:

auto hash = el::String::fromByteBlock(data);
auto bytes = el::String::fromByteBlock(data, el::ByteFormat::separated());
auto dump = el::String::fromByteBlock(data, el::ByteFormat::memoryDump());

Use a ByteFormat object in a print argument list to change the format for following byte blocks:

el::io::printLine("hash: "_el, data);
el::io::print(el::ByteFormat::memoryDump(), data);
Bounded Output and Truncation

Use setMaximum() to limit the number of byte-like output items. The default is ByteLength::infinite(). If the byte block exceeds this maximum, setTruncateMode() selects which source bytes are retained and setEllipsis() provides the inserted truncation marker.

A non-empty ellipsis occupies one output item, just like one formatted byte. Therefore, a maximum of 16 emits at most 15 source bytes and one ellipsis. A maximum of zero always emits nothing, while a maximum of one emits only a non-empty ellipsis when truncation is required. An empty ellipsis does not occupy an item. Middle truncation assigns an odd extra retained byte to the prefix.

The ellipsis participates in separator, byte-group, and line layout as one byte would. Source offsets still count only actual source bytes. Beginning and middle truncation are available only for single-line formats whose flags contain no bits other than Separator. Other layouts use end truncation.

forDiagnostic() creates a compact lowercase format with a maximum of 16 items, middle truncation, and the ASCII ellipsis ...:

auto diagnostic = el::String::fromByteBlock(data, el::ByteFormat::forDiagnostic());

Byte Format Flag

ByteFormatFlag controls optional byte formatting behavior. Use ByteFormatFlags when several flags are combined.

Separator inserts the configured separator between bytes. ByteGroups changes separator placement so multiple bytes are grouped together. Lines wraps output after the configured number of bytes. Offset emits a hexadecimal byte offset in front of each line. LineGroups inserts an empty line after each configured group of lines.

Float Format

FloatFormat describes how floating-point values are written to Erbsland Core strings and stream print helpers. It wraps the simple presentation styles provided by std::format and supports an optional precision.

Use a FloatFormat object in a print argument list to change the format for following floating-point values:

auto fixed = el::FloatFormat::fixed().setPrecision(el::ItemCount{2U});
el::io::printLine("height: "_el, fixed, 18.756, " m"_el);

Float Parse Flag

FloatParseFlag controls optional floating-point parsing behavior. Use FloatParseFlags when several flags are combined.

IgnoreTrailingChars makes parsing stop successfully after the floating-point value. Without this flag, parsing requires full consumption.

Float Parse Options

FloatParseOptions controls floating-point parsing from Erbsland Core strings. By default the parser accepts general floating-point syntax and requires the complete input to be consumed.

Use a style when accepted syntax must be constrained:

auto options = el::FloatParseOptions{};
options.setStyle(el::FloatParseOptions::Style::Scientific);

Integer Base

IntegerBase selects the syntax base for integer text conversion. Decimal uses base 10, hexadecimal uses base 16, binary uses base 2, and octal uses base 8.

The type is an enum-like class instead of a plain enum so base-specific helpers stay with the base vocabulary. Use baseFactor() for arithmetic conversion and digitGroupSize() for separator grouping. prefixChar() returns the base prefix character used after the leading 0 for prefixed output. toString() returns the canonical name: decimal, hexadecimal, binary, or octal.

When parsing with IntegerParseOptions and no fixed base, the parser detects 0x /0X as hexadecimal, 0b /0B as binary, and 0o /0O as octal. Otherwise it uses decimal. Use fromPrefixChar() when implementing matching prefix detection logic.

Integer Format

IntegerFormat describes how integers are written to Erbsland Core strings and AnyStringBuilder. The default format is decimal with no flags, lowercase letters, a zero field width, no precision, and negative-only sign output.

Use the convenience factories for readable call sites:

auto decimal = el::IntegerFormat::decimal();
auto hex = el::IntegerFormat::hexadecimal().setFlags(el::IntegerFormatFlag::BasePrefix);
auto binary = el::IntegerFormat::binary().setFlags(el::IntegerFormatFlag::Separator);
auto octal = el::IntegerFormat{el::IntegerBase::Octal};

Integer Format Flag

IntegerFormatFlag controls optional integer formatting behavior. Use IntegerFormatFlags when several flags are combined.

ZeroFill pads the digit field with zeroes. Separator inserts ASCII apostrophe digit group separators. BasePrefix emits 0x /0X for hexadecimal, 0b /0B for binary, and 0o /0O for octal.

Integer Sign Mode

IntegerSignMode controls whether positive values are written without a sign, with +, or with a leading space.

Integer Parse Flag

IntegerParseFlag controls optional integer parsing behavior. Use IntegerParseFlags when several flags are combined.

AllowSeparator accepts the configured digit separator between digits. IgnoreTrailingChars makes parsing stop successfully after the integer value. Without this flag, parsing requires full consumption. AcceptMinusSign accepts a leading - and records a negative result. IgnorePlusSign accepts a leading + without changing the result sign. StopAtMaximum stops low-level reader parsing when the configured maximum digit count is reached.

Integer Parse Options

IntegerParseOptions controls integer parsing from Erbsland Core strings and from StringCharReader. parserDefault() is the default option set for low-level parsers and tokenizers. It does not accept signs or separators and reads a single integer token. stringDefault() is the default used by string-to-integer conversion. It accepts - and + signs and requires the complete input unless IgnoreTrailingChars is set.

Use a fixed base when the syntax base is known. A fixed base rejects base prefixes such as 0x, 0b, and 0o. Leave the base unset to auto-detect these prefixes. Use minimumDigits and maximumDigits to control the accepted digit count. Without StopAtMaximum, extra digits beyond a finite maximum are an error. With StopAtMaximum, reader parsing stops when the maximum is reached. Use fixedDecimal() and fixedHex() for fixed-width grammar fields. When AllowSeparator is enabled, the configured separator must appear between digits and must not start, end, or repeat in the consumed integer.

Letter Case

LetterCase selects the letter case for text output and parsing. It is used by integer formatting, character case-mapping, and other text operations that need case control.

Capitalization

Capitalization selects the capitalization for generated words. It is used by boolean formatting where titlecase output is useful for user-facing text.

Safe String Flag

SafeStringFlag controls optional safety checks for string operations. Use SafeStringFlags when several flags are combined.

Truncate Mode

TruncateMode controls how truncation is indicated when text exceeds a configured width.

Literals

The literal helpers in erbsland::text::literals are the preferred way to write static UTF-8 text in Erbsland Core code. They keep the type of the literal visible, avoid unsafe pointer-and-size pairs in user code, and let read-only APIs refer directly to the original literal storage.

using namespace erbsland::text::literals;

constexpr auto label = u8"Status"_el;       // U8StringLiteral<char8_t>
auto labelText = el::U8String{u8"Status"_el}; // U8String
auto labelEditor = el::U8StringEditor{u8"Status"_el};
labelEditor.append(u8": ready"_el);           // explicit local mutable construction

Use "_el" when you want a constexpr-capable U8StringLiteral. Use "_el" for APIs that inspect text through U8String. Construct U8StringEditor explicitly for local mutable construction or in-place editing.

Display Escaping

EscapeFormat::Display is intended for untrusted text in diagnostics and other user-facing output. It preserves printable punctuation and Unicode text while converting control and format characters into readable C-style sequences. Together with EscapeAmount::Balanced, it provides safe output without obscuring ordinary quotes, backslashes, or path punctuation.

Log Escaping

EscapeFormat::Log applies the same balanced safety rule as display escaping, except that U+000A line feeds remain real line breaks. All other Unicode control and format characters are converted into visible escapes. Use it for untrusted messages that may intentionally contain short multiline listings but must not contain terminal control sequences, bidirectional format controls, or hidden line separators.

Markdown Escaping

EscapeFormat::Markdown protects ordinary CommonMark text. At EscapeAmount::Required it prefixes escapable ASCII punctuation with a backslash. Higher amounts encode controls, format characters, and requested non-ASCII code points as decimal numeric references. This format does not protect CommonMark contexts in which backslash escaping is disabled, such as code spans and code blocks.

String Parser and Reader

Introduction

String Char Reader

StringCharReader is a sequential reader for decoded Unicode code points. It accepts U8String, U16String, and U32String and exposes the same read API for all encodings. Editor values are accepted for compatibility and converted to the corresponding owning read-only string.

The reader keeps the source storage alive through the read-only string object stored in its backend. Copying a reader shares the immutable source data, but the cursor state is copied, so moving one reader forward does not move another copy.

Positions and States

position() returns the current decoded code-point index as unit::CpIndex. This is the value user code should use for diagnostics and parse errors. save() and restore() capture and restore the backend cursor and decoded position in constant time. A saved state must be restored only to the reader that created it or to a compatible copy over the same visible text and encoding; passing it to another reader is undefined.

Reader Operations

read() consumes the next decoded character, while peek() only inspects it. advance() skips decoded characters when the value is not needed.

Use readIf() and advanceIf() for optional grammar characters. They leave the cursor unchanged when the next character does not match. The string overload of advanceIf() matches a complete UTF-8 token by decoded character and restores the starting position after a partial match or insufficient input. Its optional character-comparison function supports cases such as ASCII-insensitive grammar tokens without converting the source text. The OrThrow variants reject end-of-data and malformed encoding before matching.

readWhile() and readUntil() invoke a callback and return LoopResult because the callback can stop or report an error. advanceWhile() and advanceUntil() have no callback and instead return the unit::CpLength actually skipped. They leave the boundary character unread and stop at the configured maximum or end-of-data. The count can be ignored when only the skip operation matters, for example when discarding optional whitespace.

Each while/until operation accepts either a CharSet or an AsciiCategory. Prefer the category overload for standard ASCII grammar classes such as whitespace, digits, words, URL schemes, Base64 text, and HTTP tokens. The UTF-8, UTF-16, and UTF-32 backends decode each character once and classify it directly, without constructing a temporary CharSet.

auto reader = el::StringCharReader{source};
reader.advanceWhile(el::AsciiCategory::Whitespace);
reader.startCapture();
reader.advanceWhile(el::AsciiCategory::WordWithHyphen);
auto identifier = reader.takeCapture().toString();

Use a CharSet when the grammar has a custom or dynamic character combination that no category represents.

parseInteger() parses a low-level integer token with IntegerParseOptions. It restores the original reader position on failure and returns the parsed magnitude, sign state, resolved base, digit count, and status. Use readIntegerOrThrow<T>() when a reader should consume an integer token, convert it into a native or saturating integer type, and report failures as ParseNumberError.

Capture and Buffer

The capture API marks a source range and returns it as an inexpensive owning read-only string slice. Use startCapture() and takeCapture() when the parsed token can be represented as an unchanged slice of the input.

The reader buffer is owned parser text in the same encoding as the reader backend. Use it for tokens that are assembled, normalized, escaped, or mixed from source text and manually appended characters. readToBuffer() and the readToBufferIf() variants consume and append one character. readToBufferWhile() and readToBufferUntil() append only accepted characters; stop, mismatch, end-of-data, and limit characters are left unread and are not appended.

Saved reader states restore only the cursor position. Capture and buffer state intentionally remain unchanged.

Interface

class BooleanFormat

Options for boolean text formatting.

Public Types

enum class Style : uint8_t

The word pair used for boolean values.

Values:

enumerator TrueFalse

Write true and false.

enumerator YesNo

Write yes and no.

enumerator OnOff

Write on and off.

enumerator EnabledDisabled

Write enabled and disabled.

Public Functions

constexpr BooleanFormat() noexcept = default

Create the default true/false lowercase format.

inline constexpr BooleanFormat(const Style style) noexcept

Create a boolean format for the given style.

inline constexpr Style style() const noexcept

Get the word pair style.

inline constexpr BooleanFormat &setStyle(Style style) noexcept

Set the word pair style.

inline constexpr Capitalization capitalization() const noexcept

Get the word capitalization.

inline constexpr BooleanFormat &setCapitalization(Capitalization capitalization) noexcept

Set the word capitalization.

StringLiteral text(bool value) const noexcept

Get the text for the given boolean value.

Public Static Functions

static inline constexpr BooleanFormat defaultFormat() noexcept

Create the default format.

static inline constexpr BooleanFormat trueFalse() noexcept

Create a true/false format.

static inline constexpr BooleanFormat yesNo() noexcept

Create a yes/no format.

static inline constexpr BooleanFormat onOff() noexcept

Create an on/off format.

static inline constexpr BooleanFormat enabledDisabled() noexcept

Create an enabled/disabled format.

class ByteFormat

Options for byte block hexadecimal text formatting.

Public Functions

ByteFormat()

Create the default compact byte format.

ByteFormat(ByteFormatFlags flags)

Create a byte format with the given flags.

~ByteFormat()

Destroy this byte format.

ByteFormat(const ByteFormat&)

Copy another byte format.

ByteFormat &operator=(const ByteFormat&)

Copy another byte format into this byte format.

ByteFormatFlags flags() const noexcept

Get the format flags.

ByteFormat &setFlags(ByteFormatFlags flags) noexcept

Set the format flags.

ByteFormat &addFlags(ByteFormatFlags flags) noexcept

Add format flags.

ByteFormat &clearFlags(ByteFormatFlags flags) noexcept

Clear format flags.

bool hasFlag(ByteFormatFlag flag) const noexcept

Test if the given format flag is set.

LetterCase letterCase() const noexcept

Get the letter case for hexadecimal digits.

ByteFormat &setLetterCase(LetterCase letterCase) noexcept

Set the letter case for hexadecimal digits.

unit::ByteLength bytesPerLine() const noexcept

Get the number of bytes per line.

ByteFormat &setBytesPerLine(unit::ByteLength bytesPerLine) noexcept

Set the number of bytes per line.

unit::ByteLength byteGroupSize() const noexcept

Get the number of bytes per group.

ByteFormat &setByteGroupSize(unit::ByteLength byteGroupSize) noexcept

Set the number of bytes per group.

unit::ItemCount lineGroupSize() const noexcept

Get the number of lines per group.

ByteFormat &setLineGroupSize(unit::ItemCount lineGroupSize) noexcept

Set the number of lines per group.

const String &byteSeparator() const noexcept

Get the byte or byte group separator.

ByteFormat &setByteSeparator(const String &byteSeparator) noexcept

Set the byte or byte group separator.

const String &offsetSeparator() const noexcept

Get the separator between offsets and byte data.

ByteFormat &setOffsetSeparator(const String &offsetSeparator)

Set the separator between offsets and byte data.

const String &linePrefix() const noexcept

Get the prefix inserted before each byte-data line.

ByteFormat &setLinePrefix(const String &linePrefix)

Set the prefix inserted before each byte-data line.

const String &lineSuffix() const noexcept

Get the suffix inserted after each byte-data line.

ByteFormat &setLineSuffix(const String &lineSuffix)

Set the suffix inserted after each byte-data line.

unit::ByteIndex startOffset() const noexcept

Get the starting byte offset.

ByteFormat &setStartOffset(unit::ByteIndex startOffset) noexcept

Set the starting byte offset.

unit::ByteLength maximum() const noexcept

Get the maximum number of byte-like output items.

ByteFormat &setMaximum(unit::ByteLength maximum) noexcept

Set the maximum number of byte-like output items.

TruncateMode truncateMode() const noexcept

Get the truncation mode.

ByteFormat &setTruncateMode(TruncateMode truncateMode) noexcept

Set the truncation mode.

const String &ellipsis() const noexcept

Get the ellipsis inserted when bytes are truncated.

ByteFormat &setEllipsis(const String &ellipsis)

Set the ellipsis inserted when bytes are truncated.

Public Static Functions

static ByteFormat defaultFormat()

Create the default compact format.

static ByteFormat compact()

Create the default compact format.

static ByteFormat separated()

Create a single-line format with spaces between bytes.

static ByteFormat memoryDump()

Create a multi-line memory dump format with offsets and byte groups.

static ByteFormat forDiagnostic()

Create a compact diagnostic format limited to sixteen output items.

enum class erbsland::text::ByteFormatFlag : uint8_t

Flags for byte block text formatting.

Values:

enumerator Separator

Insert separators between bytes or byte groups.

enumerator ByteGroups

Group multiple bytes between separators.

enumerator Lines

Split output into lines.

enumerator Offset

Add a hexadecimal byte offset in front of each line.

enumerator LineGroups

Insert an empty line after each line group.

enumerator All
using erbsland::text::ByteFormatFlags = util::EnumFlags<ByteFormatFlag>

A set of byte format flags.

enum class erbsland::text::Capitalization : uint8_t

The capitalization to use for generated words.

Values:

enumerator Lowercase

Use all lowercase letters.

enumerator Uppercase

Use all uppercase letters.

enumerator Titlecase

Use an uppercase first letter and lowercase remaining letters.

class EscapeAmount

What range of characters shall get escaped.

Public Types

enum Value

The escape amount value.

Values:

enumerator Nothing

Escape nothing.

enumerator Required

Escape only required characters.

enumerator Balanced

Escape invisible and control characters.

enumerator NonAscii

Escape everything, except visible ASCII characters.

enumerator Everything

Escape everything.

Public Functions

inline constexpr EscapeAmount(const Value value) noexcept

Create an escape amount from a value.

inline constexpr Value toRawValue() const noexcept

Get the raw escape amount value.

String toString() const

Convert this escape amount to its canonical string.

Public Static Functions

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

Create an escape amount from a canonical string.

static EscapeAmount fromStringOrThrow(const String &text)

Create an escape amount from a canonical string.

Throws:

err::ParseError – if the string is not a supported escape amount.

static std::optional<EscapeAmount> fromSuffix(Char character) noexcept

Create an escape amount from a format suffix character.

class EscapeFormat

The target syntax for escaped text.

Public Types

enum Value

The escape format value.

Values:

enumerator None

Do not escape any characters.

enumerator Html

Escape for HTML text.

enumerator Json

Escape for JSON text.

enumerator Cpp

Escape for C++ literals.

enumerator Xml

Escape for XML text.

enumerator RegEx

Escape for regular expression literal patterns.

enumerator Display

Escape unsafe characters for human-readable display text (equals Config).

enumerator Log

Escape unsafe log text while preserving line feeds.

enumerator Config

Escape for Erbsland Configuration Language text literals.

enumerator ConfigTest

Escape for Erbsland Configuration Language test strings.

enumerator Markdown

Escape normal CommonMark text using backslash and numeric references.

enumerator _valueCount

Number of escape formats.

Public Functions

inline constexpr EscapeFormat(const Value value) noexcept

Create an escape format from a value.

Parameters:

value – The raw escape-format value.

inline constexpr Value toRawValue() const noexcept

Get the raw escape format value.

String toString() const

Convert this escape format to its canonical string.

Returns:

The lowercase canonical identifier for this format.

Public Static Functions

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

Create an escape format from a canonical string.

Parameters:

text – The canonical identifier to parse.

Returns:

The parsed format, or an empty optional if text is unknown.

static EscapeFormat fromStringOrThrow(const String &text)

Create an escape format from a canonical string.

Parameters:

text – The canonical identifier to parse.

Throws:

err::ParseError – if the string is not a supported escape format.

Returns:

The parsed escape format.

class FloatFormat

Options for floating point text formatting.

Public Types

enum class Style : uint8_t

The floating point presentation style.

Values:

enumerator Default

Use the default std::format floating point presentation.

enumerator Fixed

Use fixed-point notation.

enumerator Scientific

Use scientific notation.

enumerator General

Use general notation.

enumerator Hexadecimal

Use hexadecimal floating point notation.

Public Functions

constexpr FloatFormat() noexcept = default

Create the default floating point format.

inline constexpr FloatFormat(const Style style) noexcept

Create a floating point format for the given style.

inline constexpr Style style() const noexcept

Get the presentation style.

inline constexpr FloatFormat &setStyle(Style style) noexcept

Set the presentation style.

inline constexpr bool hasPrecision() const noexcept

Test if a precision is configured.

inline constexpr unit::ItemCount precision() const noexcept

Get the configured precision, or zero if no precision is configured.

inline constexpr FloatFormat &setPrecision(unit::ItemCount precision) noexcept

Set the precision.

inline constexpr FloatFormat &clearPrecision() noexcept

Clear the precision.

inline constexpr LetterCase letterCase() const noexcept

Get the letter case used by styles that emit letters.

inline constexpr FloatFormat &setLetterCase(LetterCase letterCase) noexcept

Set the letter case used by styles that emit letters.

Public Static Functions

static inline constexpr FloatFormat defaultFormat() noexcept

Create the default format.

static inline constexpr FloatFormat fixed() noexcept

Create a fixed-point format.

static inline constexpr FloatFormat scientific() noexcept

Create a scientific format.

static inline constexpr FloatFormat general() noexcept

Create a general format.

static inline constexpr FloatFormat hexadecimal() noexcept

Create a hexadecimal floating point format.

enum class erbsland::text::FloatParseFlag : uint8_t

Flags for floating point parsing.

Values:

enumerator IgnoreTrailingChars

Stop parsing successfully after the floating point value.

enumerator All
using erbsland::text::FloatParseFlags = util::EnumFlags<FloatParseFlag>

A set of floating point parse flags.

class FloatParseOptions

Options for floating point parsing.

Public Types

enum class Style : uint8_t

The accepted floating point presentation style.

Values:

enumerator General

Accept fixed or scientific notation.

enumerator Fixed

Accept fixed-point notation.

enumerator Scientific

Accept scientific notation.

enumerator Hexadecimal

Accept hexadecimal floating point notation.

Public Functions

constexpr FloatParseOptions() noexcept = default

Create the default parse options.

inline constexpr Style style() const noexcept

Get the accepted presentation style.

inline constexpr FloatParseOptions &setStyle(Style style) noexcept

Set the accepted presentation style.

inline constexpr FloatParseFlags flags() const noexcept

Get the parse flags.

inline constexpr FloatParseOptions &setFlags(FloatParseFlags flags) noexcept

Set the parse flags.

inline constexpr FloatParseOptions &addFlags(FloatParseFlags flags) noexcept

Add parse flags.

inline constexpr FloatParseOptions &clearFlags(FloatParseFlags flags) noexcept

Clear parse flags.

inline constexpr bool hasFlag(FloatParseFlag flag) const noexcept

Test if the given parse flag is set.

Public Static Functions

static inline constexpr FloatParseOptions defaultOptions() noexcept

Create the default parse options.

class FormatArgument

A small owning adapter for one runtime format argument.

Public Functions

FormatArgument() = default

Create an empty format argument.

template<typename T>
inline explicit FormatArgument(T &&value)

Create a format argument by constructing the matching variant alternative.

FormatArgumentKind kind() const noexcept

Get the argument kind.

U8String u8Text() const

Get the UTF-8 text argument.

U16String u16Text() const

Get the UTF-16 text argument.

U32String u32Text() const

Get the UTF-32 text argument.

int64_t signedInteger() const

Get the signed integer argument.

uint64_t unsignedInteger() const

Get the unsigned integer argument.

double floatingPoint() const

Get the floating point argument.

bool boolean() const

Get the boolean argument.

Char character() const

Get the character argument.

mem::ByteBlock bytes() const

Get the byte-block argument.

enum class erbsland::text::FormatArgumentKind : uint8_t

The supported runtime format argument kind.

Values:

enumerator None
enumerator U8Text
enumerator U16Text
enumerator U32Text
enumerator SignedInteger
enumerator UnsignedInteger
enumerator FloatingPoint
enumerator Boolean
enumerator Character
enumerator Bytes
template<typename T>
struct FormatAs

Override the default UTF-8 text representation for formatting.

Value types with toString() const -> String are automatically supported. Specialize this template for a custom value type only when formatting requires a different representation.

See: Text Formatting and Parsing

class FormatError : public erbsland::err::RuntimeError

A format string or format operation error.

These exceptions are thrown when a format pattern is invalid, a format argument does not match the requested field, or formatting would exceed configured safety limits.

Public Functions

inline explicit FormatError(String reason) noexcept

Create a format error with a reason.

Parameters:

reason – The reason for the format error.

inline explicit FormatError(const std::string_view reason) noexcept

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

class IntegerBase

The base used for integer text conversion.

Public Types

enum Value

The integer base value.

Values:

enumerator Decimal

Decimal base 10.

enumerator Hexadecimal

Hexadecimal base 16.

enumerator Binary

Binary base 2.

enumerator Octal

Octal base 8.

Public Functions

inline constexpr IntegerBase(const Value value) noexcept

Create an integer base from a value.

inline constexpr Value toRawValue() const noexcept

Get the raw integer base value.

inline constexpr unsigned int baseFactor() const noexcept

Get the numeric factor for this base.

inline constexpr std::size_t digitGroupSize() const noexcept

Get the digit group size for separators.

template<std::integral T>
constexpr std::size_t digitCount(T value) const noexcept

Count the digits required to represent the magnitude of an integer value in this base.

Count the digits required to represent an integer in this base.

The sign is not counted for signed negative values.

Char prefixChar(LetterCase letterCase) const noexcept

Get the ASCII prefix character for this base, or a null character if the base has no prefix.

String toString() const noexcept

Convert this integer base to its canonical name.

Public Static Functions

static std::optional<IntegerBase> fromPrefixChar(Char character) noexcept

Create an integer base from an ASCII prefix character.

class IntegerFormat

Options for integer text formatting.

Public Functions

constexpr IntegerFormat() noexcept = default

Create the default decimal integer format.

inline constexpr IntegerFormat(const IntegerBase base) noexcept

Create an integer format for the given base.

inline constexpr IntegerBase base() const noexcept

Get the integer base.

inline constexpr IntegerFormat &setBase(IntegerBase base) noexcept

Set the integer base.

bool setFromBasePrefix(Char character) noexcept

Set the integer base and letter case from an ASCII base prefix character.

Returns:

true if the prefix character was supported.

inline constexpr IntegerFormatFlags flags() const noexcept

Get the format flags.

inline constexpr IntegerFormat &setFlags(IntegerFormatFlags flags) noexcept

Set the format flags.

inline constexpr IntegerFormat &addFlags(IntegerFormatFlags flags) noexcept

Add format flags.

inline constexpr IntegerFormat &clearFlags(IntegerFormatFlags flags) noexcept

Clear format flags.

inline constexpr bool hasFlag(IntegerFormatFlag flag) const noexcept

Test if the given format flag is set.

inline constexpr LetterCase letterCase() const noexcept

Get the letter case.

inline constexpr IntegerFormat &setLetterCase(LetterCase letterCase) noexcept

Set the letter case.

inline constexpr unit::CpLength fieldWidth() const noexcept

Get the minimum digit field width.

inline constexpr IntegerFormat &setFieldWidth(unit::CpLength fieldWidth) noexcept

Set the minimum digit field width.

inline constexpr bool hasPrecision() const noexcept

Test if a minimum digit precision is configured.

inline constexpr unit::CpLength precision() const noexcept

Get the minimum digit precision, or zero if no precision is configured.

inline constexpr IntegerFormat &setPrecision(unit::CpLength precision) noexcept

Set the minimum digit precision.

inline constexpr IntegerFormat &clearPrecision() noexcept

Clear the minimum digit precision.

inline constexpr IntegerSignMode signMode() const noexcept

Get the sign handling mode.

inline constexpr IntegerFormat &setSignMode(IntegerSignMode signMode) noexcept

Set the sign handling mode.

Public Static Functions

static inline constexpr IntegerFormat defaultFormat() noexcept

Create the default format.

static inline constexpr IntegerFormat decimal() noexcept

Create a decimal format.

static inline constexpr IntegerFormat hexadecimal() noexcept

Create a hexadecimal format.

static inline constexpr IntegerFormat binary() noexcept

Create a binary format.

static inline constexpr IntegerFormat octal() noexcept

Create an octal format.

enum class erbsland::text::IntegerFormatFlag : uint8_t

Flags for integer text formatting.

Values:

enumerator ZeroFill

Pad the digit field with zeroes.

enumerator Separator

Insert digit group separators.

enumerator BasePrefix

Add a base prefix for hexadecimal, binary, and octal output.

enumerator All
using erbsland::text::IntegerFormatFlags = util::EnumFlags<IntegerFormatFlag>

A set of integer format flags.

enum class erbsland::text::IntegerParseFlag : uint8_t

Flags for integer parsing.

Values:

enumerator AllowSeparator

Accept digit group separators.

enumerator IgnoreTrailingChars

Stop parsing at the first trailing non-digit character.

enumerator AcceptMinusSign

Accept a leading minus sign.

enumerator IgnorePlusSign

Accept and ignore a leading plus sign.

enumerator StopAtMaximum

Stop reading digits when the maximum digit count is reached.

enumerator All
using erbsland::text::IntegerParseFlags = util::EnumFlags<IntegerParseFlag>

A set of integer parse flags.

class IntegerParseOptions

Options for integer parsing.

Public Functions

constexpr IntegerParseOptions() noexcept = default

Create the default parse options.

inline constexpr bool hasFixedBase() const noexcept

Test if a fixed base is configured.

inline constexpr std::optional<IntegerBase> fixedBase() const noexcept

Get the optional fixed base.

inline constexpr IntegerParseOptions &setFixedBase(IntegerBase base) noexcept

Set a fixed base.

inline constexpr IntegerParseOptions &clearFixedBase() noexcept

Clear the fixed base and detect the base from prefixes.

inline constexpr IntegerParseFlags flags() const noexcept

Get the parse flags.

inline constexpr IntegerParseOptions &setFlags(IntegerParseFlags flags) noexcept

Set the parse flags.

inline constexpr IntegerParseOptions &addFlags(IntegerParseFlags flags) noexcept

Add parse flags.

inline constexpr IntegerParseOptions &clearFlags(IntegerParseFlags flags) noexcept

Clear parse flags.

inline constexpr bool hasFlag(IntegerParseFlag flag) const noexcept

Test if the given parse flag is set.

inline constexpr unit::CpLength minimumDigits() const noexcept

Get the minimum number of digits to parse.

inline constexpr IntegerParseOptions &setMinimumDigits(unit::CpLength minimumDigits) noexcept

Set the minimum number of digits to parse.

inline constexpr unit::CpLength maximumDigits() const noexcept

Get the maximum number of digits to parse.

inline constexpr IntegerParseOptions &setMaximumDigits(unit::CpLength maximumDigits) noexcept

Set the maximum number of digits to parse.

inline constexpr Char separator() const noexcept

Get the digit group separator.

inline constexpr IntegerParseOptions &setSeparator(Char separator) noexcept

Set the digit group separator.

Public Static Functions

static inline constexpr IntegerParseOptions parserDefault() noexcept

Create options for parser/tokenizer use.

static inline constexpr IntegerParseOptions stringDefault() noexcept

Create options for full-string integer conversion.

static inline constexpr IntegerParseOptions defaultOptions() noexcept

Create the default parse options.

static inline constexpr IntegerParseOptions fixedDecimal(unit::CpLength count) noexcept

Create options to parse exactly the given number of decimal digits.

static inline constexpr IntegerParseOptions fixedHex(unit::CpLength count) noexcept

Create options to parse exactly the given number of hexadecimal digits.

enum class erbsland::text::IntegerSignMode : uint8_t

Sign handling for integer text formatting.

Values:

enumerator NegativeOnly

Emit a sign only for negative values.

enumerator Always

Emit + for positive values and - for negative values.

enumerator Space

Emit a space for positive values and - for negative values.

enum class erbsland::text::LetterCase : uint8_t

The case to use for generated ASCII letters.

Values:

enumerator Lowercase

Use lowercase ASCII letters.

enumerator Uppercase

Use uppercase ASCII letters.

class ParseNumberError : public erbsland::err::ParseError

A number parse error exception.

This exception adds the reader status that caused the failure.

Public Functions

explicit ParseNumberError(String reason, ReadNumberStatus status, unit::CpIndex position = unit::CpIndex::noIndex()) noexcept

Create a number parse error with a reason and status.

Parameters:
  • reason – The reason for the parse error.

  • status – The reader status that caused the error.

  • position – The optional code-point position of the parse error.

inline ReadNumberStatus status() const noexcept

Get the reader status that caused the error.

struct ReadIntegerResult

Result for reading an integer from a string reader.

Public Members

std::uint64_t value = {}

The parsed unsigned value.

unit::CpLength digitCount = {unit::CpLength::zero()}

The number of consumed digits.

bool isNegative = {false}

Whether a minus sign was consumed.

IntegerBase base = {IntegerBase::Decimal}

The resolved integer base.

unit::CpIndex position = {unit::CpIndex::noIndex()}

The start or error position.

ReadNumberStatus status = {ReadNumberStatus::Success}

The result status.

enum class erbsland::text::ReadNumberStatus : uint8_t

Result status when reading a number from a string reader.

Values:

enumerator Success
enumerator NoDigits
enumerator TooFewDigits
enumerator TooManyDigits
enumerator Overflow
enumerator ParseError
enum class erbsland::text::SafeStringFlag : uint8_t

Flags for creating safe string representations for logs and diagnostics.

Values:

enumerator None

No optional safe-string behavior.

enumerator OnlyAscii

Escape all non-ASCII characters.

enumerator AutoQuotes

Add quotes when the escaped text needs them for readability.

enumerator Defaults
enumerator All
using erbsland::text::SafeStringFlags = util::EnumFlags<SafeStringFlag>

A set of safe string flags.

class StringCharReader

A decoded-character reader for all string encodings.

The reader accepts UTF-8, UTF-16, and UTF-32 strings and exposes one sequential code-point based read API. Copies share the immutable source data but keep independent reader positions.

See: Text Formatting and Parsing

Public Types

using ReadFn = std::function<util::LoopStatus(Char)>

A function type for reading characters.

Returns true to continue reading, false to stop.

Public Functions

StringCharReader()

Create an empty reader.

explicit StringCharReader(const U8StringEditor &text)

Create a reader for a UTF-8 string.

explicit StringCharReader(const U8String &text)

Create a reader for a UTF-8 read-only string.

explicit StringCharReader(const U16StringEditor &text)

Create a reader for a UTF-16 string.

explicit StringCharReader(const U16String &text)

Create a reader for a UTF-16 read-only string.

explicit StringCharReader(const U32StringEditor &text)

Create a reader for a UTF-32 string.

explicit StringCharReader(const U32String &text)

Create a reader for a UTF-32 read-only string.

explicit StringCharReader(const AnyStringEditor &text)

Create a reader for AnyStringEditor.

explicit StringCharReader(const AnyString &text)

Create a reader for AnyString.

unit::CpIndex position() const noexcept

Get the current decoded code-point position.

The value is suitable for user-facing error locations. Malformed encoded units count as one replacement character in tolerant operations.

Returns:

The current code-point position.

StringCharReaderState save() const noexcept

Save the current reader state.

The saved state is only restorable for a reader over the same visible storage range and encoding backend.

Returns:

A saved reader state. This state only works for readers with the same backend and visible storage range.

void restore(StringCharReaderState state) noexcept

Restore a saved reader state in constant time.

The state must originate from this reader or a compatible copy over the same visible text and encoding. Passing any other state is undefined.

Parameters:

state – The reader state to restore.

void reset() noexcept

Reset the reader position to the start of the string.

Char read() noexcept

Read a character, tolerating malformed encoding, and advance on success.

At the end of data, this returns Char::endOfData() and keeps the current position unchanged.

Returns:

The read character, or Char::endOfData() if at the end of data.

bool readIf(Char expected) noexcept

Read a character only if it matches a given character.

If there is no match, the current position is unchanged. Signal characters never match. Malformed encoding is handled like read() and may match a replacement character.

Parameters:

expected – The character to match.

Returns:

true if the character was read and matched, false otherwise.

std::optional<Char> readIf(const CharSet &expected) noexcept

Read a character only if it matches a given character set.

If there is no match, the current position is unchanged. Signal characters never match. Malformed encoding is handled like read() and may match a replacement character from the expected set.

Parameters:

expected – The character set to match.

Returns:

The character if it matches, std::nullopt otherwise.

Char peek() const noexcept

Peek a character, tolerating malformed encoding.

This method never advances the current position.

bool advance() noexcept

Advance by one decoded character (Skip one character).

Returns:

true if the cursor was moved, false if at the end of data.

bool advanceIf(Char expected) noexcept

Advance one character if it matches a given character (Skip if).

Signal characters never match.

Parameters:

expected – The character to match.

Returns:

true if the character matched and the position was advanced, false otherwise.

bool advanceIf(const CharSet &expected) noexcept

Advance one character if it matches a given character set (Skip if).

Signal characters never match.

Parameters:

expected – The character set to match.

Returns:

true if the character matched and the position was advanced, false otherwise.

bool advanceIf(const String &expected, CharCompareFn compareFn = {}) noexcept

Advance if the following decoded characters match an expected UTF-8 string.

The current position remains unchanged if the complete string does not match. An empty expected string succeeds without changing the position. Malformed source and expected text is compared tolerantly as replacement characters.

Parameters:
  • expected – The decoded character sequence to match.

  • compareFn – The optional character comparison function.

Returns:

true if the complete string matched and was skipped, false otherwise.

bool advance(unit::CpLength count) noexcept

Advance by decoded characters.

Tolerant decoding rules are used for malformed encoded data. Returns false when no movement was possible, returns true if moves at least one character.

void advanceOrThrow()

Advance by one decoded character or throw if no movement was possible.

void advanceOrThrow(unit::CpLength count)

Advance by decoded characters or throw if no movement was possible.

bool isAtEnd() const noexcept

Test if the reader is at the end of data.

bool canRead(unit::CpLength count) const noexcept

Test if at least count decoded characters are available.

auto readWhile(const ReadFn &readFn, const CharSet &expected, unit::CpLength maximum = unit::CpLength::infinite()) noexcept -> util::LoopResult

Read characters while they match an expected set of characters.

Does not consume a character that does not match. If the read function requests a stop or an error, the reader position is pointing to the character that caused the stop or error.

Parameters:
  • readFn – The read function, or nullptr to continue for all read characters.

  • expected – The expected character set.

  • maximum – The maximum number of characters to read.

Returns:

LoopResult::Success when the first character does not match, LoopResult::Stopped when the read function requested a stop, LoopResult::LimitReached if maximum was reached, but the next character would match expected too, LoopResult::EndOfData if the end of the string was reached, LoopResult::Error if the function reports an error.

auto readWhile(const ReadFn &readFn, AsciiCategory expected, unit::CpLength maximum = unit::CpLength::infinite()) noexcept -> util::LoopResult

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

auto readUntil(const ReadFn &readFn, const CharSet &stopSet, unit::CpLength maximum = unit::CpLength::infinite()) noexcept -> util::LoopResult

Read characters until, but without a character from the given set.

Does not consume the stop character.

Parameters:
  • readFn – The read function, or nullptr to continue for all read characters.

  • stopSet – The set with stop characters.

  • maximum – The maximum number of characters to read.

Returns:

LoopResult::Success when a stop character was encountered, LoopResult::Stopped when the read requested a stop, LoopResult::LimitReached if maximum was reached, but the next character would not match stopSet, LoopResult::EndOfData if the end of the string was reached, LoopResult::Error if the function reports an error.

auto readUntil(const ReadFn &readFn, AsciiCategory stopCategory, unit::CpLength maximum = unit::CpLength::infinite()) noexcept -> util::LoopResult

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

unit::CpLength advanceWhile(const CharSet &expected, unit::CpLength maximum = unit::CpLength::infinite()) noexcept

Advance while decoded characters match expected.

Stops before the first nonmatching character, at the end of data, or after maximum characters. Malformed encoded data is handled tolerantly like read(). The returned count may be ignored when only the skip side effect is needed.

Parameters:
  • expected – The expected character set.

  • maximum – The maximum number of characters to advance.

Returns:

The number of decoded characters skipped.

unit::CpLength advanceWhile(AsciiCategory expected, unit::CpLength maximum = unit::CpLength::infinite()) noexcept

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

unit::CpLength advanceUntil(const CharSet &stopSet, unit::CpLength maximum = unit::CpLength::infinite()) noexcept

Advance until, but without consuming, a decoded character from stopSet.

Stops before the first matching character, at the end of data, or after maximum characters. Malformed encoded data is handled tolerantly like read(). The returned count may be ignored when only the skip side effect is needed.

Parameters:
  • stopSet – The set with stop characters.

  • maximum – The maximum number of characters to advance.

Returns:

The number of decoded characters skipped.

unit::CpLength advanceUntil(AsciiCategory stopCategory, unit::CpLength maximum = unit::CpLength::infinite()) noexcept

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

ReadIntegerResult parseInteger(const IntegerParseOptions &options) noexcept

Parse an integer using configurable low-level parse options.

On failure, the reader position is restored to the original state.

Parameters:

options – The integer parsing options.

Returns:

The parse result.

template<math::AnyIntegerType T>
T readIntegerOrThrow(const IntegerParseOptions &options = IntegerParseOptions::parserDefault())

Read an integer using configurable low-level parse options.

On failure, the reader position is restored to the original state.

Template Parameters:

T – The native or saturating integer type to read.

Parameters:

options – The integer parsing options.

Throws:
  • text::ParseNumberError – when the integer cannot be read.

  • err::OverflowError – when the integer cannot be converted into the requested type.

Returns:

The parsed integer converted into the requested type.

void startCapture() noexcept

Set the capture start position.

AnyString takeCapture() noexcept

Take the current capture and set the new capture start point to the current reader position.

If the capture point is at or before the start position, an empty string is returned. The returned string always matches the encoding of the parsed string, it is returned as an inexpensive slice of that string - no copy is made.

Returns:

The captured string or an empty string if the capture point is invalid.

void clearBuffer() noexcept

Clear all text from the buffer while keeping any retained capacity.

AnyString takeBuffer()

Move out the buffer and reset it.

Returns:

The buffered text as an owning string.

AnyString bufferView() const noexcept

Get the current buffer content without consuming it.

Returns:

The buffer text.

unit::CpLength bufferCharacterLength() const noexcept

Get the current decoded code-point length of the buffer.

Returns:

The buffer length in decoded code points.

bool isBufferEmpty() const noexcept

Test if the buffer is empty.

void setBuffer(const AnyString &text)

Replace the buffer with text converted to the reader encoding.

Parameters:

text – The new buffer content.

void appendToBuffer(Char character)

Append one Unicode code point to the buffer.

Signal characters are ignored.

Parameters:

character – The character to append.

void appendToBuffer(const AnyString &text)

Append text to the buffer, converting it to the reader encoding if needed.

Parameters:

text – The text to append.

void appendCaptureToBuffer()

Take the current capture and append it to the buffer.

Char readToBuffer()

Read a character and append it to the buffer.

At the end of data, this returns Char::endOfData() and does not change the buffer.

Returns:

The read character, or Char::endOfData() if at the end of data.

bool readToBufferIf(Char expected)

Read a character only if it matches and append it to the buffer.

Parameters:

expected – The character to match.

Returns:

true if the character was read, matched, and appended.

std::optional<Char> readToBufferIf(const CharSet &expected)

Read a character only if it matches and append it to the buffer.

Parameters:

expected – The character set to match.

Returns:

The character if it matched and was appended, std::nullopt otherwise.

util::LoopResult readToBufferWhile(const CharSet &expected, unit::CpLength maximum = unit::CpLength::infinite())

Read matching characters and append them to the buffer.

Parameters:
  • expected – The expected character set.

  • maximum – The maximum number of characters to read.

Returns:

The loop result, with the same meaning as readWhile().

util::LoopResult readToBufferWhile(AsciiCategory expected, unit::CpLength maximum = unit::CpLength::infinite())

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

util::LoopResult readToBufferUntil(const CharSet &stopSet, unit::CpLength maximum = unit::CpLength::infinite())

Read characters until, but without, a stop character and append them to the buffer.

Parameters:
  • stopSet – The set with stop characters.

  • maximum – The maximum number of characters to read.

Returns:

The loop result, with the same meaning as readUntil().

auto readToBufferUntil(AsciiCategory stopCategory, unit::CpLength maximum = unit::CpLength::infinite()) -> util::LoopResult

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

class StringCharReaderState

A saved state for StringReader.

This value is intentionally opaque. It stores the reader backend cursor and decoded code-point position. Create it via StringCharReader::save() and only pass it back to the same reader or a compatible copy over the same visible text and encoding. Passing it to any other reader is undefined.

See: Text Formatting and Parsing

Public Functions

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

Test if two saved states are equal.

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

Test if two saved states differ.

using erbsland::text::StringFormat = U8Format

The common string format type.

enum class erbsland::text::StringSide : uint8_t

Select one side of a string-like value.

Values:

enumerator Front

The start of the string.

enumerator Back

The end of the string.

enum class erbsland::text::TruncateMode : uint8_t

The side of a string where text is removed when truncating.

Values:

enumerator End

Keep the beginning and cut at the end.

enumerator Middle

Keep beginning and end, cutting in the middle.

enumerator Begin

Keep the end and cut at the beginning.

class U16Format

A reusable validated UTF-16 format.

See: Text Formatting and Parsing

Public Functions

explicit U16Format(std::u16string_view pattern)

Parse and validate a UTF-16 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

explicit U16Format(const U16String &pattern)

Parse and validate a UTF-16 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

unit::ArgumentCount fieldCount() const noexcept

Get the number of argument fields in the pattern.

template<typename ...Args>
U16String build(Args&&... args) const

Build a UTF-16 string from the arguments.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.

template<typename ...Args>
AnyStringBuilder &appendTo(AnyStringBuilder &builder, Args&&... args) const

Append formatted arguments to a string builder.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.

class U32Format

A reusable validated UTF-32 format.

See: Text Formatting and Parsing

Public Functions

explicit U32Format(std::u32string_view pattern)

Parse and validate a UTF-32 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

explicit U32Format(const U32String &pattern)

Parse and validate a UTF-32 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

unit::ArgumentCount fieldCount() const noexcept

Get the number of argument fields in the pattern.

template<typename ...Args>
U32String build(Args&&... args) const

Build a UTF-32 string from the arguments.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.

template<typename ...Args>
AnyStringBuilder &appendTo(AnyStringBuilder &builder, Args&&... args) const

Append formatted arguments to a string builder.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.

class U8Format

A reusable validated UTF-8 format.

See: Text Formatting and Parsing

Public Functions

explicit U8Format(std::string_view pattern)

Parse and validate a UTF-8 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

explicit U8Format(const U8String &pattern)

Parse and validate a UTF-8 format pattern.

Throws:

text::FormatError – If the pattern is invalid or exceeds format limits.

unit::ArgumentCount fieldCount() const noexcept

Get the number of argument fields in the pattern.

template<typename ...Args>
U8String build(Args&&... args) const

Build a UTF-8 string from the arguments.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.

template<typename ...Args>
AnyStringBuilder &appendTo(AnyStringBuilder &builder, Args&&... args) const

Append formatted arguments to a string builder.

Throws:

text::FormatError – If arguments do not match the pattern or output exceeds limits.