Coverage Report

Created: 2026-02-14 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brunsli/c/dec/bit_reader.h
Line
Count
Source
1
// Copyright (c) Google LLC 2019
2
//
3
// Use of this source code is governed by an MIT-style
4
// license that can be found in the LICENSE file or at
5
// https://opensource.org/licenses/MIT.
6
7
/* Bit reading helpers */
8
9
#ifndef BRUNSLI_DEC_BIT_READER_H_
10
#define BRUNSLI_DEC_BIT_READER_H_
11
12
#include "../common/platform.h"
13
#include <brunsli/types.h>
14
15
namespace brunsli {
16
17
struct BrunsliBitReader {
18
  const uint8_t* next_;
19
  const uint8_t* end_;
20
  uint32_t num_bits_;
21
  uint32_t bits_;
22
  /*
23
     Number of "virtual" zero bytes located after the end of buffer being
24
     put into the bit buffer.
25
26
     The concept of debt is useful for two purposes:
27
      - postpone handling of "unexpected end of input"
28
      - allow efficient peeking of input near the end
29
30
     It is OK to have debt, while "balance" is non-negative.
31
     BrunsliBitReaderUnload returns debt, if possible.
32
   */
33
  uint32_t num_debt_bytes_;
34
  bool is_healthy_;
35
  bool is_optimistic_;
36
};
37
38
/**
39
 * Prepare instance.
40
 *
41
 * The instance lifecycle looks like:
42
 *  - Init
43
 *  - Resume
44
 *  - (read bits)
45
 *  - Suspend
46
 *  - (optionally, go back to Resume stage)
47
 *  - Finish
48
 */
49
void BrunsliBitReaderInit(BrunsliBitReader* br);
50
/**
51
 * Supply instance with new chunk of input.
52
 */
53
void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer,
54
                          size_t length);
55
/**
56
 * Returns the number of unused bytes.
57
 */
58
size_t BrunsliBitReaderSuspend(BrunsliBitReader* br);
59
/**
60
 * Drops unused bits of the last used byte.
61
 *
62
 * Marks instance as unhealthy, if unused bits are not all 0.
63
 */
64
void BrunsliBitReaderFinish(BrunsliBitReader* br);
65
66
bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br);
67
68
13.6M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
13.6M
  return ~((0xFFFFFFFFu) << n);
70
13.6M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
8.60M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
8.60M
  return ~((0xFFFFFFFFu) << n);
70
8.60M
}
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
30.9k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
30.9k
  return ~((0xFFFFFFFFu) << n);
70
30.9k
}
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
249k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
249k
  return ~((0xFFFFFFFFu) << n);
70
249k
}
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
1.63M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
1.63M
  return ~((0xFFFFFFFFu) << n);
70
1.63M
}
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
bit_reader.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
3.08M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
3.08M
  return ~((0xFFFFFFFFu) << n);
70
3.08M
}
71
72
/* Internal. */
73
147k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
147k
  br->num_bits_ += 8;
75
147k
  br->num_debt_bytes_++;
76
147k
}
brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
49
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
49
  br->num_bits_ += 8;
75
49
  br->num_debt_bytes_++;
76
49
}
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
1.09k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
1.09k
  br->num_bits_ += 8;
75
1.09k
  br->num_debt_bytes_++;
76
1.09k
}
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
1.85k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
1.85k
  br->num_bits_ += 8;
75
1.85k
  br->num_debt_bytes_++;
76
1.85k
}
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
144k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
144k
  br->num_bits_ += 8;
75
144k
  br->num_debt_bytes_++;
76
144k
}
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Unexecuted instantiation: bit_reader.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
77
78
/* Internal. */
79
static BRUNSLI_INLINE void BrunsliBitReaderMaybeFetchByte(BrunsliBitReader* br,
80
10.5M
                                                          uint32_t n_bits) {
81
10.5M
  if (br->num_bits_ < n_bits) {
82
5.53M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
147k
      BrunsliBitReaderOweByte(br);
84
5.39M
    } else {
85
5.39M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
5.39M
      br->num_bits_ += 8;
87
5.39M
      br->next_++;
88
5.39M
    }
89
5.53M
  }
90
10.5M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
8.61M
                                                          uint32_t n_bits) {
81
8.61M
  if (br->num_bits_ < n_bits) {
82
5.31M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
49
      BrunsliBitReaderOweByte(br);
84
5.31M
    } else {
85
5.31M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
5.31M
      br->num_bits_ += 8;
87
5.31M
      br->next_++;
88
5.31M
    }
89
5.31M
  }
90
8.61M
}
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
31.1k
                                                          uint32_t n_bits) {
81
31.1k
  if (br->num_bits_ < n_bits) {
82
1.60k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
1.09k
      BrunsliBitReaderOweByte(br);
84
1.09k
    } else {
85
518
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
518
      br->num_bits_ += 8;
87
518
      br->next_++;
88
518
    }
89
1.60k
  }
