Files
cuetools.net/CUETools.Codecs.FLAKE/BitWriter.cs
2009-08-20 04:09:53 +00:00

180 lines
3.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
namespace CUETools.Codecs.FLAKE
{
class BitWriter
{
uint bit_buf;
int bit_left;
byte[] buffer;
int buf_start, buf_ptr, buf_end;
bool eof;
public BitWriter(byte[] buf, int pos, int len)
{
buffer = buf;
buf_start = pos;
buf_ptr = pos;
buf_end = pos + len;
bit_left = 32;
bit_buf = 0;
eof = false;
}
public void writebits_signed(int bits, int val)
{
writebits(bits, val & ((1 << bits) - 1));
}
public void writebits_signed(uint bits, int val)
{
writebits((int) bits, val & ((1 << (int) bits) - 1));
}
public void writebits(int bits, int val)
{
writebits(bits, (uint)val);
}
public void writebits64(int bits, ulong val)
{
if (bits > 32)
{
writebits(bits - 32, (uint)(val >> 32));
val &= 0xffffffffL;
bits = 32;
}
writebits(bits, (uint)val);
}
public void writebits(int bits, uint val)
{
//assert(bits == 32 || val < (1U << bits));
if (bits == 0 || eof) return;
if ((buf_ptr + 3) >= buf_end)
{
eof = true;
return;
}
if (bits < bit_left)
{
bit_buf = (bit_buf << bits) | val;
bit_left -= bits;
}
else
{
uint bb = 0;
if (bit_left == 32)
{
//assert(bits == 32);
bb = val;
}
else
{
bb = (bit_buf << bit_left) | (val >> (bits - bit_left));
bit_left += (32 - bits);
}
if (buffer != null)
{
buffer[buf_ptr + 3] = (byte)(bb & 0xFF); bb >>= 8;
buffer[buf_ptr + 2] = (byte)(bb & 0xFF); bb >>= 8;
buffer[buf_ptr + 1] = (byte)(bb & 0xFF); bb >>= 8;
buffer[buf_ptr + 0] = (byte)(bb & 0xFF);
}
buf_ptr += 4;
bit_buf = val;
}
}
public void write_utf8(int val)
{
write_utf8((uint)val);
}
public void write_utf8(uint val)
{
if (val < 0x80)
{
writebits(8, val);
return;
}
int bytes = (Flake.log2i(val) + 4) / 5;
int shift = (bytes - 1) * 6;
writebits(8, (256U - (256U >> bytes)) | (val >> shift));
while (shift >= 6)
{
shift -= 6;
writebits(8, 0x80 | ((val >> shift) & 0x3F));
}
}
public void write_unary_signed(int val)
{
// convert signed to unsigned
int v = -2 * val - 1;
v ^= (v >> 31);
// write quotient in unary
int q = v + 1;
while (q > 31)
{
writebits(31, 0);
q -= 31;
}
writebits(q, 1);
}
public void write_rice_signed(int k, int val)
{
int v, q;
// convert signed to unsigned
v = -2 * val - 1;
v ^= (v >> 31);
// write quotient in unary
q = (v >> k) + 1;
while (q > 31)
{
writebits(31, 0);
q -= 31;
}
writebits(q, 1);
// write write remainder in binary using 'k' bits
writebits(k, v & ((1 << k) - 1));
}
public void flush()
{
bit_buf <<= bit_left;
while (bit_left < 32 && !eof)
{
if (buf_ptr >= buf_end)
{
eof = true;
break;
}
if (buffer != null)
buffer[buf_ptr] = (byte)(bit_buf >> 24);
buf_ptr++;
bit_buf <<= 8;
bit_left += 8;
}
bit_left = 32;
bit_buf = 0;
}
public int Length
{
get
{
return buf_ptr - buf_start;
}
}
}
}