60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package compression
|
|
|
|
import "github.com/inkyblackness/hacked/ss1/serial"
|
|
|
|
// WordWriter serializes a stream of word entries.
|
|
type WordWriter struct {
|
|
coder serial.Coder
|
|
|
|
bufferedBits uint
|
|
scratch uint32
|
|
|
|
outBuffer [1024]byte
|
|
outUsed int
|
|
}
|
|
|
|
// NewWordWriter returns a new instance.
|
|
func NewWordWriter(coder serial.Coder) *WordWriter {
|
|
writer := &WordWriter{coder: coder, bufferedBits: 0, scratch: 0}
|
|
|
|
return writer
|
|
}
|
|
|
|
// Close finishes the stream of words.
|
|
func (writer *WordWriter) Close() {
|
|
writer.Write(EndOfStream)
|
|
if writer.bufferedBits > 0 {
|
|
writer.writeByte(byte(writer.scratch >> 16))
|
|
}
|
|
writer.writeByte(byte(0x00))
|
|
writer.flushBuffer()
|
|
}
|
|
|
|
// Write adds the given word to the stream.
|
|
func (writer *WordWriter) Write(value Word) {
|
|
writer.scratch |= uint32(value) << ((16 - bitsPerWord) + (8 - writer.bufferedBits))
|
|
writer.bufferedBits += bitsPerWord
|
|
writer.writeByte(byte(writer.scratch >> 16))
|
|
writer.scratch <<= 8
|
|
writer.bufferedBits -= 8
|
|
|
|
if writer.bufferedBits >= 8 {
|
|
writer.writeByte(byte(writer.scratch >> 16))
|
|
writer.scratch <<= 8
|
|
writer.bufferedBits -= 8
|
|
}
|
|
}
|
|
|
|
func (writer *WordWriter) writeByte(value byte) {
|
|
writer.outBuffer[writer.outUsed] = value
|
|
writer.outUsed++
|
|
if writer.outUsed >= len(writer.outBuffer) {
|
|
writer.flushBuffer()
|
|
}
|
|
}
|
|
|
|
func (writer *WordWriter) flushBuffer() {
|
|
writer.coder.Code(writer.outBuffer[:writer.outUsed])
|
|
writer.outUsed = 0
|
|
}
|