Coverage Report

Created: 2026-02-26 06:59

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
3.49M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
3.49M
  return ~((0xFFFFFFFFu) << n);
70
3.49M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
2.47M
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
2.47M
  return ~((0xFFFFFFFFu) << n);
70
2.47M
}
context_map_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
9.05k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
9.05k
  return ~((0xFFFFFFFFu) << n);
70
9.05k
}
histogram_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
126k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
126k
  return ~((0xFFFFFFFFu) << n);
70
126k
}
huffman_decode.cc:brunsli::BrunsliBitReaderBitMask(unsigned int)
Line
Count
Source
68
803k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
803k
  return ~((0xFFFFFFFFu) << n);
70
803k
}
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
72.2k
static BRUNSLI_INLINE uint32_t BrunsliBitReaderBitMask(uint32_t n) {
69
72.2k
  return ~((0xFFFFFFFFu) << n);
70
72.2k
}
71
72
/* Internal. */
73
30.9k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
30.9k
  br->num_bits_ += 8;
75
30.9k
  br->num_debt_bytes_++;
76
30.9k
}
brunsli_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
29
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
29
  br->num_bits_ += 8;
75
29
  br->num_debt_bytes_++;
76
29
}
context_map_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
223
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
223
  br->num_bits_ += 8;
75
223
  br->num_debt_bytes_++;
76
223
}
histogram_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
579
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
579
  br->num_bits_ += 8;
75
579
  br->num_debt_bytes_++;
76
579
}
huffman_decode.cc:brunsli::BrunsliBitReaderOweByte(brunsli::BrunsliBitReader*)
Line
Count
Source
73
30.0k
static BRUNSLI_INLINE void BrunsliBitReaderOweByte(BrunsliBitReader* br) {
74
30.0k
  br->num_bits_ += 8;
75
30.0k
  br->num_debt_bytes_++;
76
30.0k
}
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
3.43M
                                                          uint32_t n_bits) {
81
3.43M
  if (br->num_bits_ < n_bits) {
82
1.54M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
30.9k
      BrunsliBitReaderOweByte(br);
84
1.51M
    } else {
85
1.51M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
1.51M
      br->num_bits_ += 8;
87
1.51M
      br->next_++;
88
1.51M
    }
89
1.54M
  }
90
3.43M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
2.48M
                                                          uint32_t n_bits) {
81
2.48M
  if (br->num_bits_ < n_bits) {
82
1.47M
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
29
      BrunsliBitReaderOweByte(br);
84
1.47M
    } else {
85
1.47M
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
1.47M
      br->num_bits_ += 8;
87
1.47M
      br->next_++;
88
1.47M
    }
89
1.47M
  }
90
2.48M
}
context_map_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
9.14k
                                                          uint32_t n_bits) {
81
9.14k
  if (br->num_bits_ < n_bits) {
82
272
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
223
      BrunsliBitReaderOweByte(br);
84
223
    } else {
85
49
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
49
      br->num_bits_ += 8;
87
49
      br->next_++;
88
49
    }
89
272
  }
90
9.14k
}
histogram_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
128k
                                                          uint32_t n_bits) {
81
128k
  if (br->num_bits_ < n_bits) {
82
26.8k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
579
      BrunsliBitReaderOweByte(br);
84
26.2k
    } else {
85
26.2k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
26.2k
      br->num_bits_ += 8;
87
26.2k
      br->next_++;
88
26.2k
    }
89
26.8k
  }
