Thread overview
writef / doFormat without formatting.
Sep 15, 2005
AJG
Sep 15, 2005
Derek Parnell
Sep 17, 2005
AJG
September 15, 2005
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.
September 15, 2005
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
September 17, 2005
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.