Coverage Report

Created: 2026-04-01 06:57

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
6.00M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
6.00M
  return ~((0xFFFFFFFFu) << n);
70
6.00M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
3.52M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
3.52M
  return ~((0xFFFFFFFFu) << n);
70
3.52M
}
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
24.0k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
24.0k
  return ~((0xFFFFFFFFu) << n);
70
24.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
264k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
264k
  return ~((0xFFFFFFFFu) << n);
70
264k
}
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
1.54M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
1.54M
  return ~((0xFFFFFFFFu) << n);
70
1.54M
}
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
652k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
652k
  return ~((0xFFFFFFFFu) << n);
70
652k
}
71
72
/* Internal. */
73
102k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
102k
  br->num_bits_ += 8;
75
102k
  br->num_debt_bytes_++;
76
102k
}
brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
46
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
46
  br->num_bits_ += 8;
75
46
  br->num_debt_bytes_++;
76
46
}
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
316
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
316
  br->num_bits_ += 8;
75
316
  br->num_debt_bytes_++;
76
316
}
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
1.41k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
1.41k
  br->num_bits_ += 8;
75
1.41k
  br->num_debt_bytes_++;
76
1.41k
}
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
100k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
100k
  br->num_bits_ += 8;
75
100k
  br->num_debt_bytes_++;
76
100k
}
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
5.38M
                                                          uint32_t n_bits) {
81
5.38M
  if (br->num_bits_ < n_bits) {
82
2.04M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
102k
      BrunsliBitReaderOweByte(br);
84
1.94M
    } else {
85
1.94M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
1.94M
      br->num_bits_ += 8;
87
1.94M
      br->next_++;
88
1.94M
    }
89
2.04M
  }
90
5.38M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
3.52M
                                                          uint32_t n_bits) {
81
3.52M
  if (br->num_bits_ < n_bits) {
82
1.86M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
46
      BrunsliBitReaderOweByte(br);
84
1.86M
    } else {
85
1.86M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
1.86M
      br->num_bits_ += 8;
87
1.86M
      br->next_++;
88
1.86M
    }
89
1.86M
  }
90
3.52M
}
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
24.2k
                                                          uint32_t n_bits) {
81
24.2k
  if (br->num_bits_ < n_bits) {
82
627
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
316
      BrunsliBitReaderOweByte(br);
84
316
    } else {
85
311
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
311
      br->num_bits_ += 8;
87
311
      br->next_++;
88
311
    }
89
627
  }
90
24.2k
}
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
268k
                                                          uint32_t n_bits) {
81
268k
  if (br->num_bits_ < n_bits) {
82
57.7k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
1.41k
      BrunsliBitReaderOweByte(br);
84
56.2k
    } else {
85
56.2k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
56.2k
      br->num_bits_ += 8;
87
56.2k
      br->next_++;
88
56.2k
    }
89
57.7k
  }
90
268k
}
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
1.54M
                                                          uint32_t n_bits) {
81
1.54M
  if (br->num_bits_ < n_bits) {
82
125k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
100k
      BrunsliBitReaderOweByte(br);
84
100k
    } else {
85
24.8k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
24.8k
      br->num_bits_ += 8;
87
24.8k
      br->next_++;
88
24.8k
    }
89
125k
  }
90
1.54M
}
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
25.8k
                                                          uint32_t n_bits) {
81
25.8k
  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
25.8k
}
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
5.37M
                                                   uint32_t n_bits) {
110
5.37M
  BRUNSLI_DCHECK(n_bits <= 24);
111
5.37M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
5.37M
  if (n_bits > 8) {
113
9.13k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
9.13k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
9.13k
  }
116
5.37M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
5.37M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
3.52M
                                                   uint32_t n_bits) {
110
3.52M
  BRUNSLI_DCHECK(n_bits <= 24);
111
3.52M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
3.52M
  if (n_bits > 8) {
113
3.96k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
3.96k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
3.96k
  }
116
3.52M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
3.52M
}
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
24.0k
                                                   uint32_t n_bits) {
110
24.0k
  BRUNSLI_DCHECK(n_bits <= 24);
111
24.0k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
24.0k
  if (n_bits > 8) {
113
205
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
205
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
205
  }
116
24.0k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
24.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
264k
                                                   uint32_t n_bits) {
110
264k
  BRUNSLI_DCHECK(n_bits <= 24);
111
264k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
264k
  if (n_bits > 8) {
113
4.81k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
4.81k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
4.81k
  }
116
264k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
264k
}
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
1.54M
                                                   uint32_t n_bits) {
110
1.54M
  BRUNSLI_DCHECK(n_bits <= 24);
111
1.54M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
1.54M
  if (n_bits > 8) {
113
150
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
150
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
150
  }
116
1.54M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
1.54M
}
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
25.8k
                                                   uint32_t n_bits) {
110
25.8k
  BRUNSLI_DCHECK(n_bits <= 24);
111
25.8k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
25.8k
  if (n_bits > 8) {
113
0
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
0
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
0
  }
116
25.8k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
25.8k
}
118
119
static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br,
120
5.37M
                                                uint32_t n_bits) {
121
5.37M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
5.37M
  br->bits_ >>= n_bits;
123
5.37M
  br->num_bits_ -= n_bits;
124
5.37M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
3.52M
                                                uint32_t n_bits) {
121
3.52M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
3.52M
  br->bits_ >>= n_bits;
123
3.52M
  br->num_bits_ -= n_bits;
124
3.52M
}
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
24.0k
                                                uint32_t n_bits) {
121
24.0k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
24.0k
  br->bits_ >>= n_bits;
123
24.0k
  br->num_bits_ -= n_bits;
124
24.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
264k
                                                uint32_t n_bits) {
121
264k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
264k
  br->bits_ >>= n_bits;
123
264k
  br->num_bits_ -= n_bits;
124
264k
}
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
1.54M
                                                uint32_t n_bits) {
121
1.54M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
1.54M
  br->bits_ >>= n_bits;
123
1.54M
  br->num_bits_ -= n_bits;
124
1.54M
}
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
25.8k
                                                uint32_t n_bits) {
121
25.8k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
25.8k
  br->bits_ >>= n_bits;
123
25.8k
  br->num_bits_ -= n_bits;
124
25.8k
}
125
126
BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br,
127
3.84M
                                                    uint32_t n_bits) {
128
3.84M
  uint32_t result = BrunsliBitReaderGet(br, n_bits);
129
3.84M
  BrunsliBitReaderDrop(br, n_bits);
130
3.84M
  return result;
131
3.84M
}
132
133
}  // namespace brunsli
134
135
#endif  // BRUNSLI_DEC_BIT_READER_H_