Pixie
Loading...
Searching...
No Matches
packed_bit_builder.h
1#pragma once
2
3#include <algorithm>
4#include <cstddef>
5#include <cstdint>
6#include <limits>
7#include <stdexcept>
8#include <utility>
9#include <vector>
10
11namespace pixie {
12
21 private:
22 std::size_t size_ = 0;
23 std::vector<std::uint64_t> data_;
24
25 public:
29 void write_bit(bool bit) {
30 if (size_ % 64 == 0) {
31 data_.push_back(static_cast<std::uint64_t>(bit));
32 } else if (bit) {
33 data_.back() |= 1ull << (size_ % 64);
34 }
35 ++size_;
36 }
37
44 void write_bits(std::uint64_t bits, std::size_t width) {
45 if (width > 64) {
46 throw std::invalid_argument("Packed bit width is greater than 64");
47 }
48 if (width == 0) {
49 return;
50 }
51 if (size_ > std::numeric_limits<std::size_t>::max() - width) {
52 throw std::length_error("Packed bit sequence is too large");
53 }
54
55 const std::size_t offset = size_ % 64;
56 if (offset == 0) {
57 data_.push_back(width == 64 ? bits : bits & ((1ull << width) - 1));
58 } else {
59 const std::size_t prefix = std::min(width, 64 - offset);
60 const std::uint64_t prefix_mask =
61 prefix == 64 ? ~std::uint64_t{0} : (1ull << prefix) - 1;
62 data_.back() |= (bits & prefix_mask) << offset;
63 if (prefix < width) {
64 data_.push_back(bits >> prefix);
65 }
66 }
67 size_ += width;
68 }
69
71 std::size_t size_bits() const noexcept { return size_; }
72
76 void reserve_bits(std::size_t size_bits) {
77 const std::size_t words =
78 size_bits / 64 + static_cast<std::size_t>(size_bits % 64 != 0);
79 data_.reserve(words);
80 }
81
85 std::vector<std::uint64_t> take_words() {
86 size_ = 0;
87 return std::exchange(data_, {});
88 }
89};
90
91} // namespace pixie
Builder for a packed LSB-first bit sequence.
Definition packed_bit_builder.h:20
void write_bit(bool bit)
Append one bit.
Definition packed_bit_builder.h:29
std::vector< std::uint64_t > take_words()
Transfer the packed words and reset this builder.
Definition packed_bit_builder.h:85
std::size_t size_bits() const noexcept
Return the number of appended bits.
Definition packed_bit_builder.h:71
void reserve_bits(std::size_t size_bits)
Reserve storage for at least size_bits bits.
Definition packed_bit_builder.h:76
void write_bits(std::uint64_t bits, std::size_t width)
Append the low width bits of bits, least-significant bit first.
Definition packed_bit_builder.h:44