[Aaru.Helpers] Move all stream extensions from around the application to this project.

This commit is contained in:
2023-10-07 21:29:49 +01:00
parent c71817f087
commit 6b44679fbb
19 changed files with 19 additions and 1605 deletions

View File

@@ -35,6 +35,7 @@ using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs;
using Aaru.Filters;
using Aaru.Helpers.IO;
using FileAttributes = System.IO.FileAttributes;
namespace Aaru.Archives;

View File

@@ -58,7 +58,6 @@
<Compile Include="LZIP.cs"/>
<Compile Include="LZMA.cs"/>
<Compile Include="Native.cs"/>
<Compile Include="NonClosableStream.cs"/>
<Compile Include="TeleDiskLzh.cs"/>
<Compile Include="cuetools.net/CUETools.Codecs/*.cs"/>
<Compile Include="cuetools.net/CUETools.Codecs/CommandLine/*.cs"/>

View File

@@ -28,6 +28,7 @@
using System.IO;
using System.Runtime.InteropServices;
using Aaru.Helpers.IO;
using CUETools.Codecs;
using CUETools.Codecs.Flake;

View File

@@ -1,81 +0,0 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : NonClosableStream.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Compression.
//
// --[ Description ] ----------------------------------------------------------
//
// Overrides MemoryStream to ignore standard close requests.
//
// --[ 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/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Aaru.Helpers;
namespace Aaru.Compression;
/// <inheritdoc />
/// <summary>Creates a MemoryStream that ignores close commands</summary>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
sealed class NonClosableStream : Stream
{
readonly MemoryStream _baseStream;
internal NonClosableStream(byte[] buffer) => _baseStream = new MemoryStream(buffer);
internal NonClosableStream() => _baseStream = new MemoryStream();
public override bool CanRead => _baseStream.CanRead;
public override bool CanSeek => _baseStream.CanSeek;
public override bool CanWrite => _baseStream.CanWrite;
public override long Length => _baseStream.Length;
public override long Position
{
get => _baseStream.Position;
set => _baseStream.Position = value;
}
public override void Flush() => _baseStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _baseStream.EnsureRead(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _baseStream.Seek(offset, origin);
public override void SetLength(long value) => _baseStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _baseStream.Write(buffer, offset, count);
public override void Close()
{
// Do nothing
}
internal byte[] GetBuffer() => _baseStream.GetBuffer();
internal byte[] ToArray() => _baseStream.ToArray();
internal void ReallyClose() => _baseStream.Close();
}

View File

@@ -38,6 +38,7 @@ using System.Runtime.InteropServices;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using Marshal = Aaru.Helpers.Marshal;
namespace Aaru.Filters;

View File

@@ -38,6 +38,7 @@ using System.Runtime.InteropServices;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using Marshal = Aaru.Helpers.Marshal;
namespace Aaru.Filters;

View File

@@ -35,6 +35,7 @@ using System.IO;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using Ionic.BZip2;
namespace Aaru.Filters;

View File

@@ -1,258 +0,0 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : ForcedSeekStream.cs
// Author(s) : Natalia Portillo <claunia@claunia.com>
//
// Component : Filters.
//
// --[ Description ] ----------------------------------------------------------
//
// Provides a seekable stream from a forward-readable 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/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.IO;
using Aaru.Helpers;
namespace Aaru.Filters;
/// <summary>
/// ForcedSeekStream allows to seek a forward-readable stream (like System.IO.Compression streams) by doing the
/// slow and known trick of rewinding and forward reading until arriving the desired position.
/// </summary>
/// <inheritdoc />
public sealed class ForcedSeekStream<T> : Stream where T : Stream
{
const int BUFFER_LEN = 1048576;
readonly string _backFile;
readonly FileStream _backStream;
readonly T _baseStream;
long _streamLength;
/// <summary>Initializes a new instance of the <see cref="T:Aaru.Filters.ForcedSeekStream`1" /> class.</summary>
/// <param name="length">The real (uncompressed) length of the stream.</param>
/// <param name="args">Parameters that are used to create the base stream.</param>
/// <inheritdoc />
public ForcedSeekStream(long length, params object[] args)
{
_streamLength = length;
_baseStream = (T)Activator.CreateInstance(typeof(T), args);
_backFile = Path.GetTempFileName();
_backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
if(length == 0)
CalculateLength();
}
/// <summary>Initializes a new instance of the <see cref="T:Aaru.Filters.ForcedSeekStream`1" /> class.</summary>
/// <param name="args">Parameters that are used to create the base stream.</param>
/// <inheritdoc />
public ForcedSeekStream(params object[] args)
{
_baseStream = (T)Activator.CreateInstance(typeof(T), args);
_backFile = Path.GetTempFileName();
_backStream = new FileStream(_backFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
CalculateLength();
}
/// <inheritdoc />
public override bool CanRead => _baseStream.CanRead;
/// <inheritdoc />
public override bool CanSeek => true;
/// <inheritdoc />
public override bool CanWrite => false;
/// <inheritdoc />
public override long Length => _streamLength;
/// <inheritdoc />
public override long Position
{
get => _backStream.Position;
set => SetPosition(value);
}
/// <summary>
/// Calculates the real (uncompressed) length of the stream. It basically reads (uncompresses) the whole stream to
/// memory discarding its contents, so it should be used as a last resort.
/// </summary>
/// <returns>The length.</returns>
public void CalculateLength()
{
int read;
do
{
var buffer = new byte[BUFFER_LEN];
read = _baseStream.EnsureRead(buffer, 0, BUFFER_LEN);
_backStream.Write(buffer, 0, read);
} while(read == BUFFER_LEN);
_streamLength = _backStream.Length;
_backStream.Position = 0;
}
void SetPosition(long position)
{
if(position == _backStream.Position)
return;
if(position < _backStream.Length)
{
_backStream.Position = position;
return;
}
if(position > _streamLength)
position = _streamLength;
_backStream.Position = _backStream.Length;
long toPosition = position - _backStream.Position;
var fullBufferReads = (int)(toPosition / BUFFER_LEN);
var restToRead = (int)(toPosition % BUFFER_LEN);
byte[] buffer;
int bufPos;
int left;
for(var i = 0; i < fullBufferReads; i++)
{
buffer = new byte[BUFFER_LEN];
bufPos = 0;
left = BUFFER_LEN;
while(left > 0)
{
int done = _baseStream.EnsureRead(buffer, bufPos, left);
left -= done;
bufPos += done;
}
_backStream.Write(buffer, 0, BUFFER_LEN);
}
buffer = new byte[restToRead];
bufPos = 0;
left = restToRead;
while(left > 0)
{
int done = _baseStream.EnsureRead(buffer, bufPos, left);
left -= done;
bufPos += done;
}
_backStream.Write(buffer, 0, restToRead);
}
/// <inheritdoc />
public override void Flush()
{
_baseStream.Flush();
_backStream.Flush();
}
/// <inheritdoc />
public override int Read(byte[] buffer, int offset, int count)
{
if(_backStream.Position + count > _streamLength)
count = (int)(_streamLength - _backStream.Position);
if(_backStream.Position + count <= _backStream.Length)
return _backStream.EnsureRead(buffer, offset, count);
long oldPosition = _backStream.Position;
SetPosition(_backStream.Position + count);
SetPosition(oldPosition);
return _backStream.EnsureRead(buffer, offset, count);
}
/// <inheritdoc />
public override int ReadByte()
{
if(_backStream.Position + 1 > _streamLength)
return -1;
if(_backStream.Position + 1 <= _backStream.Length)
return _backStream.ReadByte();
SetPosition(_backStream.Position + 1);
SetPosition(_backStream.Position - 1);
return _backStream.ReadByte();
}
/// <inheritdoc />
public override long Seek(long offset, SeekOrigin origin)
{
switch(origin)
{
case SeekOrigin.Begin:
if(offset < 0)
throw new IOException(Localization.Cannot_seek_before_stream_start);
SetPosition(offset);
break;
case SeekOrigin.End:
if(offset > 0)
throw new IOException(Localization.Cannot_seek_after_stream_end);
if(_streamLength == 0)
CalculateLength();
SetPosition(_streamLength + offset);
break;
default:
SetPosition(_backStream.Position + offset);
break;
}
return _backStream.Position;
}
/// <inheritdoc />
public override void SetLength(long value) => throw new NotSupportedException();
/// <inheritdoc />
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
/// <inheritdoc />
public override void Close()
{
_backStream?.Close();
File.Delete(_backFile);
}
~ForcedSeekStream()
{
_backStream?.Close();
File.Delete(_backFile);
}
}

View File

@@ -36,6 +36,7 @@ using System.IO.Compression;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
namespace Aaru.Filters;

View File

@@ -35,6 +35,7 @@ using System.IO;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using SharpCompress.Compressors;
using SharpCompress.Compressors.LZMA;

View File

@@ -77,15 +77,6 @@ namespace Aaru.Filters {
}
}
/// <summary>
/// Looks up a localized string similar to Asynchronous I/O is not supported..
/// </summary>
internal static string Asynchronous_IO_is_not_supported {
get {
return ResourceManager.GetString("Asynchronous_IO_is_not_supported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to BZip2.
/// </summary>
@@ -95,78 +86,6 @@ namespace Aaru.Filters {
}
}
/// <summary>
/// Looks up a localized string similar to Cannot read past stream end..
/// </summary>
internal static string Cannot_read_past_stream_end {
get {
return ResourceManager.GetString("Cannot_read_past_stream_end", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot seek after stream end..
/// </summary>
internal static string Cannot_seek_after_stream_end {
get {
return ResourceManager.GetString("Cannot_seek_after_stream_end", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot seek before stream start..
/// </summary>
internal static string Cannot_seek_before_stream_start {
get {
return ResourceManager.GetString("Cannot_seek_before_stream_start", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot set position past stream end..
/// </summary>
internal static string Cannot_set_position_past_stream_end {
get {
return ResourceManager.GetString("Cannot_set_position_past_stream_end", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Cannot write past stream end..
/// </summary>
internal static string Cannot_write_past_stream_end {
get {
return ResourceManager.GetString("Cannot_write_past_stream_end", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End can&apos;t be a negative number..
/// </summary>
internal static string End_cant_be_a_negative_number {
get {
return ResourceManager.GetString("End_cant_be_a_negative_number", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End is after stream end..
/// </summary>
internal static string End_is_after_stream_end {
get {
return ResourceManager.GetString("End_is_after_stream_end", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Growing OffsetStream is not supported..
/// </summary>
internal static string Growing_OffsetStream_is_not_supported {
get {
return ResourceManager.GetString("Growing_OffsetStream_is_not_supported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to GZip.
/// </summary>
@@ -194,24 +113,6 @@ namespace Aaru.Filters {
}
}
/// <summary>
/// Looks up a localized string similar to Non-readable streams are not supported.
/// </summary>
internal static string Non_readable_streams_are_not_supported {
get {
return ResourceManager.GetString("Non_readable_streams_are_not_supported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Non-seekable streams are not supported.
/// </summary>
internal static string Non_seekable_streams_are_not_supported {
get {
return ResourceManager.GetString("Non_seekable_streams_are_not_supported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to PCExchange.
/// </summary>
@@ -221,24 +122,6 @@ namespace Aaru.Filters {
}
}
/// <summary>
/// Looks up a localized string similar to Start can&apos;t be a negative number..
/// </summary>
internal static string Start_cant_be_a_negative_number {
get {
return ResourceManager.GetString("Start_cant_be_a_negative_number", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This stream is read-only.
/// </summary>
internal static string This_stream_is_read_only {
get {
return ResourceManager.GetString("This_stream_is_read_only", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to XZ.
/// </summary>

View File

@@ -21,36 +21,9 @@
</data>
<data name="AppleSingle_Name" xml:space="preserve">
<value>AppleSingle</value>
</data>
<data name="Asynchronous_IO_is_not_supported" xml:space="preserve">
<value>E/S asíncrona no soportada.</value>
</data>
<data name="BZip2_Name" xml:space="preserve">
<value>BZip2</value>
</data>
<data name="Cannot_read_past_stream_end" xml:space="preserve">
<value>No se puede leer más allá del final de la secuencia.</value>
</data>
<data name="Cannot_seek_after_stream_end" xml:space="preserve">
<value>No se puede posicionar después del final de la secuencia.</value>
</data>
<data name="Cannot_seek_before_stream_start" xml:space="preserve">
<value>No se puede posicionar antes del comienzo de la secuencia.</value>
</data>
<data name="Cannot_set_position_past_stream_end" xml:space="preserve">
<value>No se puede establecer la posición más allá del final de la secuencia.</value>
</data>
<data name="Cannot_write_past_stream_end" xml:space="preserve">
<value>No se puede escribir después del final de la secuencia.</value>
</data>
<data name="End_cant_be_a_negative_number" xml:space="preserve">
<value>El final no puede ser un número negativo.</value>
</data>
<data name="End_is_after_stream_end" xml:space="preserve">
<value>El final está después del final de la secuencia.</value>
</data>
<data name="Growing_OffsetStream_is_not_supported" xml:space="preserve">
<value>No se puede agrandar un OffsetStream.</value>
</data>
<data name="GZip_Name" xml:space="preserve">
<value>GZip</value>
@@ -60,21 +33,9 @@
</data>
<data name="MacBinary_Name" xml:space="preserve">
<value>MacBinary</value>
</data>
<data name="Non_readable_streams_are_not_supported" xml:space="preserve">
<value>Las secuencias no legíbles no están soportadas.</value>
</data>
<data name="Non_seekable_streams_are_not_supported" xml:space="preserve">
<value>Las secuencias no posicionables no están soportadas.</value>
</data>
<data name="PcExchange_Name" xml:space="preserve">
<value>PCExchange</value>
</data>
<data name="Start_cant_be_a_negative_number" xml:space="preserve">
<value>El comienzo no puede ser un número negativo.</value>
</data>
<data name="This_stream_is_read_only" xml:space="preserve">
<value>Esta secuencia es de sólo lectura.</value>
</data>
<data name="XZ_Name" xml:space="preserve">
<value>XZ</value>

View File

@@ -31,12 +31,6 @@
</data>
<data name="BZip2_Name" xml:space="preserve">
<value>BZip2</value>
</data>
<data name="Cannot_seek_before_stream_start" xml:space="preserve">
<value>Cannot seek before stream start.</value>
</data>
<data name="Cannot_seek_after_stream_end" xml:space="preserve">
<value>Cannot seek after stream end.</value>
</data>
<data name="GZip_Name" xml:space="preserve">
<value>GZip</value>
@@ -46,42 +40,9 @@
</data>
<data name="MacBinary_Name" xml:space="preserve">
<value>MacBinary</value>
</data>
<data name="Start_cant_be_a_negative_number" xml:space="preserve">
<value>Start can't be a negative number.</value>
</data>
<data name="End_cant_be_a_negative_number" xml:space="preserve">
<value>End can't be a negative number.</value>
</data>
<data name="End_is_after_stream_end" xml:space="preserve">
<value>End is after stream end.</value>
</data>
<data name="Cannot_set_position_past_stream_end" xml:space="preserve">
<value>Cannot set position past stream end.</value>
</data>
<data name="Cannot_read_past_stream_end" xml:space="preserve">
<value>Cannot read past stream end.</value>
</data>
<data name="Cannot_write_past_stream_end" xml:space="preserve">
<value>Cannot write past stream end.</value>
</data>
<data name="Growing_OffsetStream_is_not_supported" xml:space="preserve">
<value>Growing OffsetStream is not supported.</value>
</data>
</data>
<data name="PcExchange_Name" xml:space="preserve">
<value>PCExchange</value>
</data>
<data name="Non_seekable_streams_are_not_supported" xml:space="preserve">
<value>Non-seekable streams are not supported</value>
</data>
<data name="Non_readable_streams_are_not_supported" xml:space="preserve">
<value>Non-readable streams are not supported</value>
</data>
<data name="Asynchronous_IO_is_not_supported" xml:space="preserve">
<value>Asynchronous I/O is not supported.</value>
</data>
<data name="This_stream_is_read_only" xml:space="preserve">
<value>This stream is read-only</value>
</data>
<data name="XZ_Name" xml:space="preserve">
<value>XZ</value>

View File

@@ -37,6 +37,7 @@ using System.Text;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using Marshal = Aaru.Helpers.Marshal;
namespace Aaru.Filters;

View File

@@ -1,681 +0,0 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// 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/>.
//
// ----------------------------------------------------------------------------
// Copyright © 2011-2023 Natalia Portillo
// ****************************************************************************/
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Aaru.Helpers;
using Microsoft.Win32.SafeHandles;
#if !NETSTANDARD2_0
#endif
namespace Aaru.Filters;
/// <summary>Creates a stream that is a subset of another stream.</summary>
/// <inheritdoc />
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public sealed class OffsetStream : Stream
{
readonly Stream _baseStream;
readonly long _streamEnd;
readonly long _streamStart;
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(Stream stream, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = stream;
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize,
FileOptions options, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode, access, share, bufferSize, options);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.FileStream" /> object.
/// </param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(SafeFileHandle handle, FileAccess access, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(handle, access);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(handle, access, bufferSize);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(handle, access, bufferSize, isAsync);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync,
long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode, access, share, bufferSize, useAsync);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, long start,
long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode, access, share, bufferSize);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, FileAccess access, FileShare share, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode, access, share);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.IO.FileStream" /> object.
/// </param>
/// <param name="start">Start position</param>
/// <param name="end">Last readable position</param>
/// <exception cref="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, FileAccess access, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode, access);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(string path, FileMode mode, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new FileStream(path, mode);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new MemoryStream(buffer, index, count, writable, publiclyVisible);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(byte[] buffer, int index, int count, bool writable, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new MemoryStream(buffer, index, count, writable);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(byte[] buffer, int index, int count, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new MemoryStream(buffer, index, count);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(byte[] buffer, bool writable, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new MemoryStream(buffer, writable);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
/// <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="T:System.ArgumentOutOfRangeException">Invalid range</exception>
public OffsetStream(byte[] buffer, long start, long end)
{
if(start < 0)
throw new ArgumentOutOfRangeException(nameof(start), Localization.Start_cant_be_a_negative_number);
if(end < 0)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_cant_be_a_negative_number);
_streamStart = start;
_streamEnd = end;
_baseStream = new MemoryStream(buffer);
if(end > _baseStream.Length)
throw new ArgumentOutOfRangeException(nameof(end), Localization.End_is_after_stream_end);
_baseStream.Position = start;
}
/// <inheritdoc />
public override bool CanRead => _baseStream.CanRead;
/// <inheritdoc />
public override bool CanSeek => _baseStream.CanSeek;
/// <inheritdoc />
public override bool CanWrite => _baseStream.CanWrite;
/// <inheritdoc />
public override long Length => _streamEnd - _streamStart + 1;
/// <inheritdoc />
public override long Position
{
get => _baseStream.Position - _streamStart;
set
{
if(value + _streamStart > _streamEnd)
throw new IOException(Localization.Cannot_set_position_past_stream_end);
_baseStream.Position = value + _streamStart;
}
}
~OffsetStream()
{
_baseStream.Close();
_baseStream.Dispose();
}
/// <inheritdoc />
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
if(_baseStream.Position + count > _streamEnd)
throw new IOException(Localization.Cannot_read_past_stream_end);
return _baseStream.BeginRead(buffer, offset, count, callback, state);
}
/// <inheritdoc />
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
if(_baseStream.Position + count > _streamEnd)
throw new IOException(Localization.Cannot_write_past_stream_end);
return _baseStream.BeginWrite(buffer, offset, count, callback, state);
}
/// <inheritdoc />
public override void Close() => _baseStream.Close();
/// <inheritdoc />
public override int EndRead(IAsyncResult asyncResult) => _baseStream.EndRead(asyncResult);
/// <inheritdoc />
public override void EndWrite(IAsyncResult asyncResult) => _baseStream.EndWrite(asyncResult);
/// <inheritdoc />
public override int ReadByte() => _baseStream.Position == _streamEnd + 1 ? -1 : _baseStream.ReadByte();
/// <inheritdoc />
public override void WriteByte(byte value)
{
if(_baseStream.Position + 1 > _streamEnd)
throw new IOException(Localization.Cannot_write_past_stream_end);
_baseStream.WriteByte(value);
}
/// <inheritdoc />
public override void Flush() => _baseStream.Flush();
/// <inheritdoc />
public override int Read(byte[] buffer, int offset, int count)
{
if(_baseStream.Position + count > _streamEnd + 1)
throw new IOException(Localization.Cannot_read_past_stream_end);
return _baseStream.EnsureRead(buffer, offset, count);
}
/// <inheritdoc />
public override long Seek(long offset, SeekOrigin origin)
{
switch(origin)
{
case SeekOrigin.Begin:
if(offset + _streamStart > _streamEnd)
throw new IOException(Localization.Cannot_seek_after_stream_end);
return _baseStream.Seek(offset + _streamStart, SeekOrigin.Begin) - _streamStart;
case SeekOrigin.End:
if(offset - (_baseStream.Length - _streamEnd) < _streamStart)
throw new IOException(Localization.Cannot_seek_before_stream_start);
return _baseStream.Seek(offset - (_baseStream.Length - _streamEnd), SeekOrigin.End) - _streamStart;
default:
if(offset + _baseStream.Position > _streamEnd)
throw new IOException(Localization.Cannot_seek_after_stream_end);
return _baseStream.Seek(offset, SeekOrigin.Current) - _streamStart;
}
}
/// <inheritdoc />
public override void SetLength(long value) =>
throw new NotSupportedException(Localization.Growing_OffsetStream_is_not_supported);
/// <inheritdoc />
public override void Write(byte[] buffer, int offset, int count)
{
if(_baseStream.Position + count > _streamEnd)
throw new IOException(Localization.Cannot_write_past_stream_end);
_baseStream.Write(buffer, offset, count);
}
}

View File

@@ -1,382 +0,0 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Aaru.CommonTypes.Interfaces;
using Microsoft.Win32.SafeHandles;
namespace Aaru.Filters;
/// <inheritdoc />
/// <summary>Implements a stream that joins two or more files (sequentially) as a single stream</summary>
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public class SplitJoinStream : Stream
{
readonly Dictionary<long, Stream> _baseStreams;
long _position;
long _streamLength;
/// <inheritdoc />
public SplitJoinStream()
{
_baseStreams = new Dictionary<long, Stream>();
_streamLength = 0;
_position = 0;
Filter = new ZZZNoFilter();
Filter.Open(this);
}
/// <inheritdoc />
public override bool CanRead => true;
/// <inheritdoc />
public override bool CanSeek => true;
/// <inheritdoc />
public override bool CanWrite => false;
/// <inheritdoc />
public override long Length => _streamLength;
/// <inheritdoc />
public override long Position
{
get => _position;
set
{
if(value >= _streamLength)
throw new IOException(Localization.Cannot_set_position_past_stream_end);
_position = value;
}
}
/// <summary>Gets a filter from this stream</summary>
public IFilter Filter { get; }
/// <summary>Adds a stream at the end of the current stream</summary>
/// <param name="stream">Stream to add</param>
/// <exception cref="ArgumentException">The specified stream is non-readable or non-seekable</exception>
public void Add(Stream stream)
{
if(!stream.CanSeek)
throw new ArgumentException(Localization.Non_seekable_streams_are_not_supported);
if(!stream.CanRead)
throw new ArgumentException(Localization.Non_readable_streams_are_not_supported);
_baseStreams[_streamLength] = stream;
_streamLength += stream.Length;
}
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize,
FileOptions options) => Add(new FileStream(path, mode, access, share, bufferSize, options));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(SafeFileHandle handle, FileAccess access) => Add(new FileStream(handle, access));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(SafeFileHandle handle, FileAccess access, int bufferSize) =>
Add(new FileStream(handle, access, bufferSize));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) =>
Add(new FileStream(handle, access, bufferSize, isAsync));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) =>
Add(new FileStream(path, mode, access, share, bufferSize, useAsync));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize) =>
Add(new FileStream(path, mode, access, share, bufferSize));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode, FileAccess access, FileShare share) =>
Add(new FileStream(path, mode, access, share));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode, FileAccess access) => Add(new FileStream(path, mode, access));
/// <summary>Adds the specified file to the end of the current stream</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>
public void Add(string path, FileMode mode) => Add(new FileStream(path, mode));
/// <summary>Adds the specified byte array to the end of the current stream</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>
public void Add(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) =>
Add(new MemoryStream(buffer, index, count, writable, publiclyVisible));
/// <summary>Adds the specified byte array to the end of the current stream</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>
public void Add(byte[] buffer, int index, int count, bool writable) =>
Add(new MemoryStream(buffer, index, count, writable));
/// <summary>Adds the specified byte array to the end of the current stream</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>
public void Add(byte[] buffer, int index, int count) => Add(new MemoryStream(buffer, index, count));
/// <summary>Adds the specified byte array to the end of the current stream</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>
public void Add(byte[] buffer, bool writable) => Add(new MemoryStream(buffer, writable));
/// <summary>Adds the specified byte array to the end of the current stream</summary>
/// <param name="buffer">The array of unsigned bytes to add at the end of this stream.</param>
public void Add(byte[] buffer) => Add(new MemoryStream(buffer));
/// <summary>Adds the data fork of the specified filter to the end of the current stream</summary>
/// <param name="filter">Filter</param>
public void Add(IFilter filter) => Add(filter.GetDataForkStream());
/// <summary>Adds a range of files to the end of the current stream, alphabetically sorted</summary>
/// <param name="basePath">Base file path, directory path only</param>
/// <param name="counterFormat">Counter format, includes filename and a formatting string</param>
/// <param name="counterStart">Counter start, defaults to 0</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>
public void AddRange(string basePath, string counterFormat = "{0:D3}", int counterStart = 0,
FileAccess access = FileAccess.Read)
{
while(true)
{
string filePath = Path.Combine(basePath, string.Format(counterFormat, counterStart));
if(!File.Exists(filePath))
break;
Add(filePath, FileMode.Open, access);
counterStart++;
}
}
~SplitJoinStream()
{
foreach(Stream stream in _baseStreams.Values)
{
stream.Close();
stream.Dispose();
}
_baseStreams.Clear();
_position = 0;
}
/// <inheritdoc />
public override IAsyncResult
BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) =>
throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported);
/// <inheritdoc />
public override IAsyncResult
BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) =>
throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported);
/// <inheritdoc />
public override void Close()
{
foreach(Stream stream in _baseStreams.Values)
stream.Close();
_baseStreams.Clear();
_position = 0;
}
/// <inheritdoc />
public override int EndRead(IAsyncResult asyncResult) =>
throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported);
/// <inheritdoc />
public override void EndWrite(IAsyncResult asyncResult) =>
throw new NotSupportedException(Localization.Asynchronous_IO_is_not_supported);
/// <inheritdoc />
public override int ReadByte()
{
if(_position >= _streamLength)
return -1;
KeyValuePair<long, Stream> baseStream = _baseStreams.FirstOrDefault(s => s.Key >= _position);
if(baseStream.Value == null)
return -1;
baseStream.Value.Position = _position - baseStream.Key;
_position++;
return baseStream.Value.ReadByte();
}
/// <inheritdoc />
public override void WriteByte(byte value) => throw new ReadOnlyException(Localization.This_stream_is_read_only);
/// <inheritdoc />
public override void Flush() {}
/// <inheritdoc />
public override int Read(byte[] buffer, int offset, int count)
{
var read = 0;
while(count > 0)
{
KeyValuePair<long, Stream> baseStream = _baseStreams.LastOrDefault(s => s.Key <= _position);
if(baseStream.Value == null)
break;
baseStream.Value.Position = _position - baseStream.Key;
int currentCount = count;
if(baseStream.Value.Position + currentCount > baseStream.Value.Length)
currentCount = (int)(baseStream.Value.Length - baseStream.Value.Position);
read += baseStream.Value.Read(buffer, offset, currentCount);
count -= currentCount;
offset += currentCount;
}
return read;
}
/// <inheritdoc />
public override long Seek(long offset, SeekOrigin origin)
{
switch(origin)
{
case SeekOrigin.Begin:
if(offset >= _streamLength)
throw new IOException(Localization.Cannot_seek_after_stream_end);
_position = offset;
break;
case SeekOrigin.End:
if(_position - offset < 0)
throw new IOException(Localization.Cannot_seek_before_stream_start);
_position -= offset;
break;
default:
if(_position + offset >= _streamLength)
throw new IOException(Localization.Cannot_seek_after_stream_end);
_position += offset;
break;
}
return _position;
}
/// <inheritdoc />
public override void SetLength(long value) => throw new ReadOnlyException(Localization.This_stream_is_read_only);
/// <inheritdoc />
public override void Write(byte[] buffer, int offset, int count) =>
throw new ReadOnlyException(Localization.This_stream_is_read_only);
}

View File

@@ -35,6 +35,7 @@ using System.IO;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using SharpCompress.Compressors.Xz;
namespace Aaru.Filters;

View File

@@ -48,6 +48,7 @@ using Aaru.Decoders.SCSI;
using Aaru.Decoders.SCSI.MMC;
using Aaru.Filters;
using Aaru.Helpers;
using Aaru.Helpers.IO;
using DMI = Aaru.Decoders.Xbox.DMI;
using Sector = Aaru.Decoders.CD.Sector;
using Session = Aaru.CommonTypes.Structs.Session;
@@ -980,8 +981,9 @@ public sealed partial class BlindWrite5
return ErrorNumber.NoSuchFile;
}
track.Filter = splitStream.Filter;
track.File = $"{filename}.{extension}";
track.Filter = new ZZZNoFilter();
track.Filter.Open(splitStream);
track.File = $"{filename}.{extension}";
if(trk.startLba >= 0)
track.FileOffset = (ulong)(trk.startLba * splitStartChars.SectorSize + splitStartChars.Offset);
@@ -1001,9 +1003,10 @@ public sealed partial class BlindWrite5
_imageInfo.ReadableSectorTags.Add(SectorTagType.CdSectorSubchannel);
}
splitStartChars.FileFilter = splitStream.Filter;
splitStartChars.Sectors = trk.sectors;
splitStartChars.StartLba = trk.startLba;
splitStartChars.FileFilter = new ZZZNoFilter();
splitStartChars.FileFilter.Open(splitStream);
splitStartChars.Sectors = trk.sectors;
splitStartChars.StartLba = trk.startLba;
_filePaths.Clear();
_filePaths.Add(splitStartChars);
}