Text Placeholders

Replacer expands placeholders in ordinary strings using registered sources and filters. ReplacerOptions selects the frame, separators, and escape mode. Providers can be custom implementations of Source and Filter, or the built-in environment, variable, and text providers.

Use Completing Text with Placeholders for the replacement workflow, Using Built-in Placeholder Sources for built-in value sources, Transforming Placeholder Text with Built-in Filters for reusable text filters, Providing Your Own Placeholder Values and Filters for custom providers, and Choosing Placeholder Syntax for Your Text for syntax and escaping. ReplacerError reports a category and optional input offset.

Persistent Secrets

SecureStorageSource resolves ${secure:item} through a namespace-bound cryptology::SecureStorage. Register it explicitly through Replacer::addSource() or conf::Parser::addPlaceholderSource(). It uses current-user Keychain items on macOS and Credential Manager items on Windows; Linux reports unsupported. See Protected Data for storage limits and interaction policy.

Validation checks the item name without accessing storage. Resolution retrieves the value synchronously and preserves its exact UTF-8 text, including whitespace and empty values. Invalid UTF-8 and control characters other than tab, line feed, and carriage return are rejected. Missing items report ReplacerErrorCategory::ValueNotFound; storage access failures report Access. Diagnostics do not include the retrieved value.

Resolved text uses sensitive UTF-8 storage, which propagates through replacement, built-in filters, and concatenation. This does not set conf::Value::isSecret(): applications must annotate secret fields in validation rules and control logging and export. Custom filters remain responsible for plaintext copies they create. See Configuring TLS Profiles for registering the source and loading a signing-key password.

Interface

class EnvironmentSource : public erbsland::text::placeholder::Source

Built-in environment-variable placeholder source.

Public Functions

explicit EnvironmentSource(const String &name = {})

Create the environment source with env or a custom registered name.

virtual StringList sourceNames() const override

Get all source names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual String resolve(const String &sourceName, const String &parameter) override

Resolve a placeholder source.

Parameters:
  • sourceName – The normalized, case-insensitive source name.

  • parameter – The decoded, case-preserving source parameter.

Throws:

ReplacerError – If the source cannot resolve the value.

Returns:

The replacement text.

virtual bool validate(const String &sourceName, const String &parameter) override

Validate a source name and parameter without producing a replacement.

The default calls resolve() and returns false if it throws ReplacerError.

Returns:

true when this source accepts the expression.

enum class erbsland::text::placeholder::EscapeMode : uint8_t

How literal placeholder delimiters are represented.

Values:

enumerator Backslash

A backslash escapes the next delimiter-start code point.

enumerator Double

Repeating a delimiter-start code point makes it literal.

class Filter

A provider for one or more placeholder filters.

See: Completing Text with Placeholders

Subclassed by erbsland::text::placeholder::TextFilter

Public Functions

virtual StringList filterNames() const = 0

Get all filter names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual auto apply(const String &filterName, const String &parameter, const String &value) -> String = 0

Apply a filter to a placeholder value.

Parameters:
  • filterName – The normalized, case-insensitive filter name.

  • parameter – The decoded, case-preserving filter parameter.

  • value – The value from the source or preceding filter.

Throws:

ReplacerError – If the value cannot be filtered.

Returns:

The filtered replacement text.

virtual bool validate(const String &filterName, const String &parameter)

Validate a filter name and parameter without a current value.

The default calls apply() with an empty value and returns false if it throws ReplacerError.

Returns:

true when this filter accepts the expression.

using erbsland::text::placeholder::FilterPtr = std::shared_ptr<Filter>

Shared pointer for a placeholder filter.

class Replacer

Replaces configured placeholders in ordinary UTF-8 strings.

Configure it once and reuse it with one instance per concurrently executing thread.

See: Completing Text with Placeholders

Public Functions

explicit Replacer(ReplacerOptions options = {})

Create a local replacer with validated syntax options.

void addSource(const SourcePtr &source)

Add a source provider, rejecting null, invalid, or duplicate names.

void removeSource(const SourcePtr &source) noexcept

Remove all names of a source provider by pointer identity.

SourcePtr source(const String &name) const

Find a source by its case-insensitive name, or return null.

void addFilter(const FilterPtr &filter)

Add a filter provider, rejecting null, invalid, or duplicate names.

void removeFilter(const FilterPtr &filter) noexcept

Remove all names of a filter provider by pointer identity.

FilterPtr filter(const String &name) const

Find a filter by its case-insensitive name, or return null.

void addEnvironmentSource(const String &name = {})

Register the built-in environment source under env or a custom name.

void setVariableSource(StringMap<String> variables, const String &name = {})

Register or update the built-in variable source under var or a custom name.

void addTextFilters()

Register all built-in text filters.

bool validate(const String &input) const

Test expressions and provider parameters without producing replacement text.

At least one placeholder source must be registered.

void validateOrThrow(const String &input) const

Validate expressions and report the first error with a code-point offset.

At least one placeholder source must be registered.

Throws:

ReplacerError – For malformed syntax or rejected provider parameters.

String replace(const String &input) const

Replace valid expressions; keep invalid expressions unchanged and continue.

At least one placeholder source must be registered.

String replaceOrThrow(const String &input) const

Replace expressions or report the first error with a code-point offset.

At least one placeholder source must be registered.

Throws:

ReplacerError – For malformed syntax or provider failures.

Public Static Functions

static ReplacerPtr create(ReplacerOptions options = {})

Create a shared replacer with validated syntax options.

using erbsland::text::placeholder::ReplacerPtr = std::shared_ptr<Replacer>

Shared pointer to a configured placeholder replacer.

class ReplacerError : public erbsland::err::RuntimeError

