Coverage Report

Created: 2025-11-09 06:57

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