www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Pretty fields string

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I've done this a couple of times before but I always had issues, e.g.
functions and property calls would be mixed in. But I think I have a
good go-to function now:

import std.algorithm;
import std.conv;
import std.string;
import std.stdio;
import std.range;

struct Foo
{
    int one = 1;
     property int test() { return 1; }
    int three = 3;
    string[string] aa;
    string toString() { return prettyFieldsString(this); }
}

string prettyFieldsString(T)(T t)
    if (is(T == struct) || is(T == class))
{
    Appender!string result;
    Appender!(string[]) fields;
    Appender!(string[]) values;

    foreach (member; __traits(allMembers, T))
    {
        mixin("
        static if (!is( FunctionTypeOf!(t." ~ member ~ ") ))
        {
            static if (member != " ~ `"toString"` ~ ")
            {
                fields.put(member);
                values.put(to!string(__traits(getMember, t, " ~ `"` ~
member ~ `"` ~ ")));
            }
        }
        ");
    }

    size_t spaceLen = 1;
    foreach (field; fields.data)  // should use reduce!() here..
        spaceLen = max(spaceLen, field.length);

    alias std.array.replicate replicate;
    string spaceString = replicate(" ", spaceLen);

    foreach (field, value; lockstep(fields.data, values.data))
        result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen
- field.length), value));

    return result.data;
}

void main()
{
    Foo foo;
    foo.aa["foo"] = "bar";
    writeln(foo);
}

Sample output: http://paste.pocoo.org/show/558492/

I've had to put everything into one foreach loop since there are still
some CTFE bugs I run into. I also had to add a check against toString,
otherwise I get an infinite loop in the toString() call.

Anyway, feel free to use/improve this function.
Feb 29 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-02-29 10:58, Andrej Mitrovic wrote:
 I've done this a couple of times before but I always had issues, e.g.
 functions and property calls would be mixed in. But I think I have a
 good go-to function now:

 import std.algorithm;
 import std.conv;
 import std.string;
 import std.stdio;
 import std.range;

 struct Foo
 {
      int one = 1;
       property int test() { return 1; }
      int three = 3;
      string[string] aa;
      string toString() { return prettyFieldsString(this); }
 }

 string prettyFieldsString(T)(T t)
      if (is(T == struct) || is(T == class))
 {
      Appender!string result;
      Appender!(string[]) fields;
      Appender!(string[]) values;

      foreach (member; __traits(allMembers, T))
      {
          mixin("
          static if (!is( FunctionTypeOf!(t." ~ member ~ ") ))
          {
              static if (member != " ~ `"toString"` ~ ")
              {
                  fields.put(member);
                  values.put(to!string(__traits(getMember, t, " ~ `"` ~
 member ~ `"` ~ ")));
              }
          }
          ");
      }

      size_t spaceLen = 1;
      foreach (field; fields.data)  // should use reduce!() here..
          spaceLen = max(spaceLen, field.length);

      alias std.array.replicate replicate;
      string spaceString = replicate(" ", spaceLen);

      foreach (field, value; lockstep(fields.data, values.data))
          result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen
 - field.length), value));

      return result.data;
 }

 void main()
 {
      Foo foo;
      foo.aa["foo"] = "bar";
      writeln(foo);
 }

 Sample output: http://paste.pocoo.org/show/558492/

 I've had to put everything into one foreach loop since there are still
 some CTFE bugs I run into. I also had to add a check against toString,
 otherwise I get an infinite loop in the toString() call.

 Anyway, feel free to use/improve this function.

Seems like what I have in my serialization library Orange: https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d "fieldsOf" and "getValueOfField". These work only on instance variables and don't care if the variable is public or not. -- /Jacob Carlborg
Feb 29 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 2/29/12, Jacob Carlborg <doob me.com> wrote:
 Seems like what I have in my serialization library Orange:

Sweet. I was gonna take a look at Orange for just this purpose. Thanks.
Feb 29 2012