95 lines
1.9 KiB
Nim
95 lines
1.9 KiB
Nim
type
|
|
BitWriter * = tuple
|
|
file: File
|
|
bits: uint8
|
|
nRemain: int
|
|
|
|
BitReader * = tuple
|
|
file: File
|
|
bits: uint8
|
|
nRemain: int
|
|
nRead: int
|
|
|
|
proc newBitWriter * (file: File) : ref BitWriter =
|
|
result = new BitWriter
|
|
result.file = file
|
|
result.bits = 0
|
|
result.nRemain = 8
|
|
|
|
proc flushBits (stream : ref BitWriter) =
|
|
discard stream.file.writeBuffer(stream.bits.addr, 1)
|
|
stream.nRemain = 8
|
|
stream.bits = 0
|
|
|
|
proc write * (stream: ref BitWriter, bits: uint8, nBits: int) =
|
|
assert(nBits <= 8)
|
|
|
|
for ii in countdown((nBits - 1), 0) :
|
|
stream.bits = (stream.bits shl 1) or ((bits shr ii) and 1)
|
|
stream.nRemain.dec(1)
|
|
if stream.nRemain == 0:
|
|
stream.flushBits
|
|
|
|
proc flush * (stream: ref BitWriter) =
|
|
if stream.nRemain < 8:
|
|
stream.bits = stream.bits shl stream.nRemain
|
|
stream.flushBits
|
|
|
|
proc newBitReader * (file: File) : ref BitReader =
|
|
result = new BitReader
|
|
result.file = file
|
|
result.bits = 0
|
|
result.nRemain = 0
|
|
result.nRead = 0
|
|
|
|
proc read * (stream: ref BitReader, nBits: int) : uint8 =
|
|
assert(nBits <= 8)
|
|
|
|
result = 0
|
|
for ii in 0 .. < nBits :
|
|
if stream.nRemain == 0:
|
|
stream.nRead = stream.file.readBuffer(stream.bits.addr, 1)
|
|
if stream.nRead == 0:
|
|
break
|
|
stream.nRemain = 8
|
|
|
|
result = (result shl 1) or ((stream.bits shr 7) and 1)
|
|
|
|
stream.bits = stream.bits shl 1
|
|
stream.nRemain.dec(1)
|
|
|
|
|
|
when isMainModule:
|
|
var
|
|
file: File
|
|
writer: ref BitWriter
|
|
reader: ref BitReader
|
|
|
|
file = open("testfile.dat", fmWrite)
|
|
writer = newBitWriter(file)
|
|
|
|
for ii in 0 .. 255:
|
|
writer.write(ii.uint8, 7)
|
|
|
|
writer.flush
|
|
file.close
|
|
|
|
var dataCtr = 0
|
|
|
|
file = open("testfile.dat", fmRead)
|
|
reader = newBitReader(file)
|
|
|
|
while true:
|
|
let aByte = reader.read(7)
|
|
|
|
if reader.nRead == 0:
|
|
break
|
|
|
|
assert((dataCtr and 0x7f).uint8 == aByte)
|
|
|
|
assert(dataCtr == 256)
|
|
|
|
file.close
|
|
|
|
echo "OK"
|