Esempio n. 1
0
        /// <summary>
        /// Function to pin an array and return a <see cref="GorgonNativeBuffer{T}"/> containing the pinned data.
        /// </summary>
        /// <typeparam name="T">The type of data in the array. Must be an unmanaged value type.</typeparam>
        /// <param name="array">The array to turn into a native buffer.</param>
        /// <param name="index">[Optional] The index in the array that represents the beginning of the native buffer.</param>
        /// <param name="count">[Optional] The number of items in the array that will be contained in the buffer.</param>
        /// <returns>A new <see cref="GorgonNativeBuffer{T}"/> containing the <paramref name="array"/> data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="array"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is less than 0.</exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="index"/> + <paramref name="count"/> are equal to or greater than the length of <paramref name="array"/>.</exception>
        /// <remarks>
        /// <para>
        /// This method pins the supplied <paramref name="array"/> and returns a new <see cref="GorgonNativeBuffer{T}"/> containing the pinned data.
        /// </para>
        /// <para>
        /// If the <paramref name="index"/> is not supplied, then the beginning of the <paramref name="array"/> is used as the start of the buffer, and if the <paramref name="count"/> parameter is not
        /// supplied, then the length of the <paramref name="array"/> (minus the <paramref name="index"/>) is used.
        /// </para>
        /// <para>
        /// <note type="warning">
        /// This method <b>pins</b> the <paramref name="array"/>, which can cause performance issues with the garbage collector. Applications should only pin their objects for a very short time for best
        /// performance.
        /// </note>
        /// </para>
        /// </remarks>
        public static GorgonNativeBuffer <T> ToPinned <T>(this T[] array, int index = 0, int?count = null)
            where T : unmanaged
        {
            if (count == null)
            {
                count = array.Length - index;
            }

            return(GorgonNativeBuffer <T> .Pin(array, index, count));
        }
