The Labs \ Source Viewer \ SSCLI \ System \ BitConverter

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  BitConverter
  18. **
  19. **
  20. ** Purpose: Allows developers to view the base data types as
  21. **          an arbitrary array of bits.
  22. **
  23. **
  24. ===========================================================*/
  25. namespace System
  26. {
  27.    
  28.     using System;
  29.     using System.Runtime.CompilerServices;
  30.     // The BitConverter class contains methods for
  31.     // converting an array of bytes to one of the base data
  32.     // types, as well as for converting a base data type to an
  33.     // array of bytes.
  34.     //
  35.     // Only statics, does not need to be marked with the serializable attribute
  36.     public static class BitConverter
  37.     {
  38.        
  39.         // This field indicates the "endianess" of the architecture.
  40.         // The value is set to true if the architecture is
  41.         // little endian; false if it is big endian.
  42.         #if BIGENDIAN
  43.             /* = false */        public static readonly bool IsLittleEndian;
  44.         #else
  45.         public static readonly bool IsLittleEndian = true;
  46.         #endif
  47.        
  48.         // Converts a byte into an array of bytes with length one.
  49.         public static byte[] GetBytes(bool value)
  50.         {
  51.             byte[] r = new byte[1];
  52.             r[0] = (value ? (byte)Boolean.True : (byte)Boolean.False);
  53.             return r;
  54.         }
  55.        
  56.         // Converts a char into an array of bytes with length two.
  57.         public static byte[] GetBytes(char value)
  58.         {
  59.             return GetBytes((short)value);
  60.         }
  61.        
  62.         // Converts a short into an array of bytes with length
  63.         // two.
  64.         unsafe public static byte[] GetBytes(short value)
  65.         {
  66.             byte[] bytes = new byte[2];
  67.             fixed (byte* b = bytes)
  68.                 *((short*)b) = value;
  69.             return bytes;
  70.         }
  71.        
  72.         // Converts an int into an array of bytes with length
  73.         // four.
  74.         unsafe public static byte[] GetBytes(int value)
  75.         {
  76.             byte[] bytes = new byte[4];
  77.             fixed (byte* b = bytes)
  78.                 *((int*)b) = value;
  79.             return bytes;
  80.         }
  81.        
  82.         // Converts a long into an array of bytes with length
  83.         // eight.
  84.         unsafe public static byte[] GetBytes(long value)
  85.         {
  86.             byte[] bytes = new byte[8];
  87.             fixed (byte* b = bytes)
  88.                 *((long*)b) = value;
  89.             return bytes;
  90.         }
  91.        
  92.         // Converts an ushort into an array of bytes with
  93.         // length two.
  94.         [CLSCompliant(false)]
  95.         public static byte[] GetBytes(ushort value)
  96.         {
  97.             return GetBytes((short)value);
  98.         }
  99.        
  100.         // Converts an uint into an array of bytes with
  101.         // length four.
  102.         [CLSCompliant(false)]
  103.         public static byte[] GetBytes(uint value)
  104.         {
  105.             return GetBytes((int)value);
  106.         }
  107.        
  108.         // Converts an unsigned long into an array of bytes with
  109.         // length eight.
  110.         [CLSCompliant(false)]
  111.         public static byte[] GetBytes(ulong value)
  112.         {
  113.             return GetBytes((long)value);
  114.         }
  115.        
  116.         // Converts a float into an array of bytes with length
  117.         // four.
  118.         unsafe public static byte[] GetBytes(float value)
  119.         {
  120.             return GetBytes(*(int*)&value);
  121.         }
  122.        
  123.         // Converts a double into an array of bytes with length
  124.         // eight.
  125.         unsafe public static byte[] GetBytes(double value)
  126.         {
  127.             return GetBytes(*(long*)&value);
  128.         }
  129.        
  130.         // Converts an array of bytes into a char.
  131.         public static char ToChar(byte[] value, int startIndex)
  132.         {
  133.             return (char)ToInt16(value, startIndex);
  134.         }
  135.        
  136.         // Converts an array of bytes into a short.
  137.         unsafe public static short ToInt16(byte[] value, int startIndex)
  138.         {
  139.             if (value == null) {
  140.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
  141.             }
  142.            
  143.             if ((uint)startIndex >= value.Length) {
  144.                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
  145.             }
  146.            
  147.             if (startIndex > value.Length - 2) {
  148.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
  149.             }
  150.            
  151.             fixed (byte* pbyte = &value[startIndex]) {
  152.                 if (startIndex % 2 == 0) {
  153.                     // data is aligned
  154.                     return *((short*)pbyte);
  155.                 }
  156.                 else {
  157.                     if (IsLittleEndian) {
  158.                         return (short)((*pbyte) | (*(pbyte + 1) << 8));
  159.                     }
  160.                     else {
  161.                         return (short)((*pbyte << 8) | (*(pbyte + 1)));
  162.                     }
  163.                 }
  164.             }
  165.            
  166.         }
  167.        
  168.         // Converts an array of bytes into an int.
  169.         unsafe public static int ToInt32(byte[] value, int startIndex)
  170.         {
  171.             if (value == null) {
  172.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
  173.             }
  174.            
  175.             if ((uint)startIndex >= value.Length) {
  176.                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
  177.             }
  178.            
  179.             if (startIndex > value.Length - 4) {
  180.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
  181.             }
  182.            
  183.             fixed (byte* pbyte = &value[startIndex]) {
  184.                 if (startIndex % 4 == 0) {
  185.                     // data is aligned
  186.                     return *((int*)pbyte);
  187.                 }
  188.                 else {
  189.                     if (IsLittleEndian) {
  190.                         return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
  191.                     }
  192.                     else {
  193.                         return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
  194.                     }
  195.                 }
  196.             }
  197.         }
  198.        
  199.         // Converts an array of bytes into a long.
  200.         unsafe public static long ToInt64(byte[] value, int startIndex)
  201.         {
  202.             if (value == null) {
  203.                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
  204.             }
  205.            
  206.             if ((uint)startIndex >= value.Length) {
  207.                 ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
  208.             }
  209.            
  210.             if (startIndex > value.Length - 8) {
  211.                 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
  212.             }
  213.            
  214.             fixed (byte* pbyte = &value[startIndex]) {
  215.                 if (startIndex % 8 == 0) {
  216.                     // data is aligned
  217.                     return *((long*)pbyte);
  218.                 }
  219.                 else {
  220.                     if (IsLittleEndian) {
  221.                         int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
  222.                         int i2 = (*(pbyte + 4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24);
  223.                         return (uint)i1 | ((long)i2 << 32);
  224.                     }
  225.                     else {
  226.                         int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
  227.                         int i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
  228.                         return (uint)i2 | ((long)i1 << 32);
  229.                     }
  230.                 }
  231.             }
  232.         }
  233.        
  234.        
  235.         // Converts an array of bytes into an ushort.
  236.         //
  237.         [CLSCompliant(false)]
  238.         public static ushort ToUInt16(byte[] value, int startIndex)
  239.         {
  240.             return (ushort)ToInt16(value, startIndex);
  241.         }
  242.        
  243.         // Converts an array of bytes into an uint.
  244.         //
  245.         [CLSCompliant(false)]
  246.         public static uint ToUInt32(byte[] value, int startIndex)
  247.         {
  248.             return (uint)ToInt32(value, startIndex);
  249.         }
  250.        
  251.         // Converts an array of bytes into an unsigned long.
  252.         //
  253.         [CLSCompliant(false)]
  254.         public static ulong ToUInt64(byte[] value, int startIndex)
  255.         {
  256.             return (ulong)ToInt64(value, startIndex);
  257.         }
  258.        
  259.         // Converts an array of bytes into a float.
  260.         unsafe public static float ToSingle(byte[] value, int startIndex)
  261.         {
  262.             int val = ToInt32(value, startIndex);
  263.             return *(float*)&val;
  264.         }
  265.        
  266.         // Converts an array of bytes into a double.
  267.         unsafe public static double ToDouble(byte[] value, int startIndex)
  268.         {
  269.             long val = ToInt64(value, startIndex);
  270.             return *(double*)&val;
  271.         }
  272.        
  273.         private static char GetHexValue(int i)
  274.         {
  275.             BCLDebug.Assert(i >= 0 && i < 16, "i is out of range.");
  276.             if (i < 10) {
  277.                 return (char)(i + '0');
  278.             }
  279.            
  280.             return (char)(i - 10 + 'A');
  281.         }
  282.        
  283.         // Converts an array of bytes into a String.
  284.         public static string ToString(byte[] value, int startIndex, int length)
  285.         {
  286.            
  287.             if (value == null) {
  288.                 throw new ArgumentNullException("byteArray");
  289.             }
  290.            
  291.             int arrayLen = value.Length;
  292.             if (startIndex < 0 || (startIndex >= arrayLen && startIndex > 0)) {
  293.                 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
  294.             }
  295.            
  296.             int realLength = length;
  297.             if (realLength < 0) {
  298.                 throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
  299.             }
  300.            
  301.             if (startIndex > arrayLen - realLength) {
  302.                 throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
  303.             }
  304.            
  305.             if (realLength == 0) {
  306.                 return string.Empty;
  307.             }
  308.            
  309.             char[] chArray = new char[realLength * 3];
  310.             int i = 0;
  311.             int index = startIndex;
  312.             for (i = 0; i < realLength * 3; i += 3) {
  313.                 byte b = value[index++];
  314.                 chArray[i] = GetHexValue(b / 16);
  315.                 chArray[i + 1] = GetHexValue(b % 16);
  316.                 chArray[i + 2] = '-';
  317.             }
  318.            
  319.             // We don't need the last '-' character
  320.             return new string(chArray, 0, chArray.Length - 1);
  321.         }
  322.        
  323.         // Converts an array of bytes into a String.
  324.         public static string ToString(byte[] value)
  325.         {
  326.             if (value == null)
  327.                 throw new ArgumentNullException("value");
  328.             return ToString(value, 0, value.Length);
  329.         }
  330.        
  331.         // Converts an array of bytes into a String.
  332.         public static string ToString(byte[] value, int startIndex)
  333.         {
  334.             if (value == null)
  335.                 throw new ArgumentNullException("value");
  336.             return ToString(value, startIndex, value.Length - startIndex);
  337.         }
  338.        
  339. /*==================================ToBoolean===================================
  340.         **Action:  Convert an array of bytes to a boolean value.  We treat this array
  341.         **        as if the first 4 bytes were an Int4 an operate on this value.
  342.         **Returns: True if the Int4 value of the first 4 bytes is non-zero.
  343.         **Arguments: value -- The byte array
  344.         **          startIndex -- The position within the array.
  345.         **Exceptions: See ToInt4.
  346.         ==============================================================================*/       
  347.         // Converts an array of bytes into a boolean.
  348.         public static bool ToBoolean(byte[] value, int startIndex)
  349.         {
  350.             if (value == null)
  351.                 throw new ArgumentNullException("value");
  352.             if (startIndex < 0)
  353.                 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
  354.             if (startIndex > value.Length - 1)
  355.                 throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
  356.            
  357.             return (value[startIndex] == 0) ? false : true;
  358.         }
  359.        
  360.         unsafe public static long DoubleToInt64Bits(double value)
  361.         {
  362.             return *((long*)&value);
  363.         }
  364.        
  365.         unsafe public static double Int64BitsToDouble(long value)
  366.         {
  367.             return *((double*)&value);
  368.         }
  369.     }
  370.    
  371.    
  372. }

Developer Fusion