gonna need this bit twiddling thing

master
Jordan Orelli 8 years ago
parent 0645f224a9
commit 9b4075c881

@ -0,0 +1,51 @@
package main
import (
"io"
)
// a bitBuffer is a buffer of raw data that is not necessarily byte-aligned,
// for performing bitwise reads and manipulation. The bulk of this source is
// adapted from the bitReader defined in the standard library bzip2 package.
type bitBuffer struct {
source []byte // the source data to be read. This slice is never modified
index int // position of the last byte read out of source
scratch uint64 // scratch register of bits worthy of manipulation
bits uint // bit width of the scratch register
err error // stored error
}
func newBitBuffer(buf []byte) *bitBuffer {
return &bitBuffer{source: buf}
}
func (b *bitBuffer) readBits(bits uint) uint64 {
for bits > b.bits {
if b.index >= len(b.source) {
b.err = io.ErrUnexpectedEOF
return 0
}
b.scratch <<= 8
b.scratch |= uint64(b.source[b.index])
b.index += 1
b.bits += 8
}
// b.scratch looks like this (assuming that b.bits = 14 and bits = 6):
// Bit: 111111
// 5432109876543210
//
// (6 bits, the desired output)
// |-----|
// V V
// 0101101101001110
// ^ ^
// |------------|
// b.bits (num valid bits)
//
// This the next line right shifts the desired bits into the
// least-significant places and masks off anything above.
n := (b.scratch >> (b.bits - bits)) & ((1 << bits) - 1)
b.bits -= bits
return n
}

@ -0,0 +1,37 @@
package main
import (
"io"
"testing"
)
func TestBits(t *testing.T) {
buf := []byte{0x00}
bb := newBitBuffer(buf)
for i := 0; i < 8; i++ {
if bb.readBits(1) != 0x00 {
t.Error("hahha what")
}
if bb.err != nil {
t.Errorf("oh weird error: %v", bb.err)
}
}
if bb.readBits(1) != 0x00 {
t.Error("hahha what")
}
if bb.err != io.ErrUnexpectedEOF {
t.Errorf("oh weird error: %v", bb.err)
}
buf = []byte{0x10}
bb = newBitBuffer(buf)
if n := bb.readBits(4); n != 0x01 {
t.Errorf("shit. wanted %v, got %v", 0x01, n)
}
if n := bb.readBits(4); n != 0x00 {
t.Errorf("poop. wanted %v, got %v", 0x00, n)
}
if bb.err != nil {
t.Errorf("fuck")
}
}

@ -154,8 +154,10 @@ func (p *parser) readMessage() (*message, error) {
if _, err := io.ReadFull(p.source, buf); err != nil { if _, err := io.ReadFull(p.source, buf); err != nil {
return nil, wrap(err, "readMessage couldn't read message body") return nil, wrap(err, "readMessage couldn't read message body")
} }
// TODO: pool these!
return &message{cmd, int64(tick), compressed, buf}, nil return &message{cmd, int64(tick), compressed, buf}, nil
} }
// TODO: pool these!
return &message{cmd, int64(tick), compressed, nil}, nil return &message{cmd, int64(tick), compressed, nil}, nil
} }

Loading…
Cancel
Save