#pragma once
#include <vector>
#include <cstddef>
template<class It>
class IteratorRange {
public:
IteratorRange(It begin, It end) : begin_(begin), end_(end), size_(std::distance(begin, end)) {}
typedef It iterator;
It begin() const {
return begin_;
}
It end() const {
return end_;
}
std::size_t size() const {
return size_;
}
private:
It begin_, end_;
std::size_t size_;
};
template <typename It>
class Slicer {
public:
Slicer(It begin, It end, int page_size) : begin_(begin), end_(end), page_size_(page_size) {
while (end - begin >= page_size_) {
auto new_begin = begin;
begin += page_size_;
pages_.push_back(IteratorRange<It>(new_begin, begin));
}
if (begin != end) {
pages_.push_back(IteratorRange<It>(begin, end));
}
}
typename std::vector<IteratorRange<It>>::iterator begin() {
return pages_.begin();
}
typename std::vector<IteratorRange<It>>::iterator end() {
return pages_.end();
}
std::size_t size() const {
return pages_.size();
}
private:
It begin_, end_;
int page_size_;
std::vector<IteratorRange<It>> pages_;
};
template <typename C>
Slicer<typename C::iterator> Slice(C& c, std::size_t page_size) {
return Slicer<typename C::iterator>(c.begin(), c.end(), page_size);
}
template <typename C>
Slicer<typename C::const_iterator> Slice(const C& c, std::size_t page_size) {
return Slicer<typename C::const_iterator>(c.begin(), c.end(), page_size);
}