DbBuffer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Data / System / Data / ProviderBase / DbBuffer.cs / 1 / DbBuffer.cs

                            //------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.ProviderBase 
{
    using System; 
    using System.Data.Common;
#if ORACLE
    using System.Data.OracleClient;
#endif // ORACLE 
    using System.Diagnostics;
    using System.Runtime.CompilerServices; 
    using System.Runtime.ConstrainedExecution; 
    using System.Runtime.InteropServices;
    using System.Security; 
    using System.Security.Permissions;
    using System.Threading;

    // DbBuffer is abstract to require derived class to exist 
    // so that when debugging, we can tell the difference between one DbBuffer and another
    internal abstract class DbBuffer : SafeHandle { 
 
        internal const int LMEM_FIXED = 0x0000;
        internal const int LMEM_MOVEABLE = 0x0002; 
        internal const int LMEM_ZEROINIT = 0x0040;

        private readonly int _bufferLength;
 
#if ORACLE
        private int _baseOffset; 
#endif 

#if ORACLE 
        protected
#else
        private
#endif 
        DbBuffer(int initialSize, bool zeroBuffer) : base(IntPtr.Zero, true) {
            if (0 < initialSize) { 
                int flags = ((zeroBuffer) ? LMEM_ZEROINIT : LMEM_FIXED); 

                _bufferLength = initialSize; 
                RuntimeHelpers.PrepareConstrainedRegions();
                try {} finally {
                    base.handle = SafeNativeMethods.LocalAlloc(flags, (IntPtr)initialSize);
                } 
                if (IntPtr.Zero == base.handle) {
                    throw new OutOfMemoryException(); 
                } 
            }
        } 

        protected DbBuffer(int initialSize) : this(initialSize, true) {
        }
 
#if !ORACLE
        protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle) { 
        } 

        private int BaseOffset { get { return 0; } } 
#else
        protected int BaseOffset {
            get {
                return _baseOffset; 
            }
            set { 
                _baseOffset = value; 
            }
        } 
#endif

        public override bool IsInvalid {
            get { 
                return (IntPtr.Zero == base.handle);
            } 
        } 

        internal int Length { 
            get {
                return _bufferLength;
            }
        } 

        internal string PtrToStringUni(int offset) { 
            offset += BaseOffset; 
            Validate(offset, 2);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 

            string value = null;
            bool   mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                int length = UnsafeNativeMethods.lstrlenW(ptr); 
                Validate(offset, (2*(length+1)));
                value = Marshal.PtrToStringUni(ptr, length);
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                } 
            }
 
            return value;
        }

        internal String PtrToStringUni(int offset, int length) { 
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 

            string value = null; 
            bool   mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                value = Marshal.PtrToStringUni(ptr, length); 
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease();
                }
            } 
            return value;
        } 
 
#if !ORACLE
        internal byte ReadByte(int offset) { 
            offset += BaseOffset;
            ValidateCheck(offset, 1);
            Debug.Assert(0 == offset%4, "invalid alignment");
 
            byte value;
            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                value = Marshal.ReadByte(ptr, offset);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
            return value;
        }
#endif
 
        internal byte[] ReadBytes(int offset, int length) {
            byte[] value = new byte[length]; 
            return ReadBytes(offset, value, 0, length); 
        }
 
        internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
            return destination;
        } 

#if !ORACLE 
        internal Char ReadChar(int offset) { 
            short value = ReadInt16(offset);
            return unchecked((char)value); 
        }

        internal char[] ReadChars(int offset, char[] destination, int startIndex, int length) {
            offset += BaseOffset; 
            Validate(offset, 2*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination"); 
            Debug.Assert(startIndex + length <= destination.Length, "destination too small");
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length); 
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease();
                }
            } 
            return destination;
        } 
 
        internal Double ReadDouble(int offset) {
            Int64 value = ReadInt64(offset); 
            return BitConverter.Int64BitsToDouble(value);
        }
