Coverage Report

Created: 2025-07-18 06:08

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