76 std::uint64_t offset, std::size_t length)
const noexcept {
77 if (slots_ == 0 || length == 0)
return;
78 if (offset > logical_end || length > logical_end - offset) {
85 const auto last = (offset + length - 1) /
kPageBytes;
86 for (
auto& tag : tags_)
87 if (tag.file == file && tag.page >= first && tag.page <= last) tag.page = kInvalid;
91 void read(
const File&
source,
bool plain_disk, std::uint64_t logical_end,
92 unsigned file, std::uint64_t offset,
void* destination, std::size_t length)
const {
93 if (!plain_disk || slots_ == 0 || length == 0
94 || offset >= logical_end || length > logical_end - offset) {
95 source.read(offset, destination, length);
99 bytes_.reset(
new (std::nothrow)
unsigned char[slots_ *
kPageBytes]);
101 source.read(offset, destination, length);
105 auto* output =
static_cast<unsigned char*
>(destination);
106 while (length != 0) {
109 const auto within =
static_cast<std::size_t
>(offset - base);
110 const auto valid =
static_cast<std::size_t
>(
111 std::min<std::uint64_t>(
kPageBytes, logical_end - base));
114 const auto slot =
static_cast<std::size_t
>((page + file * 7ULL) % slots_);
115 auto& tag = tags_[slot];
116 auto* line = bytes_.get() + slot *
kPageBytes;
117 if (tag.page != page || tag.file != file) {
119 source.read(base, line, valid);
123 const auto count = std::min(length, valid - within);
124 std::memcpy(output, line + within, count);