www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - writef / doFormat without formatting.

reply AJG <AJG nospam.com> writes:
Hi there,

Is there a version of writef or doFormat that doesn't expect 
printf-style formatting?

A lot of times what I wish to do is simply print a series of variables, 
without having to worry about whether there's a '%' in there.

So, for example:

foo("%s%d ", 42, " %x ", 13.3);

Would print:

"%s%d 42 %x 13.3"

Is there currently a way to do this with a special function?

I think there should be a version of doFormat simply prints everything 
it encounters without formatting it. Does anybody have anything like that?

I quickly built two versions, but I have a feeling there's a better way 
to do this. Any help is appreciated.

The first version uses std.boxer, which is a little inefficient for a 
simple print function:

void echo(...) {
     foreach (std.boxer.Box b; std.boxer.boxArray(_arguments, _argptr))
         writef("%s", b.toString);
}

Then, I took a look at std.boxer's own toString function and modified it 
a little to get this:

void echo(...) {
     foreach (TypeInfo ti; _arguments) {
         if (ti is null) {
             writef("<null>");
             continue;
         }

         TypeInfo[2]  args;
         const size_t ssize  = string.sizeof;
         void[]       data   = new void[ssize + ti.tsize];
         string       format = "%s", result;

         void putc(dchar c) { std.utf.encode(result, c); }
         args[0]          = typeid(string);
         args[1]          = ti;
         data[0 .. ssize] = (cast (void*) &format)[0 .. ssize];
         data[ssize .. $] = _argptr[0 .. ti.tsize];
         std.format.doFormat(&putc, args, data);
         delete data;
         writef("%s", result);
         _argptr += (ti.tsize + int.sizeof - 1) & ~(int.sizeof - 1);
     }
}

Any suggestions? I think std.stdio should have something like this built-in.

Thanks,
--AJG.
Sep 14 2005
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 15 Sep 2005 02:45:20 -0400, AJG wrote:

 Hi there,
 
 Is there a version of writef or doFormat that doesn't expect 
 printf-style formatting?
 
 A lot of times what I wish to do is simply print a series of variables, 
 without having to worry about whether there's a '%' in there.
 
 So, for example:
 
 foo("%s%d ", 42, " %x ", 13.3);
 
 Would print:
 
 "%s%d 42 %x 13.3"
 
 Is there currently a way to do this with a special function?
 
 I think there should be a version of doFormat simply prints everything 
 it encounters without formatting it. Does anybody have anything like that?
 
 I quickly built two versions, but I have a feeling there's a better way 
 to do this. Any help is appreciated.
 
 The first version uses std.boxer, which is a little inefficient for a 
 simple print function:
 
 void echo(...) {
      foreach (std.boxer.Box b; std.boxer.boxArray(_arguments, _argptr))
          writef("%s", b.toString);
 }
 
 Then, I took a look at std.boxer's own toString function and modified it 
 a little to get this:
 
 void echo(...) {
      foreach (TypeInfo ti; _arguments) {
          if (ti is null) {
              writef("<null>");
              continue;
          }
 
          TypeInfo[2]  args;
          const size_t ssize  = string.sizeof;
          void[]       data   = new void[ssize + ti.tsize];
          string       format = "%s", result;
 
          void putc(dchar c) { std.utf.encode(result, c); }
          args[0]          = typeid(string);
          args[1]          = ti;
          data[0 .. ssize] = (cast (void*) &format)[0 .. ssize];
          data[ssize .. $] = _argptr[0 .. ti.tsize];
          std.format.doFormat(&putc, args, data);
          delete data;
          writef("%s", result);
          _argptr += (ti.tsize + int.sizeof - 1) & ~(int.sizeof - 1);
      }
 }
 
 Any suggestions? I think std.stdio should have something like this built-in.