An error while parsing or evaluating a placeholder.

The optional offset is a zero-based code-point index in the original input.

Public Functions

inline ReplacerError(ReplacerErrorCategory category, String reason, std::optional<unit::CpIndex> offset = {})

Create an error with a category, reason, and optional input offset.

inline ReplacerErrorCategory category() const noexcept

Get the error category.

inline std::optional<unit::CpIndex> offset() const noexcept

Get the input offset, when available.

inline ReplacerError withOffset(unit::CpIndex offset) const

Return an error with an input offset.

enum class erbsland::text::placeholder::ReplacerErrorCategory : uint8_t

The kind of placeholder processing failure.

Values:

enumerator Syntax

Invalid placeholder or parameter syntax.

enumerator UnexpectedEnd

A placeholder ended without its closing frame.

enumerator LimitExceeded

A configured or expression limit was exceeded.

enumerator Unsupported

A source or filter is not registered.

enumerator ValueNotFound

A requested value does not exist.

enumerator NameConflict

Two normalized names refer to different values.

enumerator Validation

A value failed a required condition.

enumerator Access

A provider denied access to a value.

class ReplacerOptions

Syntax options for a standalone placeholder replacer.

Public Functions

ReplacerOptions()

Create ${...} syntax with | filters, : parameters, and backslash escaping.

ReplacerOptions &setFrame(String begin, String end)

Set nonempty opening and closing frame strings, each at most 16 code points.

ReplacerOptions &setFilterSeparator(String separator)

Set the filter separator; empty disables filters.

ReplacerOptions &setNameSeparator(String separator)

Set the name/parameter separator; empty disables parameters.

ReplacerOptions &setEscapeMode(EscapeMode mode) noexcept

Set the delimiter escape strategy.

inline const String &frameBegin() const noexcept

Get the opening frame.

inline const String &frameEnd() const noexcept

Get the closing frame.

inline const String &filterSeparator() const noexcept

Get the filter separator.

inline const String &nameSeparator() const noexcept

Get the name/parameter separator.

inline EscapeMode escapeMode() const noexcept

Get the escape strategy.

void validate() const

Validate cross-field escape constraints before constructing a replacer.

class SecureStorageSource : public erbsland::text::placeholder::Source

An explicitly registered, namespace-bound ${secure:item} persistent-secret source.

See: Protected Data

Public Functions

inline explicit SecureStorageSource(cryptology::SecureStorage storage)

Bind the source to storage without retrieving secrets or unlocking a vault.

Parameters:

storage – The application namespace and interaction policy to use.

virtual StringList sourceNames() const override

Get all source names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual String resolve(const String &sourceName, const String &parameter) override

Resolve a placeholder source.

Parameters:
  • sourceName – The normalized, case-insensitive source name.

  • parameter – The decoded, case-preserving source parameter.

Throws:

ReplacerError – If the source cannot resolve the value.

Returns:

The replacement text.

virtual bool validate(const String &sourceName, const String &parameter) override

Validate a source name and parameter without producing a replacement.

The default calls resolve() and returns false if it throws ReplacerError.

Returns:

true when this source accepts the expression.

class Source

A provider for one or more placeholder sources.

See: Completing Text with Placeholders

Subclassed by erbsland::text::placeholder::EnvironmentSource, erbsland::text::placeholder::SecureStorageSource, erbsland::text::placeholder::VariableSource

Public Functions

virtual StringList sourceNames() const = 0

Get all source names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual String resolve(const String &sourceName, const String &parameter) = 0

Resolve a placeholder source.

Parameters:
  • sourceName – The normalized, case-insensitive source name.

  • parameter – The decoded, case-preserving source parameter.

Throws:

ReplacerError – If the source cannot resolve the value.

Returns:

The replacement text.

virtual bool validate(const String &sourceName, const String &parameter)

Validate a source name and parameter without producing a replacement.

The default calls resolve() and returns false if it throws ReplacerError.

Returns:

true when this source accepts the expression.

using erbsland::text::placeholder::SourcePtr = std::shared_ptr<Source>

Shared pointer for a placeholder source.

class TextFilter : public erbsland::text::placeholder::Filter

Built-in text placeholder filters.

Public Functions

virtual StringList filterNames() const override

Get all filter names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual String apply(const String &filterName, const String &parameter, const String &value) override

Apply a filter to a placeholder value.

Parameters:
  • filterName – The normalized, case-insensitive filter name.

  • parameter – The decoded, case-preserving filter parameter.

  • value – The value from the source or preceding filter.

Throws:

ReplacerError – If the value cannot be filtered.

Returns:

The filtered replacement text.

virtual bool validate(const String &filterName, const String &parameter) override

Validate a filter name and parameter without a current value.

The default calls apply() with an empty value and returns false if it throws ReplacerError.

Returns:

true when this filter accepts the expression.

class VariableSource : public erbsland::text::placeholder::Source

Built-in application-variable placeholder source.

Public Functions

explicit VariableSource(StringMap<String> variables, const String &name = {})

Create a variable source.

virtual StringList sourceNames() const override

Get all source names implemented by this provider.

Returns:

A non-empty list of unique regular ELCL names.

virtual String resolve(const String &sourceName, const String &parameter) override

Resolve a placeholder source.

Parameters:
  • sourceName – The normalized, case-insensitive source name.

  • parameter – The decoded, case-preserving source parameter.

Throws:

ReplacerError – If the source cannot resolve the value.

Returns:

The replacement text.

virtual bool validate(const String &sourceName, const String &parameter) override

Validate a source name and parameter without producing a replacement.

The default calls resolve() and returns false if it throws ReplacerError.

Returns:

true when this source accepts the expression.

void setVariables(StringMap<String> variables)

Replace all variables.