146 lines
2.9 KiB
C#
146 lines
2.9 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
public class BitReader
|
|
{
|
|
uint readData = 0;
|
|
int startPosition = 0;
|
|
int endPosition = 0;
|
|
|
|
public int InBuffer
|
|
{
|
|
get { return endPosition - startPosition; }
|
|
}
|
|
|
|
private Stream stream;
|
|
|
|
public Stream BaseStream
|
|
{
|
|
get { return stream; }
|
|
}
|
|
|
|
public BitReader(Stream stream)
|
|
{
|
|
this.stream = stream;
|
|
}
|
|
|
|
void EnsureData(int bitCount)
|
|
{
|
|
int readBits = bitCount - InBuffer;
|
|
while (readBits > 0)
|
|
{
|
|
int b = BaseStream.ReadByte();
|
|
|
|
if (b < 0) throw new InvalidOperationException("Unexpected end of stream");
|
|
|
|
readData |= checked((uint)b << endPosition);
|
|
endPosition += 8;
|
|
readBits -= 8;
|
|
}
|
|
}
|
|
|
|
public bool ReadBit()
|
|
{
|
|
return Read(1) > 0;
|
|
}
|
|
|
|
public int Read(int bitCount)
|
|
{
|
|
EnsureData(bitCount);
|
|
|
|
int result = (int)(readData >> startPosition) & ((1 << bitCount) - 1);
|
|
startPosition += bitCount;
|
|
if (endPosition == startPosition)
|
|
{
|
|
endPosition = startPosition = 0;
|
|
readData = 0;
|
|
}
|
|
else if (startPosition >= 8)
|
|
{
|
|
readData >>= startPosition;
|
|
endPosition -= startPosition;
|
|
startPosition = 0;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
public void Align()
|
|
{
|
|
endPosition = startPosition = 0;
|
|
readData = 0;
|
|
}
|
|
}
|
|
|
|
public class BitWriter
|
|
{
|
|
uint data = 0;
|
|
int dataLength = 0;
|
|
Stream stream;
|
|
|
|
public Stream BaseStream
|
|
{
|
|
get { return stream; }
|
|
}
|
|
|
|
public int BitsToAligment
|
|
{
|
|
get { return (32 - dataLength) % 8; }
|
|
}
|
|
|
|
public BitWriter(Stream stream)
|
|
{
|
|
this.stream = stream;
|
|
}
|
|
|
|
public void WriteBit(bool value)
|
|
{
|
|
Write(value ? 1 : 0, 1);
|
|
}
|
|
|
|
public void Write(int value, int length)
|
|
{
|
|
uint currentData = data | checked((uint)value << dataLength);
|
|
int currentLength = dataLength + length;
|
|
while (currentLength >= 8)
|
|
{
|
|
BaseStream.WriteByte((byte)currentData);
|
|
currentData >>= 8;
|
|
currentLength -= 8;
|
|
}
|
|
data = currentData;
|
|
dataLength = currentLength;
|
|
}
|
|
|
|
public void Align()
|
|
{
|
|
if (dataLength > 0)
|
|
{
|
|
BaseStream.WriteByte((byte)data);
|
|
|
|
data = 0;
|
|
dataLength = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
class Program
|
|
{
|
|
static void Main(string[] args)
|
|
{
|
|
MemoryStream ms = new MemoryStream();
|
|
BitWriter writer = new BitWriter(ms);
|
|
writer.WriteBit(true);
|
|
writer.Write(5, 3);
|
|
writer.Write(0x0155, 11);
|
|
writer.Align();
|
|
|
|
ms.Position = 0;
|
|
BitReader reader = new BitReader(ms);
|
|
Console.WriteLine(reader.ReadBit());
|
|
Console.WriteLine(reader.Read(3));
|
|
Console.WriteLine(reader.Read(11).ToString("x4"));
|
|
reader.Align();
|
|
}
|
|
}
|