aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/compress/bzip2/bit_reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/compress/bzip2/bit_reader.go')
-rw-r--r--libgo/go/compress/bzip2/bit_reader.go88
1 files changed, 88 insertions, 0 deletions
diff --git a/libgo/go/compress/bzip2/bit_reader.go b/libgo/go/compress/bzip2/bit_reader.go
new file mode 100644
index 0000000..50f0ec8
--- /dev/null
+++ b/libgo/go/compress/bzip2/bit_reader.go
@@ -0,0 +1,88 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package bzip2
+
+import (
+ "bufio"
+ "io"
+ "os"
+)
+
+// bitReader wraps an io.Reader and provides the ability to read values,
+// bit-by-bit, from it. Its Read* methods don't return the usual os.Error
+// because the error handling was verbose. Instead, any error is kept and can
+// be checked afterwards.
+type bitReader struct {
+ r byteReader
+ n uint64
+ bits uint
+ err os.Error
+}
+
+// bitReader needs to read bytes from an io.Reader. We attempt to cast the
+// given io.Reader to this interface and, if it doesn't already fit, we wrap in
+// a bufio.Reader.
+type byteReader interface {
+ ReadByte() (byte, os.Error)
+}
+
+func newBitReader(r io.Reader) bitReader {
+ byter, ok := r.(byteReader)
+ if !ok {
+ byter = bufio.NewReader(r)
+ }
+ return bitReader{r: byter}
+}
+
+// ReadBits64 reads the given number of bits and returns them in the
+// least-significant part of a uint64. In the event of an error, it returns 0
+// and the error can be obtained by calling Error().
+func (br *bitReader) ReadBits64(bits uint) (n uint64) {
+ for bits > br.bits {
+ b, err := br.r.ReadByte()
+ if err == os.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ if err != nil {
+ br.err = err
+ return 0
+ }
+ br.n <<= 8
+ br.n |= uint64(b)
+ br.bits += 8
+ }
+
+ // br.n looks like this (assuming that br.bits = 14 and bits = 6):
+ // Bit: 111111
+ // 5432109876543210
+ //
+ // (6 bits, the desired output)
+ // |-----|
+ // V V
+ // 0101101101001110
+ // ^ ^
+ // |------------|
+ // br.bits (num valid bits)
+ //
+ // This the next line right shifts the desired bits into the
+ // least-significant places and masks off anything above.
+ n = (br.n >> (br.bits - bits)) & ((1 << bits) - 1)
+ br.bits -= bits
+ return
+}
+
+func (br *bitReader) ReadBits(bits uint) (n int) {
+ n64 := br.ReadBits64(bits)
+ return int(n64)
+}
+
+func (br *bitReader) ReadBit() bool {
+ n := br.ReadBits(1)
+ return n != 0
+}
+
+func (br *bitReader) Error() os.Error {
+ return br.err
+}