90
31.1k
}
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
254k
                                                          uint32_t n_bits) {
81
254k
  if (br->num_bits_ < n_bits) {
82
56.8k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
1.85k
      BrunsliBitReaderOweByte(br);
84
54.9k
    } else {
85
54.9k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
54.9k
      br->num_bits_ += 8;
87
54.9k
      br->next_++;
88
54.9k
    }
89
56.8k
  }
90
254k
}
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
1.63M
                                                          uint32_t n_bits) {
81
1.63M
  if (br->num_bits_ < n_bits) {
82
167k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
144k
      BrunsliBitReaderOweByte(br);
84
144k
    } else {
85
23.2k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
23.2k
      br->num_bits_ += 8;
87
23.2k
      br->next_++;
88
23.2k
    }
89
167k
  }
90
1.63M
}
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
bit_reader.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
27.5k
                                                          uint32_t n_bits) {
81
27.5k
  if (br->num_bits_ < n_bits) {
82
0
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
0
      BrunsliBitReaderOweByte(br);
84
0
    } else {
85
0
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
0
      br->num_bits_ += 8;
87
0
      br->next_++;
88
0
    }
89
0
  }
90
27.5k
}
91
92
/**
93
 * Turns instance to optimistic mode.
94
 *
95
 * The only difference with regular operating mode is that CanRead always
96
 * returns "true". Use this mode only when instance is supplied with complete
97
 * input.
98
 */
99
void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br);
100
101
/**
102
 * Returns true if there is enough input.
103
 *
104
 * Guaranteed to work correctly only in normalized state.
105
 */
106
bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits);
107
108
static BRUNSLI_INLINE uint32_t BrunsliBitReaderGet(BrunsliBitReader* br,
109
10.5M
                                                   uint32_t n_bits) {
110
10.5M
  BRUNSLI_DCHECK(n_bits <= 24);
111
10.5M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
10.5M
  if (n_bits > 8) {
113
10.5k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
10.5k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
10.5k
  }
116
10.5M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
10.5M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
8.60M
                                                   uint32_t n_bits) {
110
8.60M
  BRUNSLI_DCHECK(n_bits <= 24);
111
8.60M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
8.60M
  if (n_bits > 8) {
113
4.90k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
4.90k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
4.90k
  }
116
8.60M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
8.60M
}
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
30.9k
                                                   uint32_t n_bits) {
110
30.9k
  BRUNSLI_DCHECK(n_bits <= 24);
111
30.9k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
30.9k
  if (n_bits > 8) {
113
212
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
212
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
212
  }
116
30.9k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
30.9k
}
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
249k
                                                   uint32_t n_bits) {
110
249k
  BRUNSLI_DCHECK(n_bits <= 24);
111
249k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
249k
  if (n_bits > 8) {
113
5.25k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
5.25k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
5.25k
  }
116
249k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
249k
}
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
1.63M
                                                   uint32_t n_bits) {
110
1.63M
  BRUNSLI_DCHECK(n_bits <= 24);
111
1.63M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
1.63M
  if (n_bits > 8) {
113
173
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
173
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
173
  }
116
1.63M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
1.63M
}
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
bit_reader.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
27.5k
                                                   uint32_t n_bits) {
110
27.5k
  BRUNSLI_DCHECK(n_bits <= 24);
111
27.5k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
27.5k
  if (n_bits > 8) {
113
0
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
0
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
0
  }
116
27.5k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
27.5k
}
118
119
static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br,
120
10.5M
                                                uint32_t n_bits) {
121
10.5M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
10.5M
  br->bits_ >>= n_bits;
123
10.5M
  br->num_bits_ -= n_bits;
124
10.5M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
8.60M
                                                uint32_t n_bits) {
121
8.60M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
8.60M
  br->bits_ >>= n_bits;
123
8.60M
  br->num_bits_ -= n_bits;
124
8.60M
}
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
30.9k
                                                uint32_t n_bits) {
121
30.9k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
30.9k
  br->bits_ >>= n_bits;
123
30.9k
  br->num_bits_ -= n_bits;
124
30.9k
}
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
249k
                                                uint32_t n_bits) {
121
249k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
249k
  br->bits_ >>= n_bits;
123
249k
  br->num_bits_ -= n_bits;
124
249k
}
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
1.63M
                                                uint32_t n_bits) {
121
1.63M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
1.63M
  br->bits_ >>= n_bits;
123
1.63M
  br->num_bits_ -= n_bits;
124
1.63M
}
Unexecuted instantiation: jpeg_data_writer.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Unexecuted instantiation: state.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
bit_reader.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
27.5k
                                                uint32_t n_bits) {
121
27.5k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
27.5k
  br->bits_ >>= n_bits;
123
27.5k
  br->num_bits_ -= n_bits;
124
27.5k
}
125
126
BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br,
127
8.92M
                                                    uint32_t n_bits) {
128
8.92M
  uint32_t result = BrunsliBitReaderGet(br, n_bits);
129
8.92M
  BrunsliBitReaderDrop(br, n_bits);
130
8.92M
  return result;
131
8.92M
}
132
133
}  // namespace brunsli
134
135
#endif  // BRUNSLI_DEC_BIT_READER_H_