Bug 4266 – add support for structs in std.format.doFormat
Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2010-06-03T14:08:00Z
Last change time
2014-09-19T22:01:45Z
Assigned to
nobody
Creator
hoganmeier
Comments
Comment #0 by hoganmeier — 2010-06-03T14:08:16Z
Currently there is a check if a struct has a toString member and it fails if not.
It is really cumbersome to code a toString() by hand for every little struct.
if (tis.xtoString is null)
throw new FormatError("Can't convert " ~ tis.toString() ~ " to string: \"string toString()\" not defined");
s = tis.xtoString(argptr);
Especially if you are dealing with external headers (in my case Windows/DirectX headers) you have to face lots of structures that don't have a toString method.
Please add support for a default struct toString that uses the "{membername: value, member2:value, member3:{mm1:v, ....}}" style just like arrays are formatted as "[a, b, c, d,...]" and AAs as "[k1:v1, k2:v2, ..]" by default.
==>
if (tis.xtoString is null)
putStruct(....);
else
s = tis.xtoString(argptr);
Comment #1 by hoganmeier — 2010-06-03T14:42:23Z
This is an (inefficient) workaround, but it does its job until this is fixed.
import std.string : format;
string myformat(T...)(T ts)
{
string res;
foreach (t; ts)
{
static if (is (typeof(t) U : U*) && !is(U == void)) // is a pointer
{
res ~= myformat(*t);
}
else static if (is (typeof(t) == struct))
{
res ~= "{";
foreach(i, el; t.tupleof)
{
res ~= t.tupleof[i].stringof[2..$] ~ ":" ~ myformat(el); // the slice cuts off the "t." that is always prepended
static if (i < t.tupleof.length-1)
res ~= ", ";
}
res ~= "}";
}
else
res ~= format(t);
}
return res;
}
Comment #2 by hoganmeier — 2010-06-03T14:51:03Z
add this branch (+ import std.traits;)
else static if (isSomeString!(typeof(t))) // enclose a string in ""
res ~= `"` ~ t ~ `"`;
and it nearly matches the C struct intialization style (except for pointers, then you need to remove the first branch):
struct S
{
int a;
S2* p;
S2 adad;
}
struct S2
{
byte[4] aaaa = [0,1,2,3];
string ddd = "asd";
}
void main()
{
S2 sss = S2([5,4,5,4], "foo");
S s = S(2, &sss);
write(myformat(s));
}
gives:
{a:2, p:{aaaa:[5,4,5,4], ddd:"foo"}, adad:{aaaa:[0,1,2,3], ddd:"asd"}}
Comment #3 by andrej.mitrovich — 2013-02-18T10:08:30Z
Did the code used to just fail to compile before? Now it prints the values:
import std.string;
import std.stdio;
struct S
{
int x;
float y;
string z;
}
void main()
{
string s = format("%s", S());
writeln(s);
}
> S(0, nan, "")
If that's good enough you can close with "WORKSFORME", thanks.
Comment #4 by hsteoh — 2014-09-19T22:01:45Z
Since there's no response, I'm closing this bug as worksforme (also just confirmed that it works on git HEAD on Linux 64-bit). If there is still a problem, please reopen this bug. Thanks!
Note that doFormat is a very old function that's basically no longer used these days; std.format correctly handles the formatting of structs.