使用:
int i;
dprintf!"hello %s %s %s %s betty\n"(3, 4.0, &i, "abc".ptr);
重写为:
printf("hello %d %g %p %s betty\n", 3, 4.0, &i, "abc".ptr);
import core.stdc.stdio : printf;
template Seq(A ...) { alias Seq = A; }
int dprintf(string f, A ...)(A args)
{
enum Fmts = Formats!(A);
enum string s = formatString(f, Fmts);
__gshared const(char)* s2 = s.ptr;
return printf(Seq!(s2, args[0..2], args[2..4]));
}
template Formats(T ...)
{
static if (T.length == 0)
enum Formats = [ ];
else static if (T.length == 1)
enum Formats = [Spec!(T[0])];
else
enum Formats = [Spec!(T[0])] ~ Formats!(T[1 .. T.length]);
}
template Spec(T : byte) { enum Spec = "%d"; }
template Spec(T : short) { enum Spec = "%d"; }
template Spec(T : int) { enum Spec = "%d"; }
template Spec(T : long) { enum Spec = "%lld"; }
template Spec(T : ubyte) { enum Spec = "%u"; }
template Spec(T : ushort) { enum Spec = "%u"; }
template Spec(T : uint) { enum Spec = "%u"; }
template Spec(T : ulong) { enum Spec = "%llu"; }
template Spec(T : float) { enum Spec = "%g"; }
template Spec(T : double) { enum Spec = "%g"; }
template Spec(T : real) { enum Spec = "%Lg"; }
template Spec(T : char) { enum Spec = "%c"; }
template Spec(T : wchar) { enum Spec = "%c"; }
template Spec(T : dchar) { enum Spec = "%c"; }
template Spec(T : immutable(char)*) { enum Spec = "%s"; }
template Spec(T : const(char)*) { enum Spec = "%s"; }
template Spec(T : T*) { enum Spec = "%p"; }
/******************************************
* Replace %s format specifiers in f with corresponding specifiers in A[].
* Other format specifiers are left as is.
* Number of format specifiers must match A.length.
* Params:
* f = printf format string
* A = replacement format specifiers
* Returns:
* replacement printf format string
*/
string formatString(string f, string[] A ...)
{
string r;
size_t i;
size_t ai;
while (i < f.length)
{
if (f[i] != '%' || i + 1 == f.length)
{
r ~= f[i];
++i;
continue;
}
char c = f[i + 1];
if (c == '%')
{
r ~= "%%";
i += 2;
continue;
}
assert(ai < A.length, "not enough arguments");
string fmt = A[ai];
++ai;
if (c == 's')
{
r ~= fmt;
i += 2;
continue;
}
r ~= '%';
++i;
continue;
}
assert(ai == A.length, "not enough formats");
return r;
}