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