mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 11:14:25 +00:00
[Aaru.Helpers] Move all stream extensions from around the application to this project.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Aaru.Helpers.IO;
|
||||
using CUETools.Codecs;
|
||||
using CUETools.Codecs.Flake;
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
117
Aaru.Filters/Localization/Localization.Designer.cs
generated
117
Aaru.Filters/Localization/Localization.Designer.cs
generated
@@ -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'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'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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Submodule Aaru.Helpers updated: a03ee5efee...0a5ccd5a9a
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user