Coverage Report

Created: 2026-05-12 06:13

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