#endif
 
        internal Int16 ReadInt16(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 2); 
            Debug.Assert(0 == offset%2, "invalid alignment");
 
            short value;
            bool  mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt16(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 

#if !ORACLE 
        internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 2*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
#endif 
        internal Int32 ReadInt32(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 4); 
            Debug.Assert(0 == offset%4, "invalid alignment");
 
            int  value;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt32(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 

#if !ORACLE 
        internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 4*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
 
        internal Int64 ReadInt64(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 8); 
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");
 
            long value;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt64(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 
#endif
        internal IntPtr ReadIntPtr(int offset) { 
            offset += BaseOffset;
            ValidateCheck(offset, IntPtr.Size);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
 
            IntPtr value;
            bool   mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                value = Marshal.ReadIntPtr(ptr, offset);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
            return value;
        }

#if !ORACLE 
        internal unsafe Single ReadSingle(int offset) {
            Int32 value = ReadInt32(offset); 
            return *(Single*)&value; 
        }
#endif 

        override protected bool ReleaseHandle() {
            // NOTE: The SafeHandle class guarantees this will be called exactly once.
            IntPtr ptr = base.handle; 
            base.handle = IntPtr.Zero;
            if (IntPtr.Zero != ptr) { 
                SafeNativeMethods.LocalFree(ptr); 
            }
            return true; 
        }

#if ORACLE
        internal 
#else
        private 
#endif 
        void StructureToPtr(int offset, object structure) {
            Debug.Assert(null != structure, "null structure"); 
            offset += BaseOffset;
            ValidateCheck(offset, Marshal.SizeOf(structure.GetType()));
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/);
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                } 
            }
        } 

#if !ORACLE
        internal void WriteByte(int offset, byte value) {
            offset += BaseOffset; 
            ValidateCheck(offset, 1);
            Debug.Assert(0 == offset%4, "invalid alignment"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteByte(ptr, offset, value);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
#endif 

        internal void WriteBytes(int offset, byte[] source, int startIndex, int length) { 
            offset += BaseOffset; 
            Validate(offset, length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != source, "null source");
            Debug.Assert(startIndex + length <= source.Length, "source too small");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(source, startIndex, ptr, length);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal void WriteCharArray(int offset, char[] source, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
            Debug.Assert(null != source, "null source"); 
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.Copy(source, startIndex, ptr, length); 
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                }
            }
        } 

        internal void WriteDouble(int offset, Double value) { 
            WriteInt64(offset, BitConverter.DoubleToInt64Bits(value)); 
        }
#endif 
        internal void WriteInt16(int offset, short value) {
            offset += BaseOffset;
            ValidateCheck(offset, 2);
            Debug.Assert(0 == offset%2, "invalid alignment"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                Marshal.WriteInt16(ptr, offset, value);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
        }

#if !ORACLE
        internal void WriteInt16Array(int offset, short[] source, int startIndex, int length) { 
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != source, "null source");
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(source, startIndex, ptr, length);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
        } 
#endif 
        internal void WriteInt32(int offset, int value) {
            offset += BaseOffset; 
            ValidateCheck(offset, 4);
            Debug.Assert(0 == offset%4, "invalid alignment");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteInt32(ptr, offset, value);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal void WriteInt32Array(int offset, int[] source, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 4*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
            Debug.Assert(null != source, "null source"); 
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.Copy(source, startIndex, ptr, length); 
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                }
            }
        } 

        internal void WriteInt64(int offset, long value) { 
            offset += BaseOffset; 
            ValidateCheck(offset, 8);
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment"); 

            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteInt64(ptr, offset, value);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
        } 
