github.com/bir3/gocompiler@v0.9.2202/extra/compress/huff0/bitreader.go (about)

     1  // Copyright 2018 Klaus Post. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  // Based on work Copyright (c) 2013, Yann Collet, released under BSD License.
     5  
     6  package huff0
     7  
     8  import (
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  )
    14  
    15  // bitReader reads a bitstream in reverse.
    16  // The last set bit indicates the start of the stream and is used
    17  // for aligning the input.
    18  type bitReaderBytes struct {
    19  	in       []byte
    20  	off      uint // next byte to read is at in[off - 1]
    21  	value    uint64
    22  	bitsRead uint8
    23  }
    24  
    25  // init initializes and resets the bit reader.
    26  func (b *bitReaderBytes) init(in []byte) error {
    27  	if len(in) < 1 {
    28  		return errors.New("corrupt stream: too short")
    29  	}
    30  	b.in = in
    31  	b.off = uint(len(in))
    32  	// The highest bit of the last byte indicates where to start
    33  	v := in[len(in)-1]
    34  	if v == 0 {
    35  		return errors.New("corrupt stream, did not find end of stream")
    36  	}
    37  	b.bitsRead = 64
    38  	b.value = 0
    39  	if len(in) >= 8 {
    40  		b.fillFastStart()
    41  	} else {
    42  		b.fill()
    43  		b.fill()
    44  	}
    45  	b.advance(8 - uint8(highBit32(uint32(v))))
    46  	return nil
    47  }
    48  
    49  // peekBitsFast requires that at least one bit is requested every time.
    50  // There are no checks if the buffer is filled.
    51  func (b *bitReaderBytes) peekByteFast() uint8 {
    52  	got := uint8(b.value >> 56)
    53  	return got
    54  }
    55  
    56  func (b *bitReaderBytes) advance(n uint8) {
    57  	b.bitsRead += n
    58  	b.value <<= n & 63
    59  }
    60  
    61  // fillFast() will make sure at least 32 bits are available.
    62  // There must be at least 4 bytes available.
    63  func (b *bitReaderBytes) fillFast() {
    64  	if b.bitsRead < 32 {
    65  		return
    66  	}
    67  
    68  	// 2 bounds checks.
    69  	v := b.in[b.off-4 : b.off]
    70  	low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
    71  	b.value |= uint64(low) << (b.bitsRead - 32)
    72  	b.bitsRead -= 32
    73  	b.off -= 4
    74  }
    75  
    76  // fillFastStart() assumes the bitReaderBytes is empty and there is at least 8 bytes to read.
    77  func (b *bitReaderBytes) fillFastStart() {
    78  	// Do single re-slice to avoid bounds checks.
    79  	b.value = binary.LittleEndian.Uint64(b.in[b.off-8:])
    80  	b.bitsRead = 0
    81  	b.off -= 8
    82  }
    83  
    84  // fill() will make sure at least 32 bits are available.
    85  func (b *bitReaderBytes) fill() {
    86  	if b.bitsRead < 32 {
    87  		return
    88  	}
    89  	if b.off > 4 {
    90  		v := b.in[b.off-4 : b.off]
    91  		low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
    92  		b.value |= uint64(low) << (b.bitsRead - 32)
    93  		b.bitsRead -= 32
    94  		b.off -= 4
    95  		return
    96  	}
    97  	for b.off > 0 {
    98  		b.value |= uint64(b.in[b.off-1]) << (b.bitsRead - 8)
    99  		b.bitsRead -= 8
   100  		b.off--
   101  	}
   102  }
   103  
   104  // finished returns true if all bits have been read from the bit stream.
   105  func (b *bitReaderBytes) finished() bool {
   106  	return b.off == 0 && b.bitsRead >= 64
   107  }
   108  
   109  func (b *bitReaderBytes) remaining() uint {
   110  	return b.off*8 + uint(64-b.bitsRead)
   111  }
   112  
   113  // close the bitstream and returns an error if out-of-buffer reads occurred.
   114  func (b *bitReaderBytes) close() error {
   115  	// Release reference.
   116  	b.in = nil
   117  	if b.remaining() > 0 {
   118  		return fmt.Errorf("corrupt input: %d bits remain on stream", b.remaining())
   119  	}
   120  	if b.bitsRead > 64 {
   121  		return io.ErrUnexpectedEOF
   122  	}
   123  	return nil
   124  }
   125  
   126  // bitReaderShifted reads a bitstream in reverse.
   127  // The last set bit indicates the start of the stream and is used
   128  // for aligning the input.
   129  type bitReaderShifted struct {
   130  	in       []byte
   131  	off      uint // next byte to read is at in[off - 1]
   132  	value    uint64
   133  	bitsRead uint8
   134  }
   135  
   136  // init initializes and resets the bit reader.
   137  func (b *bitReaderShifted) init(in []byte) error {
   138  	if len(in) < 1 {
   139  		return errors.New("corrupt stream: too short")
   140  	}
   141  	b.in = in
   142  	b.off = uint(len(in))
   143  	// The highest bit of the last byte indicates where to start
   144  	v := in[len(in)-1]
   145  	if v == 0 {
   146  		return errors.New("corrupt stream, did not find end of stream")
   147  	}
   148  	b.bitsRead = 64
   149  	b.value = 0
   150  	if len(in) >= 8 {
   151  		b.fillFastStart()
   152  	} else {
   153  		b.fill()
   154  		b.fill()
   155  	}
   156  	b.advance(8 - uint8(highBit32(uint32(v))))
   157  	return nil
   158  }
   159  
   160  // peekBitsFast requires that at least one bit is requested every time.
   161  // There are no checks if the buffer is filled.
   162  func (b *bitReaderShifted) peekBitsFast(n uint8) uint16 {
   163  	return uint16(b.value >> ((64 - n) & 63))
   164  }
   165  
   166  func (b *bitReaderShifted) advance(n uint8) {
   167  	b.bitsRead += n
   168  	b.value <<= n & 63
   169  }
   170  
   171  // fillFast() will make sure at least 32 bits are available.
   172  // There must be at least 4 bytes available.
   173  func (b *bitReaderShifted) fillFast() {
   174  	if b.bitsRead < 32 {
   175  		return
   176  	}
   177  
   178  	// 2 bounds checks.
   179  	v := b.in[b.off-4 : b.off]
   180  	low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
   181  	b.value |= uint64(low) << ((b.bitsRead - 32) & 63)
   182  	b.bitsRead -= 32
   183  	b.off -= 4
   184  }
   185  
   186  // fillFastStart() assumes the bitReaderShifted is empty and there is at least 8 bytes to read.
   187  func (b *bitReaderShifted) fillFastStart() {
   188  	// Do single re-slice to avoid bounds checks.
   189  	b.value = binary.LittleEndian.Uint64(b.in[b.off-8:])
   190  	b.bitsRead = 0
   191  	b.off -= 8
   192  }
   193  
   194  // fill() will make sure at least 32 bits are available.
   195  func (b *bitReaderShifted) fill() {
   196  	if b.bitsRead < 32 {
   197  		return
   198  	}
   199  	if b.off > 4 {
   200  		v := b.in[b.off-4 : b.off]
   201  		low := (uint32(v[0])) | (uint32(v[1]) << 8) | (uint32(v[2]) << 16) | (uint32(v[3]) << 24)
   202  		b.value |= uint64(low) << ((b.bitsRead - 32) & 63)
   203  		b.bitsRead -= 32
   204  		b.off -= 4
   205  		return
   206  	}
   207  	for b.off > 0 {
   208  		b.value |= uint64(b.in[b.off-1]) << ((b.bitsRead - 8) & 63)
   209  		b.bitsRead -= 8
   210  		b.off--
   211  	}
   212  }
   213  
   214  func (b *bitReaderShifted) remaining() uint {
   215  	return b.off*8 + uint(64-b.bitsRead)
   216  }
   217  
   218  // close the bitstream and returns an error if out-of-buffer reads occurred.
   219  func (b *bitReaderShifted) close() error {
   220  	// Release reference.
   221  	b.in = nil
   222  	if b.remaining() > 0 {
   223  		return fmt.Errorf("corrupt input: %d bits remain on stream", b.remaining())
   224  	}
   225  	if b.bitsRead > 64 {
   226  		return io.ErrUnexpectedEOF
   227  	}
   228  	return nil
   229  }