mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
- Remove `[?]` syntax. - Change `int!` to `int?` syntax. - New `fault` declarations. - Enum associated values can reference the calling enum.
94 lines
1.7 KiB
Plaintext
94 lines
1.7 KiB
Plaintext
module std::io;
|
|
|
|
struct BitReader
|
|
{
|
|
InStream reader;
|
|
uint bits;
|
|
uint len;
|
|
}
|
|
|
|
fn void BitReader.init(&self, InStream byte_reader)
|
|
{
|
|
*self = { .reader = byte_reader };
|
|
}
|
|
|
|
fn void BitReader.clear(&self) @inline
|
|
{
|
|
self.len = 0;
|
|
}
|
|
|
|
<*
|
|
@require nbits <= 8
|
|
@require self.len + nbits <= uint.sizeof * 8
|
|
*>
|
|
fn char? BitReader.read_bits(&self, uint nbits)
|
|
{
|
|
uint bits = self.bits;
|
|
if (self.len < nbits)
|
|
{
|
|
// New bits are pushed right.
|
|
char c = self.reader.read_byte()!;
|
|
bits <<= 8;
|
|
bits |= c;
|
|
self.bits = bits;
|
|
self.len += 8;
|
|
}
|
|
self.len -= nbits;
|
|
uint mask = (1 << nbits) - 1;
|
|
return (char)((bits >> self.len) & mask);
|
|
}
|
|
|
|
struct BitWriter
|
|
{
|
|
OutStream writer;
|
|
uint bits;
|
|
uint len;
|
|
}
|
|
|
|
// c3 doesn't allow to shift more than bit width of a variable,
|
|
// so use closest byte boundary of 24 instead of 32
|
|
const int WRITER_BITS = 24;
|
|
|
|
fn void BitWriter.init(&self, OutStream byte_writer)
|
|
{
|
|
*self = { .writer = byte_writer };
|
|
}
|
|
|
|
fn void? BitWriter.flush(&self)
|
|
{
|
|
if (self.len == 0) return;
|
|
|
|
int padding = ($sizeof(self.bits) * 8 - self.len);
|
|
uint bits = self.bits << padding;
|
|
uint n = (self.len + 7) / 8;
|
|
char[4] buffer;
|
|
bitorder::write(bits, &buffer, UIntBE);
|
|
io::write_all(self.writer, buffer[:n])!;
|
|
self.len = 0;
|
|
}
|
|
|
|
<*
|
|
@require nbits <= 32
|
|
*>
|
|
fn void? BitWriter.write_bits(&self, uint bits, uint nbits)
|
|
{
|
|
if (nbits == 0) return;
|
|
while (self.len + nbits > WRITER_BITS)
|
|
{
|
|
uint to_push = WRITER_BITS - self.len;
|
|
uint bits_to_push = (bits >> (nbits - to_push)) & ((1 << to_push) - 1);
|
|
|
|
self.bits <<= to_push;
|
|
self.bits |= bits_to_push;
|
|
self.len += to_push;
|
|
nbits -= to_push;
|
|
|
|
self.flush()!;
|
|
}
|
|
|
|
if (nbits == 0) return;
|
|
|
|
self.bits <<= nbits;
|
|
self.bits |= bits & ((1 << nbits) - 1);
|
|
self.len += nbits;
|
|
} |