blob: 78b3c61be3ecd3a00cb781d6dc8dbc15e736f457 [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 zstd
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
24var bitMask32 = [32]uint32{
25 0, 1, 3, 7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF,
26 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,
27 0x1ffff, 0x3ffff, 0x7FFFF, 0xfFFFF, 0x1fFFFF, 0x3fFFFF, 0x7fFFFF, 0xffFFFF,
28 0x1ffFFFF, 0x3ffFFFF, 0x7ffFFFF, 0xfffFFFF, 0x1fffFFFF, 0x3fffFFFF, 0x7fffFFFF,
29} // up to 32 bits
30
31// addBits16NC will add up to 16 bits.
32// It will not check if there is space for them,
33// so the caller must ensure that it has flushed recently.
34func (b *bitWriter) addBits16NC(value uint16, bits uint8) {
35 b.bitContainer |= uint64(value&bitMask16[bits&31]) << (b.nBits & 63)
36 b.nBits += bits
37}
38
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053039// addBits32NC will add up to 31 bits.
khenaidoo7d3c5582021-08-11 18:09:44 -040040// It will not check if there is space for them,
41// so the caller must ensure that it has flushed recently.
42func (b *bitWriter) addBits32NC(value uint32, bits uint8) {
43 b.bitContainer |= uint64(value&bitMask32[bits&31]) << (b.nBits & 63)
44 b.nBits += bits
45}
46
Akash Reddy Kankanalac28f0e22025-06-16 11:00:55 +053047// addBits64NC will add up to 64 bits.
48// There must be space for 32 bits.
49func (b *bitWriter) addBits64NC(value uint64, bits uint8) {
50 if bits <= 31 {
51 b.addBits32Clean(uint32(value), bits)
52 return
53 }
54 b.addBits32Clean(uint32(value), 32)
55 b.flush32()
56 b.addBits32Clean(uint32(value>>32), bits-32)
57}
58
59// addBits32Clean will add up to 32 bits.
60// It will not check if there is space for them.
61// The input must not contain more bits than specified.
62func (b *bitWriter) addBits32Clean(value uint32, bits uint8) {
63 b.bitContainer |= uint64(value) << (b.nBits & 63)
64 b.nBits += bits
65}
66
khenaidoo7d3c5582021-08-11 18:09:44 -040067// addBits16Clean will add up to 16 bits. value may not contain more set bits than indicated.
68// It will not check if there is space for them, so the caller must ensure that it has flushed recently.
69func (b *bitWriter) addBits16Clean(value uint16, bits uint8) {
70 b.bitContainer |= uint64(value) << (b.nBits & 63)
71 b.nBits += bits
72}
73
khenaidoo7d3c5582021-08-11 18:09:44 -040074// flush32 will flush out, so there are at least 32 bits available for writing.
75func (b *bitWriter) flush32() {
76 if b.nBits < 32 {
77 return
78 }
79 b.out = append(b.out,
80 byte(b.bitContainer),
81 byte(b.bitContainer>>8),
82 byte(b.bitContainer>>16),
83 byte(b.bitContainer>>24))
84 b.nBits -= 32
85 b.bitContainer >>= 32
86}
87
88// flushAlign will flush remaining full bytes and align to next byte boundary.
89func (b *bitWriter) flushAlign() {
90 nbBytes := (b.nBits + 7) >> 3
91 for i := uint8(0); i < nbBytes; i++ {
92 b.out = append(b.out, byte(b.bitContainer>>(i*8)))
93 }
94 b.nBits = 0
95 b.bitContainer = 0
96}
97
98// close will write the alignment bit and write the final byte(s)
99// to the output.
100func (b *bitWriter) close() error {
101 // End mark
102 b.addBits16Clean(1, 1)
103 // flush until next byte.
104 b.flushAlign()
105 return nil
106}
107
108// reset and continue writing by appending to out.
109func (b *bitWriter) reset(out []byte) {
110 b.bitContainer = 0
111 b.nBits = 0
112 b.out = out
113}