#endif 
        internal void WriteIntPtr(int offset, IntPtr value) {
            offset += BaseOffset; 
            ValidateCheck(offset, IntPtr.Size);
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteIntPtr(ptr, offset, value);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal unsafe void WriteSingle(int offset, Single value) {
            WriteInt32(offset, *(Int32*)&value);
        } 

        internal void ZeroMemory() { 
            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = DangerousGetHandle();
                SafeNativeMethods.ZeroMemory(ptr, (IntPtr)Length); 
            }
            finally { 
                if (mustRelease) { 
                    DangerousRelease();
                } 
            }
        }

        internal Guid ReadGuid(int offset) { 
            // faster than Marshal.PtrToStructure(offset, typeof(Guid))
            byte[] buffer = new byte[16]; 
            ReadBytes(offset, buffer, 0, 16); 
            return new Guid(buffer);
        } 
        internal void WriteGuid(int offset, Guid value) {
            // faster than Marshal.Copy(value.GetByteArray()
            StructureToPtr(offset, value);
        } 

        internal DateTime ReadDate(int offset) { 
            short[] buffer = new short[3]; 
            ReadInt16Array(offset, buffer, 0, 3);
            return new DateTime( 
                unchecked((ushort)buffer[0]),   // Year
                unchecked((ushort)buffer[1]),   // Month
                unchecked((ushort)buffer[2]));  // Day
        } 
        internal void WriteDate(int offset, DateTime value) {
            short[] buffer = new short[3] { 
                unchecked((short)value.Year), 
                unchecked((short)value.Month),
                unchecked((short)value.Day), 
            };
            WriteInt16Array(offset, buffer, 0, 3);
        }
 
        internal TimeSpan ReadTime(int offset) {
            short[] buffer = new short[3]; 
            ReadInt16Array(offset, buffer, 0, 3); 
            return new TimeSpan(
                unchecked((ushort)buffer[0]),   // Hours 
                unchecked((ushort)buffer[1]),   // Minutes
                unchecked((ushort)buffer[2]));  // Seconds
        }
        internal void WriteTime(int offset, TimeSpan value) { 
            short[] buffer = new short[3] {
                unchecked((short)value.Hours), 
                unchecked((short)value.Minutes), 
                unchecked((short)value.Seconds),
            }; 
            WriteInt16Array(offset, buffer, 0, 3);
        }

        internal DateTime ReadDateTime(int offset) { 
            short[] buffer = new short[6];
            ReadInt16Array(offset, buffer, 0, 6); 
            int ticks = ReadInt32(offset + 12); 
            DateTime value = new DateTime(
                unchecked((ushort)buffer[0]),  // Year 
                unchecked((ushort)buffer[1]),  // Month
                unchecked((ushort)buffer[2]),  // Day
                unchecked((ushort)buffer[3]),  // Hours
                unchecked((ushort)buffer[4]),  // Minutes 
                unchecked((ushort)buffer[5])); // Seconds
            return value.AddTicks(ticks / 100); 
        } 
        internal void WriteDateTime(int offset, DateTime value) {
            int ticks = (int)(value.Ticks % 10000000L)*100; 
            short[] buffer = new short[6] {
                unchecked((short)value.Year),
                unchecked((short)value.Month),
                unchecked((short)value.Day), 
                unchecked((short)value.Hour),
                unchecked((short)value.Minute), 
                unchecked((short)value.Second), 
            };
            WriteInt16Array(offset, buffer, 0, 6); 
            WriteInt32(offset + 12, ticks);
        }

        internal Decimal ReadNumeric(int offset) { 
            byte[] bits = new byte[20];
            ReadBytes(offset, bits, 1, 19); 
 
            int[] buffer = new int[4];
            buffer[3] = ((int) bits[2]) << 16; // scale 
            if (0 == bits[3]) {
                buffer[3] |= unchecked((int)0x80000000); //sign
            }
            buffer[0] = BitConverter.ToInt32(bits,  4);     // low 
            buffer[1] = BitConverter.ToInt32(bits,  8);     // mid
            buffer[2] = BitConverter.ToInt32(bits, 12);     // high 
            if (0 != BitConverter.ToInt32(bits, 16)) { 
                throw ADP.NumericToDecimalOverflow();
            } 
            return new Decimal(buffer);
        }

        internal void WriteNumeric(int offset, Decimal value, byte precision) { 
            int[] tmp = Decimal.GetBits(value);
            byte[] buffer = new byte[20]; 
 
            buffer[1] = precision;
            Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale 
            buffer[3] = (Byte) ((0 == buffer[3]) ? 1 : 0); // flip sign for native
            Buffer.BlockCopy(tmp, 0, buffer, 4, 12);
            buffer[16] = 0;
            buffer[17] = 0; 
            buffer[18] = 0;
            buffer[19] = 0; 
            WriteBytes(offset, buffer, 1, 19); 
        }
