Skip to content

Instantly share code, notes, and snippets.

@txdv
Created November 7, 2012 15:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save txdv/4032303 to your computer and use it in GitHub Desktop.
Save txdv/4032303 to your computer and use it in GitHub Desktop.
Bit manipulation classes for C#

BitArrayWrapper & BitArraySegment

Two classes for comfortable bit manipulation in byte arrays.

using System;
using System.Collections;
using System.Collections.Generic;
namespace System
{
public class BitArraySegment : IEnumerable<bool>
{
public BitArrayWrapper Array { get; private set; }
public int Offset { get; private set; }
public int Count { get; private set; }
public BitArraySegment(BitArrayWrapper bit)
: this(bit, 0)
{
}
public BitArraySegment(BitArrayWrapper bit, int offset)
: this(bit, offset, bit.Length - offset)
{
}
public BitArraySegment(BitArrayWrapper bit, int offset, int count)
{
Array = bit;
Offset = offset;
Count = count;
}
public int Length {
get {
return Count;
}
}
public bool Get(int index)
{
return Array[Offset + index];
}
public void Set(int index, bool value)
{
Array[Offset + index] = value;
}
public void Set(BitArraySegment bas)
{
int l = Math.Min(Count, bas.Count);
for (int i = 0; i < l; i++) {
this[i] = bas[i];
}
}
public void Set(BitArrayWrapper bas)
{
Set(bas.Sub(0));
}
public void SetAll(bool value)
{
for (int i = 0; i < Count; i++) {
Set(i, value);
}
}
public bool this[int index] {
get {
return Get(index);
}
set {
Set(index, value);
}
}
public void Not()
{
for (int i = 0; i < Count; i++) {
this[i] = !this[i];
}
}
public void And(BitArraySegment bas)
{
int l = Math.Min(Count, bas.Count);
for (int i = 0; i < l; i++) {
this[i] &= bas[i];
}
}
public void And(BitArrayWrapper bas)
{
And(new BitArraySegment(bas));
}
public void Or(BitArraySegment bas)
{
int l = Math.Min(Count, bas.Count);
for (int i = 0; i < l; i++) {
this[i] |= bas[i];
}
}
public void Or(BitArrayWrapper baw)
{
Or(new BitArraySegment(baw));
}
public void Xor(BitArraySegment bas)
{
int l = Math.Min(Count, bas.Count);
for (int i = 0; i < l; i++) {
this[i] ^= bas[i];
}
}
public void Xor(BitArrayWrapper bas)
{
Xor(new BitArraySegment(bas));
}
public BitArraySegment Sub(int offset)
{
return new BitArraySegment(Array, Offset + offset);
}
public BitArraySegment Sub(int offset, int count)
{
return new BitArraySegment(Array, Offset + offset, count);
}
public BitArraySegment Got(int count)
{
return Sub(0, count);
}
public BitArraySegment this[int offset, int count] {
get {
return Sub(offset, count);
}
}
public IEnumerator<bool> GetEnumerator()
{
for (int i = 0; i < Count; i++) {
yield return this[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
namespace System
{
public class BitArrayWrapper : IEnumerable<bool>
{
static int size = sizeof(byte) * 8;
byte[] data;
public byte[] Data {
get {
return data;
}
}
public BitArrayWrapper(byte[] data)
{
this.data = data;
}
public int Length {
get {
return data.Length * size;
}
}
public bool Get(int index)
{
var i = index / size;
var b = index % size;
return (data[i] & (1 << b)) > 0;
}
public void Set(int index, bool value)
{
var i = index / size;
var b = index % size;
if (value) {
data[i] = (byte)(data[i] | (1 << b));
} else {
data[i] = (byte)(data[i] & (~(1 << b)));
}
}
public void SetAll(bool value)
{
byte val;
if (value) {
val = 0xFF;
} else {
val = 0;
}
int l = Length;
for (int i = 0; i < l; i++) {
data[i] = val;
}
}
public bool this[int index] {
get {
return Get(index);
}
set {
Set(index, value);
}
}
public void Not()
{
int l = data.Length;
for (int i = 0; i < l; i++) {
data[i] = (byte)~data[i];
}
}
public void And(BitArrayWrapper baw)
{
int l = Math.Min(data.Length, baw.data.Length);
for (int i = 0; i < l; i++) {
data[i] &= baw.data[i];
}
}
public void Or(BitArrayWrapper baw)
{
int l = Math.Min(data.Length, baw.data.Length);
for (int i = 0; i < l; i++) {
data[i] |= baw.data[i];
}
}
public void Xor(BitArrayWrapper baw)
{
int l = Math.Min(data.Length, baw.data.Length);
for (int i = 0; i < l; i++) {
data[i] ^= baw.data[i];
}
}
public BitArraySegment Sub(int offset)
{
return new BitArraySegment(this, offset);
}
public BitArraySegment Sub(int offset, int count)
{
return new BitArraySegment(this, offset, count);
}
public BitArraySegment Got(int count)
{
return Sub(0, count);
}
public BitArraySegment this[int offset, int count]
{
get {
return Sub(offset, count);
}
}
public IEnumerator<bool> GetEnumerator()
{
for (int i = 0; i < data.Length; i++) {
byte d = data[i];
for (int j = 0; j < size; j++) {
yield return (d & 1) == 1;
d >>= 1;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
}
using System;
class MainClass
{
public static void Print(BitArrayWrapper wrapper)
{
Print(wrapper.Sub(0));
}
public static void Print(BitArraySegment wrapper)
{
foreach (var val in wrapper) {
Console.Write(val ? 1 : 0);
}
Console.WriteLine();
}
public static void Main(string[] args)
{
var data = new byte[10];
var baw = new BitArrayWrapper(data);
baw[3, 3].Not();
baw[10, 4].Not();
baw[20, 17].Not();
baw.Sub(0).And(baw.Sub(1));
Print(baw);
baw[22, 2].SetAll(false);
baw.Sub(30).Set(baw);
Print(baw);
}
}
all: Main.exe
Main.exe: Main.cs BitArrayWrapper.cs BitArraySegment.cs
gmcs $^
.PHONY: run clean
run: Main.exe
mono Main.exe
clean:
rm Main.exe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment