Example #1
0
        /// <summary>
        /// Implements the copy functionality used by Span and ReadOnlySpan.
        ///
        /// NOTE: Fast span implements TryCopyTo in corelib and therefore this implementation
        ///       is only used by portable span. The code must live in code that only compiles
        ///       for portable span which means either each individual span implementation
        ///       of this shared code file. Other shared SpanHelper.X.cs files are compiled
        ///       for both portable and fast span implementations.
        /// </summary>
        public static unsafe void CopyTo <T>(ref T dst, int dstLength, ref T src, int srcLength)
        {
            IntPtr srcMinusDst       = Unsafe.ByteOffset <T>(ref dst, ref src);
            bool   srcGreaterThanDst = (sizeof(IntPtr) == sizeof(int)) ? srcMinusDst.ToInt32() >= 0 : srcMinusDst.ToInt64() >= 0;
            IntPtr tailDiff;

            if (srcGreaterThanDst)
            {
                // If the start of source is greater than the start of destination, then we need to calculate
                // the different between the end of destination relative to the start of source.
                tailDiff = Unsafe.ByteOffset <T>(ref Unsafe.Add <T>(ref dst, dstLength), ref src);
            }
            else
            {
                // If the start of source is less than the start of destination, then we need to calculate
                // the different between the end of source relative to the start of destunation.
                tailDiff = Unsafe.ByteOffset <T>(ref Unsafe.Add <T>(ref src, srcLength), ref dst);
            }

            // If the source is entirely before or entirely after the destination and the type inside the span is not
            // itself a reference type or containing reference types, then we can do a simple block copy of the data.
            bool isOverlapped = (sizeof(IntPtr) == sizeof(int)) ? tailDiff.ToInt32() < 0 : tailDiff.ToInt64() < 0;

            if (!isOverlapped && !SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ref byte dstBytes  = ref Unsafe.As <T, byte>(ref dst);
                ref byte srcBytes  = ref Unsafe.As <T, byte>(ref src);
Example #2
0
        public static ReadOnlySpan <byte> AsBytes <T>(this ReadOnlySpan <T> source)
            where T : struct
        {
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }

            int newLength = checked (source.Length * Unsafe.SizeOf <T>());

            return(new ReadOnlySpan <byte>(Unsafe.As <Pinnable <byte> >(source.Pinnable), source.ByteOffset, newLength));
        }
Example #3
0
        public unsafe ReadOnlySpan(void *pointer, int length)
        {
            if (SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T));
            }
            if (length < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
            }

            _length     = length;
            _pinnable   = null;
            _byteOffset = new IntPtr(pointer);
        }
Example #4
0
        /// <summary>
        /// Implements the copy functionality used by Span and ReadOnlySpan.
        ///
        /// NOTE: Fast span implements TryCopyTo in corelib and therefore this implementation
        ///       is only used by portable span. The code must live in code that only compiles
        ///       for portable span which means either each individual span implementation
        ///       of this shared code file. Other shared SpanHelper.X.cs files are compiled
        ///       for both portable and fast span implementations.
        /// </summary>
        public static unsafe void CopyTo <T>(ref T dst, int dstLength, ref T src, int srcLength)
        {
            Debug.Assert(dstLength != 0);

            IntPtr srcByteCount = Unsafe.ByteOffset(ref src, ref Unsafe.Add(ref src, srcLength));
            IntPtr dstByteCount = Unsafe.ByteOffset(ref dst, ref Unsafe.Add(ref dst, dstLength));

            IntPtr diff = Unsafe.ByteOffset(ref src, ref dst);

            bool isOverlapped = (sizeof(IntPtr) == sizeof(int))
                ? (uint)diff <(uint)srcByteCount || (uint)diff> (uint) - (int)dstByteCount
                : (ulong)diff <(ulong)srcByteCount || (ulong)diff> (ulong) - (long)dstByteCount;

            if (!isOverlapped && !SpanHelpers.IsReferenceOrContainsReferences <T>())
            {
                ref byte dstBytes  = ref Unsafe.As <T, byte>(ref dst);
                ref byte srcBytes  = ref Unsafe.As <T, byte>(ref src);
        public static Span <TTo> NonPortableCast <TFrom, TTo>(this Span <TFrom> source)
            where TFrom : struct
            where TTo : struct
        {
            if (SpanHelpers.IsReferenceOrContainsReferences <TFrom>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TFrom));
            }

            if (SpanHelpers.IsReferenceOrContainsReferences <TTo>())
            {
                ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TTo));
            }

            int newLength = checked ((int)((long)source.Length * Unsafe.SizeOf <TFrom>() / Unsafe.SizeOf <TTo>()));

            return(new Span <TTo>(Unsafe.As <Pinnable <TTo> >(source.Pinnable), source.ByteOffset, newLength));
        }