blob: ec71f7a349a14bf014ace41f0fb43582cba209ea [file] [log] [blame]
khenaidoo7d3c5582021-08-11 18:09:44 -04001// 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
6package huff0
7
khenaidoo7d3c5582021-08-11 18:09:44 -04008// bitWriter will write bits.
9// First bit will be LSB of the first byte of output.
10type bitWriter struct {
11 bitContainer uint64
12 nBits uint8
13 out []byte
14}
15
16// bitMask16 is bitmasks. Has extra to avoid bounds check.
17var bitMask16 = [32]uint16{
18 0, 1, 3, 7, 0xF, 0x1F,
19 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF,
20 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0xFFFF,
21 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
22 0xFFFF, 0xFFFF} /* up to 16 bits */
23
khenaidoo7d3c5582021-08-11 18:09:44 -040024// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
25// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
26func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
27 b.bitContainer |= uint64(value) << (b.nBits & 63)
28 b.nBits += bits
29}
30
31// encSymbol will add up to 16 bits. value may not contain more set bits than indicated.
32// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
33func (b *bitWriter) encSymbol(ct cTable, symbol byte) {
34 enc := ct[symbol]
35 b.bitContainer |= uint64(enc.val) << (b.nBits & 63)
36 if false {
37 if enc.nBits == 0 {
38 panic("nbits 0")
39 }
40 }
41 b.nBits += enc.nBits
42}
43
44// encTwoSymbols will add up to 32 bits. value may not contain more set bits than indicated.
45// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
46func (b *bitWriter) encTwoSymbols(ct cTable, av, bv byte) {
47 encA := ct[av]
48 encB := ct[bv]
49 sh := b.nBits & 63
50 combined := uint64(encA.val) | (uint64(encB.val) << (encA.nBits & 63))
51 b.bitContainer |= combined << sh
52 if false {
53 if encA.nBits == 0 {
54 panic("nbitsA 0")
55 }
56 if encB.nBits == 0 {
57 panic("nbitsB 0")
58 }
59 }
60 b.nBits += encA.nBits + encB.nBits
61}
62
khenaidoo7d3c5582021-08-11 18:09:44 -040063// flush32 will flush out, so there are at least 32 bits available for writing.
64func (b *bitWriter) flush32() {
65 if b.nBits < 32 {
66 return
67 }
68 b.out = append(b.out,
69 byte(b.bitContainer),
70 byte(b.bitContainer>>8),
71 byte(b.bitContainer>>16),
72 byte(b.bitContainer>>24))
73 b.nBits -= 32
74 b.bitContainer >>= 32
75}
76
77// flushAlign will flush remaining full bytes and align to next byte boundary.
78func (b *bitWriter) flushAlign() {
79 nbBytes := (b.nBits + 7) >> 3
80 for i := uint8(0); i < nbBytes; i++ {
81 b.out = append(b.out, byte(b.bitContainer>>(i*8)))
82 }
83 b.nBits = 0
84 b.bitContainer = 0
85}
86
87// close will write the alignment bit and write the final byte(s)
88// to the output.
89func (b *bitWriter) close() error {
90 // End mark
91 b.addBits16Clean(1, 1)
92 // flush until next byte.
93 b.flushAlign()
94 return nil
95}