diff options
author | Jan Kotas <jkotas@microsoft.com> | 2019-10-18 19:23:34 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2019-10-22 16:46:29 +0300 |
commit | d4a2f01064ac0c6d7f6ae3e2ceb8a1dd15b4139f (patch) | |
tree | bb5aeb5d5619349cbfed0b90f697804b36ac4f67 /netcore/System.Private.CoreLib/shared/System/Buffer.cs | |
parent | 8ea042648814148f3145dd96e99471e346a3980a (diff) |
Rewrite Buffer.BlockCopy in C# (dotnet/coreclr#27216)
* Rewrite Buffer.BlockCopy in C#
Fixes #27106
* Workaround to enable type check optimizations for BlockCopy only
Signed-off-by: dotnet-bot <dotnet-bot@microsoft.com>
Diffstat (limited to 'netcore/System.Private.CoreLib/shared/System/Buffer.cs')
-rw-r--r-- | netcore/System.Private.CoreLib/shared/System/Buffer.cs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/netcore/System.Private.CoreLib/shared/System/Buffer.cs b/netcore/System.Private.CoreLib/shared/System/Buffer.cs index 55fd11e164c..78d82738117 100644 --- a/netcore/System.Private.CoreLib/shared/System/Buffer.cs +++ b/netcore/System.Private.CoreLib/shared/System/Buffer.cs @@ -26,6 +26,54 @@ namespace System { public static partial class Buffer { + // Copies from one primitive array to another primitive array without + // respecting types. This calls memmove internally. The count and + // offset parameters here are in bytes. If you want to use traditional + // array element indices and counts, use Array.Copy. + public static unsafe void BlockCopy(Array src, int srcOffset, Array dst, int dstOffset, int count) + { + if (src == null) + throw new ArgumentNullException(nameof(src)); + if (dst == null) + throw new ArgumentNullException(nameof(dst)); + + nuint uSrcLen = (nuint)src.LongLength; + if (src.GetType() != typeof(byte[])) + { + if (!IsPrimitiveTypeArray(src)) + throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(src)); + uSrcLen *= (nuint)src.GetElementSize(); + } + + nuint uDstLen = uSrcLen; + if (src != dst) + { + uDstLen = (nuint)dst.LongLength; + if (dst.GetType() != typeof(byte[])) + { + if (!IsPrimitiveTypeArray(dst)) + throw new ArgumentException(SR.Arg_MustBePrimArray, nameof(dst)); + uDstLen *= (nuint)dst.GetElementSize(); + } + } + + if (srcOffset < 0) + throw new ArgumentOutOfRangeException(nameof(srcOffset), SR.ArgumentOutOfRange_MustBeNonNegInt32); + if (dstOffset < 0) + throw new ArgumentOutOfRangeException(nameof(dstOffset), SR.ArgumentOutOfRange_MustBeNonNegInt32); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_MustBeNonNegInt32); + + nuint uCount = (nuint)count; + nuint uSrcOffset = (nuint)srcOffset; + nuint uDstOffset = (nuint)dstOffset; + + if ((uSrcLen < uSrcOffset + uCount) || (uDstLen < uDstOffset + uCount)) + throw new ArgumentException(SR.Argument_InvalidOffLen); + + Memmove(ref Unsafe.AddByteOffset(ref dst.GetRawArrayData(), uDstOffset), ref Unsafe.AddByteOffset(ref src.GetRawArrayData(), uSrcOffset), uCount); + } + public static int ByteLength(Array array) { // Is the array present? |