Mercurial > projects > ldc
diff tango/tango/io/stream/EndianStream.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/tango/io/stream/EndianStream.d Fri Jan 11 17:57:40 2008 +0100 @@ -0,0 +1,176 @@ +/******************************************************************************* + + copyright: Copyright (c) 2007 Kris Bell. All rights reserved + + license: BSD style: $(LICENSE) + + version: Initial release: Nov 2007 + + author: Kris + + Streams for swapping endian-order. The stream is treated as a set + of same-sized elements. Note that partial elements are not mutated + +*******************************************************************************/ + +module tango.io.stream.EndianStream; + +private import tango.io.Buffer, + tango.io.Conduit; + +private import tango.core.ByteSwap; + +/******************************************************************************* + + Type T is the element type + +*******************************************************************************/ + +class EndianInput(T) : InputFilter +{ + static if ((T.sizeof != 2) && (T.sizeof != 4) && (T.sizeof != 8)) + pragma (msg, "EndianInput :: type should be of length 2, 4, or 8 bytes"); + + + private IBuffer input; + + /*********************************************************************** + + ***********************************************************************/ + + this (InputStream stream) + { + super (input = Buffer.share (stream)); + } + + /*********************************************************************** + + Buffered interface + + ***********************************************************************/ + + final IBuffer buffer () + { + return input; + } + + /*********************************************************************** + + Read from conduit into a target array. The provided dst + will be populated with content from the conduit. + + Returns the number of bytes read, which may be less than + requested in dst (or IOStream.Eof for end-of-flow). Note + that a trailing partial element will be placed into dst, + but the returned length will effectively ignore it + + ***********************************************************************/ + + final override uint read (void[] dst) + { + uint len = input.fill (dst[0 .. dst.length & ~(T.sizeof-1)]); + if (len != Eof) + { + // the final read may be misaligned ... + len &= ~(T.sizeof - 1); + + static if (T.sizeof == 2) + ByteSwap.swap16 (dst.ptr, len); + + static if (T.sizeof == 4) + ByteSwap.swap32 (dst.ptr, len); + + static if (T.sizeof == 8) + ByteSwap.swap64 (dst.ptr, len); + } + return len; + } +} + + + +/******************************************************************************* + + Type T is the element type + +*******************************************************************************/ + +class EndianOutput (T) : OutputFilter +{ + static if ((T.sizeof != 2) && (T.sizeof != 4) && (T.sizeof != 8)) + pragma (msg, "EndianOutput :: type should be of length 2, 4, or 8 bytes"); + + private IBuffer output; + + /*********************************************************************** + + ***********************************************************************/ + + this (OutputStream stream) + { + super (output = Buffer.share (stream)); + } + + /*********************************************************************** + + Write to output stream from a source array. The provided + src content will be consumed and left intact. + + Returns the number of bytes written from src, which may + be less than the quantity provided. Note that any partial + elements will not be consumed + + ***********************************************************************/ + + final override uint write (void[] src) + { + uint writer (void[] dst) + { + auto len = dst.length; + if (len > src.length) + len = src.length; + + len &= ~(T.sizeof - 1); + dst [0..len] = src [0..len]; + + static if (T.sizeof == 2) + ByteSwap.swap16 (dst.ptr, len); + + static if (T.sizeof == 4) + ByteSwap.swap32 (dst.ptr, len); + + static if (T.sizeof == 8) + ByteSwap.swap64 (dst.ptr, len); + + return len; + } + + uint bytes = src.length; + + // flush if we used all buffer space + if ((bytes -= output.write (&writer)) >= T.sizeof) + if (output.output) + output.drain (output.output); + else + return Eof; + return src.length - bytes; + } +} + + +/******************************************************************************* + +*******************************************************************************/ + +debug (UnitTest) +{ + import tango.io.Stdout; + + unittest + { + auto inp = new EndianInput!(dchar)(new Buffer("hello world"d)); + auto oot = new EndianOutput!(dchar)(new Buffer(64)); + oot.copy (inp); + assert (oot.output.slice == "hello world"d); + } +}