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
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 scope 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 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 == 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 const void toString(C, W)(scope ref W w) { w.put(C('a')); } }
static struct S { scope const void toString(W)(scope ref W w) { w.put("s"); } }
static struct D { scope const void toString(Dg)(scope Dg sink) { sink("d"); } }
static struct F { scope const const(char)[] toString()() 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 { scope const void toString(C, W)(scope ref W w) { w.put(C('a')); } }
static class S { scope const void toString(W)(scope ref W w) { w.put("s"); } }
static class D { scope const void toString(Dg)(scope Dg sink) { sink("d"); } }
static class F { scope const const(char)[] toString()() 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);