singrdk/base/Applications/Runtime/Full/System/BitConverter.cs

545 lines
22 KiB
C#

// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
//============================================================
//
// Class: BitConverter
//
// Purpose: Allows developers to view the base data types as
// an arbitrary array of bits.
//
//===========================================================
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.
//
//| <include path='docs/doc[@for="BitConverter"]/*' />
[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.
//| <include path='docs/doc[@for="BitConverter.IsLittleEndian"]/*' />
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. -- mbj
// ======================================================================
// 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. -- mbj
// ======================================================================
// Converts a byte into an array of bytes with length one.
//| <include path='docs/doc[@for="BitConverter.GetBytes"]/*' />
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.
//| <include path='docs/doc[@for="BitConverter.GetBytes1"]/*' />
public static unsafe byte[] GetBytes(char value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes2"]/*' />
public static unsafe byte[] GetBytes(short value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes3"]/*' />
public static unsafe byte[] GetBytes(int value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes4"]/*' />
public static unsafe byte[] GetBytes(long value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes5"]/*' />
[CLSCompliant(false)]
public static unsafe byte[] GetBytes(ushort value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes6"]/*' />
[CLSCompliant(false)]
public static unsafe byte[] GetBytes(uint value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes7"]/*' />
[CLSCompliant(false)]
public static unsafe byte[] GetBytes(ulong value) {
// 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.
//| <include path='docs/doc[@for="BitConverter.GetBytes8"]/*' />
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.
//| <include path='docs/doc[@for="BitConverter.GetBytes9"]/*' />
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.
//| <include path='docs/doc[@for="BitConverter.ToChar"]/*' />
public static unsafe char ToChar(byte[] value, int startIndex) {
// 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.
//| <include path='docs/doc[@for="BitConverter.ToInt16"]/*' />
public static unsafe short ToInt16(byte[] value, int startIndex)
{
if (value == null) {
throw new ArgumentNullException("value");
}
if (((uint)startIndex) >= (uint)value.Length) {
throw new ArgumentOutOfRangeException("startIndex");
}
if (startIndex > (value.Length - 2)) {
throw new ArgumentException("startIndex");
}
fixed (byte* p = &value[startIndex]) {
if ((startIndex % 2) == 0) {
return *((short*)p);
}
if (IsLittleEndian) {
return (short)(p[0] | (p[1] << 8));
}
else {
return (short)(p[1] | (p[0] << 8));
}
}
}
// Converts an array of bytes into an int.
//| <include path='docs/doc[@for="BitConverter.ToInt32"]/*' />
public static unsafe int ToInt32(byte[]value, int startIndex)
{
if (value == null) {
throw new ArgumentNullException("value");
}
if (((uint)startIndex) >= (uint)value.Length) {
throw new ArgumentOutOfRangeException("startIndex");
}
if (startIndex > (value.Length - 4)) {
throw new ArgumentException("startIndex");
}
fixed (byte* p = &value[startIndex]) {
if ((startIndex % 4) == 0) {
return *((int*)p);
}
if (IsLittleEndian) {
return (
((int)p[0]) |
(((int)p[1]) << 8) |
(((int)p[2]) << 16) |
(((int)p[3]) << 24)
);
}
else {
return (
((int)p[3]) |
(((int)p[2]) << 8) |
(((int)p[1]) << 16) |
(((int)p[0]) << 24)
);
}
}
}
// Converts an array of bytes into a long.
//| <include path='docs/doc[@for="BitConverter.ToInt64"]/*' />
public static unsafe long ToInt64(byte[] value, int startIndex)
{
if (value == null) {
throw new ArgumentNullException("value");
}
if (((uint)startIndex) >= (uint)value.Length) {
throw new ArgumentOutOfRangeException("startIndex");
}
if (startIndex > (value.Length - 8)) {
throw new ArgumentException("startIndex");
}
fixed (byte* p = &value[startIndex]) {
if ((startIndex % 8) == 0) {
return *((long*)p);
}
if (IsLittleEndian) {
int lo = (((int)p[0]) |
(((int)p[1]) << 8) |
(((int)p[2]) << 16) |
(((int)p[3]) << 24)
);
int hi = (((int)p[4]) |
(((int)p[5]) << 8) |
(((int)p[6]) << 16) |
(((int)p[7]) << 24)
);
return (long)(((ulong)lo) | ((ulong)hi) << 32);
}
else {
int hi = (((int)p[3]) |
(((int)p[2]) << 8) |
(((int)p[1]) << 16) |
(((int)p[0]) << 24)
);
int lo = (((int)p[7]) |
(((int)p[6]) << 8) |
(((int)p[5]) << 16) |
(((int)p[4]) << 24)
);
return (long)(((ulong)lo) | ((ulong)hi) << 32);
}
}
}
// Converts an array of bytes into an ushort.
//
//| <include path='docs/doc[@for="BitConverter.ToUInt16"]/*' />
[CLSCompliant(false)]
public static ushort ToUInt16(byte[] value, int startIndex)
{
unchecked {
return (ushort)ToInt16(value, startIndex);
}
}
// Converts an array of bytes into an uint.
//
//| <include path='docs/doc[@for="BitConverter.ToUInt32"]/*' />
[CLSCompliant(false)]
public static uint ToUInt32(byte[] value, int startIndex)
{
unchecked {
return (uint)ToInt32(value, startIndex);
}
}
// Converts an array of bytes into an unsigned long.
//
//| <include path='docs/doc[@for="BitConverter.ToUInt64"]/*' />
[CLSCompliant(false)]
public static unsafe ulong ToUInt64(byte[] value, int startIndex)
{
unchecked {
return (ulong)ToInt64(value, startIndex);
}
}
// Converts an array of bytes into a float.
//| <include path='docs/doc[@for="BitConverter.ToSingle"]/*' />
public static unsafe float ToSingle(byte[]value, int startIndex) {
// 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.
//| <include path='docs/doc[@for="BitConverter.ToDouble"]/*' />
public static unsafe double ToDouble(byte []value, int startIndex) {
// 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.
//| <include path='docs/doc[@for="BitConverter.ToBoolean"]/*' />
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;
}
//| <include path='docs/doc[@for="BitConverter.DoubleToInt64Bits"]/*' />
[Inline]
public static unsafe long DoubleToInt64Bits(double value) {
return *((long *)&value);
}
//| <include path='docs/doc[@for="BitConverter.Int64BitsToDouble"]/*' />
[Inline]
public static unsafe double Int64BitsToDouble(long value) {
return *((double *)&value);
}
//| <include path='docs/doc[@for="BitConverter.DoubleToUInt64Bits"]/*' />
[Inline]
[CLSCompliant(false)]
public static unsafe ulong DoubleToUInt64Bits(double value) {
return *((ulong *)&value);
}
//| <include path='docs/doc[@for="BitConverter.UInt64BitsToDouble"]/*' />
[Inline]
[CLSCompliant(false)]
public static unsafe double UInt64BitsToDouble(ulong value) {
return *((double *)&value);
}
//| <include path='docs/doc[@for="BitConverter.SingleToUInt32Bits"]/*' />
[Inline]
[CLSCompliant(false)]
public static unsafe uint SingleToUInt32Bits(float value) {
return *((uint *)&value);
}
//| <include path='docs/doc[@for="BitConverter.UInt32BitsToSingle"]/*' />
[Inline]
[CLSCompliant(false)]
public static unsafe float UInt32BitsToSingle(uint value) {
return *((float *)&value);
}
}
}