123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
|
/*******************************************************************************
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.Endian;
private import tango.core.ByteSwap;
private import tango.io.device.Conduit;
private import tango.io.stream.Buffered;
/*******************************************************************************
Type T is the element type.
*******************************************************************************/
class EndianInput(T) : InputFilter, InputFilter.Mutator
{
static if ((T.sizeof != 2) && (T.sizeof != 4) && (T.sizeof != 8))
pragma (msg, "EndianInput :: type should be of length 2, 4, or 8 bytes");
/***********************************************************************
***********************************************************************/
this (InputStream stream)
{
super (BufferedInput.create (stream));
}
/***********************************************************************
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 size_t read (void[] dst)
{
auto len = source.read (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, OutputFilter.Mutator
{
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 OutputBuffer output;
/***********************************************************************
***********************************************************************/
this (OutputStream stream)
{
super (output = BufferedOutput.create (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 size_t write (const(void)[] src)
{
size_t 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;
}
return output.writer (&writer);
}
}
/*******************************************************************************
*******************************************************************************/
debug (UnitTest)
{
import tango.io.device.Array;
unittest
{
auto inp = new EndianInput!(dchar)(new Array("hello world"d.dup));
auto oot = new EndianOutput!(dchar)(new Array(64));
oot.copy (inp);
assert (oot.output.slice() == "hello world"d);
}
}
|