Buffer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / untmp / whidbey / QFE / ndp / clr / src / BCL / System / Buffer.cs / 3 / Buffer.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
namespace System {
 
    //Only contains static methods.  Does not require serialization 

    using System; 
    using System.Runtime.CompilerServices;
[System.Runtime.InteropServices.ComVisible(true)]
    public static class Buffer
    { 
        // Copies from one primitive array to another primitive array without
        // respecting types.  This calls memmove internally. 
        [MethodImplAttribute(MethodImplOptions.InternalCall)] 
        public static extern void BlockCopy(Array src, int srcOffset,
            Array dst, int dstOffset, int count); 

        // A very simple and efficient array copy that assumes all of the
        // parameter validation has already been done.  All counts here are
        // in bytes. 
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        internal static extern void InternalBlockCopy(Array src, int srcOffset, 
            Array dst, int dstOffset, int count); 

        // This is ported from the optimized CRT assembly in memchr.asm. The JIT generates 
        // pretty good code here and this ends up being within a couple % of the CRT asm.
        // It is however cross platform as the CRT hasn't ported their fast version to 64-bit
        // platforms.
        // 
        internal unsafe static int IndexOfByte(byte* src, byte value, int index, int count)
        { 
            BCLDebug.Assert(src != null, "src should not be null"); 

            byte* pByte = src + index; 

            // Align up the pointer to sizeof(int).
            while (((int)pByte & 3) != 0)
            { 
                if (count == 0)
                    return -1; 
                else if (*pByte == value) 
                    return (int) (pByte - src);
 
                count--;
                pByte++;
            }
 
            // Fill comparer with value byte for comparisons
            // 
            // comparer = 0/0/value/value 
            uint comparer = (((uint)value << 8) + (uint)value);
            // comparer = value/value/value/value 
            comparer = (comparer << 16) + comparer;

            // Run through buffer until we hit a 4-byte section which contains
            // the byte we're looking for or until we exhaust the buffer. 
            while (count > 3)
            { 
                // Test the buffer for presence of value. comparer contains the byte 
                // replicated 4 times.
                uint t1 = *(uint*)pByte; 
                t1 = t1 ^ comparer;
                uint t2 = 0x7efefeff + t1;
                t1 = t1 ^ 0xffffffff;
                t1 = t1 ^ t2; 
                t1 = t1 & 0x81010100;
 
                // if t1 is zero then these 4-bytes don't contain a match 
                if (t1 != 0)
                { 
                    // We've found a match for value, figure out which position it's in.
                    int foundIndex = (int) (pByte - src);
                    if (pByte[0] == value)
                        return foundIndex; 
                    else if (pByte[1] == value)
                        return foundIndex + 1; 
                    else if (pByte[2] == value) 
                        return foundIndex + 2;
                    else if (pByte[3] == value) 
                        return foundIndex + 3;
                }

                count -= 4; 
                pByte += 4;
 
            } 

            // Catch any bytes that might be left at the tail of the buffer 
            while (count > 0)
            {
                if (*pByte == value)
                    return (int) (pByte - src); 

                count--; 
                pByte++; 
            }
 
            // If we don't have a match return -1;
            return -1;
        }
  
        // Gets a particular byte out of the array.  The array must be an
        // array of primitives. 
        // 
        // This essentially does the following:
        // return ((byte*)array) + index. 
        //
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public static extern byte GetByte(Array array, int index);
 
        // Sets a particular byte in an the array.  The array must be an
        // array of primitives. 
        // 
        // This essentially does the following:
        // *(((byte*)array) + index) = value. 
        //
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public static extern void SetByte(Array array, int index, byte value);
 
        // Gets a particular byte out of the array.  The array must be an
        // array of primitives. 
        // 
        // This essentially does the following:
        // return array.length * sizeof(array.UnderlyingElementType). 
        //
        [MethodImplAttribute(MethodImplOptions.InternalCall)]
        public static extern int ByteLength(Array array);
 
        internal unsafe static void ZeroMemory(byte* src, long len)
        { 
            while(len-- > 0) 
                *(src + len) = 0;
        } 

        internal unsafe static void memcpy(byte* src, int srcIndex, byte[] dest, int destIndex, int len) {
            BCLDebug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
            BCLDebug.Assert(dest.Length - destIndex >= len, "not enough bytes in dest"); 
            // If dest has 0 elements, the fixed statement will throw an
            // IndexOutOfRangeException.  Special-case 0-byte copies. 
            if (len==0) 
                return;
            fixed(byte* pDest = dest) { 
                memcpyimpl(src+srcIndex, pDest+destIndex, len);
            }
        }
 
        internal unsafe static void memcpy(byte[] src, int srcIndex, byte* pDest, int destIndex, int len) {
            BCLDebug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); 
            BCLDebug.Assert(src.Length - srcIndex >= len, "not enough bytes in src"); 
            // If dest has 0 elements, the fixed statement will throw an
            // IndexOutOfRangeException.  Special-case 0-byte copies. 
            if (len==0)
                return;
            fixed(byte* pSrc = src) {
                memcpyimpl(pSrc+srcIndex, pDest+destIndex, len); 
            }
        } 
 
