3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
11 ** Purpose: Allows developers to view the base data types as
12 ** an arbitrary array of bits.
15 ===========================================================*/
19 using System.Runtime.CompilerServices;
20 using System.Diagnostics.Contracts;
21 using System.Security;
23 // The BitConverter class contains methods for
24 // converting an array of bytes to one of the base data
25 // types, as well as for converting a base data type to an
28 // Only statics, does not need to be marked with the serializable attribute
29 public static class BitConverter {
31 public static readonly bool IsLittleEndian = AmILittleEndian ();
33 static unsafe bool AmILittleEndian ()
35 // binary representations of 1.0:
36 // big endian: 3f f0 00 00 00 00 00 00
37 // little endian: 00 00 00 00 00 00 f0 3f
43 // This field indicates the "endianess" of the architecture.
44 // The value is set to true if the architecture is
45 // little endian; false if it is big endian.
47 public static readonly bool IsLittleEndian /* = false */;
49 public static readonly bool IsLittleEndian = true;
52 // Converts a byte into an array of bytes with length one.
53 public static byte[] GetBytes(bool value) {
54 Contract.Ensures(Contract.Result<byte[]>() != null);
55 Contract.Ensures(Contract.Result<byte[]>().Length == 1);
57 byte[] r = new byte[1];
58 r[0] = (value ? (byte)Boolean.True : (byte)Boolean.False );
62 // Converts a char into an array of bytes with length two.
63 public static byte[] GetBytes(char value)
65 Contract.Ensures(Contract.Result<byte[]>() != null);
66 Contract.Ensures(Contract.Result<byte[]>().Length == 2);
68 return GetBytes((short)value);
71 // Converts a short into an array of bytes with length
73 [System.Security.SecuritySafeCritical] // auto-generated
74 public unsafe static byte[] GetBytes(short value)
76 Contract.Ensures(Contract.Result<byte[]>() != null);
77 Contract.Ensures(Contract.Result<byte[]>().Length == 2);
79 byte[] bytes = new byte[2];
80 fixed(byte* b = bytes)
85 // Converts an int into an array of bytes with length
87 [System.Security.SecuritySafeCritical] // auto-generated
88 public unsafe static byte[] GetBytes(int value)
90 Contract.Ensures(Contract.Result<byte[]>() != null);
91 Contract.Ensures(Contract.Result<byte[]>().Length == 4);
93 byte[] bytes = new byte[4];
94 fixed(byte* b = bytes)
99 // Converts a long into an array of bytes with length
101 [System.Security.SecuritySafeCritical] // auto-generated
102 public unsafe static byte[] GetBytes(long value)
104 Contract.Ensures(Contract.Result<byte[]>() != null);
105 Contract.Ensures(Contract.Result<byte[]>().Length == 8);
107 byte[] bytes = new byte[8];
108 fixed(byte* b = bytes)
113 // Converts an ushort into an array of bytes with
115 [CLSCompliant(false)]
116 public static byte[] GetBytes(ushort value) {
117 Contract.Ensures(Contract.Result<byte[]>() != null);
118 Contract.Ensures(Contract.Result<byte[]>().Length == 2);
120 return GetBytes((short)value);
123 // Converts an uint into an array of bytes with
125 [CLSCompliant(false)]
126 public static byte[] GetBytes(uint value) {
127 Contract.Ensures(Contract.Result<byte[]>() != null);
128 Contract.Ensures(Contract.Result<byte[]>().Length == 4);
130 return GetBytes((int)value);
133 // Converts an unsigned long into an array of bytes with
135 [CLSCompliant(false)]
136 public static byte[] GetBytes(ulong value) {
137 Contract.Ensures(Contract.Result<byte[]>() != null);
138 Contract.Ensures(Contract.Result<byte[]>().Length == 8);
140 return GetBytes((long)value);
143 // Converts a float into an array of bytes with length
145 [System.Security.SecuritySafeCritical] // auto-generated
146 public unsafe static byte[] GetBytes(float value)
148 Contract.Ensures(Contract.Result<byte[]>() != null);
149 Contract.Ensures(Contract.Result<byte[]>().Length == 4);
151 return GetBytes(*(int*)&value);
154 // Converts a double into an array of bytes with length
156 [System.Security.SecuritySafeCritical] // auto-generated
157 public unsafe static byte[] GetBytes(double value)
159 Contract.Ensures(Contract.Result<byte[]>() != null);
160 Contract.Ensures(Contract.Result<byte[]>().Length == 8);
162 return GetBytes(*(long*)&value);
165 // Converts an array of bytes into a char.
166 public static char ToChar(byte[] value, int startIndex)
169 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
172 if ((uint)startIndex >= value.Length) {
173 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
176 if (startIndex > value.Length - 2) {
177 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
179 Contract.EndContractBlock();
181 return (char)ToInt16(value, startIndex);
184 // Converts an array of bytes into a short.
185 [System.Security.SecuritySafeCritical] // auto-generated
186 public static unsafe short ToInt16(byte[] value, int startIndex) {
188 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
191 if ((uint) startIndex >= value.Length) {
192 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
195 if (startIndex > value.Length -2) {
196 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
198 Contract.EndContractBlock();
200 fixed( byte * pbyte = &value[startIndex]) {
201 if( startIndex % 2 == 0) { // data is aligned
202 return *((short *) pbyte);
205 if( IsLittleEndian) {
206 return (short)((*pbyte) | (*(pbyte + 1) << 8)) ;
209 return (short)((*pbyte << 8) | (*(pbyte + 1)));
216 // Converts an array of bytes into an int.
217 [System.Security.SecuritySafeCritical] // auto-generated
218 public static unsafe int ToInt32 (byte[] value, int startIndex) {
220 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
223 if ((uint) startIndex >= value.Length) {
224 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
227 if (startIndex > value.Length -4) {
228 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
230 Contract.EndContractBlock();
232 fixed( byte * pbyte = &value[startIndex]) {
233 if( startIndex % 4 == 0) { // data is aligned
234 return *((int *) pbyte);
237 if( IsLittleEndian) {
238 return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
241 return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
247 // Converts an array of bytes into a long.
248 [System.Security.SecuritySafeCritical] // auto-generated
249 public static unsafe long ToInt64 (byte[] value, int startIndex) {
251 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
254 if ((uint) startIndex >= value.Length) {
255 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
258 if (startIndex > value.Length -8) {
259 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
261 Contract.EndContractBlock();
263 fixed( byte * pbyte = &value[startIndex]) {
264 if( startIndex % 8 == 0) { // data is aligned
265 return *((long *) pbyte);
268 if( IsLittleEndian) {
269 int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
270 int i2 = (*(pbyte+4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24);
271 return (uint)i1 | ((long)i2 << 32);
274 int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
275 int i2 = (*(pbyte+4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
276 return (uint)i2 | ((long)i1 << 32);
283 // Converts an array of bytes into an ushort.
285 [CLSCompliant(false)]
286 public static ushort ToUInt16(byte[] value, int startIndex)
289 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
290 if ((uint)startIndex >= value.Length)
291 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
292 if (startIndex > value.Length - 2)
293 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
294 Contract.EndContractBlock();
296 return (ushort)ToInt16(value, startIndex);
299 // Converts an array of bytes into an uint.
301 [CLSCompliant(false)]
302 public static uint ToUInt32(byte[] value, int startIndex)
305 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
306 if ((uint)startIndex >= value.Length)
307 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
308 if (startIndex > value.Length - 4)
309 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
310 Contract.EndContractBlock();
312 return (uint)ToInt32(value, startIndex);
315 // Converts an array of bytes into an unsigned long.
317 [CLSCompliant(false)]
318 public static ulong ToUInt64(byte[] value, int startIndex)
321 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
322 if ((uint)startIndex >= value.Length)
323 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
324 if (startIndex > value.Length - 8)
325 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
326 Contract.EndContractBlock();
328 return (ulong)ToInt64(value, startIndex);
331 // Converts an array of bytes into a float.
332 [System.Security.SecuritySafeCritical] // auto-generated
333 unsafe public static float ToSingle (byte[] value, int startIndex)
336 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
337 if ((uint)startIndex >= value.Length)
338 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
339 if (startIndex > value.Length - 4)
340 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
341 Contract.EndContractBlock();
343 int val = ToInt32(value, startIndex);
344 return *(float*)&val;
347 // Converts an array of bytes into a double.
348 [System.Security.SecuritySafeCritical] // auto-generated
349 unsafe public static double ToDouble (byte[] value, int startIndex)
352 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
353 if ((uint)startIndex >= value.Length)
354 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
355 if (startIndex > value.Length - 8)
356 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
357 Contract.EndContractBlock();
359 long val = ToInt64(value, startIndex);
360 return *(double*)&val;
363 private static char GetHexValue(int i) {
364 Contract.Assert( i >=0 && i <16, "i is out of range.");
366 return (char)(i + '0');
369 return (char)(i - 10 + 'A');
372 // Converts an array of bytes into a String.
373 public static String ToString (byte[] value, int startIndex, int length) {
375 throw new ArgumentNullException("byteArray");
378 if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array.
379 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
383 throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
386 if (startIndex > value.Length - length) {
387 throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
389 Contract.EndContractBlock();
395 if (length > (Int32.MaxValue / 3)) {
396 // (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB
397 throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthTooLarge", (Int32.MaxValue / 3)));
400 int chArrayLength = length * 3;
402 char[] chArray = new char[chArrayLength];
404 int index = startIndex;
405 for (i = 0; i < chArrayLength; i += 3) {
406 byte b = value[index++];
407 chArray[i]= GetHexValue(b/16);
408 chArray[i+1] = GetHexValue(b%16);
412 // We don't need the last '-' character
413 return new String(chArray, 0, chArray.Length - 1);
416 // Converts an array of bytes into a String.
417 public static String ToString(byte [] value) {
419 throw new ArgumentNullException("value");
420 Contract.Ensures(Contract.Result<String>() != null);
421 Contract.EndContractBlock();
422 return ToString(value, 0, value.Length);
425 // Converts an array of bytes into a String.
426 public static String ToString (byte [] value, int startIndex) {
428 throw new ArgumentNullException("value");
429 Contract.Ensures(Contract.Result<String>() != null);
430 Contract.EndContractBlock();
431 return ToString(value, startIndex, value.Length - startIndex);
434 /*==================================ToBoolean===================================
435 **Action: Convert an array of bytes to a boolean value. We treat this array
436 ** as if the first 4 bytes were an Int4 an operate on this value.
437 **Returns: True if the Int4 value of the first 4 bytes is non-zero.
438 **Arguments: value -- The byte array
439 ** startIndex -- The position within the array.
440 **Exceptions: See ToInt4.
441 ==============================================================================*/
442 // Converts an array of bytes into a boolean.
443 public static bool ToBoolean(byte[] value, int startIndex) {
445 throw new ArgumentNullException("value");
447 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
448 if (startIndex > value.Length - 1)
449 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
450 Contract.EndContractBlock();
452 return (value[startIndex]==0)?false:true;
455 [SecuritySafeCritical]
456 public static unsafe long DoubleToInt64Bits(double value) {
457 // If we're on a big endian machine, what should this method do? You could argue for
458 // either big endian or little endian, depending on whether you are writing to a file that
459 // should be used by other programs on that processor, or for compatibility across multiple
460 // formats. Because this is ambiguous, we're excluding this from the Portable Library & Win8 Profile.
461 // If we ever run on big endian machines, produce two versions where endianness is specified.
462 Contract.Assert(IsLittleEndian, "This method is implemented assuming little endian with an ambiguous spec.");
463 return *((long *)&value);
466 [SecuritySafeCritical]
467 public static unsafe double Int64BitsToDouble(long value) {
468 // If we're on a big endian machine, what should this method do? You could argue for
469 // either big endian or little endian, depending on whether you are writing to a file that
470 // should be used by other programs on that processor, or for compatibility across multiple
471 // formats. Because this is ambiguous, we're excluding this from the Portable Library & Win8 Profile.
472 // If we ever run on big endian machines, produce two versions where endianness is specified.
473 Contract.Assert(IsLittleEndian, "This method is implemented assuming little endian with an ambiguous spec.");
474 return *((double*)&value);