10 for (
auto& r : requests) {
11 r.data =
read(r.offset, r.length);
18 : path_(path), stream_(path, std::ios::binary | std::ios::ate) {
22 size_ =
static_cast<std::uint64_t
>(stream_.tellg());
34 const std::uint64_t n = std::min<std::uint64_t>(length, size_ -
offset);
35 std::vector<std::uint8_t> out(
static_cast<std::size_t
>(n));
38 stream_.seekg(
static_cast<std::streamoff
>(
offset), std::ios::beg);
39 stream_.read(
reinterpret_cast<char*
>(out.data()),
static_cast<std::streamsize
>(n));
40 if (stream_.gcount() !=
static_cast<std::streamsize
>(n)) {
49 std::uint64_t min_req_size)
50 : inner_(std::move(inner)), min_req_size_(min_req_size) {}
54std::uint64_t BufferedRangeReader::clamped_fetch(std::uint64_t
offset, std::uint64_t length) {
58 const std::uint64_t want = std::max<std::uint64_t>(length, min_req_size_);
59 const std::uint64_t total = inner_->total_size();
62 return std::min<std::uint64_t>(want, total -
offset);
65bool BufferedRangeReader::covers(std::uint64_t
offset, std::uint64_t length)
const {
69 if (buf_.empty() ||
offset < buf_offset_)
75std::vector<std::uint8_t> BufferedRangeReader::slice_from_buffer(std::uint64_t
offset,
76 std::uint64_t length)
const {
77 const std::uint64_t rel =
offset - buf_offset_;
78 return std::vector<std::uint8_t>(buf_.begin() +
static_cast<std::ptrdiff_t
>(rel),
79 buf_.begin() +
static_cast<std::ptrdiff_t
>(rel + length));
86 if (!covers(
offset, length)) {
87 buf_ = inner_->read(
offset, clamped_fetch(
offset, length));
91 const std::uint64_t rel =
offset - buf_offset_;
92 if (rel >= buf_.size())
94 const std::uint64_t n = std::min<std::uint64_t>(length, buf_.size() - rel);
95 return slice_from_buffer(
offset, n);
108 std::vector<Miss> misses;
109 misses.reserve(requests.size());
111 for (std::size_t i = 0; i < requests.size(); ++i) {
112 auto& r = requests[i];
115 }
else if (covers(r.offset, r.length)) {
116 r.data = slice_from_buffer(r.offset, r.length);
118 misses.push_back(Miss{i, r.offset, r.length, clamped_fetch(r.offset, r.length)});
126 std::vector<RangeRequest> fetches;
127 fetches.reserve(misses.size());
128 for (
const auto& m : misses) {
132 inner_->read_batch(fetches);
135 for (std::size_t k = 0; k < misses.size(); ++k) {
136 const auto& m = misses[k];
137 auto& got = fetches[k].data;
138 const std::uint64_t n = std::min<std::uint64_t>(m.want, got.size());
139 requests[m.index].data.assign(got.begin(), got.begin() +
static_cast<std::ptrdiff_t
>(n));
144 buf_offset_ = misses.back().offset;
145 buf_ = std::move(fetches.back().data);
void read_batch(std::vector< RangeRequest > &requests) override
Fill every request, preserving order.
std::vector< std::uint8_t > read(std::uint64_t offset, std::uint64_t length) override
Read length bytes at offset, subject to the contract above.
std::uint64_t total_size() override
Total byte length of the resource.
BufferedRangeReader(std::shared_ptr< RangeReader > inner, std::uint64_t min_req_size)
Every failure the library reports is one of these.
FileRangeReader(const std::string &path)
std::uint64_t total_size() override
Total byte length of the resource.
std::vector< std::uint8_t > read(std::uint64_t offset, std::uint64_t length) override
Read length bytes at offset, subject to the contract above.
virtual void read_batch(std::vector< RangeRequest > &requests)
Fill every request, preserving order.
virtual std::vector< std::uint8_t > read(std::uint64_t offset, std::uint64_t length)=0
Read length bytes at offset, subject to the contract above.
std::uint64_t range_end(std::uint64_t offset, std::uint64_t length)
End of a range, checked.
One range in a batched read. data is filled in place by read_batch().