Exemplo n.º 1
0
        static unsafe bool BlockCopyInternal(byte *src, int srcOffset, byte *dest, int destOffset,
                                             int count)
        {
            /* Return false on overflow within src or dest */
            int srcElemSize = *(int *)(src + ArrayOperations.GetElemSizeOffset());
            //int srcIALength = *(int*)(src + ArrayOperations.GetInnerArrayLengthOffset());
            int srcIALength = 0;

            throw new NotImplementedException();
            int srcByteSize = srcElemSize * srcIALength;

            if ((srcOffset + count) > srcByteSize)
            {
                return(false);
            }

            int destElemSize = *(int *)(dest + ArrayOperations.GetElemSizeOffset());
            //int destIALength = *(int*)(dest + ArrayOperations.GetInnerArrayLengthOffset());
            int destIALength = 0;
            int destByteSize = destElemSize * destIALength;

            if ((destOffset + count) > destByteSize)
            {
                return(false);
            }

            /* Get source and dest addresses */
            byte *srcAddr  = *(byte **)(src + ArrayOperations.GetInnerArrayOffset()) + srcOffset;
            byte *destAddr = *(byte **)(dest + ArrayOperations.GetInnerArrayOffset()) + destOffset;

            /* Execute a memmove */
            MemoryOperations.MemMove((void *)destAddr, (void *)srcAddr, count);

            return(true);
        }
Exemplo n.º 2
0
        static unsafe void Copy(void *srcArr, int srcIndex, void *dstArr, int dstIndex, int length,
                                bool reliable)
        {
            /* Ensure arrays are valid */
            if (srcArr == null || dstArr == null)
            {
                throw new ArgumentNullException();
            }

            /* Ensure length is valid */
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            /* Ensure both arrays are of the same rank */
            var srcRank = *(int *)((byte *)srcArr + ArrayOperations.GetRankOffset());
            var dstRank = *(int *)((byte *)dstArr + ArrayOperations.GetRankOffset());

            if (srcRank != dstRank)
            {
                throw new RankException();
            }

            /* Get source and dest element types */
            var srcET = *(void **)((byte *)srcArr + ArrayOperations.GetElemTypeOffset());
            var dstET = *(void **)((byte *)dstArr + ArrayOperations.GetElemTypeOffset());

            /* See if we can do a quick copy */
            bool can_quick_copy = false;

            if (srcET == dstET)
            {
                can_quick_copy = true;
            }
            else if (TysosType.CanCast(srcET, dstET))
            {
                can_quick_copy = true;
            }
            else if (reliable)
            {
                throw new ArrayTypeMismatchException();   /* ConstrainedCopy requires types to be the same or derived */
            }
            else
            {
                can_quick_copy = false;
            }

            /* For now we don't handle arrays with lobounds != 0 */
            var srcLobounds = *(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset());
            var dstLobounds = *(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset());

            for (int i = 0; i < srcRank; i++)
            {
                if (srcLobounds[i] != 0)
                {
                    throw new NotImplementedException("srcLobounds != 0");
                }
                if (dstLobounds[i] != 0)
                {
                    throw new NotImplementedException("dstLobounds != 0");
                }
            }
            if (srcIndex < 0 || dstIndex < 0)
            {
                throw new ArgumentOutOfRangeException();
            }

            /* Ensure we don't overflow */
            var src_len = GetLength(srcArr);
            var dst_len = GetLength(dstArr);

            if (srcIndex + length > src_len)
            {
                System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy srcIndex/length out of range");
                System.Diagnostics.Debugger.Log(length, "libsupcs", "length");
                System.Diagnostics.Debugger.Log(srcIndex, "libsupcs", "srcIndex");
                System.Diagnostics.Debugger.Log(src_len, "libsupcs", "src_len");
                throw new ArgumentOutOfRangeException();
            }
            if (dstIndex + length > dst_len)
            {
                System.Diagnostics.Debugger.Log(0, "libsupcs", "Array.Copy dstIndex/length out of range");
                System.Diagnostics.Debugger.Log(length, "libsupcs", "length");
                System.Diagnostics.Debugger.Log(dstIndex, "libsupcs", "dstIndex");
                System.Diagnostics.Debugger.Log(dst_len, "libsupcs", "dst_len");
                throw new ArgumentOutOfRangeException();
            }

            if (can_quick_copy)
            {
                /* Elem size of both arrays is guaranteed to be the same and we can do a shallow copy */
                var e_size = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset());

                var src_ia = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset());
                var dst_ia = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset());

                MemoryOperations.MemMove(dst_ia + dstIndex * e_size, src_ia + srcIndex * e_size, length * e_size);
            }
            else
            {
                /* TODO: implement as per System.Array.Copy() semantics */
                throw new NotImplementedException("Cannot quick copy " + ((ulong)srcET).ToString("X") +
                                                  " to " + ((ulong)dstET).ToString("X"));
            }
        }
Exemplo n.º 3
0
        static unsafe bool FastCopy(void *srcArr, int srcIndex, void *dstArr, int dstIndex, int length)
        {
            /* This is often called with length == 0 when the
             * first item is added to a List<T> as the default
             * array within the list has length 0.
             */

            if (length == 0)
            {
                return(true);
            }

            // Ensure both arrays are of rank 1
            int srcRank = *(int *)((byte *)srcArr + ArrayOperations.GetRankOffset());
            int dstRank = *(int *)((byte *)dstArr + ArrayOperations.GetRankOffset());

            if (srcRank != 1)
            {
                return(false);
            }
            if (dstRank != 1)
            {
                return(false);
            }

            // Ensure srcIndex is valid
            int srcLobound = **(int **)((byte *)srcArr + ArrayOperations.GetLoboundsOffset());
            int srcSize    = **(int **)((byte *)srcArr + ArrayOperations.GetSizesOffset());

            srcIndex -= srcLobound;
            if (srcIndex + length > srcSize)
            {
                return(false);
            }

            // Ensure destIndex is valid
            int dstLobound = **(int **)((byte *)dstArr + ArrayOperations.GetLoboundsOffset());
            int dstSize    = **(int **)((byte *)dstArr + ArrayOperations.GetSizesOffset());

            dstIndex -= dstLobound;
            if (dstIndex + length > dstSize)
            {
                return(false);
            }

            // Ensure both have same element type
            void *srcET = *(void **)((byte *)srcArr + ArrayOperations.GetElemTypeOffset());
            void *dstET = *(void **)((byte *)dstArr + ArrayOperations.GetElemTypeOffset());

            if (srcET != dstET)
            {
                return(false);
            }

            // Get element size
            int elemSize = *(int *)((byte *)srcArr + ArrayOperations.GetElemSizeOffset());

            srcIndex *= elemSize;
            dstIndex *= elemSize;

            byte *srcAddr = *(byte **)((byte *)srcArr + ArrayOperations.GetInnerArrayOffset()) + srcIndex;
            byte *dstAddr = *(byte **)((byte *)dstArr + ArrayOperations.GetInnerArrayOffset()) + dstIndex;

            length *= elemSize;

            MemoryOperations.MemMove(dstAddr, srcAddr, length);

            return(true);
        }