@ -10,9 +10,8 @@ namespace ImageSharp.IO
using System.Text ;
/// <summary>
/// Equivalent of <see cref="BinaryReader"/>, but with either endianness, depending on
/// the EndianBitConverter it is constructed with. No data is buffered in the
/// reader; the client may seek within the stream at will.
/// Equivalent of <see cref="BinaryReader"/>, but with either endianness, depending on the <see cref="EndianBitConverter"/> it is constructed with.
/// No data is buffered in the reader; the client may seek within the stream at will.
/// </summary>
internal class EndianBinaryReader : IDisposable
{
@ -24,7 +23,7 @@ namespace ImageSharp.IO
/// <summary>
/// Buffer used for temporary storage before conversion into primitives
/// </summary>
private readonly byte [ ] b uffer = new byte [ 1 6 ] ;
private readonly byte [ ] storageB uffer = new byte [ 1 6 ] ;
/// <summary>
/// Buffer used for temporary storage when reading a single character
@ -67,26 +66,10 @@ namespace ImageSharp.IO
/// <param name="encoding">Encoding to use when reading character data</param>
public EndianBinaryReader ( EndianBitConverter bitConverter , Stream stream , Encoding encoding )
{
// TODO: Use Guard
if ( bitConverter = = null )
{
throw new ArgumentNullException ( "bitConverter" ) ;
}
if ( stream = = null )
{
throw new ArgumentNullException ( "stream" ) ;
}
if ( encoding = = null )
{
throw new ArgumentNullException ( "encoding" ) ;
}
if ( ! stream . CanRead )
{
throw new ArgumentException ( "Stream isn't writable" , "stream" ) ;
}
Guard . NotNull ( bitConverter , nameof ( bitConverter ) ) ;
Guard . NotNull ( stream , nameof ( stream ) ) ;
Guard . NotNull ( encoding , nameof ( encoding ) ) ;
Guard . IsTrue ( stream . CanRead , nameof ( stream ) , "Stream isn't readable." ) ;
this . BaseStream = stream ;
this . BitConverter = bitConverter ;
@ -140,8 +123,8 @@ namespace ImageSharp.IO
/// <returns>The byte read</returns>
public byte ReadByte ( )
{
this . ReadInternal ( this . b uffer, 1 ) ;
return this . b uffer[ 0 ] ;
this . ReadInternal ( this . storageB uffer, 1 ) ;
return this . storageB uffer[ 0 ] ;
}
/// <summary>
@ -150,8 +133,8 @@ namespace ImageSharp.IO
/// <returns>The byte read</returns>
public sbyte ReadSByte ( )
{
this . ReadInternal ( this . b uffer, 1 ) ;
return unchecked ( ( sbyte ) this . b uffer[ 0 ] ) ;
this . ReadInternal ( this . storageB uffer, 1 ) ;
return unchecked ( ( sbyte ) this . storageB uffer[ 0 ] ) ;
}
/// <summary>
@ -160,8 +143,8 @@ namespace ImageSharp.IO
/// <returns>The boolean read</returns>
public bool ReadBoolean ( )
{
this . ReadInternal ( this . b uffer, 1 ) ;
return this . BitConverter . ToBoolean ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 1 ) ;
return this . BitConverter . ToBoolean ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -171,8 +154,8 @@ namespace ImageSharp.IO
/// <returns>The 16-bit integer read</returns>
public short ReadInt16 ( )
{
this . ReadInternal ( this . b uffer, 2 ) ;
return this . BitConverter . ToInt16 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 2 ) ;
return this . BitConverter . ToInt16 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -182,8 +165,8 @@ namespace ImageSharp.IO
/// <returns>The 32-bit integer read</returns>
public int ReadInt32 ( )
{
this . ReadInternal ( this . b uffer, 4 ) ;
return this . BitConverter . ToInt32 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 4 ) ;
return this . BitConverter . ToInt32 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -193,8 +176,8 @@ namespace ImageSharp.IO
/// <returns>The 64-bit integer read</returns>
public long ReadInt64 ( )
{
this . ReadInternal ( this . b uffer, 8 ) ;
return this . BitConverter . ToInt64 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 8 ) ;
return this . BitConverter . ToInt64 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -204,8 +187,8 @@ namespace ImageSharp.IO
/// <returns>The 16-bit unsigned integer read</returns>
public ushort ReadUInt16 ( )
{
this . ReadInternal ( this . b uffer, 2 ) ;
return this . BitConverter . ToUInt16 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 2 ) ;
return this . BitConverter . ToUInt16 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -215,8 +198,8 @@ namespace ImageSharp.IO
/// <returns>The 32-bit unsigned integer read</returns>
public uint ReadUInt32 ( )
{
this . ReadInternal ( this . b uffer, 4 ) ;
return this . BitConverter . ToUInt32 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 4 ) ;
return this . BitConverter . ToUInt32 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -226,8 +209,8 @@ namespace ImageSharp.IO
/// <returns>The 64-bit unsigned integer read</returns>
public ulong ReadUInt64 ( )
{
this . ReadInternal ( this . b uffer, 8 ) ;
return this . BitConverter . ToUInt64 ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 8 ) ;
return this . BitConverter . ToUInt64 ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -237,8 +220,8 @@ namespace ImageSharp.IO
/// <returns>The floating point value read</returns>
public float ReadSingle ( )
{
this . ReadInternal ( this . b uffer, 4 ) ;
return this . BitConverter . ToSingle ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 4 ) ;
return this . BitConverter . ToSingle ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -248,8 +231,8 @@ namespace ImageSharp.IO
/// <returns>The floating point value read</returns>
public double ReadDouble ( )
{
this . ReadInternal ( this . b uffer, 8 ) ;
return this . BitConverter . ToDouble ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 8 ) ;
return this . BitConverter . ToDouble ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -259,8 +242,8 @@ namespace ImageSharp.IO
/// <returns>The decimal value read</returns>
public decimal ReadDecimal ( )
{
this . ReadInternal ( this . b uffer, 1 6 ) ;
return this . BitConverter . ToDecimal ( this . b uffer, 0 ) ;
this . ReadInternal ( this . storageB uffer, 1 6 ) ;
return this . BitConverter . ToDecimal ( this . storageB uffer, 0 ) ;
}
/// <summary>
@ -296,33 +279,17 @@ namespace ImageSharp.IO
{
this . CheckDisposed ( ) ;
// TODO: Use Guard
if ( this . buffer = = null )
{
throw new ArgumentNullException ( "buffer" ) ;
}
if ( index < 0 )
{
throw new ArgumentOutOfRangeException ( "index" ) ;
}
if ( count < 0 )
{
throw new ArgumentOutOfRangeException ( "index" ) ;
}
if ( count + index > data . Length )
{
throw new ArgumentException ( "Not enough space in buffer for specified number of characters starting at specified index" ) ;
}
Guard . NotNull ( this . storageBuffer , nameof ( this . storageBuffer ) ) ;
Guard . MustBeGreaterThanOrEqualTo ( index , 0 , nameof ( index ) ) ;
Guard . MustBeGreaterThanOrEqualTo ( count , 0 , nameof ( count ) ) ;
Guard . IsFalse ( count + index > data . Length , nameof ( data . Length ) , "Not enough space in buffer for specified number of characters starting at specified index." ) ;
int read = 0 ;
bool firstTime = true ;
// Use the normal buffer if we're only reading a small amount, otherwise
// use at most 4K at a time.
byte [ ] byteBuffer = this . b uffer;
byte [ ] byteBuffer = this . storageBuffer ;
if ( byteBuffer . Length < count * this . minBytesPerChar )
{
@ -339,11 +306,10 @@ namespace ImageSharp.IO
amountToRead = count * this . minBytesPerChar ;
firstTime = false ;
}
// After that we can only assume we need to fully read 'chars left -1' characters
// and a single byte of the character we may be in the middle of
else
{
// After that we can only assume we need to fully read 'chars left -1' characters
// and a single byte of the character we may be in the middle of
amountToRead = ( ( count - read - 1 ) * this . minBytesPerChar ) + 1 ;
}
@ -379,25 +345,11 @@ namespace ImageSharp.IO
public int Read ( byte [ ] buffer , int index , int count )
{
this . CheckDisposed ( ) ;
if ( buffer = = null )
{
throw new ArgumentNullException ( "buffer" ) ;
}
if ( index < 0 )
{
throw new ArgumentOutOfRangeException ( "index" ) ;
}
if ( count < 0 )
{
throw new ArgumentOutOfRangeException ( "index" ) ;
}
if ( count + index > buffer . Length )
{
throw new ArgumentException ( "Not enough space in buffer for specified number of bytes starting at specified index" ) ;
}
Guard . NotNull ( this . storageBuffer , nameof ( this . storageBuffer ) ) ;
Guard . MustBeGreaterThanOrEqualTo ( index , 0 , nameof ( index ) ) ;
Guard . MustBeGreaterThanOrEqualTo ( count , 0 , nameof ( count ) ) ;
Guard . IsFalse ( count + index > buffer . Length , nameof ( buffer . Length ) , "Not enough space in buffer for specified number of bytes starting at specified index." ) ;
int read = 0 ;
while ( count > 0 )
@ -426,10 +378,7 @@ namespace ImageSharp.IO
public byte [ ] ReadBytes ( int count )
{
this . CheckDisposed ( ) ;
if ( count < 0 )
{
throw new ArgumentOutOfRangeException ( "count" ) ;
}
Guard . MustBeGreaterThanOrEqualTo ( count , 0 , nameof ( count ) ) ;
byte [ ] ret = new byte [ count ] ;
int index = 0 ;
@ -581,11 +530,7 @@ namespace ImageSharp.IO
int read = this . BaseStream . Read ( data , index , size - index ) ;
if ( read = = 0 )
{
throw new EndOfStreamException (
string . Format (
"End of stream reached with {0} byte{1} left to read." ,
size - index ,
size - index = = 1 ? "s" : string . Empty ) ) ;
throw new EndOfStreamException ( $"End of stream reached with {size - index} byte{(size - index == 1 ? " s " : string.Empty)} left to read." ) ;
}
index + = read ;
@ -618,4 +563,4 @@ namespace ImageSharp.IO
return index ;
}
}
}
}