#region Copyright and License
/*
This file is part of FFTW.NET, a wrapper around the FFTW library for the .NET framework.
Copyright (C) 2017 Tobias Meyer
License: Microsoft Reciprocal License (MS-RL)
*/
#endregion
using System;
using System.Runtime.InteropServices;
namespace FFTW.NET
{
///
/// Wrapper around which provides some level of type-safety.
/// If you have access to the strongly typed instance of the underlying buffer (e.g. T[], T[,], T[,,], etc.)
/// you should always get and set values using the strongly typed instance.
/// uses / internally which is much slower than
/// using the strongly typed instance directly.
///
public class PinnedArray : IPinnedArray
where T : struct
{
readonly System.Array _buffer;
readonly PinnedGCHandle _pin;
public int Rank => _buffer.Rank;
public Array Buffer => _buffer;
public int Length => _buffer.Length;
public IntPtr Pointer => _pin.Pointer;
public bool IsDisposed => !_pin.IsAllocated;
public PinnedArray(params int[] lengths)
: this(Array.CreateInstance(typeof(T), lengths)) { }
public PinnedArray(Array array)
{
if (array.GetType().GetElementType() != typeof(T))
throw new ArgumentException($"Must have elements of type {typeof(T).FullName}.", nameof(array));
_buffer = array;
_pin = PinnedGCHandle.Pin(_buffer);
}
public int GetLength(int dimension) => _buffer.GetLength(dimension);
public int[] GetSize()
{
int[] result = new int[Rank];
for (int i = 0; i < Rank; i++)
result[i] = GetLength(i);
return result;
}
public T this[params int[] indices]
{
get { return (T)_buffer.GetValue(indices); }
set { _buffer.SetValue(value, indices); }
}
public T this[int index]
{
get { return (T)_buffer.GetValue(index); }
set { _buffer.SetValue(value, index); }
}
public T this[int i1, int i2]
{
get { return (T)_buffer.GetValue(i1, i2); }
set { _buffer.SetValue(value, i1, i2); }
}
public T this[int i1, int i2, int i3]
{
get { return (T)_buffer.GetValue(i1, i2, i3); }
set { _buffer.SetValue(value, i1, i2, i3); }
}
public static implicit operator Array(PinnedArray array) => array._buffer;
public static explicit operator PinnedArray(Array array) => new PinnedArray(array);
public void Dispose() => _pin.Free();
}
}