Two classes for comfortable bit manipulation in byte arrays.
Created
November 7, 2012 15:38
-
-
Save txdv/4032303 to your computer and use it in GitHub Desktop.
Bit manipulation classes for C#
This file contains hidden or 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; | |
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(); | |
} | |
} | |
} |
This file contains hidden or 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; | |
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(); | |
} | |
} | |
} |
This file contains hidden or 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; | |
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); | |
} | |
} |
This file contains hidden or 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
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