Esempio n. 2
0
        /// <summary>
        /// Function to copy the contents of a stream into a <see cref="GorgonNativeBuffer{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type of value in the buffer. Must be an unmanaged value type.</typeparam>
        /// <param name="stream">The stream to read from.</param>
        /// <param name="count">[Optional] The maximum number of items to read from the stream.</param>
        /// <returns>A <see cref="GorgonNativeBuffer{T}"/> containing the contents of the stream.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is <b>null</b>.</exception>
        /// <exception cref="EndOfStreamException">Thrown when the <paramref name="stream"/> is at its end.</exception>
        /// <exception cref="IOException">Thrown when the <paramref name="stream"/> is write only.</exception>
        public static GorgonNativeBuffer <T> ToNativeBuffer <T>(this Stream stream, int?count = null)
            where T : unmanaged
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (stream.Position == stream.Length)
            {
                throw new EndOfStreamException();
            }

            if (!stream.CanRead)
            {
                throw new IOException(Resources.GOR_ERR_STREAM_IS_WRITEONLY);
            }

            int typeSize = Unsafe.SizeOf <T>();

            if (count == null)
            {
                if (typeSize == 1)
                {
                    count = (int)(stream.Length - stream.Position);
                }
                else
                {
                    count = (int)((stream.Length - stream.Position) / typeSize);
                }
            }

            var result = new GorgonNativeBuffer <T>(count.Value);

            using (var reader = new GorgonBinaryReader(stream, true))
            {
                for (int i = 0; i < count.Value; ++i)
                {
                    if (stream.Position + typeSize >= stream.Length)
                    {
                        break;
                    }

                    reader.ReadValue(out result[i]);
                }
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Function to convert an array into a <see cref="GorgonNativeBuffer{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type of data in the array. Must be an unmanaged value type.</typeparam>
        /// <param name="array">The array to turn into a native buffer.</param>
        /// <param name="index">[Optional] The index in the array that represents the beginning of the native buffer.</param>
        /// <param name="count">[Optional] The number of items in the array that will be contained in the buffer.</param>
        /// <returns>A new <see cref="GorgonNativeBuffer{T}"/> containing the <paramref name="array"/> data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="array"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="index"/> is less than 0.</exception>
        /// <exception cref="ArgumentException">Thrown when the <paramref name="index"/> + <paramref name="count"/> are equal to or greater than the length of <paramref name="array"/>.</exception>
        /// <remarks>
        /// <para>
        /// This method copies the contents of an array into a <see cref="GorgonNativeBuffer{T}"/> so that the data can be used with native code.
        /// </para>
        /// <para>
        /// If the <paramref name="index"/> is not supplied, then the beginning of the <paramref name="array"/> is used as the start of the buffer, and if the <paramref name="count"/> parameter is not
        /// supplied, then the length of the <paramref name="array"/> (minus the <paramref name="index"/>) is used.
        /// </para>
        /// <para>
        /// <note type="warning">
        /// This method <b>copies</b> the data from the array into the buffer. This may have a negative impact on performance and memory usage.
        /// </note>
        /// </para>
        /// </remarks>
        public static GorgonNativeBuffer <T> ToNativeBuffer <T>(this T[] array, int index = 0, int?count = null)
            where T : unmanaged
        {
            if (count == null)
            {
                count = array.Length - index;
            }

            GorgonNativeBuffer <T> .ValidateArrayParams(array, index, count.Value);

            var result = new GorgonNativeBuffer <T>(count.Value);

            unsafe
            {
                fixed(T *srcPtr = &array[index])
                {
                    Unsafe.CopyBlock((T *)result, srcPtr, (uint)(Unsafe.SizeOf <T>() * count.Value));
                }
            }

            return(result);
        }
Esempio n. 4
0
        /// <summary>
        /// Function to copy the contents of an array into a <see cref="GorgonNativeBuffer{T}"/>.
        /// </summary>
        /// <typeparam name="T">The type of data in the array and buffer. Must be an unmanaged value type.</typeparam>
        /// <param name="array">The array to copy from.</param>
        /// <param name="buffer">The buffer that will receive the data.</param>
        /// <param name="arrayIndex">[Optional] The index in the array to start copying from.</param>
        /// <param name="count">[Optional] The number of items to copy.</param>
        /// <param name="bufferIndex">[Optional] The index in the buffer to start writing into.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="array"/>, or <paramref name="buffer"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="arrayIndex"/>, or the <paramref name="bufferIndex"/> parameter is less than 0.</exception>
        /// <exception cref="ArgumentException">
        /// <para>Thrown when the <paramref name="arrayIndex"/> + <paramref name="count"/> is too big for the <paramref name="array"/>.</para>
        /// <para>-or-</para>
        /// <para>Thrown when the <paramref name="bufferIndex"/> + <paramref name="count"/> is too big for the <paramref name="buffer"/>.</para>
        /// </exception>
        /// <remarks>
        /// <para>
        /// If the <paramref name="count"/> parameter is ommitted, then the full length of the source buffer, minus the <paramref name="arrayIndex"/> is used. Ensure that there is enough space in the
        /// <paramref name="buffer"/> to accomodate the amount of data required.
        /// </para>
        /// </remarks>
        public static void CopyTo <T>(this T[] array, GorgonNativeBuffer <T> buffer, int arrayIndex = 0, int?count = null, int bufferIndex = 0)
            where T : unmanaged
        {
            if (array == null)
            {
                throw new ArgumentNullException(nameof(array));
            }

            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (count == null)
            {
                count = array.Length - arrayIndex;
            }

            GorgonNativeBuffer <T> .ValidateArrayParams(array, arrayIndex, count.Value);

            if (bufferIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(bufferIndex), Resources.GOR_ERR_DATABUFF_OFFSET_TOO_SMALL);
            }

            if (bufferIndex + count.Value > buffer.Length)
            {
                throw new ArgumentException(string.Format(Resources.GOR_ERR_DATABUFF_SIZE_OFFSET_TOO_LARGE, bufferIndex, count));
            }

            unsafe
            {
                fixed(T *srcPtr = &array[arrayIndex])
                fixed(T * destPtr = &buffer[bufferIndex])
                {
                    Unsafe.CopyBlock(destPtr, srcPtr, (uint)count.Value);
                }
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Function to copy the contents of this buffer into other.
        /// </summary>
        /// <param name="destination">The destination buffer that will receive the data.</param>
        /// <param name="sourceIndex">[Optional] The first index to start copying from.</param>
        /// <param name="count">[Optional] The number of items to copy.</param>
        /// <param name="destIndex">[Optional] The destination index in the destination buffer to start copying into.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="destination"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the <paramref name="sourceIndex"/>, or the <paramref name="destIndex"/> parameter is less than 0.</exception>
        /// <exception cref="ArgumentException">
        /// <para>Thrown when the <paramref name="sourceIndex"/> + <paramref name="count"/> is too big for this buffer.</para>
        /// <para>-or-</para>
        /// <para>Thrown when the <paramref name="destIndex"/> + <paramref name="count"/> is too big for the <paramref name="destination"/> buffer.</para>
        /// </exception>
        /// <remarks>
        /// <para>
        /// If the <paramref name="count"/> parameter is ommitted, then the full length of the source buffer, minus the <paramref name="sourceIndex"/> is used. Ensure that there is enough space in the
        /// <paramref name="destination"/> buffer to accomodate the amount of data required.
        /// </para>
        /// </remarks>
        public void CopyTo(GorgonNativeBuffer <T> destination, int sourceIndex = 0, int?count = null, int destIndex = 0)
        {
            if (destination == null)
            {
                throw new ArgumentNullException(nameof(destination));
            }

            if (sourceIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(sourceIndex), Resources.GOR_ERR_DATABUFF_OFFSET_TOO_SMALL);
            }

            if (destIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(destIndex), Resources.GOR_ERR_DATABUFF_OFFSET_TOO_SMALL);
            }

            if (count == null)
            {
                count = Length - sourceIndex;
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count), Resources.GOR_ERR_DATABUFF_SIZE_TOO_SMALL);
            }

            if (sourceIndex + count.Value > Length)
            {
                throw new ArgumentException(string.Format(Resources.GOR_ERR_DATABUFF_SIZE_OFFSET_TOO_LARGE, sourceIndex, count.Value));
            }

            if (destIndex + count.Value > destination.Length)
            {
                throw new ArgumentException(string.Format(Resources.GOR_ERR_DATABUFF_SIZE_OFFSET_TOO_LARGE, destIndex, count.Value));
            }

            Unsafe.CopyBlock(destination._memoryBlock + (destIndex * _typeSize), _memoryBlock + (sourceIndex * _typeSize), (uint)(count * _typeSize));
        }
