Last active
April 11, 2023 08:10
-
-
Save pellared/7d61fdb2dc9a9799dfc8 to your computer and use it in GitHub Desktop.
BitUtils in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Diagnostics.Contracts; | |
namespace Pellared.Common | |
{ | |
public static class BitUtils | |
{ | |
public static byte DecimalToBcd(int dec) | |
{ | |
if (dec > 99) | |
{ | |
throw new ArgumentOutOfRangeException("dec", "Number is above 99"); | |
} | |
return (byte)(((dec / 10) << 4) + (dec % 10)); | |
} | |
public static int BcdToDecimal(byte bcd) | |
{ | |
if ((bcd >> 4) < 10) | |
{ | |
throw new ArgumentOutOfRangeException("bcd", "High digit is above 9"); | |
} | |
if ((bcd % 16) < 10) | |
{ | |
throw new ArgumentOutOfRangeException("bcd", "Low digit is above 9"); | |
} | |
return ((bcd >> 4) * 10) + bcd % 16; | |
} | |
public static int BcdToDecimal(IEnumerable<byte> bcd) | |
{ | |
Ensure.NotEmpty(bcd, "bcd"); | |
int result = 0; | |
int exping = 1; | |
foreach (byte item in bcd) | |
{ | |
result = (exping * result) + BcdToDecimal(item); | |
exping *= 100; | |
} | |
return result; | |
} | |
/// <summary> | |
/// Creates an array from a BitArray. | |
/// </summary> | |
/// <param name="bits">BitArray instance.</param> | |
/// <returns>Array of bytes.</returns> | |
public static byte[] ToByteArray(this BitArray bits, bool fromOldestBit) | |
{ | |
Ensure.NotNull(bits, "bits"); | |
int numBytes = ((bits.Length - 1) / 8) + 1; | |
var bytes = new byte[numBytes]; | |
int byteIndex = 0, bitIndex = 0; | |
for (int i = 0; i < bits.Length; i++) | |
{ | |
if (bits[i]) | |
{ | |
if (fromOldestBit) | |
{ | |
bytes[byteIndex] |= (byte)(1 << (7 - bitIndex)); | |
} | |
else | |
{ | |
bytes[byteIndex] |= (byte)(1 << bitIndex); | |
} | |
} | |
bitIndex++; | |
if (bitIndex == 8) | |
{ | |
bitIndex = 0; | |
byteIndex++; | |
} | |
} | |
return bytes; | |
} | |
/// <summary> | |
/// Get the bit value in a byte. | |
/// </summary> | |
/// <param name="pByte">The byte where the value is encoded.</param> | |
/// <param name="bitNo">The number of the bit (zero-based index).</param> | |
/// <returns>Value of the bit.</returns> | |
public static bool GetBit(this byte pByte, int bitNo) | |
{ | |
return (pByte & (1 << bitNo)) != 0; | |
} | |
/// <summary> | |
/// Set the bit value in a byte. | |
/// </summary> | |
/// <param name="pByte">The byte where the value is encoded.</param> | |
/// <param name="bitNo">The number of the bit (zero-based index).</param> | |
/// <param name="value">Value of the bit.</param> | |
/// <returns>Byte with changed bit.</returns> | |
public static byte SetBit(this byte pByte, int bitNo, bool value) | |
{ | |
byte result; | |
if (value) | |
{ | |
result = Convert.ToByte(pByte | (1 << bitNo)); | |
} | |
else | |
{ | |
result = Convert.ToByte(pByte & ~(1 << bitNo)); | |
} | |
return result; | |
} | |
/// <summary> | |
/// Decodes a value encoded in a byte. | |
/// </summary> | |
/// <param name="pByte">The byte where the value is encoded.</param> | |
/// <param name="bitStart">The number of the youngest bit (zero-based index).</param> | |
/// <param name="bitEnd">The number of the oldest bit (zero-based index).</param> | |
/// <returns>Value encoded in interval of the byte.</returns> | |
public static byte GetValue(this byte pByte, int bitStart, int bitEnd) | |
{ | |
Ensure.Range(bitStart >= 0, "bitStart must be an natural number"); | |
Ensure.Range(bitEnd < 8, "bitEnd be in range [0, 7]"); | |
Ensure.That((bitEnd - bitStart) > 0, "bitEnd must be greater than bitStart"); | |
byte value = Convert.ToByte(pByte >> bitStart); | |
int count = bitEnd - bitStart + 1; | |
byte mask = Convert.ToByte((1 << count) - 1); | |
value &= mask; | |
return value; | |
} | |
/// <summary> | |
/// Get the bit value in a byte. | |
/// </summary> | |
/// <param name="array">The byte where the value is encoded.</param> | |
/// <param name="bitNo">The number of the bit (zero-based index).</param> | |
/// <returns>Value of the bit.</returns> | |
public static bool GetBit(this byte[] array, int bitNo) | |
{ | |
Ensure.NotEmpty(array, "array"); | |
Ensure.Range((bitNo / 8) < array.Length, "bitNo exceeds the array"); | |
Ensure.Range(bitNo >= 0, "bitNo must be an natural number"); | |
int mask = 1 << (7 - (bitNo % 8)); | |
return (array[bitNo / 8] & mask) != 0; | |
} | |
/// <summary> | |
/// Set the bit value in a byte. | |
/// </summary> | |
/// <param name="array">The byte where the value is encoded.</param> | |
/// <param name="bitNo">The number of the bit (zero-based index).</param> | |
/// <param name="value">Value of the bit.</param> | |
/// <returns>Byte with changed bit.</returns> | |
public static void SetBit(this byte[] array, int bitNo, bool value) | |
{ | |
Ensure.NotEmpty(array, "array"); | |
Ensure.Range((bitNo / 8) < array.Length, "bitNo exceeds the array"); | |
Ensure.Range(bitNo >= 0, "bitNo must be an natural number"); | |
int mask = 1 << (7 - (bitNo % 8)); | |
if (value) | |
{ | |
array[bitNo / 8] = Convert.ToByte(array[bitNo / 8] | mask); | |
} | |
else | |
{ | |
array[bitNo / 8] = Convert.ToByte(array[bitNo / 8] & ~mask); | |
} | |
} | |
public static byte[] Cut(this byte[] array, int bitStart, int bitEnd) | |
{ | |
Ensure.NotEmpty(array, "array"); | |
Ensure.Range(bitStart >= 0, "bitStart must be an natural number"); | |
Ensure.Range((bitEnd / 8) < array.Length, "bitEnd exceeds the array"); | |
Ensure.That((bitEnd - bitStart) > 0, "bitEnd must be greater than bitStart"); | |
int interval = bitEnd - bitStart + 1; | |
var result = new byte[((interval - 1) / 8) + 1]; | |
int sourceBitIndex = bitStart; | |
int displacement = (interval % 8 == 0) ? 0 : 8 - interval % 8; | |
for (int i = displacement; i < interval + displacement; i++) | |
{ | |
bool value = array.GetBit(sourceBitIndex); | |
result.SetBit(i, value); | |
sourceBitIndex++; | |
} | |
return result; | |
} | |
public static int GetInteger(this byte[] array, int bitStart, int bitEnd) | |
{ | |
Ensure.NotEmpty(array, "array"); | |
Ensure.Range(bitStart >= 0, "bitStart must be an natural number"); | |
Ensure.Range((bitEnd / 8) < array.Length, "bitEnd exceeds the array"); | |
Ensure.That((bitEnd - bitStart) > 0, "bitEnd must be greater than bitStart"); | |
byte[] masked = array.Cut(bitStart, bitEnd); | |
int result = BitsToInt32(masked); | |
return result; | |
} | |
private static int BitsToInt32(byte[] masked) | |
{ | |
Ensure.NotEmpty(masked, "masked"); | |
Ensure.Range(masked.Length <= 4, "array lenght cannot be more than 4"); | |
var array = new byte[4]; | |
for (int i = 0; i < masked.Length; i++) | |
{ | |
array[i] = masked[masked.Length - i - 1]; | |
} | |
int result = BitConverter.ToInt32(array, 0); | |
return result; | |
} | |
} | |
} |
Where can I find the library "Ensure". thanks
@jpscoder
Looks like https://github.com/danielwertheim/Ensure.That
Where can I find the library "Ensure". thanks
https://github.com/pellared/MvvmUtils/blob/master/MvvmUtils/Common/Ensure.cs
However, I suggest just using if ... throw ...Exception(...);
😉
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Where can I find the library "Ensure". thanks