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.cc
Line
Count
Source
1
// Copyright (c) Google LLC 2020
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
#include "./bit_reader.h"
8
9
#include "../common/platform.h"
10
11
namespace brunsli {
12
13
47.1k
void BrunsliBitReaderInit(BrunsliBitReader* br) {
14
47.1k
  br->num_bits_ = 0;
15
47.1k
  br->bits_ = 0;
16
47.1k
  br->num_debt_bytes_ = 0;
17
47.1k
  br->is_healthy_ = true;
18
47.1k
  br->is_optimistic_ = false;
19
47.1k
}
20
21
void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer,
22
2.96M
                              size_t length) {
23
2.96M
  br->next_ = buffer;
24
2.96M
  br->end_ = buffer + length;
25
2.96M
  br->is_optimistic_ = false;
26
2.96M
}
27
28
/*
29
   Tries to return "debt" if any, and normalize the state.
30
31
   Normal state means that less than 8 bits are held in bit buffer.
32
   Peeking (BrunsliBitReaderGet) more bits than actually using
33
   (BrunsliBitReaderDrop) could put bit reader into denormal state.
34
*/
35
3.05M
static BRUNSLI_INLINE void BrunsliBitReaderUnload(BrunsliBitReader* br) {
36
  // Cancel the overdraft.
37
3.05M
  while ((br->num_debt_bytes_ > 0) && (br->num_bits_ >= 8)) {
38
324
    br->num_debt_bytes_--;
39
324
    br->num_bits_ -= 8;
40
324
  }
41
  // Return unused bytes.
42
3.05M
  while (br->num_bits_ >= 8) {
43
1.61k
    br->next_--;
44
1.61k
    br->num_bits_ -= 8;
45
1.61k
  }
46
3.05M
  br->bits_ &= BrunsliBitReaderBitMask(br->num_bits_);
47
3.05M
}
48
49
2.96M
size_t BrunsliBitReaderSuspend(BrunsliBitReader* br) {
50
2.96M
  BrunsliBitReaderUnload(br);
51
2.96M
  size_t unused_bytes = br->end_ - br->next_;
52
2.96M
  br->next_ = nullptr;
53
2.96M
  br->end_ = nullptr;
54
2.96M
  return unused_bytes;
55
2.96M
}
56
57
38.8k
void BrunsliBitReaderFinish(BrunsliBitReader* br) {
58
38.8k
  uint32_t n_bits = br->num_bits_;
59
  // Likely, did not invoke Suspend before.
60
38.8k
  if (n_bits >= 8) {
61
0
    br->is_healthy_ = false;
62
0
    return;
63
0
  }
64
38.8k
  if (n_bits > 0) {
65
27.5k
    uint32_t padding_bits = BrunsliBitReaderRead(br, n_bits);
66
27.5k
    if (padding_bits != 0) br->is_healthy_ = false;
67
27.5k
  }
68
38.8k
}
69
70
89.3k
bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br) {
71
89.3k
  BrunsliBitReaderUnload(br);
72
89.3k
  return (br->num_debt_bytes_ == 0) && (br->is_healthy_);
73
89.3k
}
74
75
11.8k
void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br) {
76
11.8k
  br->is_optimistic_ = true;
77
11.8k
}
78
79
12.2M
bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits) {
80
12.2M
  if (br->is_optimistic_) return true;
81
10.7M
  if (br->num_debt_bytes_ != 0) return false;
82
10.7M
  if (br->num_bits_ >= n_bits) return true;
83
7.79M
  size_t num_extra_bytes = (n_bits - br->num_bits_ + 7) >> 3;
84
7.79M
  return (br->next_ + num_extra_bytes <= br->end_);
85
10.7M
}
86
87
}  // namespace brunsli