format.sformat: Support range-based toString()
This commit is contained in:
parent
5a134ce768
commit
87ba58098e
@ -17,11 +17,19 @@
|
|||||||
* To escape `{` or `}`, use `{{` and `}}` respectively. `{{` will be outputted
|
* To escape `{` or `}`, use `{{` and `}}` respectively. `{{` will be outputted
|
||||||
* as a single `{`, `}}` - as a single `}`.
|
* as a single `{`, `}}` - as a single `}`.
|
||||||
*
|
*
|
||||||
* If a custom data type (like $(D_KEYWORD struct) or $(D_KEYWORD class))
|
* To define the string representation for a custom data type (like
|
||||||
* defines a `stringify()` function that is callable without arguments and
|
* $(D_KEYWORD class) or $(D_KEYWORD struct)), `toString()`-function can be
|
||||||
* returns a $(D_PSYMBOL String), this function is used to produce a string
|
* implemented for that type. `toString()` should be $(D_KEYWORD const) and
|
||||||
* representation for the value. String conversions for the most built-in
|
* accept exactly one argument: an output range for `const(char)[]`. It should
|
||||||
* data types a also available.
|
* return the same output range, advanced after putting the corresponding value
|
||||||
|
* into it. That is `toString()` signature should look like:
|
||||||
|
*
|
||||||
|
* ---
|
||||||
|
* OR toString(OR)(OR range) const
|
||||||
|
* if (isOutputRange!(OR, const(char)[]));
|
||||||
|
* ---
|
||||||
|
*
|
||||||
|
* String conversions for the most built-in data types a also available.
|
||||||
*
|
*
|
||||||
* $(D_KEYWORD char), $(D_KEYWORD wchar) and $(D_KEYWORD dchar) ranges are
|
* $(D_KEYWORD char), $(D_KEYWORD wchar) and $(D_KEYWORD dchar) ranges are
|
||||||
* outputted as plain strings (without any delimiters between their elements).
|
* outputted as plain strings (without any delimiters between their elements).
|
||||||
@ -2271,6 +2279,8 @@ private void printToString(string fmt, OR, Args...)(ref OR result,
|
|||||||
}
|
}
|
||||||
else static if (is(Unqual!(typeof(args[0].stringify())) == String))
|
else static if (is(Unqual!(typeof(args[0].stringify())) == String))
|
||||||
{
|
{
|
||||||
|
pragma(msg, ".stringify() is deprecated. Use toString() with an output"
|
||||||
|
~ " range instead");
|
||||||
static if (is(Arg == class) || is(Arg == interface))
|
static if (is(Arg == class) || is(Arg == interface))
|
||||||
{
|
{
|
||||||
if (args[0] is null)
|
if (args[0] is null)
|
||||||
@ -2287,6 +2297,24 @@ private void printToString(string fmt, OR, Args...)(ref OR result,
|
|||||||
put(result, args[0].stringify()[]);
|
put(result, args[0].stringify()[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else static if (is(typeof(args[0].toString(result)) == OR))
|
||||||
|
{
|
||||||
|
static if (is(Arg == class) || is(Arg == interface))
|
||||||
|
{
|
||||||
|
if (args[0] is null)
|
||||||
|
{
|
||||||
|
put(result, "null");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = args[0].toString(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = args[0].toString(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
else static if (is(Arg == class))
|
else static if (is(Arg == class))
|
||||||
{
|
{
|
||||||
put(result, args[0] is null ? "null" : args[0].toString());
|
put(result, args[0] is null ? "null" : args[0].toString());
|
||||||
@ -2365,7 +2393,7 @@ String format(string fmt, Args...)(auto ref Args args)
|
|||||||
*
|
*
|
||||||
* Returns: $(D_PARAM output).
|
* Returns: $(D_PARAM output).
|
||||||
*/
|
*/
|
||||||
R sformat(string fmt, R, Args...)(return R output, auto ref Args args)
|
R sformat(string fmt, R, Args...)(R output, auto ref Args args)
|
||||||
if (isOutputRange!(R, const(char)[]))
|
if (isOutputRange!(R, const(char)[]))
|
||||||
{
|
{
|
||||||
alias Specs = ParseFmt!fmt;
|
alias Specs = ParseFmt!fmt;
|
||||||
@ -2523,14 +2551,15 @@ if (isOutputRange!(R, const(char)[]))
|
|||||||
}
|
}
|
||||||
assert(format!"{}"(Nested()) == "Nested(0)");
|
assert(format!"{}"(Nested()) == "Nested(0)");
|
||||||
|
|
||||||
static struct WithStringify
|
static struct WithToString
|
||||||
{
|
{
|
||||||
String stringify() const @nogc nothrow pure @safe
|
OR toString(OR)(OR range) const
|
||||||
{
|
{
|
||||||
return String("stringify method");
|
put(range, "toString method");
|
||||||
|
return range;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(format!"{}"(WithStringify()) == "stringify method");
|
assert(format!"{}"(WithToString()) == "toString method");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aggregate types.
|
// Aggregate types.
|
||||||
@ -2552,9 +2581,10 @@ if (isOutputRange!(R, const(char)[]))
|
|||||||
|
|
||||||
class B
|
class B
|
||||||
{
|
{
|
||||||
String stringify() @nogc nothrow pure @safe
|
OR toString(OR)(OR range) const
|
||||||
{
|
{
|
||||||
return String("Class B");
|
put(range, "Class B");
|
||||||
|
return range;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(format!"{}"(cast(B) null) == "null");
|
assert(format!"{}"(cast(B) null) == "null");
|
||||||
|
Loading…
Reference in New Issue
Block a user