#endif
-template<typename T>
+template<typename T, typename Map = std::map<T,T>>
class interval_set {
public:
class iterator : public std::iterator <std::forward_iterator_tag, T>
{
public:
- explicit iterator(typename std::map<T,T>::iterator iter)
+ explicit iterator(typename Map::iterator iter)
: _iter(iter)
{ }
return prev;
}
- friend class interval_set<T>::const_iterator;
+ friend class interval_set<T,Map>::const_iterator;
protected:
- typename std::map<T,T>::iterator _iter;
- friend class interval_set<T>;
+ typename Map::iterator _iter;
+ friend class interval_set<T,Map>;
};
class const_iterator : public std::iterator <std::forward_iterator_tag, T>
{
public:
- explicit const_iterator(typename std::map<T,T>::const_iterator iter)
+ explicit const_iterator(typename Map::const_iterator iter)
: _iter(iter)
{ }
}
protected:
- typename std::map<T,T>::const_iterator _iter;
+ typename Map::const_iterator _iter;
};
interval_set() : _size(0) {}
- interval_set(std::map<T,T>& other) {
+ interval_set(Map& other) {
m.swap(other);
_size = 0;
for (auto& i : m) {
return m.size();
}
- typename interval_set<T>::iterator begin() {
- return typename interval_set<T>::iterator(m.begin());
+ typename interval_set<T,Map>::iterator begin() {
+ return typename interval_set<T,Map>::iterator(m.begin());
}
- typename interval_set<T>::iterator lower_bound(T start) {
- return typename interval_set<T>::iterator(find_inc_m(start));
+ typename interval_set<T,Map>::iterator lower_bound(T start) {
+ return typename interval_set<T,Map>::iterator(find_inc_m(start));
}
- typename interval_set<T>::iterator end() {
- return typename interval_set<T>::iterator(m.end());
+ typename interval_set<T,Map>::iterator end() {
+ return typename interval_set<T,Map>::iterator(m.end());
}
- typename interval_set<T>::const_iterator begin() const {
- return typename interval_set<T>::const_iterator(m.begin());
+ typename interval_set<T,Map>::const_iterator begin() const {
+ return typename interval_set<T,Map>::const_iterator(m.begin());
}
- typename interval_set<T>::const_iterator lower_bound(T start) const {
- return typename interval_set<T>::const_iterator(find_inc(start));
+ typename interval_set<T,Map>::const_iterator lower_bound(T start) const {
+ return typename interval_set<T,Map>::const_iterator(find_inc(start));
}
- typename interval_set<T>::const_iterator end() const {
- return typename interval_set<T>::const_iterator(m.end());
+ typename interval_set<T,Map>::const_iterator end() const {
+ return typename interval_set<T,Map>::const_iterator(m.end());
}
// helpers
private:
- typename std::map<T,T>::const_iterator find_inc(T start) const {
- typename std::map<T,T>::const_iterator p = m.lower_bound(start); // p->first >= start
+ typename Map::const_iterator find_inc(T start) const {
+ typename Map::const_iterator p = m.lower_bound(start); // p->first >= start
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
return p;
}
- typename std::map<T,T>::iterator find_inc_m(T start) {
- typename std::map<T,T>::iterator p = m.lower_bound(start);
+ typename Map::iterator find_inc_m(T start) {
+ typename Map::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might overlap?
return p;
}
- typename std::map<T,T>::const_iterator find_adj(T start) const {
- typename std::map<T,T>::const_iterator p = m.lower_bound(start);
+ typename Map::const_iterator find_adj(T start) const {
+ typename Map::const_iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
return p;
}
- typename std::map<T,T>::iterator find_adj_m(T start) {
- typename std::map<T,T>::iterator p = m.lower_bound(start);
+ typename Map::iterator find_adj_m(T start) {
+ typename Map::iterator p = m.lower_bound(start);
if (p != m.begin() &&
(p == m.end() || p->first > start)) {
p--; // might touch?
}
void bound_encode(size_t& p) const {
- denc_traits<std::map<T,T>>::bound_encode(m, p);
+ denc_traits<Map>::bound_encode(m, p);
}
void encode(bufferlist::contiguous_appender& p) const {
denc(m, p);
}
void encode_nohead(bufferlist::contiguous_appender& p) const {
- denc_traits<std::map<T,T>>::encode_nohead(m, p);
+ denc_traits<Map>::encode_nohead(m, p);
}
void decode_nohead(int n, bufferptr::iterator& p) {
- denc_traits<std::map<T,T>>::decode_nohead(n, m, p);
+ denc_traits<Map>::decode_nohead(n, m, p);
_size = 0;
for (const auto& i : m) {
_size += i.second;
}
bool contains(T i, T *pstart=0, T *plen=0) const {
- typename std::map<T,T>::const_iterator p = find_inc(i);
+ typename Map::const_iterator p = find_inc(i);
if (p == m.end()) return false;
if (p->first > i) return false;
if (p->first+p->second <= i) return false;
return true;
}
bool contains(T start, T len) const {
- typename std::map<T,T>::const_iterator p = find_inc(start);
+ typename Map::const_iterator p = find_inc(start);
if (p == m.end()) return false;
if (p->first > start) return false;
if (p->first+p->second <= start) return false;
}
T range_start() const {
assert(!empty());
- typename std::map<T,T>::const_iterator p = m.begin();
+ typename Map::const_iterator p = m.begin();
return p->first;
}
T range_end() const {
assert(!empty());
- typename std::map<T,T>::const_iterator p = m.end();
+ typename Map::const_iterator p = m.end();
p--;
return p->first+p->second;
}
// interval start after p (where p not in set)
bool starts_after(T i) const {
assert(!contains(i));
- typename std::map<T,T>::const_iterator p = find_inc(i);
+ typename Map::const_iterator p = find_inc(i);
if (p == m.end()) return false;
return true;
}
T start_after(T i) const {
assert(!contains(i));
- typename std::map<T,T>::const_iterator p = find_inc(i);
+ typename Map::const_iterator p = find_inc(i);
return p->first;
}
// interval end that contains start
T end_after(T start) const {
assert(contains(start));
- typename std::map<T,T>::const_iterator p = find_inc(start);
+ typename Map::const_iterator p = find_inc(start);
return p->first+p->second;
}
//cout << "insert " << start << "~" << len << endl;
assert(len > 0);
_size += len;
- typename std::map<T,T>::iterator p = find_adj_m(start);
+ typename Map::iterator p = find_adj_m(start);
if (p == m.end()) {
m[start] = len; // new interval
if (pstart)
p->second += len; // append to end
- typename std::map<T,T>::iterator n = p;
+ typename Map::iterator n = p;
n++;
if (n != m.end() &&
start+len == n->first) { // combine with next, too!
}
}
- void swap(interval_set<T>& other) {
+ void swap(interval_set<T,Map>& other) {
m.swap(other.m);
std::swap(_size, other._size);
}
}
void erase(T start, T len) {
- typename std::map<T,T>::iterator p = find_inc_m(start);
+ typename Map::iterator p = find_inc_m(start);
_size -= len;
assert(_size >= 0);
void subtract(const interval_set &a) {
- for (typename std::map<T,T>::const_iterator p = a.m.begin();
+ for (typename Map::const_iterator p = a.m.begin();
p != a.m.end();
p++)
erase(p->first, p->second);
}
void insert(const interval_set &a) {
- for (typename std::map<T,T>::const_iterator p = a.m.begin();
+ for (typename Map::const_iterator p = a.m.begin();
p != a.m.end();
p++)
insert(p->first, p->second);
return;
}
- typename std::map<T,T>::const_iterator pa = a.m.begin();
- typename std::map<T,T>::const_iterator pb = b.m.begin();
+ typename Map::const_iterator pa = a.m.begin();
+ typename Map::const_iterator pb = b.m.begin();
typename decltype(m)::iterator mi = m.begin();
while (pa != a.m.end() && pb != b.m.end()) {
if (big.size() / size() < 10)
return subset_size_sym(big);
- for (typename std::map<T,T>::const_iterator i = m.begin();
+ for (typename Map::const_iterator i = m.begin();
i != m.end();
i++)
if (!big.contains(i->first, i->second)) return false;
if (end == start) {
return;
}
- typename std::map<T,T>::const_iterator p = other.find_inc(start);
+ typename Map::const_iterator p = other.find_inc(start);
if (p == other.m.end())
return;
if (p->first < start) {
*/
void span_of(const interval_set &other, T start, T len) {
clear();
- typename std::map<T,T>::const_iterator p = other.find_inc(start);
+ typename Map::const_iterator p = other.find_inc(start);
if (p == other.m.end())
return;
if (p->first < start) {
}
/*
- * Move contents of m into another std::map<T,T>. Use that instead of
- * encoding interval_set into bufferlist then decoding it back into std::map.
+ * Move contents of m into another Map. Use that instead of
+ * encoding interval_set into bufferlist then decoding it back into Map.
*/
- void move_into(std::map<T,T>& other) {
+ void move_into(Map& other) {
other = std::move(m);
}
private:
// data
int64_t _size;
- std::map<T,T> m; // map start -> len
+ Map m; // map start -> len
};
// declare traits explicitly because (1) it's templatized, and (2) we
// want to include _nohead variants.
-template<typename T>
-struct denc_traits<interval_set<T>> {
+template<typename T, typename Map>
+struct denc_traits<interval_set<T,Map>> {
static constexpr bool supported = true;
static constexpr bool bounded = false;
static constexpr bool featured = false;
- static constexpr bool need_contiguous = denc_traits<T>::need_contiguous;
- static void bound_encode(const interval_set<T>& v, size_t& p) {
+ static constexpr bool need_contiguous = denc_traits<T,Map>::need_contiguous;
+ static void bound_encode(const interval_set<T,Map>& v, size_t& p) {
v.bound_encode(p);
}
- static void encode(const interval_set<T>& v,
+ static void encode(const interval_set<T,Map>& v,
bufferlist::contiguous_appender& p) {
v.encode(p);
}
- static void decode(interval_set<T>& v, bufferptr::iterator& p) {
+ static void decode(interval_set<T,Map>& v, bufferptr::iterator& p) {
v.decode(p);
}
template<typename U=T>
static typename std::enable_if<sizeof(U) && !need_contiguous>::type
- decode(interval_set<T>& v, bufferlist::iterator& p) {
+ decode(interval_set<T,Map>& v, bufferlist::iterator& p) {
v.decode(p);
}
- static void encode_nohead(const interval_set<T>& v,
+ static void encode_nohead(const interval_set<T,Map>& v,
bufferlist::contiguous_appender& p) {
v.encode_nohead(p);
}
- static void decode_nohead(size_t n, interval_set<T>& v,
+ static void decode_nohead(size_t n, interval_set<T,Map>& v,
bufferptr::iterator& p) {
v.decode_nohead(n, p);
}
};
-template<class T>
-inline std::ostream& operator<<(std::ostream& out, const interval_set<T> &s) {
+template<class T, typename Map>
+inline std::ostream& operator<<(std::ostream& out, const interval_set<T,Map> &s) {
out << "[";
const char *prequel = "";
- for (typename interval_set<T>::const_iterator i = s.begin();
+ for (typename interval_set<T,Map>::const_iterator i = s.begin();
i != s.end();
++i)
{