1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System
.Runtime
.CompilerServices
;
6 using System
.Runtime
.InteropServices
;
8 using Internal
.Runtime
.CompilerServices
;
12 // The BitConverter class contains methods for
13 // converting an array of bytes to one of the base data
14 // types, as well as for converting a base data type to an
16 public static class BitConverter
18 // This field indicates the "endianess" of the architecture.
19 // The value is set to true if the architecture is
20 // little endian; false if it is big endian.
23 public static readonly bool IsLittleEndian
/* = false */;
26 public static readonly bool IsLittleEndian
= true;
29 // Converts a Boolean into an array of bytes with length one.
30 public static byte[] GetBytes(bool value)
32 byte[] r
= new byte[1];
33 r
[0] = (value ? (byte)1 : (byte)0);
37 // Converts a Boolean into a Span of bytes with length one.
38 public static bool TryWriteBytes(Span
<byte> destination
, bool value)
40 if (destination
.Length
< sizeof(byte))
43 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value ? (byte)1 : (byte)0);
47 // Converts a char into an array of bytes with length two.
48 public static byte[] GetBytes(char value)
50 byte[] bytes
= new byte[sizeof(char)];
51 Unsafe
.As
<byte, char>(ref bytes
[0]) = value;
55 // Converts a char into a Span
56 public static bool TryWriteBytes(Span
<byte> destination
, char value)
58 if (destination
.Length
< sizeof(char))
61 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
65 // Converts a short into an array of bytes with length
67 public static byte[] GetBytes(short value)
69 byte[] bytes
= new byte[sizeof(short)];
70 Unsafe
.As
<byte, short>(ref bytes
[0]) = value;
74 // Converts a short into a Span
75 public static bool TryWriteBytes(Span
<byte> destination
, short value)
77 if (destination
.Length
< sizeof(short))
80 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
84 // Converts an int into an array of bytes with length
86 public static byte[] GetBytes(int value)
88 byte[] bytes
= new byte[sizeof(int)];
89 Unsafe
.As
<byte, int>(ref bytes
[0]) = value;
93 // Converts an int into a Span
94 public static bool TryWriteBytes(Span
<byte> destination
, int value)
96 if (destination
.Length
< sizeof(int))
99 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
103 // Converts a long into an array of bytes with length
105 public static byte[] GetBytes(long value)
107 byte[] bytes
= new byte[sizeof(long)];
108 Unsafe
.As
<byte, long>(ref bytes
[0]) = value;
112 // Converts a long into a Span
113 public static bool TryWriteBytes(Span
<byte> destination
, long value)
115 if (destination
.Length
< sizeof(long))
118 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
122 // Converts an ushort into an array of bytes with
124 [CLSCompliant(false)]
125 public static byte[] GetBytes(ushort value)
127 byte[] bytes
= new byte[sizeof(ushort)];
128 Unsafe
.As
<byte, ushort>(ref bytes
[0]) = value;
132 // Converts a ushort into a Span
133 [CLSCompliant(false)]
134 public static bool TryWriteBytes(Span
<byte> destination
, ushort value)
136 if (destination
.Length
< sizeof(ushort))
139 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
143 // Converts an uint into an array of bytes with
145 [CLSCompliant(false)]
146 public static byte[] GetBytes(uint value)
148 byte[] bytes
= new byte[sizeof(uint)];
149 Unsafe
.As
<byte, uint>(ref bytes
[0]) = value;
153 // Converts a uint into a Span
154 [CLSCompliant(false)]
155 public static bool TryWriteBytes(Span
<byte> destination
, uint value)
157 if (destination
.Length
< sizeof(uint))
160 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
164 // Converts an unsigned long into an array of bytes with
166 [CLSCompliant(false)]
167 public static byte[] GetBytes(ulong value)
169 byte[] bytes
= new byte[sizeof(ulong)];
170 Unsafe
.As
<byte, ulong>(ref bytes
[0]) = value;
174 // Converts a ulong into a Span
175 [CLSCompliant(false)]
176 public static bool TryWriteBytes(Span
<byte> destination
, ulong value)
178 if (destination
.Length
< sizeof(ulong))
181 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
185 // Converts a float into an array of bytes with length
187 public static byte[] GetBytes(float value)
189 byte[] bytes
= new byte[sizeof(float)];
190 Unsafe
.As
<byte, float>(ref bytes
[0]) = value;
194 // Converts a float into a Span
195 public static bool TryWriteBytes(Span
<byte> destination
, float value)
197 if (destination
.Length
< sizeof(float))
200 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
204 // Converts a double into an array of bytes with length
206 public static byte[] GetBytes(double value)
208 byte[] bytes
= new byte[sizeof(double)];
209 Unsafe
.As
<byte, double>(ref bytes
[0]) = value;
213 // Converts a double into a Span
214 public static bool TryWriteBytes(Span
<byte> destination
, double value)
216 if (destination
.Length
< sizeof(double))
219 Unsafe
.WriteUnaligned(ref MemoryMarshal
.GetReference(destination
), value);
223 // Converts an array of bytes into a char.
224 public static char ToChar(byte[] value, int startIndex
) => unchecked((char)ToInt16(value, startIndex
));
226 // Converts a Span into a char
227 public static char ToChar(ReadOnlySpan
<byte> value)
229 if (value.Length
< sizeof(char))
230 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
231 return Unsafe
.ReadUnaligned
<char>(ref MemoryMarshal
.GetReference(value));
234 // Converts an array of bytes into a short.
235 public static short ToInt16(byte[] value, int startIndex
)
238 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
239 if (unchecked((uint)startIndex
) >= unchecked((uint)value.Length
))
240 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
);
241 if (startIndex
> value.Length
- sizeof(short))
242 ThrowHelper
.ThrowArgumentException(ExceptionResource
.Arg_ArrayPlusOffTooSmall
, ExceptionArgument
.value);
244 return Unsafe
.ReadUnaligned
<short>(ref value[startIndex
]);
247 // Converts a Span into a short
248 public static short ToInt16(ReadOnlySpan
<byte> value)
250 if (value.Length
< sizeof(short))
251 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
252 return Unsafe
.ReadUnaligned
<short>(ref MemoryMarshal
.GetReference(value));
255 // Converts an array of bytes into an int.
256 public static int ToInt32(byte[] value, int startIndex
)
259 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
260 if (unchecked((uint)startIndex
) >= unchecked((uint)value.Length
))
261 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
);
262 if (startIndex
> value.Length
- sizeof(int))
263 ThrowHelper
.ThrowArgumentException(ExceptionResource
.Arg_ArrayPlusOffTooSmall
, ExceptionArgument
.value);
265 return Unsafe
.ReadUnaligned
<int>(ref value[startIndex
]);
268 // Converts a Span into an int
269 public static int ToInt32(ReadOnlySpan
<byte> value)
271 if (value.Length
< sizeof(int))
272 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
273 return Unsafe
.ReadUnaligned
<int>(ref MemoryMarshal
.GetReference(value));
276 // Converts an array of bytes into a long.
277 public static long ToInt64(byte[] value, int startIndex
)
280 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
281 if (unchecked((uint)startIndex
) >= unchecked((uint)value.Length
))
282 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
);
283 if (startIndex
> value.Length
- sizeof(long))
284 ThrowHelper
.ThrowArgumentException(ExceptionResource
.Arg_ArrayPlusOffTooSmall
, ExceptionArgument
.value);
286 return Unsafe
.ReadUnaligned
<long>(ref value[startIndex
]);
289 // Converts a Span into a long
290 public static long ToInt64(ReadOnlySpan
<byte> value)
292 if (value.Length
< sizeof(long))
293 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
294 return Unsafe
.ReadUnaligned
<long>(ref MemoryMarshal
.GetReference(value));
297 // Converts an array of bytes into an ushort.
299 [CLSCompliant(false)]
300 public static ushort ToUInt16(byte[] value, int startIndex
) => unchecked((ushort)ToInt16(value, startIndex
));
302 // Converts a Span into a ushort
303 [CLSCompliant(false)]
304 public static ushort ToUInt16(ReadOnlySpan
<byte> value)
306 if (value.Length
< sizeof(ushort))
307 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
308 return Unsafe
.ReadUnaligned
<ushort>(ref MemoryMarshal
.GetReference(value));
311 // Converts an array of bytes into an uint.
313 [CLSCompliant(false)]
314 public static uint ToUInt32(byte[] value, int startIndex
) => unchecked((uint)ToInt32(value, startIndex
));
316 // Convert a Span into a uint
317 [CLSCompliant(false)]
318 public static uint ToUInt32(ReadOnlySpan
<byte> value)
320 if (value.Length
< sizeof(uint))
321 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
322 return Unsafe
.ReadUnaligned
<uint>(ref MemoryMarshal
.GetReference(value));
325 // Converts an array of bytes into an unsigned long.
327 [CLSCompliant(false)]
328 public static ulong ToUInt64(byte[] value, int startIndex
) => unchecked((ulong)ToInt64(value, startIndex
));
330 // Converts a Span into an unsigned long
331 [CLSCompliant(false)]
332 public static ulong ToUInt64(ReadOnlySpan
<byte> value)
334 if (value.Length
< sizeof(ulong))
335 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
336 return Unsafe
.ReadUnaligned
<ulong>(ref MemoryMarshal
.GetReference(value));
339 // Converts an array of bytes into a float.
340 public static float ToSingle(byte[] value, int startIndex
) => Int32BitsToSingle(ToInt32(value, startIndex
));
342 // Converts a Span into a float
343 public static float ToSingle(ReadOnlySpan
<byte> value)
345 if (value.Length
< sizeof(float))
346 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
347 return Unsafe
.ReadUnaligned
<float>(ref MemoryMarshal
.GetReference(value));
350 // Converts an array of bytes into a double.
351 public static double ToDouble(byte[] value, int startIndex
) => Int64BitsToDouble(ToInt64(value, startIndex
));
353 // Converts a Span into a double
354 public static double ToDouble(ReadOnlySpan
<byte> value)
356 if (value.Length
< sizeof(double))
357 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
358 return Unsafe
.ReadUnaligned
<double>(ref MemoryMarshal
.GetReference(value));
361 // Converts an array of bytes into a String.
362 public static string ToString(byte[] value, int startIndex
, int length
)
365 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
366 if (startIndex
< 0 || startIndex
>= value.Length
&& startIndex
> 0)
367 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
);
369 throw new ArgumentOutOfRangeException(nameof(length
), SR
.ArgumentOutOfRange_GenericPositive
);
370 if (startIndex
> value.Length
- length
)
371 ThrowHelper
.ThrowArgumentException(ExceptionResource
.Arg_ArrayPlusOffTooSmall
, ExceptionArgument
.value);
378 if (length
> (int.MaxValue
/ 3))
380 // (int.MaxValue / 3) == 715,827,882 Bytes == 699 MB
381 throw new ArgumentOutOfRangeException(nameof(length
), SR
.Format(SR
.ArgumentOutOfRange_LengthTooLarge
, int.MaxValue
/ 3));
384 return string.Create(length
* 3 - 1, (value, startIndex
, length
), (dst
, state
) =>
386 const string HexValues
= "0123456789ABCDEF";
388 var src
= new ReadOnlySpan
<byte>(state
.value, state
.startIndex
, state
.length
);
394 dst
[j
++] = HexValues
[b
>> 4];
395 dst
[j
++] = HexValues
[b
& 0xF];
397 while (i
< src
.Length
)
401 dst
[j
++] = HexValues
[b
>> 4];
402 dst
[j
++] = HexValues
[b
& 0xF];
407 // Converts an array of bytes into a String.
408 public static string ToString(byte[] value)
411 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
412 return ToString(value, 0, value.Length
);
415 // Converts an array of bytes into a String.
416 public static string ToString(byte[] value, int startIndex
)
419 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
420 return ToString(value, startIndex
, value.Length
- startIndex
);
423 /*==================================ToBoolean===================================
424 **Action: Convert an array of bytes to a boolean value. We treat this array
425 ** as if the first 4 bytes were an Int4 an operate on this value.
426 **Returns: True if the Int4 value of the first 4 bytes is non-zero.
427 **Arguments: value -- The byte array
428 ** startIndex -- The position within the array.
429 **Exceptions: See ToInt4.
430 ==============================================================================*/
431 // Converts an array of bytes into a boolean.
432 public static bool ToBoolean(byte[] value, int startIndex
)
435 ThrowHelper
.ThrowArgumentNullException(ExceptionArgument
.value);
437 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
);
438 if (startIndex
> value.Length
- 1)
439 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.startIndex
, ExceptionResource
.ArgumentOutOfRange_Index
); // differs from other overloads, which throw base ArgumentException
441 return value[startIndex
] != 0;
444 public static bool ToBoolean(ReadOnlySpan
<byte> value)
446 if (value.Length
< sizeof(byte))
447 ThrowHelper
.ThrowArgumentOutOfRangeException(ExceptionArgument
.value);
448 return Unsafe
.ReadUnaligned
<byte>(ref MemoryMarshal
.GetReference(value)) != 0;
451 [MethodImpl(MethodImplOptions
.AggressiveInlining
)]
452 public static unsafe long DoubleToInt64Bits(double value)
454 return *((long*)&value);
457 [MethodImpl(MethodImplOptions
.AggressiveInlining
)]
458 public static unsafe double Int64BitsToDouble(long value)
460 return *((double*)&value);
463 [MethodImpl(MethodImplOptions
.AggressiveInlining
)]
464 public static unsafe int SingleToInt32Bits(float value)
466 return *((int*)&value);
469 [MethodImpl(MethodImplOptions
.AggressiveInlining
)]
470 public static unsafe float Int32BitsToSingle(int value)
472 return *((float*)&value);