Coverage Report

Created: 2025-10-10 06:44

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