123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
/*******************************************************************************

        copyright:      Copyright (c) 2007 Kris Bell. All rights reserved

        license:        BSD style: $(LICENSE)

        version:        Initial release: Nov 2007

        author:         Kris

        Streams to expose simple native types as discrete elements. I/O
        is buffered and should yield fair performance.

*******************************************************************************/

module tango.io.stream.Typed;

private import tango.io.device.Conduit;

private import tango.io.stream.Buffered;

/*******************************************************************************

        Type T is the target or destination type.

*******************************************************************************/

class TypedInput(T) : InputFilter
{
        /***********************************************************************

        ***********************************************************************/

        this (InputStream stream)
        {
                super (BufferedInput.create (stream));
        }

        /***********************************************************************

                Override this to give back a useful chaining reference.

        ***********************************************************************/

        final override TypedInput flush ()
        {
                super.flush();
                return this;
        }

        /***********************************************************************

                Read a value from the stream. Returns false when all
                content has been consumed.

        ***********************************************************************/

        final bool read (ref T x)
        {
                return source.read((&x)[0..1]) is T.sizeof;
        }

        /***********************************************************************

                Iterate over all content.

        ***********************************************************************/

        final int opApply (scope int delegate(ref T x) dg)
        {
                T x;
                int ret;

                while ((source.read((&x)[0..1]) is T.sizeof))
                        if ((ret = dg (x)) != 0)
                             break;
                return ret;
        }
}



/*******************************************************************************

        Type T is the target or destination type.

*******************************************************************************/

class TypedOutput(T) : OutputFilter
{
        /***********************************************************************

        ***********************************************************************/

        this (OutputStream stream)
        {
                super (BufferedOutput.create (stream));
        }

        /***********************************************************************

                Append a value to the output stream.

        ***********************************************************************/

        final void write (ref T x)
        {
                sink.write ((&x)[0..1]);
        }
}


/*******************************************************************************

*******************************************************************************/

debug (UnitTest)
{
        import tango.io.Stdout;
        import tango.io.stream.Utf;
        import tango.io.device.Array;

        unittest
        {
                Array output;

                auto inp = new TypedInput!(char)(new Array("hello world".dup));
                auto oot = new TypedOutput!(char)(output = new Array(20));

                foreach (x; inp)
                         oot.write (x);
                assert (output.slice() == "hello world");

                auto xx = new TypedInput!(char)(new UtfInput!(char, dchar)(new Array("hello world"d.dup)));
                char[] yy;
                foreach (x; xx)
                         yy ~= x;
                assert (yy == "hello world");
        }
}