#endif 

        [ConditionalAttribute("DEBUG")]
        protected void ValidateCheck(int offset, int count) {
            Validate(offset, count); 
        }
 
        protected void Validate(int offset, int count) { 
            if ((offset < 0) || (count < 0) || (Length < checked(offset + count))) {
                throw ADP.InternalError(ADP.InternalErrorCode.InvalidBuffer); 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
namespace System.Data.ProviderBase 
{
    using System; 
    using System.Data.Common;
#if ORACLE
    using System.Data.OracleClient;
#endif // ORACLE 
    using System.Diagnostics;
    using System.Runtime.CompilerServices; 
    using System.Runtime.ConstrainedExecution; 
    using System.Runtime.InteropServices;
    using System.Security; 
    using System.Security.Permissions;
    using System.Threading;

    // DbBuffer is abstract to require derived class to exist 
    // so that when debugging, we can tell the difference between one DbBuffer and another
    internal abstract class DbBuffer : SafeHandle { 
 
        internal const int LMEM_FIXED = 0x0000;
        internal const int LMEM_MOVEABLE = 0x0002; 
        internal const int LMEM_ZEROINIT = 0x0040;

        private readonly int _bufferLength;
 
#if ORACLE
        private int _baseOffset; 
#endif 

#if ORACLE 
        protected
#else
        private
#endif 
        DbBuffer(int initialSize, bool zeroBuffer) : base(IntPtr.Zero, true) {
            if (0 < initialSize) { 
                int flags = ((zeroBuffer) ? LMEM_ZEROINIT : LMEM_FIXED); 

                _bufferLength = initialSize; 
                RuntimeHelpers.PrepareConstrainedRegions();
                try {} finally {
                    base.handle = SafeNativeMethods.LocalAlloc(flags, (IntPtr)initialSize);
                } 
                if (IntPtr.Zero == base.handle) {
                    throw new OutOfMemoryException(); 
                } 
            }
        } 

        protected DbBuffer(int initialSize) : this(initialSize, true) {
        }
 
#if !ORACLE
        protected DbBuffer(IntPtr invalidHandleValue, bool ownsHandle) : base(invalidHandleValue, ownsHandle) { 
        } 

        private int BaseOffset { get { return 0; } } 
#else
        protected int BaseOffset {
            get {
                return _baseOffset; 
            }
            set { 
                _baseOffset = value; 
            }
        } 
#endif

        public override bool IsInvalid {
            get { 
                return (IntPtr.Zero == base.handle);
            } 
        } 

        internal int Length { 
            get {
                return _bufferLength;
            }
        } 

        internal string PtrToStringUni(int offset) { 
            offset += BaseOffset; 
            Validate(offset, 2);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 

            string value = null;
            bool   mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                int length = UnsafeNativeMethods.lstrlenW(ptr); 
                Validate(offset, (2*(length+1)));
                value = Marshal.PtrToStringUni(ptr, length);
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                } 
            }
 
            return value;
        }

        internal String PtrToStringUni(int offset, int length) { 
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 

            string value = null; 
            bool   mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                value = Marshal.PtrToStringUni(ptr, length); 
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease();
                }
            } 
            return value;
        } 
 