90
128k
}
huffman_decode.cc:brunsli::BrunsliBitReaderMaybeFetchByte(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
80
803k
                                                          uint32_t n_bits) {
81
803k
  if (br->num_bits_ < n_bits) {
82
41.5k
    if (BRUNSLI_PREDICT_FALSE(br->next_ >= br->end_)) {
83
30.0k
      BrunsliBitReaderOweByte(br);
84
30.0k
    } else {
85
11.4k
      br->bits_ |= static_cast<uint32_t>(*br->next_) << br->num_bits_;
86
11.4k
      br->num_bits_ += 8;
87
11.4k
      br->next_++;
88
11.4k
    }
89
41.5k
  }
90
803k
}
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
12.1k
                                                          uint32_t n_bits) {
81
12.1k
  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
12.1k
}
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
3.43M
                                                   uint32_t n_bits) {
110
3.43M
  BRUNSLI_DCHECK(n_bits <= 24);
111
3.43M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
3.43M
  if (n_bits > 8) {
113
3.59k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
3.59k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
3.59k
  }
116
3.43M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
3.43M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
2.47M
                                                   uint32_t n_bits) {
110
2.47M
  BRUNSLI_DCHECK(n_bits <= 24);
111
2.47M
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
2.47M
  if (n_bits > 8) {
113
1.42k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
1.42k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
1.42k
  }
116
2.47M
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
2.47M
}
context_map_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
9.05k
                                                   uint32_t n_bits) {
110
9.05k
  BRUNSLI_DCHECK(n_bits <= 24);
111
9.05k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
9.05k
  if (n_bits > 8) {
113
93
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
93
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
93
  }
116
9.05k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
9.05k
}
histogram_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
126k
                                                   uint32_t n_bits) {
110
126k
  BRUNSLI_DCHECK(n_bits <= 24);
111
126k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
126k
  if (n_bits > 8) {
113
2.02k
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
2.02k
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
2.02k
  }
116
126k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
126k
}
huffman_decode.cc:brunsli::BrunsliBitReaderGet(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
109
803k
                                                   uint32_t n_bits) {
110
803k
  BRUNSLI_DCHECK(n_bits <= 24);
111
803k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
803k
  if (n_bits > 8) {
113
54
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
54
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
54
  }
116
803k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
803k
}
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
12.1k
                                                   uint32_t n_bits) {
110
12.1k
  BRUNSLI_DCHECK(n_bits <= 24);
111
12.1k
  BrunsliBitReaderMaybeFetchByte(br, n_bits);
112
12.1k
  if (n_bits > 8) {
113
0
    BrunsliBitReaderMaybeFetchByte(br, n_bits);
114
0
    if (n_bits > 16) BrunsliBitReaderMaybeFetchByte(br, n_bits);
115
0
  }
116
12.1k
  return br->bits_ & BrunsliBitReaderBitMask(n_bits);
117
12.1k
}
118
119
static BRUNSLI_INLINE void BrunsliBitReaderDrop(BrunsliBitReader* br,
120
3.43M
                                                uint32_t n_bits) {
121
3.43M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
3.43M
  br->bits_ >>= n_bits;
123
3.43M
  br->num_bits_ -= n_bits;
124
3.43M
}
brunsli_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
2.47M
                                                uint32_t n_bits) {
121
2.47M
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
2.47M
  br->bits_ >>= n_bits;
123
2.47M
  br->num_bits_ -= n_bits;
124
2.47M
}
context_map_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
9.05k
                                                uint32_t n_bits) {
121
9.05k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
9.05k
  br->bits_ >>= n_bits;
123
9.05k
  br->num_bits_ -= n_bits;
124
9.05k
}
histogram_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
126k
                                                uint32_t n_bits) {
121
126k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
126k
  br->bits_ >>= n_bits;
123
126k
  br->num_bits_ -= n_bits;
124
126k
}
huffman_decode.cc:brunsli::BrunsliBitReaderDrop(brunsli::BrunsliBitReader*, unsigned int)
Line
Count
Source
120
803k
                                                uint32_t n_bits) {
121
803k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
803k
  br->bits_ >>= n_bits;
123
803k
  br->num_bits_ -= n_bits;
124
803k
}
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
12.1k
                                                uint32_t n_bits) {
121
12.1k
  BRUNSLI_DCHECK(n_bits <= br->num_bits_);
122
12.1k
  br->bits_ >>= n_bits;
123
12.1k
  br->num_bits_ -= n_bits;
124
12.1k
}
125
126
BRUNSLI_INLINE uint32_t BrunsliBitReaderRead(BrunsliBitReader* br,
127
2.62M
                                                    uint32_t n_bits) {
128
2.62M
  uint32_t result = BrunsliBitReaderGet(br, n_bits);
129
2.62M
  BrunsliBitReaderDrop(br, n_bits);
130
2.62M
  return result;
131
2.62M
}
132
133
}  // namespace brunsli
134
135
#endif  // BRUNSLI_DEC_BIT_READER_H_