mirror of https://github.com/SixLabors/ImageSharp
13 changed files with 154 additions and 43 deletions
@ -0,0 +1,21 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Memory |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Represents discontiguous group of multiple uniformly-sized memory segments.
|
||||
|
/// The last segment can be smaller than the preceding ones.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The element type.</typeparam>
|
||||
|
public interface IMemoryGroup<T> : IReadOnlyList<Memory<T>> |
||||
|
where T : struct |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the number of elements per contiguous sub-block.
|
||||
|
/// </summary>
|
||||
|
public int BlockSize { get; } |
||||
|
|
||||
|
bool IsValid { get; } |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
using System; |
using System; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
namespace SixLabors.ImageSharp.Memory |
||||
{ |
{ |
||||
public class InvalidMemoryOperationException : InvalidOperationException |
public class InvalidMemoryOperationException : InvalidOperationException |
||||
{ |
{ |
||||
@ -1,12 +1,12 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
|
||||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
namespace SixLabors.ImageSharp.Memory |
||||
{ |
{ |
||||
internal abstract partial class UniformMemoryGroup<T> |
internal abstract partial class MemoryGroup<T> |
||||
{ |
{ |
||||
// Analogous to the "consumed" variant of MemorySource
|
// Analogous to the "consumed" variant of MemorySource
|
||||
private class Consumed : UniformMemoryGroup<T> |
private class Consumed : MemoryGroup<T> |
||||
{ |
{ |
||||
private readonly ReadOnlyMemory<Memory<T>> source; |
private readonly ReadOnlyMemory<Memory<T>> source; |
||||
|
|
||||
@ -1,15 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Memory.DiscontinuousProto |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Represents discontinuous group of multiple uniformly-sized memory segments.
|
|
||||
/// The last segment can be smaller than the preceding ones.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="T">The element type.</typeparam>
|
|
||||
public interface IUniformMemoryGroup<T> : IReadOnlyList<Memory<T>> where T : struct |
|
||||
{ |
|
||||
bool IsValid { get; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,96 @@ |
|||||
|
using System.Linq; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using SixLabors.ImageSharp.Memory; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers |
||||
|
{ |
||||
|
public class MemoryGroupTests |
||||
|
{ |
||||
|
public class Allocate |
||||
|
{ |
||||
|
private readonly TestMemoryAllocator memoryAllocator = new TestMemoryAllocator(); |
||||
|
|
||||
|
#pragma warning disable SA1509
|
||||
|
public static TheoryData<object, int, int, long, int, int, int> AllocateData = |
||||
|
new TheoryData<object, int, int, long, int, int, int>() |
||||
|
{ |
||||
|
{ default(S5), 22, 4, 4, 1, 4, 4 }, |
||||
|
{ default(S5), 22, 4, 7, 2, 4, 3 }, |
||||
|
{ default(S5), 22, 4, 8, 2, 4, 4 }, |
||||
|
{ default(S5), 22, 4, 21, 5, 4, 1 }, |
||||
|
{ default(S5), 22, 4, 0, 0, -1, -1 }, |
||||
|
|
||||
|
{ default(S4), 50, 12, 12, 1, 12, 12 }, |
||||
|
{ default(S4), 50, 7, 12, 2, 7, 5 }, |
||||
|
{ default(S4), 50, 6, 12, 2, 6, 6 }, |
||||
|
{ default(S4), 50, 5, 12, 2, 10, 2 }, |
||||
|
{ default(S4), 50, 4, 12, 1, 12, 12 }, |
||||
|
{ default(S4), 50, 3, 12, 1, 12, 12 }, |
||||
|
{ default(S4), 50, 2, 12, 1, 12, 12 }, |
||||
|
{ default(S4), 50, 1, 12, 1, 12, 12 }, |
||||
|
|
||||
|
{ default(S4), 50, 12, 13, 2, 12, 1 }, |
||||
|
{ default(S4), 50, 7, 21, 3, 7, 7 }, |
||||
|
{ default(S4), 50, 7, 23, 3, 7, 2 }, |
||||
|
|
||||
|
{ default(byte), 1000, 512, 2047, 4, 512, 511 } |
||||
|
}; |
||||
|
|
||||
|
[Theory] |
||||
|
[MemberData(nameof(AllocateData))] |
||||
|
public void CreatesBlocksOfCorrectSizes<T>( |
||||
|
T dummy, |
||||
|
int blockCapacity, |
||||
|
int blockAlignment, |
||||
|
long totalLength, |
||||
|
int expectedNumberOfBlocks, |
||||
|
int expectedBlockSize, |
||||
|
int expectedSizeOfLastBlock) |
||||
|
where T : struct |
||||
|
{ |
||||
|
this.memoryAllocator.BlockCapacity = blockCapacity; |
||||
|
|
||||
|
// Act:
|
||||
|
using var g = MemoryGroup<T>.Allocate(this.memoryAllocator, totalLength, blockAlignment); |
||||
|
|
||||
|
// Assert:
|
||||
|
Assert.Equal(expectedNumberOfBlocks, g.Count); |
||||
|
Assert.Equal(expectedBlockSize, g.BlockSize); |
||||
|
if (g.Count == 0) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < g.Count - 1; i++) |
||||
|
{ |
||||
|
Assert.Equal(g[i].Length, expectedBlockSize); |
||||
|
} |
||||
|
|
||||
|
Assert.Equal(g.Last().Length, expectedSizeOfLastBlock); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void WhenBlockAlignmentIsOverCapacity_Throws_InvalidMemoryOperationException() |
||||
|
{ |
||||
|
this.memoryAllocator.BlockCapacity = 42; |
||||
|
|
||||
|
Assert.Throws<InvalidMemoryOperationException>(() => |
||||
|
{ |
||||
|
MemoryGroup<byte>.Allocate(this.memoryAllocator, 50, 43); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential, Size = 5)] |
||||
|
private struct S5 |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential, Size = 4)] |
||||
|
private struct S4 |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue