BitStream
BitStream.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace System.IO
{
public class BitStream : Stream
{
Stream stream;
public enum Access
{
Read,
Write,
}
Access access;
public BitStream(Stream stream, Access access)
{
if (stream == null)
{
throw new ArgumentNullException();
}
this.stream = stream;
this.access = access;
read_buffer = 0;
read_buffer_bit_length = 0;
write_buffer = 0;
write_buffer_bit_length = 0;
}
public override bool CanRead
{
get
{
return (access == Access.Read) && stream.CanRead;
}
}
public override bool CanWrite
{
get
{
return (access == Access.Write) && stream.CanWrite;
}
}
public override bool CanSeek => false;
public override long Length => throw new InvalidOperationException();
public override long Position
{
get => throw new InvalidOperationException();
set => throw new InvalidOperationException();
}
public override long Seek(long offset, SeekOrigin origin) => throw new InvalidOperationException();
public override void SetLength(long value) => throw new InvalidOperationException();
public override int Read(byte[] buffer, int offset, int count)
{
return (ReadBit(buffer, offset, count * 8) + 7) / 8;
}
public override void Write(byte[] buffer, int offset, int count)
{
WriteBit(buffer, offset, count * 8);
}
byte[] byte_buffer = new byte[1];
int read_buffer;
int read_buffer_bit_length;
public int ReadBit(byte[] buffer, int offset, int bit_count)
{
if (access != Access.Read)
{
throw new InvalidOperationException();
}
if (bit_count <= 0)
{
if (bit_count == 0)
{
return 0;
}
throw new ArgumentOutOfRangeException();
}
int byte_count = bit_count / 8;
if (read_buffer_bit_length == 0)
{
if (byte_count > 0)
{
int read_count = stream.Read(buffer, offset, byte_count);
if (read_count < byte_count)
{
return 8 * read_count;
}
}
}
else
{
for (int i = 0; i < byte_count; i++)
{
while (read_buffer_bit_length < 8)
{
if (stream.Read(byte_buffer, 0, 1) < 1)
{
int read_count = 8 * i;
if (read_buffer_bit_length > 0)
{
read_count += read_buffer_bit_length;
buffer[offset + i] = (byte)read_buffer;
read_buffer = 0;
read_buffer_bit_length = 0;
}
return read_count;
}
read_buffer |= ((int)byte_buffer[0]) << read_buffer_bit_length;
read_buffer_bit_length += 8;
}
buffer[offset + i] = (byte)read_buffer;
read_buffer >>= 8;
read_buffer_bit_length -= 8;
}
}
int remain = bit_count % 8;
if (remain != 0)
{
while (read_buffer_bit_length < remain)
{
if (stream.Read(byte_buffer, 0, 1) < 1)
{
int read_count = 8 * byte_count;
if (read_buffer_bit_length > 0)
{
read_count += read_buffer_bit_length;
buffer[offset + byte_count] = (byte)read_buffer;
read_buffer = 0;
read_buffer_bit_length = 0;
}
return read_count;
}
read_buffer |= ((int)byte_buffer[0]) << read_buffer_bit_length;
read_buffer_bit_length += 8;
}
buffer[offset + byte_count] = (byte)(read_buffer & ((1 << remain) - 1));
read_buffer >>= remain;
read_buffer_bit_length -= remain;
}
return bit_count;
}
int write_buffer;
int write_buffer_bit_length;
public void WriteBit(byte[] buffer, int offset, int bit_count)
{
if (access != Access.Write)
{
throw new InvalidOperationException();
}
if (bit_count <= 0)
{
if (bit_count == 0)
{
return;
}
throw new ArgumentOutOfRangeException();
}
int byte_count = bit_count / 8;
if (write_buffer_bit_length == 0)
{
if (byte_count > 0)
{
stream.Write(buffer, offset, byte_count);
}
}
else
{
for (int i = 0; i < byte_count; i++)
{
write_buffer |= buffer[offset + i] << write_buffer_bit_length;
write_buffer_bit_length += 8;
while (write_buffer_bit_length >= 8)
{
byte_buffer[0] = (byte)write_buffer;
stream.Write(byte_buffer, 0, 1);
write_buffer >>= 8;
write_buffer_bit_length -= 8;
}
}
}
int remain = bit_count % 8;
if (remain != 0)
{
write_buffer |= buffer[offset + byte_count] << write_buffer_bit_length;
write_buffer_bit_length += remain;
while (write_buffer_bit_length >= 8)
{
byte_buffer[0] = (byte)write_buffer;
stream.Write(byte_buffer, 0, 1);
write_buffer >>= 8;
write_buffer_bit_length -= 8;
}
}
}
public override void Flush()
{
if (access == Access.Write)
{
if (write_buffer_bit_length > 0)
{
while (write_buffer_bit_length >= 8)
{
byte_buffer[0] = (byte)write_buffer;
stream.Write(byte_buffer, 0, 1);
write_buffer >>= 8;
write_buffer_bit_length -= 8;
}
if (write_buffer_bit_length > 0)
{
byte_buffer[0] = (byte)write_buffer;
stream.Write(byte_buffer, 0, 1);
write_buffer = 0;
write_buffer_bit_length = 0;
}
}
}
}
public override void Close()
{
if (access == Access.Write)
{
Flush();
}
base.Close();
}
public static int GetNecessaryBitLength(int value)
{
if (value <= 0)
{
if (value == 0)
{
return 1;
}
return 32;
}
int i = 31;
int bit = 0x40000000;
while (true)
{
if ((value & bit) != 0)
{
return i;
}
bit >>= 1;
i--;
}
}
public static int GetNecessaryBitLength(Int64 value)
{
if (value <= 0)
{
if (value == 0)
{
return 1;
}
return 64;
}
int i = 63;
Int64 bit = 0x4000000000000000L;
while (true)
{
if ((value & bit) != 0)
{
return i;
}
bit >>= 1;
i--;
}
}
public static int RestrictBitLength(int value, int bit_length)
{
if (bit_length <= 0 || bit_length >= 32)
{
if (bit_length == 0)
{
return 0;
}
if (bit_length == 32)
{
return value;
}
throw new ArgumentOutOfRangeException();
}
return value & ((1 << bit_length) - 1);
}
public static Int64 RestrictBitLength(Int64 value, int bit_length)
{
if (bit_length <= 0 || bit_length >= 64)
{
if (bit_length == 0)
{
return 0;
}
if (bit_length == 64)
{
return value;
}
throw new ArgumentOutOfRangeException();
}
return value & ((1L << bit_length) - 1);
}
}
}