mirror of https://github.com/SixLabors/ImageSharp
17 changed files with 87 additions and 562 deletions
@ -1,176 +0,0 @@ |
|||||
// Copyright (c) Six Labors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.IO; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Utility class to encapsulate a sub-portion of another <see cref="Stream"/>.
|
|
||||
/// </summary>
|
|
||||
/// <remarks>
|
|
||||
/// Note that disposing of the <see cref="SubStream"/> does not dispose the underlying
|
|
||||
/// <see cref="Stream"/>.
|
|
||||
/// </remarks>
|
|
||||
internal class SubStream : Stream |
|
||||
{ |
|
||||
private Stream innerStream; |
|
||||
private long offset; |
|
||||
private long endOffset; |
|
||||
private long length; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SubStream"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="innerStream">The underlying <see cref="Stream"/> to wrap.</param>
|
|
||||
/// <param name="length">The length of the sub-stream.</param>
|
|
||||
/// <remarks>
|
|
||||
/// Note that calling the sub-stream with start from the current offset of the
|
|
||||
/// underlying <see cref="Stream"/>
|
|
||||
/// </remarks>
|
|
||||
public SubStream(Stream innerStream, long length) |
|
||||
{ |
|
||||
this.innerStream = innerStream; |
|
||||
this.offset = this.innerStream.Position; |
|
||||
this.endOffset = this.offset + length; |
|
||||
this.length = length; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="SubStream"/> class.
|
|
||||
/// </summary>
|
|
||||
/// <param name="innerStream">The underlying <see cref="Stream"/> to wrap.</param>
|
|
||||
/// <param name="offset">The offset of the sub-stream within the underlying <see cref="Stream"/>.</param>
|
|
||||
/// <param name="length">The length of the sub-stream.</param>
|
|
||||
/// <remarks>
|
|
||||
/// Note that calling the constructor will immediately move the underlying
|
|
||||
/// <see cref="Stream"/> to the specified offset.
|
|
||||
/// </remarks>
|
|
||||
public SubStream(Stream innerStream, long offset, long length) |
|
||||
{ |
|
||||
this.innerStream = innerStream; |
|
||||
this.offset = offset; |
|
||||
this.endOffset = offset + length; |
|
||||
this.length = length; |
|
||||
|
|
||||
innerStream.Seek(offset, SeekOrigin.Begin); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool CanRead |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return true; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool CanWrite |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool CanSeek |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return this.innerStream.CanSeek; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override long Length |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return this.length; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override long Position |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
return this.innerStream.Position - this.offset; |
|
||||
} |
|
||||
|
|
||||
set |
|
||||
{ |
|
||||
this.Seek(value, SeekOrigin.Begin); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override void Flush() |
|
||||
{ |
|
||||
throw new NotSupportedException(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int Read(byte[] buffer, int offset, int count) |
|
||||
{ |
|
||||
long bytesRemaining = this.endOffset - this.innerStream.Position; |
|
||||
|
|
||||
if (bytesRemaining < count) |
|
||||
{ |
|
||||
count = (int)bytesRemaining; |
|
||||
} |
|
||||
|
|
||||
return this.innerStream.Read(buffer, offset, count); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override int ReadByte() |
|
||||
{ |
|
||||
if (this.innerStream.Position < this.endOffset) |
|
||||
{ |
|
||||
return this.innerStream.ReadByte(); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
return -1; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override void Write(byte[] array, int offset, int count) |
|
||||
{ |
|
||||
throw new NotSupportedException(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override void WriteByte(byte value) |
|
||||
{ |
|
||||
throw new NotSupportedException(); |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override long Seek(long offset, SeekOrigin origin) |
|
||||
{ |
|
||||
switch (origin) |
|
||||
{ |
|
||||
case SeekOrigin.Current: |
|
||||
return this.innerStream.Seek(offset, SeekOrigin.Current) - this.offset; |
|
||||
case SeekOrigin.Begin: |
|
||||
return this.innerStream.Seek(this.offset + offset, SeekOrigin.Begin) - this.offset; |
|
||||
case SeekOrigin.End: |
|
||||
return this.innerStream.Seek(this.endOffset - offset, SeekOrigin.Begin) - this.offset; |
|
||||
default: |
|
||||
throw new ArgumentException("Invalid seek origin."); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override void SetLength(long value) |
|
||||
{ |
|
||||
throw new NotSupportedException(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,328 +0,0 @@ |
|||||
// Copyright (c) Six Labors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.IO; |
|
||||
|
|
||||
using SixLabors.ImageSharp.Formats.Experimental.Tiff.Utils; |
|
||||
|
|
||||
using Xunit; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Tests.Formats.Tiff |
|
||||
{ |
|
||||
[Trait("Format", "Tiff")] |
|
||||
public class SubStreamTests |
|
||||
{ |
|
||||
[Fact] |
|
||||
public void Constructor_PositionsStreamCorrectly_WithSpecifiedOffset() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
innerStream.Position = 2; |
|
||||
|
|
||||
SubStream stream = new SubStream(innerStream, 4, 6); |
|
||||
|
|
||||
Assert.Equal(0, stream.Position); |
|
||||
Assert.Equal(6, stream.Length); |
|
||||
Assert.Equal(4, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Constructor_PositionsStreamCorrectly_WithCurrentOffset() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
innerStream.Position = 2; |
|
||||
|
|
||||
SubStream stream = new SubStream(innerStream, 6); |
|
||||
|
|
||||
Assert.Equal(0, stream.Position); |
|
||||
Assert.Equal(6, stream.Length); |
|
||||
Assert.Equal(2, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanRead_ReturnsTrue() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.True(stream.CanRead); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanWrite_ReturnsFalse() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.False(stream.CanWrite); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void CanSeek_ReturnsTrue() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.True(stream.CanSeek); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Length_ReturnsTheConstrainedLength() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Equal(6, stream.Length); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Position_ReturnsZeroBeforeReading() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Equal(0, stream.Position); |
|
||||
Assert.Equal(2, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Position_ReturnsPositionAfterReading() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Read(new byte[2], 0, 2); |
|
||||
|
|
||||
Assert.Equal(2, stream.Position); |
|
||||
Assert.Equal(4, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Position_ReturnsPositionAfterReadingTwice() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Read(new byte[2], 0, 2); |
|
||||
stream.Read(new byte[2], 0, 2); |
|
||||
|
|
||||
Assert.Equal(4, stream.Position); |
|
||||
Assert.Equal(6, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Position_SettingPropertySeeksToNewPosition() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 3; |
|
||||
|
|
||||
Assert.Equal(3, stream.Position); |
|
||||
Assert.Equal(5, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Flush_ThrowsNotSupportedException() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Throws<NotSupportedException>(() => stream.Flush()); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Read_Reads_FromStartOfSubStream() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
byte[] buffer = new byte[3]; |
|
||||
var result = stream.Read(buffer, 0, 3); |
|
||||
|
|
||||
Assert.Equal(new byte[] { 3, 4, 5 }, buffer); |
|
||||
Assert.Equal(3, result); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(2, SeekOrigin.Begin)] |
|
||||
[InlineData(1, SeekOrigin.Current)] |
|
||||
[InlineData(4, SeekOrigin.End)] |
|
||||
public void Read_Reads_FromMiddleOfSubStream(long offset, SeekOrigin origin) |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
stream.Seek(offset, origin); |
|
||||
byte[] buffer = new byte[3]; |
|
||||
var result = stream.Read(buffer, 0, 3); |
|
||||
|
|
||||
Assert.Equal(new byte[] { 5, 6, 7 }, buffer); |
|
||||
Assert.Equal(3, result); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(3, SeekOrigin.Begin)] |
|
||||
[InlineData(2, SeekOrigin.Current)] |
|
||||
[InlineData(3, SeekOrigin.End)] |
|
||||
public void Read_Reads_FromEndOfSubStream(long offset, SeekOrigin origin) |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
stream.Seek(offset, origin); |
|
||||
byte[] buffer = new byte[3]; |
|
||||
var result = stream.Read(buffer, 0, 3); |
|
||||
|
|
||||
Assert.Equal(new byte[] { 6, 7, 8 }, buffer); |
|
||||
Assert.Equal(3, result); |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[InlineData(4, SeekOrigin.Begin)] |
|
||||
[InlineData(3, SeekOrigin.Current)] |
|
||||
[InlineData(2, SeekOrigin.End)] |
|
||||
public void Read_Reads_FromBeyondEndOfSubStream(long offset, SeekOrigin origin) |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
stream.Seek(offset, origin); |
|
||||
byte[] buffer = new byte[3]; |
|
||||
var result = stream.Read(buffer, 0, 3); |
|
||||
|
|
||||
Assert.Equal(new byte[] { 7, 8, 0 }, buffer); |
|
||||
Assert.Equal(2, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ReadByte_Reads_FromStartOfSubStream() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
var result = stream.ReadByte(); |
|
||||
|
|
||||
Assert.Equal(3, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ReadByte_Reads_FromMiddleOfSubStream() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 3; |
|
||||
var result = stream.ReadByte(); |
|
||||
|
|
||||
Assert.Equal(6, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ReadByte_Reads_FromEndOfSubStream() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 5; |
|
||||
var result = stream.ReadByte(); |
|
||||
|
|
||||
Assert.Equal(8, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void ReadByte_Reads_FromBeyondEndOfSubStream() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 5; |
|
||||
stream.ReadByte(); |
|
||||
var result = stream.ReadByte(); |
|
||||
|
|
||||
Assert.Equal(-1, result); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Write_ThrowsNotSupportedException() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Throws<NotSupportedException>(() => stream.Write(new byte[] { 1, 2 }, 0, 2)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void WriteByte_ThrowsNotSupportedException() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Throws<NotSupportedException>(() => stream.WriteByte(42)); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Seek_MovesToNewPosition_FromBegin() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
long result = stream.Seek(2, SeekOrigin.Begin); |
|
||||
|
|
||||
Assert.Equal(2, result); |
|
||||
Assert.Equal(2, stream.Position); |
|
||||
Assert.Equal(4, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Seek_MovesToNewPosition_FromCurrent() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
long result = stream.Seek(2, SeekOrigin.Current); |
|
||||
|
|
||||
Assert.Equal(3, result); |
|
||||
Assert.Equal(3, stream.Position); |
|
||||
Assert.Equal(5, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Seek_MovesToNewPosition_FromEnd() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
stream.Position = 1; |
|
||||
long result = stream.Seek(2, SeekOrigin.End); |
|
||||
|
|
||||
Assert.Equal(4, result); |
|
||||
Assert.Equal(4, stream.Position); |
|
||||
Assert.Equal(6, innerStream.Position); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void Seek_ThrowsException_WithInvalidOrigin() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
var e = Assert.Throws<ArgumentException>(() => stream.Seek(2, (SeekOrigin)99)); |
|
||||
Assert.Equal("Invalid seek origin.", e.Message); |
|
||||
} |
|
||||
|
|
||||
[Fact] |
|
||||
public void SetLength_ThrowsNotSupportedException() |
|
||||
{ |
|
||||
Stream innerStream = new MemoryStream(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); |
|
||||
SubStream stream = new SubStream(innerStream, 2, 6); |
|
||||
|
|
||||
Assert.Throws<NotSupportedException>(() => stream.SetLength(5)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue