Coverage Report

Created: 2026-09-01 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/brunsli/c/dec/brunsli_input.h
Line
Count
Source
1
// Copyright (c) Google LLC 2019
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
#ifndef BRUNSLI_DEC_BRUNSLI_INPUT_H_
8
#define BRUNSLI_DEC_BRUNSLI_INPUT_H_
9
10
#include <brunsli/types.h>
11
12
#include "../common/platform.h"
13
14
namespace brunsli {
15
16
static const int kBitMask[] = {0,    1,    3,     7,     15,   31,
17
                               63,   127,  255,   511,   1023, 2047,
18
                               4095, 8191, 16383, 32767, 65535};
19
20
struct WordSource {
21
  WordSource(const uint8_t* data, size_t len, bool optimistic)
22
10.1k
      : data_(data),
23
10.1k
        len_(len & ~1),
24
10.1k
        pos_(0),
25
10.1k
        error_(false),
26
10.1k
        optimistic_(optimistic) {}
27
28
3.16M
  uint16_t GetNextWord() {
29
3.16M
    uint16_t val = 0;
30
3.16M
    if (pos_ < len_) { /* NB: both pos_ and len_ are even. */
31
3.14M
      val = BRUNSLI_UNALIGNED_LOAD16LE(data_ + pos_);
32
3.14M
    } else {
33
21.3k
      error_ = true;
34
21.3k
    }
35
    // TODO(eustas): take care of overflows?
36
3.16M
    pos_ += 2;
37
3.16M
    return val;
38
3.16M
  }
39
40
34.9M
  bool CanRead(size_t n) {
41
34.9M
    if (optimistic_) return true;
42
24.8M
    size_t delta = 2 * n;
43
24.8M
    size_t projected_end = pos_ + delta;
44
    // Check for overflow; just in case.
45
24.8M
    if (projected_end < pos_) return false;
46
24.8M
    return projected_end <= len_;
47
24.8M
  }
48
49
  const uint8_t* data_;
50
  size_t len_;
51
  size_t pos_;
52
  bool error_;
53
  bool optimistic_;
54
};
55
56
struct BitSource {
57
20.2k
  BitSource() {}
58
59
9.93k
  void Init(WordSource* in) {
60
9.93k
    val_ = in->GetNextWord();
61
9.93k
    bit_pos_ = 0;
62
9.93k
  }
63
64
3.53M
  uint32_t ReadBits(int nbits, WordSource* in) {
65
3.53M
    if (bit_pos_ + nbits > 16) {
66
1.00M
      uint32_t new_bits = in->GetNextWord();
67
1.00M
      val_ |= new_bits << 16;
68
1.00M
    }
69
3.53M
    uint32_t result = (val_ >> bit_pos_) & kBitMask[nbits];
70
3.53M
    bit_pos_ += nbits;
71
3.53M
    if (bit_pos_ > 16) {
72
1.00M
      bit_pos_ -= 16;
73
1.00M
      val_ >>= 16;
74
1.00M
    }
75
3.53M
    return result;
76
3.53M
  }
77
78
8.84k
  bool Finish() {
79
8.84k
    size_t n_bits = 16 - bit_pos_;
80
8.84k
    if (n_bits > 0) {
81
7.70k
      int padding_bits = (val_ >> bit_pos_) & kBitMask[n_bits];
82
7.70k
      if (padding_bits != 0) return false;
83
7.70k
    }
84
8.82k
    return true;
85
8.84k
  }
86
87
  uint32_t val_;
88
  int bit_pos_;
89
};
90
91
}  // namespace brunsli
92
93
#endif  // BRUNSLI_DEC_BRUNSLI_INPUT_H_