2017-05-19 20:28:49 +01:00
// /***************************************************************************
2020-02-27 12:31:25 +00:00
// Aaru Data Preservation Suite
2016-09-05 17:37:31 +01:00
// ----------------------------------------------------------------------------
//
// Filename : OffsetStream.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a stream that's a subset of another stream.
//
// --[ License ] --------------------------------------------------------------
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, see <http://www.gnu.org/licenses/>.
//
// ----------------------------------------------------------------------------
2020-12-31 23:08:23 +00:00
// Copyright © 2011-2021 Natalia Portillo
2016-09-05 17:37:31 +01:00
// ****************************************************************************/
using System ;
using System.IO ;
2018-12-31 13:17:27 +00:00
using Microsoft.Win32.SafeHandles ;
2019-03-11 19:22:26 +00:00
2018-08-27 22:03:20 +01:00
#if ! NETSTANDARD2_0
2020-02-29 18:03:35 +00:00
2018-08-27 22:03:20 +01:00
#endif
2016-09-05 17:37:31 +01:00
2020-02-27 00:33:26 +00:00
namespace Aaru.Filters
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
/// <summary>Creates a stream that is a subset of another stream.</summary>
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-22 13:20:25 +01:00
public sealed class OffsetStream : Stream
2016-09-05 17:37:31 +01:00
{
2020-07-20 21:11:32 +01:00
readonly Stream _baseStream ;
readonly long _streamEnd ;
readonly long _streamStart ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified stream, both inclusive.
/// </summary>
/// <param name="stream">Base stream</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( Stream stream , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = stream ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="share">A bitwise combination of the enumeration values that determines how the file will be shared by processes.</param>
/// <param name="bufferSize">A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is 4096.</param>
/// <param name="options">A bitwise combination of the enumeration values that specifies additional file options.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2020-02-29 18:03:35 +00:00
public OffsetStream ( string path , FileMode mode , FileAccess access , FileShare share , int bufferSize ,
FileOptions options , long start , long end )
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode , access , share , bufferSize , options ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="handle">A file handle for the file that the stream will encapsulate.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( SafeFileHandle handle , FileAccess access , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( handle , access ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="handle">A file handle for the file that the stream will encapsulate.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="bufferSize">A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is 4096.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( SafeFileHandle handle , FileAccess access , int bufferSize , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( handle , access , bufferSize ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="handle">A file handle for the file that the stream will encapsulate.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="bufferSize">A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is 4096.</param>
/// <param name="isAsync">Specifies whether to use asynchronous I/O or synchronous I/O.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2017-12-19 20:33:03 +00:00
public OffsetStream ( SafeFileHandle handle , FileAccess access , int bufferSize , bool isAsync , long start ,
2020-02-29 18:03:35 +00:00
long end )
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( handle , access , bufferSize , isAsync ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="share">A bitwise combination of the enumeration values that determines how the file will be shared by processes.</param>
/// <param name="bufferSize">A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is 4096.</param>
/// <param name="useAsync">Specifies whether to use asynchronous I/O or synchronous I/O.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2020-02-29 18:03:35 +00:00
public OffsetStream ( string path , FileMode mode , FileAccess access , FileShare share , int bufferSize ,
bool useAsync , long start , long end )
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode , access , share , bufferSize , useAsync ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="share">A bitwise combination of the enumeration values that determines how the file will be shared by processes.</param>
/// <param name="bufferSize">A positive Int32 value greater than 0 indicating the buffer size. The default buffer size is 4096.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2017-12-19 20:33:03 +00:00
public OffsetStream ( string path , FileMode mode , FileAccess access , FileShare share , int bufferSize , long start ,
2020-02-29 18:03:35 +00:00
long end )
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode , access , share , bufferSize ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="share">A bitwise combination of the enumeration values that determines how the file will be shared by processes.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( string path , FileMode mode , FileAccess access , FileShare share , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode , access , share ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="access">A bitwise combination of the enumeration values that determines how the file can be accessed by a <see cref="FileStream" /> object.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( string path , FileMode mode , FileAccess access , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode , access ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified file, both inclusive.
/// </summary>
/// <param name="path">A relative or absolute path for the file that the stream will encapsulate.</param>
/// <param name="mode">One of the enumeration values that determines how to open or create the file.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( string path , FileMode mode , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new FileStream ( path , mode ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified byte array, both inclusive.
/// </summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
/// <param name="index">The index into <paramref name="buffer"/> at which the stream begins.</param>
/// <param name="count">The length in bytes to add to the end of the current stream.</param>
/// <param name="writable">The setting of the CanWrite property, currently ignored.</param>
/// <param name="publiclyVisible">Currently ignored.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2017-12-19 20:33:03 +00:00
public OffsetStream ( byte [ ] buffer , int index , int count , bool writable , bool publiclyVisible , long start ,
2020-02-29 18:03:35 +00:00
long end )
2016-09-05 17:37:31 +01:00
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new MemoryStream ( buffer , index , count , writable , publiclyVisible ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified byte array, both inclusive.
/// </summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
/// <param name="index">The index into <paramref name="buffer"/> at which the stream begins.</param>
/// <param name="count">The length in bytes to add to the end of the current stream.</param>
/// <param name="writable">The setting of the CanWrite property, currently ignored.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( byte [ ] buffer , int index , int count , bool writable , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new MemoryStream ( buffer , index , count , writable ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified byte array, both inclusive.
/// </summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
/// <param name="index">The index into <paramref name="buffer"/> at which the stream begins.</param>
/// <param name="count">The length in bytes to add to the end of the current stream.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( byte [ ] buffer , int index , int count , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new MemoryStream ( buffer , index , count ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified byte array, both inclusive.
/// </summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
/// <param name="writable">The setting of the CanWrite property, currently ignored.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( byte [ ] buffer , bool writable , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new MemoryStream ( buffer , writable ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <summary>
/// Initializes a stream that only allows reading from <paramref name="start"/> to <paramref name="end"/> of the specified byte array, both inclusive.
/// </summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="ArgumentOutOfRangeException">Invalid range</exception>
2016-09-05 17:37:31 +01:00
public OffsetStream ( byte [ ] buffer , long start , long end )
{
2020-02-29 18:03:35 +00:00
if ( start < 0 )
throw new ArgumentOutOfRangeException ( nameof ( start ) , "Start can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-02-29 18:03:35 +00:00
if ( end < 0 )
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End can't be a negative number." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_streamStart = start ;
_streamEnd = end ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream = new MemoryStream ( buffer ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
if ( end > _baseStream . Length )
2020-02-29 18:03:35 +00:00
throw new ArgumentOutOfRangeException ( nameof ( end ) , "End is after stream end." ) ;
2021-06-04 16:15:03 +01:00
_baseStream . Position = start ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override bool CanRead = > _baseStream . CanRead ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override bool CanSeek = > _baseStream . CanSeek ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override bool CanWrite = > _baseStream . CanWrite ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2021-06-04 16:15:03 +01:00
public override long Length = > _streamEnd - _streamStart + 1 ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2016-09-05 17:37:31 +01:00
public override long Position
{
2020-07-20 21:11:32 +01:00
get = > _baseStream . Position - _streamStart ;
2016-09-05 17:37:31 +01:00
set
{
2020-07-20 21:11:32 +01:00
if ( value + _streamStart > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot set position past stream end." ) ;
2016-09-05 17:37:31 +01:00
2021-06-04 16:15:03 +01:00
_baseStream . Position = value + _streamStart ;
2016-09-05 17:37:31 +01:00
}
}
2017-12-24 02:43:49 +00:00
~ OffsetStream ( )
{
2020-07-20 21:11:32 +01:00
_baseStream . Close ( ) ;
_baseStream . Dispose ( ) ;
2017-12-24 02:43:49 +00:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2017-12-19 20:33:03 +00:00
public override IAsyncResult BeginRead ( byte [ ] buffer , int offset , int count , AsyncCallback callback ,
object state )
2016-09-05 17:37:31 +01:00
{
2020-07-20 21:11:32 +01:00
if ( _baseStream . Position + count > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot read past stream end." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
return _baseStream . BeginRead ( buffer , offset , count , callback , state ) ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2017-12-19 20:33:03 +00:00
public override IAsyncResult BeginWrite ( byte [ ] buffer , int offset , int count , AsyncCallback callback ,
object state )
2016-09-05 17:37:31 +01:00
{
2020-07-20 21:11:32 +01:00
if ( _baseStream . Position + count > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot write past stream end." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
return _baseStream . BeginWrite ( buffer , offset , count , callback , state ) ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override void Close ( ) = > _baseStream . Close ( ) ;
2016-09-05 17:37:31 +01:00
2020-07-22 13:20:25 +01:00
new void Dispose ( )
2016-09-05 17:37:31 +01:00
{
2020-07-20 21:11:32 +01:00
_baseStream . Dispose ( ) ;
2016-09-05 17:37:31 +01:00
base . Dispose ( ) ;
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override int EndRead ( IAsyncResult asyncResult ) = > _baseStream . EndRead ( asyncResult ) ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override void EndWrite ( IAsyncResult asyncResult ) = > _baseStream . EndWrite ( asyncResult ) ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override int ReadByte ( ) = > _baseStream . Position = = _streamEnd + 1 ? - 1 : _baseStream . ReadByte ( ) ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2016-09-05 17:37:31 +01:00
public override void WriteByte ( byte value )
{
2020-07-20 21:11:32 +01:00
if ( _baseStream . Position + 1 > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot write past stream end." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream . WriteByte ( value ) ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-07-20 21:11:32 +01:00
public override void Flush ( ) = > _baseStream . Flush ( ) ;
2016-09-05 17:37:31 +01:00
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2016-09-05 17:37:31 +01:00
public override int Read ( byte [ ] buffer , int offset , int count )
{
2020-07-20 21:11:32 +01:00
if ( _baseStream . Position + count > _streamEnd + 1 )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot read past stream end." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
return _baseStream . Read ( buffer , offset , count ) ;
2016-09-05 17:37:31 +01:00
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2016-09-05 17:37:31 +01:00
public override long Seek ( long offset , SeekOrigin origin )
{
switch ( origin )
{
case SeekOrigin . Begin :
2020-07-20 21:11:32 +01:00
if ( offset + _streamStart > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot seek past stream end." ) ;
2017-12-19 20:33:03 +00:00
2020-07-20 21:11:32 +01:00
return _baseStream . Seek ( offset + _streamStart , SeekOrigin . Begin ) - _streamStart ;
2016-09-05 17:37:31 +01:00
case SeekOrigin . End :
2020-07-20 21:11:32 +01:00
if ( offset - ( _baseStream . Length - _streamEnd ) < _streamStart )
2016-09-05 17:37:31 +01:00
throw new IOException ( "Cannot seek before stream start." ) ;
2017-12-19 20:33:03 +00:00
2020-07-20 21:11:32 +01:00
return _baseStream . Seek ( offset - ( _baseStream . Length - _streamEnd ) , SeekOrigin . End ) - _streamStart ;
2016-09-05 17:37:31 +01:00
default :
2020-07-20 21:11:32 +01:00
if ( offset + _baseStream . Position > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot seek past stream end." ) ;
2017-12-19 20:33:03 +00:00
2020-07-20 21:11:32 +01:00
return _baseStream . Seek ( offset , SeekOrigin . Current ) - _streamStart ;
2016-09-05 17:37:31 +01:00
}
}
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2020-02-29 18:03:35 +00:00
public override void SetLength ( long value ) = >
2016-09-05 17:37:31 +01:00
throw new NotSupportedException ( "Growing OffsetStream is not supported." ) ;
2021-08-17 13:56:05 +01:00
/// <inheritdoc />
2016-09-05 17:37:31 +01:00
public override void Write ( byte [ ] buffer , int offset , int count )
{
2020-07-20 21:11:32 +01:00
if ( _baseStream . Position + count > _streamEnd )
2020-02-29 18:03:35 +00:00
throw new IOException ( "Cannot write past stream end." ) ;
2016-09-05 17:37:31 +01:00
2020-07-20 21:11:32 +01:00
_baseStream . Write ( buffer , offset , count ) ;
2016-09-05 17:37:31 +01:00
}
}
2017-12-19 20:33:03 +00:00
}