// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: BitConverter ** ** ** Purpose: Allows developers to view the base data types as ** an arbitrary array of bits. ** ** Date: August 9, 1998 ** ===========================================================*/ namespace System { using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; // The BitConverter class contains methods for // converting an array of bytes to one of the base data // types, as well as for converting a base data type to an // array of bytes. // //| [CCtorIsRunDuringStartup] public sealed class BitConverter { // This field indicates the "endianness" of the architecture. // The value is set to true if the architecture is // little endian; false if it is big endian. //| public static readonly bool IsLittleEndian; static BitConverter() { byte [] ba = GetBytes((short)0xF); if (ba[0]==0xF) { IsLittleEndian=true; } else { IsLittleEndian=false; } } // This class only contains static methods and may not be instantiated. private BitConverter() { } // ====================================================================== // Convert from primitive types to byte array slices. These functions // do not perform memory allocation and so are suitable for use in // interrupt handlers and other no-allocation-allowed contexts. // ====================================================================== // Converts a byte into an existing array slice of bytes with length one. public static void GetBytes(bool value, byte[] array, int startIndex) { const int bytesNeeded = 1; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } array[startIndex] = (value ? (byte)Boolean.True : (byte)Boolean.False ); } // Converts a char into an existing array slice of bytes with length two. public static unsafe void GetBytes(char value, byte[] array, int startIndex) { const int bytesNeeded = 2; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((char *) ptr) = value; } } // Converts a short into an existing array slice of bytes with length two. public static unsafe void GetBytes(short value, byte[] array, int startIndex) { const int bytesNeeded = 2; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((short *) ptr) = value; } } // Converts an int into an existing array slice of bytes with length four. public static unsafe void GetBytes(int value, byte[] array, int startIndex) { const int bytesNeeded = 4; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((int *) ptr) = value; } } // Converts a long into an existing array slice of bytes with length eight. public static unsafe void GetBytes(long value, byte[] array, int startIndex) { const int bytesNeeded = 8; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((long *) ptr) = value; } } // Converts an ushort into an existing array slice of bytes with length two. [CLSCompliant(false)] public static unsafe void GetBytes(ushort value, byte[] array, int startIndex) { const int bytesNeeded = 2; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((ushort *) ptr) = value; } } // Converts an uint into an existing array slice of bytes with length four. [CLSCompliant(false)] public static unsafe void GetBytes(uint value, byte[] array, int startIndex) { const int bytesNeeded = 4; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((uint *) ptr) = value; } } // Converts an unsigned long into an existing array slice of bytes with length eight. [CLSCompliant(false)] public static unsafe void GetBytes(ulong value, byte[] array, int startIndex) { const int bytesNeeded = 8; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) { *((ulong *) ptr) = value; } } // Converts a float into an existing array slice of bytes with length four. public unsafe static void GetBytes(float value, byte[] array, int startIndex) { const int bytesNeeded = 4; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) *((float*) ptr) = value; } // Converts a double into an existing array slice of bytes with length eight. public unsafe static void GetBytes(double value, byte[] array, int startIndex) { const int bytesNeeded = 8; if (startIndex < 0) { throw new ArgumentOutOfRangeException("startIndex is negative"); } if (startIndex + bytesNeeded > array.Length) { throw new ArgumentException("Array is too small"); } fixed (byte *ptr = &array[startIndex]) *((double*) ptr) = value; } // ====================================================================== // Convert from primitive types to new byte arrays. These functions // perform memory allocation and so are unsuitable for use in // interrupt handlers and other no-allocation-allowed contexts. // ====================================================================== // Converts a byte into an array of bytes with length one. //| public static byte[] GetBytes(bool value) { byte[] result = new byte[1]; GetBytes(value, result, 0); return result; } // Converts a char into an array of bytes with length two. //| public static unsafe byte[] GetBytes(char value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::CharToBytes byte[] result = new byte[2]; GetBytes(value, result, 0); return result; } // Converts a short into an array of bytes with length // two. //| public static unsafe byte[] GetBytes(short value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::I2ToBytes byte[] result = new byte[2]; GetBytes(value, result, 0); return result; } // Converts an int into an array of bytes with length // four. //| public static unsafe byte[] GetBytes(int value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::I4ToBytes byte[] result = new byte[4]; GetBytes(value, result, 0); return result; } // Converts a long into an array of bytes with length // eight. //| public static unsafe byte[] GetBytes(long value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::I8ToBytes byte[] result = new byte[8]; GetBytes(value, result, 0); return result; } // Converts an ushort into an array of bytes with // length two. //| [CLSCompliant(false)] public static unsafe byte[] GetBytes(ushort value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::U2ToBytes byte[] result = new byte[2]; GetBytes(value, result, 0); return result; } // Converts an uint into an array of bytes with // length four. //| [CLSCompliant(false)] public static unsafe byte[] GetBytes(uint value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::U4ToBytes byte[] result = new byte[4]; GetBytes(value, result, 0); return result; } // Converts an unsigned long into an array of bytes with // length eight. //| [CLSCompliant(false)] public static unsafe byte[] GetBytes(ulong value) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::U8ToBytes byte[] result = new byte[8]; GetBytes(value, result, 0); return result; } // Converts a float into an array of bytes with length // four. //| public unsafe static byte[] GetBytes(float value) { byte[] result = new byte[4]; GetBytes(value, result, 0); return result; } // Converts a double into an array of bytes with length // eight. //| public unsafe static byte[] GetBytes(double value) { byte[] result = new byte[8]; GetBytes(value, result, 0); return result; } // ============ Convert from byte array slices to primitive types ============ // Converts an array of bytes into a char. //| public static unsafe char ToChar(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToChar char result; fixed (byte *ptr = value) { result = *((char *) (ptr + startIndex)); } return result; } // Converts an array of bytes into a short. //| public static unsafe short ToInt16(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToI2 short result; fixed (byte *ptr = value) { result = *((short *) (ptr + startIndex)); } return result; } // Converts an array of bytes into an int. //| public static unsafe int ToInt32(byte[]value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToI4 int result; fixed (byte *ptr = value) { result = *((int *) (ptr + startIndex)); } return result; } // Converts an array of bytes into a long. //| public static unsafe long ToInt64(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToI8 long result; fixed (byte *ptr = value) { result = *((long *) (ptr + startIndex)); } return result; } // Converts an array of bytes into an ushort. // //| [CLSCompliant(false)] // public static unsafe ushort ToUInt16(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToU2 ushort result; fixed (byte *ptr = value) { result = *((ushort *) (ptr + startIndex)); } return result; } // Converts an array of bytes into an uint. // //| [CLSCompliant(false)] // public static unsafe uint ToUInt32(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToU4 uint result; fixed (byte *ptr = value) { result = *((uint *) (ptr + startIndex)); } return result; } // Converts an array of bytes into an unsigned long. // //| [CLSCompliant(false)] // public static unsafe ulong ToUInt64(byte[] value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToU8 ulong result; fixed (byte *ptr = value) { result = *((ulong *) (ptr + startIndex)); } return result; } // Converts an array of bytes into a float. //| public static unsafe float ToSingle(byte[]value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToR4 float result; fixed (byte *ptr = value) { result = *((float *) (ptr + startIndex)); } return result; } // Converts an array of bytes into a double. //| public static unsafe double ToDouble(byte []value, int startIndex) { // rusa: see also Lightning\Src\VM\COMUtilNative.cpp::BytesToR8 double result; fixed (byte *ptr = value) { result = *((double *) (ptr + startIndex)); } return result; } /*==================================ToBoolean=================================== **Action: Convert an array of bytes to a boolean value. We treat this array ** as if the first 4 bytes were an Int4 an operate on this value. **Returns: True if the Int4 value of the first 4 bytes is non-zero. **Arguments: value -- The byte array ** startIndex -- The position within the array. **Exceptions: See ToInt4. ==============================================================================*/ // Converts an array of bytes into a boolean. //| public static bool ToBoolean(byte[]value, int startIndex) { if (value==null) throw new ArgumentNullException("value"); if (startIndex < 0) throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_NeedNonNegNum"); if (startIndex > value.Length - 1) throw new ArgumentOutOfRangeException("ArgumentOutOfRange_Index"); return (value[startIndex]==0)?false:true; } //| [Inline] public static unsafe long DoubleToInt64Bits(double value) { return *((long *)&value); } //| [Inline] public static unsafe double Int64BitsToDouble(long value) { return *((double *)&value); } //| [Inline] [CLSCompliant(false)] public static unsafe ulong DoubleToUInt64Bits(double value) { return *((ulong *)&value); } //| [Inline] [CLSCompliant(false)] public static unsafe double UInt64BitsToDouble(ulong value) { return *((double *)&value); } //| [Inline] [CLSCompliant(false)] public static unsafe uint SingleToUInt32Bits(float value) { return *((uint *)&value); } //| [Inline] [CLSCompliant(false)] public static unsafe float UInt32BitsToSingle(uint value) { return *((float *)&value); } } }