Coverage Report

Created: 2026-10-28 06:29

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 <brunsli/types.h>
13
14
#include "../common/platform.h"
15
16
namespace brunsli {
17
18
struct BrunsliBitReader {
19
  const uint8_t* next_;
20
  const uint8_t* end_;
21
  uint32_t num_bits_;
22
  uint32_t bits_;
23
  /*
24
     Number of "virtual" zero bytes located after the end of buffer being
25
     put into the bit buffer.
26
27
     The concept of debt is useful for two purposes:
28
      - postpone handling of "unexpected end of input"
29
      - allow efficient peeking of input near the end
30
31
     It is OK to have debt, while "balance" is non-negative.
32
     BrunsliBitReaderUnload returns debt, if possible.
33
   */
34
  uint32_t num_debt_bytes_;
35
  bool is_healthy_;
36
  bool is_optimistic_;
37
};
38
39
/**
40
 * Prepare instance.
41
 *
42
 * The instance lifecycle looks like:
43
 *  - Init
44
 *  - Resume
45
 *  - (read bits)
46
 *  - Suspend
47
 *  - (optionally, go back to Resume stage)
48
 *  - Finish
49
 */
50
void BrunsliBitReaderInit(BrunsliBitReader* br);
51
/**
52
 * Supply instance with new chunk of input.
53
 */
54
void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer,
55
                            size_t length);
56
/**
57
 * Returns the number of unused bytes.
58
 */
59
size_t BrunsliBitReaderSuspend(BrunsliBitReader* br);
60
/**
61
 * Drops unused bits of the last used byte.
62
 *
63
 * Marks instance as unhealthy, if unused bits are not all 0.
64
 */
65
void BrunsliBitReaderFinish(BrunsliBitReader* br);
66
67
bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br);
68
69
35.5M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
35.5M
  return ~((0xFFFFFFFFu) << n);
71
35.5M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
69
27.4M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
27.4M
  return ~((0xFFFFFFFFu) << n);
71
27.4M
}
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
69
38.0k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
38.0k
  return ~((0xFFFFFFFFu) << n);
71
38.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
69
251k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
251k
  return ~((0xFFFFFFFFu) << n);
71
251k
}
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
69
1.94M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
1.94M
  return ~((0xFFFFFFFFu) << n);
71
1.94M
}
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
69
5.95M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
70
5.95M
  return ~((0xFFFFFFFFu) << n);
71
5.95M
}
72
73
/* Internal. */
74
140k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
75
140k
  br->num_bits_ += 8;
76
140k
  br->num_debt_bytes_++;
77
140k
}
brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
74
50
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
75
50
  br->num_bits_ += 8;
76
50
  br->num_debt_bytes_++;
77
50
}
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
74
634
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
75
634
  br->num_bits_ += 8;
76
634
  br->num_debt_bytes_++;
77
634
}
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
74
2.14k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
75
2.14k
  br->num_bits_ += 8;
76
2.14k
  br->num_debt_bytes_++;
77
2.14k
}
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
74
138k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
75
138k
  br->num_bits_ += 8;
76
138k
  br->num_debt_bytes_++;
77
138k
}
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*)
78
79
/* Internal. */
80
static BRUNSLI_INLINE void BrunsliBitReaderMaybeFetchByte(BrunsliBitReader* br,
81
29.6M
                                                          uint32_t n_bits) {
82
29.6M
  if (br->num_bits_ < n_bits) {
83
11.6M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
140k
      BrunsliBitReaderOweByte(br);
85
11.4M
    } else {
86
11.4M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
11.4M
      br->num_bits_ += 8;
88
11.4M
      br->next_++;
89
11.4M
    }
90
11.6M
  }
91
29.6M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
81
27.4M
                                                          uint32_t n_bits) {
82
27.4M
  if (br->num_bits_ < n_bits) {
83
11.3M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
50
      BrunsliBitReaderOweByte(br);
85
11.3M
    } else {
86
11.3M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
11.3M
      br->num_bits_ += 8;
88
11.3M
      br->next_++;
89
11.3M
    }
90
11.3M
  }
91
27.4M
}
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
81
38.3k
                                                          uint32_t n_bits) {
82
38.3k
  if (br->num_bits_ < n_bits) {
83
1.17k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
634
      BrunsliBitReaderOweByte(br);
85
634
    } else {
86
538
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
538
      br->num_bits_ += 8;
88
538
      br->next_++;
89
538
    }
90
1.17k
  }
91
38.3k
}
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
81
256k
                                                          uint32_t n_bits) {
82
256k
  if (br->num_bits_ < n_bits) {
83
58.0k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
2.14k
      BrunsliBitReaderOweByte(br);
85
55.9k
    } else {
86
55.9k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
55.9k
      br->num_bits_ += 8;
88
55.9k
      br->next_++;
89
55.9k
    }
90
58.0k
  }