#if !ORACLE
        internal byte ReadByte(int offset) { 
            offset += BaseOffset;
            ValidateCheck(offset, 1);
            Debug.Assert(0 == offset%4, "invalid alignment");
 
            byte value;
            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                value = Marshal.ReadByte(ptr, offset);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
            return value;
        }
#endif
 
        internal byte[] ReadBytes(int offset, int length) {
            byte[] value = new byte[length]; 
            return ReadBytes(offset, value, 0, length); 
        }
 
        internal byte[] ReadBytes(int offset, byte[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
            return destination;
        } 

#if !ORACLE 
        internal Char ReadChar(int offset) { 
            short value = ReadInt16(offset);
            return unchecked((char)value); 
        }

        internal char[] ReadChars(int offset, char[] destination, int startIndex, int length) {
            offset += BaseOffset; 
            Validate(offset, 2*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination"); 
            Debug.Assert(startIndex + length <= destination.Length, "destination too small");
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length); 
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease();
                }
            } 
            return destination;
        } 
 
        internal Double ReadDouble(int offset) {
            Int64 value = ReadInt64(offset); 
            return BitConverter.Int64BitsToDouble(value);
        }
#endif
 
        internal Int16 ReadInt16(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 2); 
            Debug.Assert(0 == offset%2, "invalid alignment");
 
            short value;
            bool  mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt16(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 

#if !ORACLE 
        internal void ReadInt16Array(int offset, short[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 2*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
#endif 
        internal Int32 ReadInt32(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 4); 
            Debug.Assert(0 == offset%4, "invalid alignment");
 
            int  value;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt32(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 

#if !ORACLE 
        internal void ReadInt32Array(int offset, int[] destination, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 4*length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != destination, "null destination");
            Debug.Assert(startIndex + length <= destination.Length, "destination too small"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(ptr, destination, startIndex, length);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
 
        internal Int64 ReadInt64(int offset) {
            offset += BaseOffset; 
            ValidateCheck(offset, 8); 
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");
 
            long value;
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                value = Marshal.ReadInt64(ptr, offset);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
            return value; 
        } 
#endif
        internal IntPtr ReadIntPtr(int offset) { 
            offset += BaseOffset;
            ValidateCheck(offset, IntPtr.Size);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
 
            IntPtr value;
            bool   mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                value = Marshal.ReadIntPtr(ptr, offset);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
            return value;
        }

#if !ORACLE 
        internal unsafe Single ReadSingle(int offset) {
            Int32 value = ReadInt32(offset); 
            return *(Single*)&value; 
        }
#endif 

        override protected bool ReleaseHandle() {
            // NOTE: The SafeHandle class guarantees this will be called exactly once.
            IntPtr ptr = base.handle; 
            base.handle = IntPtr.Zero;
            if (IntPtr.Zero != ptr) { 
                SafeNativeMethods.LocalFree(ptr); 
            }
            return true; 
        }

#if ORACLE
        internal 
#else
        private 
#endif 
        void StructureToPtr(int offset, object structure) {
            Debug.Assert(null != structure, "null structure"); 
            offset += BaseOffset;
            ValidateCheck(offset, Marshal.SizeOf(structure.GetType()));
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.StructureToPtr(structure, ptr, false/*fDeleteOld*/);
            }
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                } 
            }
        } 

#if !ORACLE
        internal void WriteByte(int offset, byte value) {
            offset += BaseOffset; 
            ValidateCheck(offset, 1);
            Debug.Assert(0 == offset%4, "invalid alignment"); 
 
            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteByte(ptr, offset, value);
            } 
            finally { 
                if (mustRelease) {
                    DangerousRelease(); 
                }
            }
        }
#endif 

        internal void WriteBytes(int offset, byte[] source, int startIndex, int length) { 
            offset += BaseOffset; 
            Validate(offset, length);
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != source, "null source");
            Debug.Assert(startIndex + length <= source.Length, "source too small");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(source, startIndex, ptr, length);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal void WriteCharArray(int offset, char[] source, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
            Debug.Assert(null != source, "null source"); 
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.Copy(source, startIndex, ptr, length); 
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                }
            }
        } 

        internal void WriteDouble(int offset, Double value) { 
            WriteInt64(offset, BitConverter.DoubleToInt64Bits(value)); 
        }
