Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.format

@nogc Formatting Utilities

Authors:
Ilya Yaroshenko
Examples:
mir.conv: to extension.
import mir.conv: to;
import mir.small_string;
alias S = SmallString!32;

assert(123.0.to!S == "123");
assert(123.to!(immutable S) == "123");
assert(true.to!S == "true");
assert(true.to!string == "true");

assert((cast(S)"str")[] == "str");

auto str = S("str");
assert(str.to!(const(char)[]) == "str"); // scope result
assert(str.to!(char[]) == "str"); // scope result
Examples:
ditto
import mir.conv: to;
import mir.small_string;
alias S = SmallString!32;

assert(123.0.to!string == "123");
assert(123.to!(char[]) == "123");

assert(S("str").to!string == "str"); // GC allocated result
string text(string separator = "", A...)(auto ref A args)
if (A.length > 0);
Concatenated string results
Examples:
assert(text("str ", true, " ", 100, " ", 124.1) == "str true 100 124.1");
assert(text!" "("str", true, 100, 124.1) == "str true 100 124.1");
struct GetData;
enum GetData getData;
struct _stringBuf(C);

alias stringBuf = _stringBuf!char._stringBuf;

alias wstringBuf = _stringBuf!wchar._stringBuf;

alias dstringBuf = _stringBuf!dchar._stringBuf;
ScopedBuffer!C buffer;
template StreamFormatOp(C)
Examples:
auto name = "D";
auto ver = 2.0;
assert(stringBuf() << "Hi " << name << ver << "!\n" << getData == "Hi D2!\n");
Examples:
auto name = "D"w;
auto ver = 2;
assert(wstringBuf() << "Hi "w << name << ver << "!\n"w << getData == "Hi D2!\n"w);
Examples:
auto name = "D"d;
auto ver = 2;
assert(dstringBuf() << "Hi "d  << name << ver << "!\n"d << getData == "Hi D2!\n");
ref scope typeof(this) opBinary(string op : "<<", T)(ref const T c);
ref scope typeof(this) opBinary(string op : "<<", T)(const T c);

scope const(C)[] opBinary(string op : "<<", T : GetData)(const T c);
struct FormatSpec;
C's compatible format specifier.
bool dash;
bool plus;
bool space;
bool hash;
bool zero;
char format;
char separator;
ubyte unitSize;
int width;
int precision;
enum SwitchLU: bool;
lower
upper
struct FormattedFloating(T) if (is(T == float) || is(T == double) || is(T == real));

FormattedFloating!T withFormat(T)(const T value, FormatSpec spec);
T value;
FormatSpec spec;
const scope void toString(C = char, W)(ref scope W w);
struct HexAddress(T) if (isUnsigned!T && !is(T == enum));
T value;
SwitchLU switchLU;
const scope void toString(C = char, W)(ref scope W w);
ref W printEscaped(C = char, W)(return ref scope W w, scope const(char)[] str);

Note Non-ASCII Unicode characters are encoded as sequence of \xXX bytes. This may be fixed in the future.

Examples:
import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
assert(w.printEscaped("Hi\t" ~ `"@nogc"`).data == `"Hi\t\"@nogc\""`, w.data);
w.reset;
assert(w.printEscaped("\xF3").data == `"\xF3"`, w.data);
ref W printElement(C = char, W, T)(return ref scope W w, auto ref scope const T c);
ref W print(C = char, W, Args...)(return ref scope W w, auto ref scope const Args args)
if (Args.length > 1);
Multiargument overload.
ref W print(C = char, W, T)(return ref scope W w, const T c)
if (is(T == enum));

ref W print(C = char, W)(return ref scope W w, bool c);

ref W print(C = char, W, V, K)(return ref scope W w, scope const V[K] c);

ref W print(C = char, W, T)(return ref scope W w, scope const(T)[] c)
if (!isSomeChar!T);

ref W print(C = char, W)(return ref scope W w, char c);

ref W print(C = char, W)(return ref scope W w, scope const(C)[] c)
if (isSomeChar!C);

ref W print(C = char, W, I)(return ref scope W w, const I c)
if (isIntegral!I && !is(I == enum));

ref W print(C = char, W, T)(return ref scope W w, const T c)
if (is(T == float) || is(T == double) || is(T == real));

ref W print(C = char, W, T)(return ref scope W w, ref const T c)
if (is(T == struct) || is(T == union));

ref W print(C = char, W, T)(return ref scope W w, scope const T c)
if (is(T == struct) || is(T == union));

ref W print(C = char, W, T)(return ref scope W w, scope const T c)
if (is(T == class) || is(T == interface));
Examples:
enum Flag
{
    no,
    yes,
}

import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
w.print(Flag.yes);
assert(w.data == "yes", w.data);
Examples:
import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
assert(w.print(true).data == `true`, w.data);
w.reset;
assert(w.print(false).data == `false`, w.data);
Examples:
import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
w.print(["a": 1, "b": 2]);
assert(w.data == `["a": 1, "b": 2]` || w.data == `["b": 2, "a": 1]`, w.data);
Examples:
import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
string[2] array = ["a\ta", "b"];
assert(w.print(array[]).data == `["a\ta", "b"]`, w.data);
Examples:
import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
assert(w
    .print('\n')
    .print('\'')
    .print('a')
    .print('\xF4')
    .data == `'\n''\'''a''\xF4'`);
Examples:
static struct A { scope void toString(C, W)(scope ref W w) const { w.put(C('a')); } }
static struct S { scope void toString(W)(scope ref W w) const { w.put("s"); } }
static struct D { scope void toString(Dg)(scope Dg sink) const { sink("d"); } }
static struct F { scope const(char)[] toString()() const return { return "f"; } }
static struct G { const(char)[] s = "g"; alias s this; }

import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
assert(stringBuf() << A() << S() << D() << F() << G() << getData == "asdfg");
Examples:
static class A { void toString(C, W)(scope ref W w) const { w.put(C('a')); } }
static class S { void toString(W)(scope ref W w) const { w.put("s"); } }
static class D { void toString(Dg)(scope Dg sink) const { sink("d"); } }
static class F { const(char)[] toString()() const return { return "f"; } }
static class G { const(char)[] s = "g"; alias s this; }

import mir.appender: ScopedBuffer;
ScopedBuffer!char w;
assert(stringBuf() << new A() << new S() << new D() << new F() << new G() << getData == "asdfg");
ref W printZeroPad(C = char, W, I)(return ref scope W w, const I c, size_t minimalLength)
if (isIntegral!I && !is(I == enum));
Examples:
import mir.appender;
ScopedBuffer!char w;

w.printZeroPad(-123, 5);
w.put(' ');
w.printZeroPad(123, 5);

assert(w.data == "-0123 00123", w.data);
size_t printBoolean(C)(bool c, ref C[5] buf)
if (is(C == char) || is(C == wchar) || is(C == dchar));
size_t printStaticString(string str, C)(ref scope C[str.length] buf)
if ((is(C == char) || is(C == wchar) || is(C == dchar)) && ((C[str.length]).sizeof <= 512));

size_t printStaticString(wstring str, C)(ref scope C[str.length] buf)
if ((is(C == wchar) || is(C == dchar)) && ((C[str.length]).sizeof <= 512));

size_t printStaticString(dstring str)(ref scope dchar[str.length] buf)
if ((dchar[str.length]).sizeof <= 512);