Coverage Report

Created: 2025-11-16 06:36

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
23.5k
void BrunsliBitReaderInit(BrunsliBitReader* br) {
14
23.5k
  br->num_bits_ = 0;
15
23.5k
  br->bits_ = 0;
16
23.5k
  br->num_debt_bytes_ = 0;
17
23.5k
  br->is_healthy_ = true;
18
23.5k
  br->is_optimistic_ = false;
19
23.5k
}
20
21
void BrunsliBitReaderResume(BrunsliBitReader* br, const uint8_t* buffer,
22
23.5k
                              size_t length) {
23
23.5k
  br->next_ = buffer;
24
23.5k
  br->end_ = buffer + length;
25
23.5k
  br->is_optimistic_ = false;
26
23.5k
}
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
67.2k
static BRUNSLI_INLINE void BrunsliBitReaderUnload(BrunsliBitReader* br) {
36
  // Cancel the overdraft.
37
67.3k
  while ((br->num_debt_bytes_ > 0) && (br->num_bits_ >= 8)) {
38
110
    br->num_debt_bytes_--;
39
110
    br->num_bits_ -= 8;
40
110
  }
41
  // Return unused bytes.
42
67.7k
  while (br->num_bits_ >= 8) {
43
571
    br->next_--;
44
571
    br->num_bits_ -= 8;
45
571
  }
46
67.2k
  br->bits_ &= BrunsliBitReaderBitMask(br->num_bits_);
47
67.2k
}
48
49
23.5k
size_t BrunsliBitReaderSuspend(BrunsliBitReader* br) {
50
23.5k
  BrunsliBitReaderUnload(br);
51
23.5k
  size_t unused_bytes = br->end_ - br->next_;
52
23.5k
  br->next_ = nullptr;
53
23.5k
  br->end_ = nullptr;
54
23.5k
  return unused_bytes;
55
23.5k
}
56
57
19.0k
void BrunsliBitReaderFinish(BrunsliBitReader* br) {
58
19.0k
  uint32_t n_bits = br->num_bits_;
59
  // Likely, did not invoke Suspend before.
60
19.0k
  if (n_bits >= 8) {
61
0
    br->is_healthy_ = false;
62
0
    return;
63
0
  }
64
19.0k
  if (n_bits > 0) {
65
13.5k
    uint32_t padding_bits = BrunsliBitReaderRead(br, n_bits);
66
13.5k
    if (padding_bits != 0) br->is_healthy_ = false;
67
13.5k
  }
68
19.0k
}
69
70
43.6k
bool BrunsliBitReaderIsHealthy(BrunsliBitReader* br) {
71
43.6k
  BrunsliBitReaderUnload(br);
72
43.6k
  return (br->num_debt_bytes_ == 0) && (br->is_healthy_);
73
43.6k
}
74
75
5.63k
void BrunsliBitReaderSetOptimistic(BrunsliBitReader* br) {
76
5.63k
  br->is_optimistic_ = true;
77
5.63k
}
78
79
3.83M
bool BrunsliBitReaderCanRead(BrunsliBitReader* br, size_t n_bits) {
80
3.83M
  if (br->is_optimistic_) return true;
81
2.85M
  if (br->num_debt_bytes_ != 0) return false;
82
2.85M
  if (br->num_bits_ >= n_bits) return true;
83
1.63M
  size_t num_extra_bytes = (n_bits - br->num_bits_ + 7) >> 3;
84
1.63M
  return (br->next_ + num_extra_bytes <= br->end_);
85
2.85M
}
86
87
}  // namespace brunsli