Esempio n. 6
0
 /// <summary>
 /// Function to determine if this buffer is equal to another.
 /// </summary>
 /// <param name="other">The other buffer to compare.</param>
 /// <returns><b>true</b> if equal, <b>false</b> if not.</returns>
 /// <remarks>
 /// <para>
 /// This method determines equality between two <see cref="GorgonNativeBuffer{T}"/> instances. The method of determining equality in this method is different from the standard <c>==</c> or <c>!=</c>
 /// operators or even the <see cref="object.Equals(object)"/> method. To determine equality, the set of rules below will be used to tell if two instances are equal or not.
 /// </para>
 /// <para>
 /// <h3>Rules for determining equality</h3>
 /// <list type="bullet">
 /// <listheader>
 ///     <term>Condition</term>
 ///     <description>Returns</description>
 /// </listheader>
 /// <item>
 ///     <term>If <paramref name="other"/> is the same reference as this instance.</term>
 ///     <description><b>true</b></description>
 /// </item>
 /// <item>
 ///     <term>If <paramref name="other"/> <b>false</b>.</term>
 ///     <description><b>false</b></description>
 /// </item>
 /// <item>
 ///     <term>If <paramref name="other"/> is not the same reference as this instance, and but has the same location in memory, and has the same <see cref="SizeInBytes"/>.</term>
 ///     <description><b>true</b></description>
 /// </item>
 /// <item>
 ///     <term>If <paramref name="other"/> is not the same reference as this instance, and does not have the same location in memory, or does not have the same <see cref="SizeInBytes"/>.</term>
 ///     <description><b>false</b></description>
 /// </item>
 /// </list>
 /// </para>
 /// </remarks>
 public bool Equals(GorgonNativeBuffer <T> other) => other == this ? true : (other != null) && (other._memoryBlock == _memoryBlock) && (SizeInBytes == other.SizeInBytes);