wowlib 0.0.0
Read & write World of Warcraft client files — a C++26 core
Loading...
Searching...
No Matches
bit_stream.hpp
Go to the documentation of this file.
1#pragma once
2
9
10#include <cstddef>
11#include <cstdint>
12#include <cstring>
13
14namespace wowlib::db::wdc {
16 class BitReader {
17 public:
20 BitReader(const std::byte* base, std::size_t limit) : _base(base), _limit(limit) {}
21
30 std::uint64_t read(std::size_t bitOffset, std::size_t bits) const {
31 if (bits == 0 || bits > 64) return 0;
32 const std::size_t byte = bitOffset / 8;
33 const std::size_t shift = bitOffset % 8;
34 const std::size_t spanBytes = (shift + bits + 7) / 8;
35 if (byte + spanBytes > _limit) return 0;
36 // Load the touched bytes as two little-endian halves: `lo` holds the
37 // first eight, `hi` the ninth when the value straddles that far.
38 std::uint64_t lo = 0, hi = 0;
39 const std::size_t loBytes = spanBytes > 8 ? 8 : spanBytes;
40 std::memcpy(&lo, _base + byte, loBytes);
41 if (spanBytes > 8) std::memcpy(&hi, _base + byte + 8, spanBytes - 8);
42 // Drop the leading bits that belong to the previous field, then splice
43 // the high half's contribution in above them.
44 std::uint64_t raw = lo >> shift;
45 if (shift != 0 && spanBytes > 8) raw |= hi << (64 - shift);
46 if (bits < 64) raw &= (std::uint64_t{1} << bits) - 1;
47 return raw;
48 }
49
50 private:
51 const std::byte* _base;
52 std::size_t _limit;
53 };
54
59 class BitWriter {
60 public:
63 BitWriter(std::byte* base, std::size_t limit) : _base(base), _limit(limit) {}
64
71 void write(std::size_t bitOffset, std::size_t bits, std::uint64_t value) {
72 for (std::size_t i = 0; i < bits; ++i) {
73 const std::size_t bo = bitOffset + i;
74 if (bo / 8 >= _limit) return;
75 const std::byte mask{static_cast<unsigned char>(1u << (bo % 8))};
76 if ((value >> i) & 1) _base[bo / 8] |= mask;
77 else _base[bo / 8] &= ~mask;
78 }
79 }
80
81 private:
82 std::byte* _base;
83 std::size_t _limit;
84 };
85}
std::uint64_t read(std::size_t bitOffset, std::size_t bits) const
Read bits (<= 64) starting at absolute bit offset bitOffset.
BitReader(const std::byte *base, std::size_t limit)
BitWriter(std::byte *base, std::size_t limit)
void write(std::size_t bitOffset, std::size_t bits, std::uint64_t value)
Write the low bits of value starting at absolute bit offset bitOffset, overwriting whatever was there...