#endif 
        internal void WriteInt16(int offset, short value) {
            offset += BaseOffset;
            ValidateCheck(offset, 2);
            Debug.Assert(0 == offset%2, "invalid alignment"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle();
                Marshal.WriteInt16(ptr, offset, value);
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease(); 
                }
            } 
        }

#if !ORACLE
        internal void WriteInt16Array(int offset, short[] source, int startIndex, int length) { 
            offset += BaseOffset;
            Validate(offset, 2*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment"); 
            Debug.Assert(null != source, "null source");
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset); 
                Marshal.Copy(source, startIndex, ptr, length);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
        } 
#endif 
        internal void WriteInt32(int offset, int value) {
            offset += BaseOffset; 
            ValidateCheck(offset, 4);
            Debug.Assert(0 == offset%4, "invalid alignment");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteInt32(ptr, offset, value);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal void WriteInt32Array(int offset, int[] source, int startIndex, int length) {
            offset += BaseOffset;
            Validate(offset, 4*length); 
            Debug.Assert(0 == offset%ADP.PtrSize, "invalid alignment");
            Debug.Assert(null != source, "null source"); 
            Debug.Assert(startIndex + length <= source.Length, "source too small"); 

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = ADP.IntPtrOffset(DangerousGetHandle(), offset);
                Marshal.Copy(source, startIndex, ptr, length); 
            } 
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                }
            }
        } 

        internal void WriteInt64(int offset, long value) { 
            offset += BaseOffset; 
            ValidateCheck(offset, 8);
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment"); 

            bool mustRelease = false;
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);
 
                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteInt64(ptr, offset, value);
            } 
            finally {
                if (mustRelease) {
                    DangerousRelease();
                } 
            }
        } 
#endif 
        internal void WriteIntPtr(int offset, IntPtr value) {
            offset += BaseOffset; 
            ValidateCheck(offset, IntPtr.Size);
            Debug.Assert(0 == offset%IntPtr.Size, "invalid alignment");

            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease); 

                IntPtr ptr = DangerousGetHandle(); 
                Marshal.WriteIntPtr(ptr, offset, value);
            }
            finally {
                if (mustRelease) { 
                    DangerousRelease();
                } 
            } 
        }
 
