github.com/tunabay/go-bitarray@v1.3.1/reader.go (about)

     1  // Copyright (c) 2021 Hirotsuna Mizuno. All rights reserved.
     2  // Use of this source code is governed by the MIT license that can be found in
     3  // the LICENSE file.
     4  
     5  package bitarray
     6  
     7  import (
     8  	"io"
     9  )
    10  
    11  // Reader implements io.Reader and io.ByteReader interfaces by reading from a
    12  // BitArray.
    13  //
    14  // The standard io.Reader family interfaces define byte-oriented reading
    15  // methods, rather than bit-oriented. And they always read in bytes and cannot
    16  // read fractional bits less than 8 bits. When the number of remaining available
    17  // bits is not a multiple of 8, the io.EOF may be reached with fractional bits
    18  // remaining. In this case, the padding bits are not added automatically and an
    19  // ErrFractionalBitsBeforeEOF is returned. To handle these trailing fractional
    20  // bits, use bit-oriented reads together, or use ToPadded8 etc in advance to
    21  // make sure that the number of bits in the source is a multiple of 8 bits.
    22  type Reader struct {
    23  	ba *BitArray
    24  	i  int
    25  }
    26  
    27  // NewReader returns a new Reader reading from the bit array ba. For mutable
    28  // types of ba, the value at the time NewReader is called is copied and
    29  // subsequent changes will not be reflected in future readings.
    30  func NewReader(ba BitArrayer) *Reader {
    31  	if ba == nil {
    32  		return &Reader{ba: zeroBitArray}
    33  	}
    34  
    35  	return &Reader{ba: ba.BitArray()}
    36  }
    37  
    38  // Reset resets the Reader to be reading from ba.
    39  func (r *Reader) Reset(ba BitArrayer) {
    40  	if ba == nil {
    41  		r.ba = zeroBitArray
    42  	} else {
    43  		r.ba = ba.BitArray()
    44  	}
    45  	r.i = 0
    46  }
    47  
    48  // Read implements the io.Reader interface. It reads up to 8 * len(p) bits from
    49  // the underlying BitArray, writes them to p as bytes, and returns the number of
    50  // bytes read. It always reads in bytes, and if only fractional bits less than 8
    51  // bits are available, it returns an ErrFractionalBitsBeforeEOF.
    52  func (r *Reader) Read(p []byte) (int, error) {
    53  	switch {
    54  	case r.ba.IsZero(), r.ba.nBits <= r.i:
    55  		return 0, io.EOF
    56  	case r.ba.nBits-8 < r.i:
    57  		return 0, ErrFractionalBitsBeforeEOF
    58  	}
    59  	nBytes := len(p)
    60  	if n := (r.ba.Len() - r.i) >> 3; n < nBytes {
    61  		nBytes = n
    62  	}
    63  	switch {
    64  	case nBytes == 0:
    65  		return 0, nil
    66  	case r.ba.b == nil:
    67  		fill00(p[:nBytes])
    68  		r.i += nBytes << 3
    69  		return nBytes, nil
    70  	}
    71  	_ = copyBits(p[:nBytes], r.ba.b, 0, r.i, nBytes<<3)
    72  	r.i += nBytes << 3
    73  	return nBytes, nil
    74  }
    75  
    76  // ReadByte implements the io.ByteReader interface. It reads 8 bits from the
    77  // underlying BitArray and returns them as a byte. If only fractional bits less
    78  // than 8 bits are available, it returns an ErrFractionalBitsBeforeEOF.
    79  func (r *Reader) ReadByte() (byte, error) {
    80  	switch {
    81  	case r.ba.IsZero(), r.ba.nBits <= r.i:
    82  		return 0, io.EOF
    83  	case r.ba.nBits-8 < r.i:
    84  		return 0, ErrFractionalBitsBeforeEOF
    85  	}
    86  	if r.ba.b == nil {
    87  		r.i += 8
    88  		return 0, nil
    89  	}
    90  	b := make([]byte, 1)
    91  	_ = copyBits(b, r.ba.b, 0, r.i, 8)
    92  	r.i += 8
    93  	return b[0], nil
    94  }
    95  
    96  // ReadBitArray reads up to nBits bits as a BitArray. The returned BitArray may
    97  // be shorter than nBits. The caller should check the length of the returned
    98  // bit array and handle it.
    99  func (r *Reader) ReadBitArray(nBits int) (*BitArray, error) {
   100  	switch {
   101  	case nBits < 0:
   102  		panicf("ReadBitArray: negative nBits %d.", nBits)
   103  	case nBits == 0:
   104  		return zeroBitArray, nil
   105  	case r.ba.IsZero(), r.ba.nBits <= r.i:
   106  		return zeroBitArray, io.EOF
   107  	}
   108  	if n := r.ba.nBits - r.i; n < nBits {
   109  		nBits = n
   110  	}
   111  	ba := r.ba.Slice(r.i, r.i+nBits)
   112  	r.i += nBits
   113  
   114  	return ba, nil
   115  }
   116  
   117  // ReadBit reads a single bit as 0 or 1.
   118  func (r *Reader) ReadBit() (byte, error) {
   119  	if r.ba.IsZero() || r.ba.nBits <= r.i {
   120  		return 0, io.EOF
   121  	}
   122  	if r.ba.b == nil {
   123  		r.i++
   124  		return 0, nil
   125  	}
   126  	b := r.ba.b[r.i>>3] >> (7 - r.i&7) & 1
   127  	r.i++
   128  	return b, nil
   129  }
   130  
   131  // ReadBits reads up to p.Len() bits into p. It returns the number of bits read
   132  // (0 <= n <= p.Len()) and any error encountered. The data in the buffer beyond
   133  // the returned length is undefined.
   134  func (r *Reader) ReadBits(p *Buffer) (int, error) {
   135  	nBits := p.Len()
   136  	switch {
   137  	case nBits == 0:
   138  		return 0, nil
   139  	case r.ba.IsZero(), r.ba.nBits <= r.i:
   140  		return 0, io.EOF
   141  	}
   142  	if n := r.ba.nBits - r.i; n < nBits {
   143  		nBits = n
   144  	}
   145  	if r.ba.b == nil {
   146  		clearBits(p.b, 0, nBits)
   147  	} else {
   148  		_ = copyBits(p.b, r.ba.b, 0, r.i, nBits)
   149  	}
   150  	r.i += nBits
   151  
   152  	return nBits, nil
   153  }
   154  
   155  /*
   156  // TODO:
   157  // WriteTo implements the io.WriterTo interface.
   158  func (r *Reader) WriteTo(w io.Writer) (int64, error) {}
   159  */