Refactoring the ARM Hardware Intrinsics based on the latest design decisions. (#26895)
[mono-project.git] / netcore / System.Private.CoreLib / shared / System / BitConverter.cs
blob8085e9cb38a76d27c8fd0d2bf0690401de7979d8
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;
10 namespace System
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
15 // array of bytes.
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.
21 #if BIGENDIAN
22 [Intrinsic]
23 public static readonly bool IsLittleEndian /* = false */;
24 #else
25 [Intrinsic]
26 public static readonly bool IsLittleEndian = true;
27 #endif
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);
34 return r;
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))
41 return false;
43 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value ? (byte)1 : (byte)0);
44 return true;
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;
52 return bytes;
55 // Converts a char into a Span
56 public static bool TryWriteBytes(Span<byte> destination, char value)
58 if (destination.Length < sizeof(char))
59 return false;
61 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
62 return true;
65 // Converts a short into an array of bytes with length
66 // two.
67 public static byte[] GetBytes(short value)
69 byte[] bytes = new byte[sizeof(short)];
70 Unsafe.As<byte, short>(ref bytes[0]) = value;
71 return bytes;
74 // Converts a short into a Span
75 public static bool TryWriteBytes(Span<byte> destination, short value)
77 if (destination.Length < sizeof(short))
78 return false;
80 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
81 return true;
84 // Converts an int into an array of bytes with length
85 // four.
86 public static byte[] GetBytes(int value)
88 byte[] bytes = new byte[sizeof(int)];
89 Unsafe.As<byte, int>(ref bytes[0]) = value;
90 return bytes;
93 // Converts an int into a Span
94 public static bool TryWriteBytes(Span<byte> destination, int value)
96 if (destination.Length < sizeof(int))
97 return false;
99 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
100 return true;
103 // Converts a long into an array of bytes with length
104 // eight.
105 public static byte[] GetBytes(long value)
107 byte[] bytes = new byte[sizeof(long)];
108 Unsafe.As<byte, long>(ref bytes[0]) = value;
109 return bytes;
112 // Converts a long into a Span
113 public static bool TryWriteBytes(Span<byte> destination, long value)
115 if (destination.Length < sizeof(long))
116 return false;
118 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
119 return true;
122 // Converts an ushort into an array of bytes with
123 // length two.
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;
129 return bytes;
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))
137 return false;
139 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
140 return true;
143 // Converts an uint into an array of bytes with
144 // length four.
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;
150 return bytes;
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))
158 return false;
160 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
161 return true;
164 // Converts an unsigned long into an array of bytes with
165 // length eight.
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;
171 return bytes;
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))
179 return false;
181 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
182 return true;
185 // Converts a float into an array of bytes with length
186 // four.
187 public static byte[] GetBytes(float value)
189 byte[] bytes = new byte[sizeof(float)];
190 Unsafe.As<byte, float>(ref bytes[0]) = value;
191 return bytes;
194 // Converts a float into a Span
195 public static bool TryWriteBytes(Span<byte> destination, float value)
197 if (destination.Length < sizeof(float))
198 return false;
200 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
201 return true;
204 // Converts a double into an array of bytes with length
205 // eight.
206 public static byte[] GetBytes(double value)
208 byte[] bytes = new byte[sizeof(double)];
209 Unsafe.As<byte, double>(ref bytes[0]) = value;
210 return bytes;
213 // Converts a double into a Span
214 public static bool TryWriteBytes(Span<byte> destination, double value)
216 if (destination.Length < sizeof(double))
217 return false;
219 Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(destination), value);
220 return true;
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)
237 if (value == null)
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)
258 if (value == null)
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)
279 if (value == null)
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)
364 if (value == null)
365 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
366 if (startIndex < 0 || startIndex >= value.Length && startIndex > 0)
367 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
368 if (length < 0)
369 throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_GenericPositive);
370 if (startIndex > value.Length - length)
371 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall, ExceptionArgument.value);
373 if (length == 0)
375 return string.Empty;
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);
390 int i = 0;
391 int j = 0;
393 byte b = src[i++];
394 dst[j++] = HexValues[b >> 4];
395 dst[j++] = HexValues[b & 0xF];
397 while (i < src.Length)
399 b = src[i++];
400 dst[j++] = '-';
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)
410 if (value == null)
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)
418 if (value == null)
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)
434 if (value == null)
435 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
436 if (startIndex < 0)
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);