I have already posted some pull requests around formatting.

#126    Improve std.format.formatValue (-> already merged)
#230    Issue 6448 - writef("%05d", BigInt) problem (-> already merged)
#231    Issue 6595 - std.string.format() and sformat() are obsolete
#235    Change toString signature taking sink
#236    to!SomeString should use formatValue

After merging them, we can use const void toString(scope void
delegate(const(char)[]) sink, ...) at all.

If you need custom formatting with class/struct, you can define
toString taking sink.

class UserClass {
    string name;
    double value;

    // taking sink and formatStr version
    const void toString(scope void delegate(const(char)[]) sink,
string formatStr) {
        formattedWrite(sink, "{%s %s}", name, value)
    }
    // taking sink and FormatSpec!char version, more efficiently than above
    const void toString(scope void delegate(const(char)[]) sink,
FormatSpec!char f) {
        std.range.put(sink, '{');
        std.range.put(sink, name);
        std.range.put(sink, ' ');
        formatValue(sink, value, f);
            // To through spec to 'value' field formatting, then
support %s, %g, %a ...
        std.range.put(sink, '}');
    }
}

And if you need heapfied formatting, you can write like follows:

auto obj = new UserClass("name", 1.0);
assert(std.conv.to!string(obj) == "{name 1.0}");  // used Appender +
formatValue internally
assert(std.string.format("%s", obj) == "{name 1.0}");  // ditto

, and if you really need formatting into stack-allocated buffer:

char[20] buf;
char[] result = std.string.sformat(sink[], "%s", obj);  // When
buf.length is insufficient, FormatError is thrown
assert(result == "{name, 1.0}");

Kenji Hara

Reply via email to