Here is my 'stringer' module. It works for every thing except structs and non-character arrays. <code> private { import std.string; import std.utf; import std.stdarg; import std.cstream; } char[] stringer(TypeInfo[] pArgTypes, va_list pArgValues) { char[] lResult; foreach (TypeInfo lTI; pArgTypes) { if (lTI is typeid(int)) { lResult ~= std.string.toString(va_arg!(int)(pArgValues)); } else if (lTI is typeid(uint)) { lResult ~= std.string.toString(va_arg!(uint)(pArgValues)); } else if (lTI is typeid(bit)) { lResult ~= std.string.toString(va_arg!(bit)(pArgValues)); } else if (lTI is typeid(byte)) { lResult ~= std.string.toString(va_arg!(byte)(pArgValues)); } else if (lTI is typeid(ubyte)) { lResult ~= std.string.toString(va_arg!(ubyte)(pArgValues)); } else if (lTI is typeid(short)) { lResult ~= std.string.toString(va_arg!(short)(pArgValues)); } else if (lTI is typeid(ushort)) { lResult ~= std.string.toString(va_arg!(ushort)(pArgValues)); } else if (lTI is typeid(long)) { lResult ~= std.string.toString(va_arg!(long)(pArgValues)); } else if (lTI is typeid(ulong)) { lResult ~= std.string.toString(va_arg!(ulong)(pArgValues)); } else if (lTI is typeid(float)) { lResult ~= std.string.toString(va_arg!(float)(pArgValues)); } else if (lTI is typeid(double)) { lResult ~= std.string.toString(va_arg!(double)(pArgValues)); } else if (lTI is typeid(real)) { lResult ~= std.string.toString(va_arg!(real)(pArgValues)); } else if (lTI is typeid(ireal)) { lResult ~= std.string.toString(va_arg!(ireal)(pArgValues)); } else if (lTI is typeid(creal)) { lResult ~= std.string.toString(va_arg!(creal)(pArgValues)); } else if (lTI is typeid(ifloat)) { lResult ~= std.string.toString(va_arg!(ifloat)(pArgValues)); } else if (lTI is typeid(cfloat)) { lResult ~= std.string.toString(va_arg!(cfloat)(pArgValues)); } else if (lTI is typeid(idouble)) { lResult ~= std.string.toString(va_arg!(idouble)(pArgValues)); } else if (lTI is typeid(cdouble)) { lResult ~= std.string.toString(va_arg!(cdouble)(pArgValues)); } else if (lTI is typeid(char)) { lResult ~= std.string.toString(va_arg!(char)(pArgValues)); } else if (lTI is typeid(char[])) { lResult ~= va_arg!(char[])(pArgValues); } else if (lTI is typeid(wchar)) { wchar[1] lTemp; lTemp[0] = va_arg!(wchar)(pArgValues); lResult ~= toUTF8(lTemp[0..0]); } else if (lTI is typeid(wchar[])) { lResult ~= toUTF8(va_arg!(wchar[])(pArgValues)); } else if (lTI is typeid(dchar)) { dchar[1] lTemp; lTemp[0] = va_arg!(dchar)(pArgValues); lResult ~= toUTF8(lTemp[0..0]); } else if (lTI is typeid(dchar[])) { lResult ~= toUTF8(va_arg!(dchar[])(pArgValues)); } else { if (lTI.tsize() == 0) pArgValues += 8; // Skip over bad data else lResult ~= (va_arg!(Object)(pArgValues)).toString; } } return lResult; } char[] toString(...) { return stringer(_arguments, _argptr); } void write(...) { dout.puts(stringer(_arguments, _argptr) ); dout.flush(); } void writeln(...) { dout.puts(stringer(_arguments, _argptr) ); dout.puts("\n"); dout.flush(); } </code> For example ... <code> import stringer; class Foo { char[] toString() { return " i am foo "; } } void main() { Foo f = new Foo; writeln( "one=", 1, " %but ", 23.0L, " is "d, true, ':', f, ":"w); } </code> -- Derek Parnell Melbourne, Australia 15/09/2005 7:44:18 PM
Sep 15 2005
parent AJG <AJG nospam.com> writes:
Derek Parnell wrote:
 On Thu, 15 Sep 2005 02:45:20 -0400, AJG wrote:
 
 
Hi there,

Is there a version of writef or doFormat that doesn't expect 
printf-style formatting?

A lot of times what I wish to do is simply print a series of variables, 
without having to worry about whether there's a '%' in there.

So, for example:

foo("%s%d ", 42, " %x ", 13.3);

Would print:

"%s%d 42 %x 13.3"

Is there currently a way to do this with a special function?

I think there should be a version of doFormat simply prints everything 
it encounters without formatting it. Does anybody have anything like that?

I quickly built two versions, but I have a feeling there's a better way 
to do this. Any help is appreciated.

The first version uses std.boxer, which is a little inefficient for a 
simple print function:

void echo(...) {
     foreach (std.boxer.Box b; std.boxer.boxArray(_arguments, _argptr))
         writef("%s", b.toString);
}

Then, I took a look at std.boxer's own toString function and modified it 
a little to get this:

void echo(...) {
     foreach (TypeInfo ti; _arguments) {
         if (ti is null) {
             writef("<null>");
             continue;
         }

         TypeInfo[2]  args;
         const size_t ssize  = string.sizeof;
         void[]       data   = new void[ssize + ti.tsize];
         string       format = "%s", result;

         void putc(dchar c) { std.utf.encode(result, c); }
         args[0]          = typeid(string);
         args[1]          = ti;
         data[0 .. ssize] = (cast (void*) &format)[0 .. ssize];
         data[ssize .. $] = _argptr[0 .. ti.tsize];
         std.format.doFormat(&putc, args, data);
         delete data;
         writef("%s", result);
         _argptr += (ti.tsize + int.sizeof - 1) & ~(int.sizeof - 1);
     }
}

Any suggestions? I think std.stdio should have something like this built-in.

Here is my 'stringer' module. It works for every thing except structs and non-character arrays.

 <snip>

Oh, wow, thanks. I think I could put that to good use. --AJG.
Sep 16 2005