        internal unsafe static void memcpy(char* pSrc, int srcIndex, char* pDest, int destIndex, int len) {
            BCLDebug.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!"); 

            // No boundary
            if (len==0)
                return; 
            memcpyimpl((byte*)(char*)(pSrc+srcIndex), (byte*)(char*)(pDest+destIndex), len*2);
        } 
 
        // Note - using a long instead of an int for the length parameter
        // slows this method down by ~18%. 
        internal unsafe static void memcpyimpl(byte* src, byte* dest, int len) {
            BCLDebug.Assert(len >= 0, "Negative length in memcopy!");

#if FEATURE_PAL 
            // Portable naive implementation
            while (len-- > 0) 
                *dest++ = *src++; 
#else
 
            // It turns out that on AMD64 it is faster to not be careful of alignment issues.
            // On IA64 it is necessary to be careful... Oh well. When we do the IA64 push we
            // can work on this implementation.
#if IA64 
            long dstAlign = 8 - (((long)dest) & 7); // number of bytes to copy before dest is 8-byte aligned
 
            while ((dstAlign > 0) && (len > 0)) 
            {
                *dest++ = *src++; 

                len--;
                dstAlign--;
            } 

            long srcAlign = 8 - (((long)src) & 7); 
 
            if (len > 0)
            { 
                if (srcAlign != 8)
                {
                    if (4 == srcAlign)
                    { 
                        while (len >= 4)
                        { 
                            ((int*)dest)[0] = ((int*)src)[0]; 
                            dest += 4;
                            src  += 4; 
                            len  -= 4;
                        }

                        srcAlign = 2;   // fall through to 2-byte copies 
                    }
 
                    if ((2 == srcAlign) || (6 == srcAlign)) 
                    {
                        while (len >= 2) 
                        {
                            ((short*)dest)[0] = ((short*)src)[0];
                            dest += 2;
                            src  += 2; 
                            len  -= 2;
                        } 
                    } 

                    while (len-- > 0) 
                    {
                        *dest++ = *src++;
                    }
                } 
                else
                { 
                    if (len >= 16) 
                    {
                        do 
                        {
                            ((long*)dest)[0] = ((long*)src)[0];
                            ((long*)dest)[1] = ((long*)src)[1];
                            dest += 16; 
                            src += 16;
                        } while ((len -= 16) >= 16); 
                    } 
                    if (len > 0)  // protection against negative len and optimization for len==16*N
                    { 
                       if ((len & 8) != 0)
                       {
                           ((long*)dest)[0] = ((long*)src)[0];
                           dest += 8; 
                           src += 8;
                       } 
                       if ((len & 4) != 0) 
                       {
                           ((int*)dest)[0] = ((int*)src)[0]; 
                           dest += 4;
                           src += 4;
                       }
                       if ((len & 2) != 0) 
                       {
                           ((short*)dest)[0] = ((short*)src)[0]; 
                           dest += 2; 
                           src += 2;
                       } 
                       if ((len & 1) != 0)
                       {
                           *dest++ = *src++;
                       } 
                    }
                } 
            } 

#else 
            // AMD64 implementation uses longs instead of ints where possible
            //
            // This is a faster memcpy implementation, from
            // COMString.cpp.  For our strings, this beat the processor's 
            // repeat & move single byte instruction, which memcpy expands into.
            // (You read that correctly.) 
            // This is 3x faster than a simple while loop copying byte by byte, 
            // for large copies.
            if (len >= 16) 
            {
                do
                {
#if AMD64 
                    ((long*)dest)[0] = ((long*)src)[0];
                    ((long*)dest)[1] = ((long*)src)[1]; 
#else 
                    ((int*)dest)[0] = ((int*)src)[0];
                    ((int*)dest)[1] = ((int*)src)[1]; 
                    ((int*)dest)[2] = ((int*)src)[2];
                    ((int*)dest)[3] = ((int*)src)[3];
#endif
                    dest += 16; 
                    src += 16;
                } while ((len -= 16) >= 16); 
            } 
            if(len > 0)  // protection against negative len and optimization for len==16*N
            { 
                if ((len & 8) != 0)
                {
#if AMD64
                    ((long*)dest)[0] = ((long*)src)[0]; 
#else
                    ((int*)dest)[0] = ((int*)src)[0]; 
                    ((int*)dest)[1] = ((int*)src)[1]; 
#endif
                    dest += 8; 
                    src += 8;
               }
               if ((len & 4) != 0)
               { 
                    ((int*)dest)[0] = ((int*)src)[0];
                    dest += 4; 
                    src += 4; 
               }
               if ((len & 2) != 0) 
               {
                    ((short*)dest)[0] = ((short*)src)[0];
                    dest += 2;
                    src += 2; 
               }
               if ((len & 1) != 0) 
                    *dest++ = *src++; 
            }
 
#endif // IA64
#endif // FEATURE_PAL
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK