Coverage Report

Created: 2026-08-31 07:17

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
278k
      : data_(data),
23
278k
        len_(len & ~1),
24
278k
        pos_(0),
25
278k
        error_(false),
26
278k
        optimistic_(optimistic) {}
27
28
2.60M
  uint16_t GetNextWord() {
29
2.60M
    uint16_t val = 0;
30
2.60M
    if (pos_ < len_) { /* NB: both pos_ and len_ are even. */
31
2.55M
      val = BRUNSLI_UNALIGNED_LOAD16LE(data_ + pos_);
32
2.55M
    } else {
33
41.1k
      error_ = true;
34
41.1k
    }
35
    // TODO(eustas): take care of overflows?
36
2.60M
    pos_ += 2;
37
2.60M
    return val;
38
2.60M
  }
39
40
59.4M
  bool CanRead(size_t n) {
41
59.4M
    if (optimistic_) return true;
42
24.0M
    size_t delta = 2 * n;
43
24.0M
    size_t projected_end = pos_ + delta;
44
    // Check for overflow; just in case.
45
24.0M
    if (projected_end < pos_) return false;
46
24.0M
    return projected_end <= len_;
47
24.0M
  }
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
39.9k
  BitSource() {}
58
59
20.2k
  void Init(WordSource* in) {
60
20.2k
    val_ = in->GetNextWord();
61
20.2k
    bit_pos_ = 0;
62
20.2k
  }
63
64
2.90M
  uint32_t ReadBits(int nbits, WordSource* in) {
65
2.90M
    if (bit_pos_ + nbits > 16) {
66
742k
      uint32_t new_bits = in->GetNextWord();
67
742k
      val_ |= new_bits << 16;
68
742k
    }
69
2.90M
    uint32_t result = (val_ >> bit_pos_) & kBitMask[nbits];
70
2.90M
    bit_pos_ += nbits;
71
2.90M
    if (bit_pos_ > 16) {
72
742k
      bit_pos_ -= 16;
73
742k
      val_ >>= 16;
74
742k
    }
75
2.90M
    return result;
76
2.90M
  }
77
78
18.1k
  bool Finish() {
79
18.1k
    size_t n_bits = 16 - bit_pos_;
80
18.1k
    if (n_bits > 0) {
81
15.5k
      int padding_bits = (val_ >> bit_pos_) & kBitMask[n_bits];
82
15.5k
      if (padding_bits != 0) return false;
83
15.5k
    }
84
18.0k
    return true;
85
18.1k
  }
86
87
  uint32_t val_;
88
  int bit_pos_;
89
};
90
91
}  // namespace brunsli
92
93
#endif  // BRUNSLI_DEC_BRUNSLI_INPUT_H_