91
256k
}
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
81
1.94M
                                                          uint32_t n_bits) {
82
1.94M
  if (br->num_bits_ < n_bits) {
83
164k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
138k
      BrunsliBitReaderOweByte(br);
85
138k
    } else {
86
26.6k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
26.6k
      br->num_bits_ += 8;
88
26.6k
      br->next_++;
89
26.6k
    }
90
164k
  }
91
1.94M
}
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
81
30.5k
                                                          uint32_t n_bits) {
82
30.5k
  if (br->num_bits_ < n_bits) {
83
0
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
84
0
      BrunsliBitReaderOweByte(br);
85
0
    } else {
86
0
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
87
0
      br->num_bits_ += 8;
88
0
      br->next_++;
89
0
    }
90
0
  }
91
30.5k
}
92
93
/**
94
 * Turns instance to optimistic mode.
95
 *
96
 * The only difference with regular operating mode is that CanRead always
97
 * returns "true". Use this mode only when instance is supplied with complete
98
 * input.
99
 */
100
void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br);
101
102
/**
103
 * Returns true if there is enough input.
104
 *
105
 * Guaranteed to work correctly only in normalized state.
106
 */
107
bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits);
108
109
static BRUNSLI_INLINE uint32_t BrunsliBitReaderGet(BrunsliBitReader* br,
110
29.6M
                                                   uint32_t n_bits) {
111
29.6M
  BRUNSLI_DCHECK(n_bits <= 24);
112
29.6M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
29.6M
  if (n_bits > 8) {
114
11.9k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
11.9k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
11.9k
  }
117
29.6M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
29.6M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
110
27.4M
                                                   uint32_t n_bits) {
111
27.4M
  BRUNSLI_DCHECK(n_bits <= 24);
112
27.4M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
27.4M
  if (n_bits > 8) {
114
5.96k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
5.96k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
5.96k
  }
117
27.4M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
27.4M
}
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
110
38.0k
                                                   uint32_t n_bits) {
111
38.0k
  BRUNSLI_DCHECK(n_bits <= 24);
112
38.0k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
38.0k
  if (n_bits > 8) {
114
343
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
343
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
343
  }
117
38.0k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
38.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
110
251k
                                                   uint32_t n_bits) {
111
251k
  BRUNSLI_DCHECK(n_bits <= 24);
112
251k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
251k
  if (n_bits > 8) {
114
5.40k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
5.40k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
5.40k
  }
117
251k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
251k
}
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
110
1.94M
                                                   uint32_t n_bits) {
111
1.94M
  BRUNSLI_DCHECK(n_bits <= 24);
112
1.94M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
1.94M
  if (n_bits > 8) {
114
284
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
284
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
284
  }
117
1.94M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
1.94M
}
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
110
30.5k
                                                   uint32_t n_bits) {
111
30.5k
  BRUNSLI_DCHECK(n_bits <= 24);
112
30.5k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
113
30.5k
  if (n_bits > 8) {
114
0
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
0
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
116
0
  }
117
30.5k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
118
30.5k
}
119
120
static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br,
121
29.6M
                                                uint32_t n_bits) {
122
29.6M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
29.6M
  br->bits_ >>= n_bits;
124
29.6M
  br->num_bits_ -= n_bits;
125
29.6M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
121
27.4M
                                                uint32_t n_bits) {
122
27.4M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
27.4M
  br->bits_ >>= n_bits;
124
27.4M
  br->num_bits_ -= n_bits;
125
27.4M
}
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
121
38.0k
                                                uint32_t n_bits) {
122
38.0k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
38.0k
  br->bits_ >>= n_bits;
124
38.0k
  br->num_bits_ -= n_bits;
125
38.0k
}
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
121
251k
                                                uint32_t n_bits) {
122
251k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
251k
  br->bits_ >>= n_bits;
124
251k
  br->num_bits_ -= n_bits;
125
251k
}
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
121
1.94M
                                                uint32_t n_bits) {
122
1.94M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
1.94M
  br->bits_ >>= n_bits;
124
1.94M
  br->num_bits_ -= n_bits;
125
1.94M
}
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
121
30.5k
                                                uint32_t n_bits) {
122
30.5k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
123
30.5k
  br->bits_ >>= n_bits;
124
30.5k
  br->num_bits_ -= n_bits;
125
30.5k
}
126
127
BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br,
128
27.7M
                                             uint32_t n_bits) {
129
27.7M
  uint32_t result = BrunsliBitReaderGet(br, n_bits);
130
27.7M
  BrunsliBitReaderDrop(br, n_bits);
131
27.7M
  return result;
132
27.7M
}
133
134
}  // namespace brunsli
135
136
#endif  // BRUNSLI_DEC_BIT_READER_H_