Compatibility Format Specifications
Existing C++ formatting knowledge is useful when reading compact patterns such as {:08x} or {:.2f}.
Erbsland Core supports a practical subset of that syntax so small patterns and migrated code remain familiar.
This compatibility layer is deliberately narrower than std::format and less self-describing than the named Core
syntax.
Use Named Format Specifications for new application-owned patterns, especially when a field
should enforce its value type; use this page when maintaining or translating compact specifications.
Compact Format Grammar
The supported grammar is:
[[fill]align][sign][#][0][width][.precision][type]
Every part is optional.
Alignment is < for left, > for right, or ^ for centered output, and the supported fill characters are space
and 0.
The sign is +, -, or space; # requests an alternate integer form; and a leading 0 before the width
requests numeric zero filling.
Width and text precision count decoded code points rather than encoded bytes.
Integer Presentation Letters and Padding
Integer presentation letters are d for decimal, x /X for hexadecimal, b /B for binary, and o
/O for octal.
Uppercase letters select uppercase digits and prefixes.
Integer precision is the minimum digit count, while width applies to the complete signed and prefixed result.
Text Precision and Alignment
Text may use s explicitly or omit the presentation type.
Precision limits the source by decoded code points before alignment, which keeps a multibyte UTF-8 character intact.
Text defaults to left alignment; numeric values default to right alignment.
text/StringFormat/TextFormats.cpp
/// Text format specifications control the alignment and truncation of text output.
void textFormats() {
const auto textPattern = el::StringFormat("{:<8}|{:>8}|{:^8}|{:.3s}"_el);
el::io::printLine(textPattern.build("cat"_el, "cat"_el, "cat"_el, "abcdef"_el));
}
Output
cat | cat| cat |abc
Floating-Point Notation and Precision
Floating-point presentation letters are f /F for fixed, e /E for scientific, g /G for general,
and a /A for hexadecimal notation.
Precision is forwarded to FloatFormat and therefore follows the selected notation.
Compact Text Escaping Extensions
The slash presentations are Erbsland Core extensions to the compatibility grammar.
/html, /json, /xml, /cpp, and /pcre escape text for the selected destination.
The suffix -, =, +, or * selects minimal, balanced, non-ASCII, or complete escaping respectively.
Precision is applied before escaping and width afterward.
Named text specifications express the same intent more clearly, for example
{:text:escape=json,escape-amount=non-ascii}.
The compact forms remain useful when preserving an existing pattern.
text/StringFormat/EscapeFormat.cpp
/// Escape format specifications control the HTML escaping of text output.
void escapeFormat() {
const auto pattern = el::StringFormat("<p>{:/html}</p>\n{:>12/html}"_el);
el::io::printLine(pattern.build("<script>alert(\"xss\")</script>"_el, "<p>"_el));
}
Output
<p><script>alert("xss")</script></p>
<p>
text/StringFormat/EscapeAmount.cpp
/// Escape format amount is controlled using a suffix after the specifier.
void escapeAmount() {
const auto pattern = el::StringFormat("/json : {0:/json}\n/json+ : {0:/json+}\n/json* : {0:/json*}"_el);
el::io::printLine(pattern.build("café\n"_el));
}
Output
/json : café\n
/json+ : caf\u00E9\n
/json* : \u0063\u0061\u0066\u00E9\n
Unsupported Compatibility Format Features
Dynamic width and precision, nested replacement fields, locale-specific formatting, chrono formatting, range formatting, and arbitrary fill characters are not part of this layer. Integer precision is a minimum digit count, and all string widths use decoded code-point measurements for text layout.
These limits keep the implementation predictable, but they also make the named syntax the better choice when a pattern needs to communicate more than one or two compact options.
Complete demo sources
text/StringFormat/IntegerFormats.cpp
// Copyright (c) 2026 Tobias Erbsland - https://erbsland.dev
// SPDX-License-Identifier: Apache-2.0
#include <DemoCommon.hpp>
#include <erbsland/StandardStreams.hpp>
#include <erbsland/StringFormat.hpp>
namespace demo {
/// Integer format specifications control the base and padding of numeric output.
void integerFormats() {
const auto pattern = el::StringFormat("{:+d} {:#x} {:.4d} {:8.4d}"_el);
el::io::printLine(pattern.build(42, 42, 42, 42));
}
}
text/StringFormat/TextFormats.cpp
// Copyright (c) 2026 Tobias Erbsland - https://erbsland.dev
// SPDX-License-Identifier: Apache-2.0
#include <DemoCommon.hpp>
#include <erbsland/StandardStreams.hpp>
#include <erbsland/StringFormat.hpp>
namespace demo {
/// Text format specifications control the alignment and truncation of text output.
void textFormats() {
const auto textPattern = el::StringFormat("{:<8}|{:>8}|{:^8}|{:.3s}"_el);
el::io::printLine(textPattern.build("cat"_el, "cat"_el, "cat"_el, "abcdef"_el));
}
}
text/StringFormat/FloatFormats.cpp
// Copyright (c) 2026 Tobias Erbsland - https://erbsland.dev
// SPDX-License-Identifier: Apache-2.0
#include <DemoCommon.hpp>
#include <erbsland/StandardStreams.hpp>
#include <erbsland/StringFormat.hpp>
namespace demo {
/// Float format specifications control the precision and sign of floating-point output.
void floatFormats() {
const auto floatPattern = el::StringFormat("{:.2f} {:+8.1f}"_el);
el::io::printLine(floatPattern.build(12.345, 1.25));
}
}
text/StringFormat/EscapeFormat.cpp
// Copyright (c) 2026 Tobias Erbsland - https://erbsland.dev
// SPDX-License-Identifier: Apache-2.0
#include <DemoCommon.hpp>
#include <erbsland/StandardStreams.hpp>
#include <erbsland/StringFormat.hpp>
namespace demo {
/// Escape format specifications control the HTML escaping of text output.
void escapeFormat() {
const auto pattern = el::StringFormat("<p>{:/html}</p>\n{:>12/html}"_el);
el::io::printLine(pattern.build("<script>alert(\"xss\")</script>"_el, "<p>"_el));
}
}
text/StringFormat/EscapeAmount.cpp
// Copyright (c) 2026 Tobias Erbsland - https://erbsland.dev
// SPDX-License-Identifier: Apache-2.0
#include <DemoCommon.hpp>
#include <erbsland/StandardStreams.hpp>
#include <erbsland/StringFormat.hpp>
namespace demo {
/// Escape format amount is controlled using a suffix after the specifier.
void escapeAmount() {
const auto pattern = el::StringFormat("/json : {0:/json}\n/json+ : {0:/json+}\n/json* : {0:/json*}"_el);
el::io::printLine(pattern.build("café\n"_el));
}
}