#if !ORACLE
        internal unsafe void WriteSingle(int offset, Single value) {
            WriteInt32(offset, *(Int32*)&value);
        } 

        internal void ZeroMemory() { 
            bool mustRelease = false; 
            RuntimeHelpers.PrepareConstrainedRegions();
            try { 
                DangerousAddRef(ref mustRelease);

                IntPtr ptr = DangerousGetHandle();
                SafeNativeMethods.ZeroMemory(ptr, (IntPtr)Length); 
            }
            finally { 
                if (mustRelease) { 
                    DangerousRelease();
                } 
            }
        }

        internal Guid ReadGuid(int offset) { 
            // faster than Marshal.PtrToStructure(offset, typeof(Guid))
            byte[] buffer = new byte[16]; 
            ReadBytes(offset, buffer, 0, 16); 
            return new Guid(buffer);
        } 
        internal void WriteGuid(int offset, Guid value) {
            // faster than Marshal.Copy(value.GetByteArray()
            StructureToPtr(offset, value);
        } 

        internal DateTime ReadDate(int offset) { 
            short[] buffer = new short[3]; 
            ReadInt16Array(offset, buffer, 0, 3);
            return new DateTime( 
                unchecked((ushort)buffer[0]),   // Year
                unchecked((ushort)buffer[1]),   // Month
                unchecked((ushort)buffer[2]));  // Day
        } 
        internal void WriteDate(int offset, DateTime value) {
            short[] buffer = new short[3] { 
                unchecked((short)value.Year), 
                unchecked((short)value.Month),
                unchecked((short)value.Day), 
            };
            WriteInt16Array(offset, buffer, 0, 3);
        }
 
        internal TimeSpan ReadTime(int offset) {
            short[] buffer = new short[3]; 
            ReadInt16Array(offset, buffer, 0, 3); 
            return new TimeSpan(
                unchecked((ushort)buffer[0]),   // Hours 
                unchecked((ushort)buffer[1]),   // Minutes
                unchecked((ushort)buffer[2]));  // Seconds
        }
        internal void WriteTime(int offset, TimeSpan value) { 
            short[] buffer = new short[3] {
                unchecked((short)value.Hours), 
                unchecked((short)value.Minutes), 
                unchecked((short)value.Seconds),
            }; 
            WriteInt16Array(offset, buffer, 0, 3);
        }

        internal DateTime ReadDateTime(int offset) { 
            short[] buffer = new short[6];
            ReadInt16Array(offset, buffer, 0, 6); 
            int ticks = ReadInt32(offset + 12); 
            DateTime value = new DateTime(
                unchecked((ushort)buffer[0]),  // Year 
                unchecked((ushort)buffer[1]),  // Month
                unchecked((ushort)buffer[2]),  // Day
                unchecked((ushort)buffer[3]),  // Hours
                unchecked((ushort)buffer[4]),  // Minutes 
                unchecked((ushort)buffer[5])); // Seconds
            return value.AddTicks(ticks / 100); 
        } 
        internal void WriteDateTime(int offset, DateTime value) {
            int ticks = (int)(value.Ticks % 10000000L)*100; 
            short[] buffer = new short[6] {
                unchecked((short)value.Year),
                unchecked((short)value.Month),
                unchecked((short)value.Day), 
                unchecked((short)value.Hour),
                unchecked((short)value.Minute), 
                unchecked((short)value.Second), 
            };
            WriteInt16Array(offset, buffer, 0, 6); 
            WriteInt32(offset + 12, ticks);
        }

        internal Decimal ReadNumeric(int offset) { 
            byte[] bits = new byte[20];
            ReadBytes(offset, bits, 1, 19); 
 
            int[] buffer = new int[4];
            buffer[3] = ((int) bits[2]) << 16; // scale 
            if (0 == bits[3]) {
                buffer[3] |= unchecked((int)0x80000000); //sign
            }
            buffer[0] = BitConverter.ToInt32(bits,  4);     // low 
            buffer[1] = BitConverter.ToInt32(bits,  8);     // mid
            buffer[2] = BitConverter.ToInt32(bits, 12);     // high 
            if (0 != BitConverter.ToInt32(bits, 16)) { 
                throw ADP.NumericToDecimalOverflow();
            } 
            return new Decimal(buffer);
        }

        internal void WriteNumeric(int offset, Decimal value, byte precision) { 
            int[] tmp = Decimal.GetBits(value);
            byte[] buffer = new byte[20]; 
 
            buffer[1] = precision;
            Buffer.BlockCopy(tmp, 14, buffer, 2, 2); // copy sign and scale 
            buffer[3] = (Byte) ((0 == buffer[3]) ? 1 : 0); // flip sign for native
            Buffer.BlockCopy(tmp, 0, buffer, 4, 12);
            buffer[16] = 0;
            buffer[17] = 0; 
            buffer[18] = 0;
            buffer[19] = 0; 
            WriteBytes(offset, buffer, 1, 19); 
        }
#endif 

        [ConditionalAttribute("DEBUG")]
        protected void ValidateCheck(int offset, int count) {
            Validate(offset, count); 
        }
 
        protected void Validate(int offset, int count) { 
            if ((offset < 0) || (count < 0) || (Length < checked(offset + count))) {
                throw ADP.InternalError(ADP.InternalErrorCode.InvalidBuffer); 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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