Skip to content

Instantly share code, notes, and snippets.

@pellared
Last active April 11, 2023 08:10
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pellared/7d61fdb2dc9a9799dfc8 to your computer and use it in GitHub Desktop.
Save pellared/7d61fdb2dc9a9799dfc8 to your computer and use it in GitHub Desktop.
BitUtils in C#
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;
}
}
}
@jpscoder
Copy link

Where can I find the library "Ensure". thanks

@wcoder
Copy link

wcoder commented Nov 1, 2021

Where can I find the library "Ensure". thanks

@jpscoder
Looks like https://github.com/danielwertheim/Ensure.That

@pellared
Copy link
Author

pellared commented Nov 3, 2021

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