RangeMask.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file RangeMask.h
  15. * @author Gav Wood <i@gavwood.com>
  16. * @date 2014
  17. */
  18. #pragma once
  19. #include <map>
  20. #include <utility>
  21. #include <vector>
  22. #include <iterator>
  23. #include <iostream>
  24. #include <assert.h>
  25. namespace dev
  26. {
  27. class RLPStream;
  28. using UnsignedRange = std::pair<unsigned, unsigned>;
  29. using UnsignedRanges = std::vector<UnsignedRange>;
  30. /**
  31. * Set of elements of a certain "ground range" representable by unions of ranges inside this
  32. * ground range.
  33. * Ranges are given as pairs (begin, end), denoting the interval [begin, end), i.e. end is excluded.
  34. * Supports set-theoretic operators, size and iteration.
  35. */
  36. template <class T>
  37. class RangeMask
  38. {
  39. template <class U> friend std::ostream& operator<<(std::ostream& _out, RangeMask<U> const& _r);
  40. public:
  41. using Range = std::pair<T, T>;
  42. using Ranges = std::vector<Range>;
  43. /// Constructs an empty range mask with empty ground range.
  44. RangeMask(): m_all(0, 0) {}
  45. /// Constructs an empty range mask with ground range [_begin, _end).
  46. RangeMask(T _begin, T _end): m_all(_begin, _end) {}
  47. /// Constructs an empty range mask with ground range _c.
  48. RangeMask(Range const& _c): m_all(_c) {}
  49. /// @returns the union with the range mask _m, taking also the union of the ground ranges.
  50. RangeMask unionedWith(RangeMask const& _m) const { return operator+(_m); }
  51. RangeMask operator+(RangeMask const& _m) const { return RangeMask(*this) += _m; }
  52. /// @returns a new range mask containing the smallest _items elements (not ranges).
  53. RangeMask lowest(decltype(T{} - T{}) _items) const
  54. {
  55. RangeMask ret(m_all);
  56. for (auto i = m_ranges.begin(); i != m_ranges.end() && _items; ++i)
  57. _items -= (ret.m_ranges[i->first] = std::min(i->first + _items, i->second)) - i->first;
  58. return ret;
  59. }
  60. /// @returns the complement of the range mask relative to the ground range.
  61. RangeMask operator~() const { return inverted(); }
  62. /// @returns a copy of this range mask representing the complement relative to the ground range.
  63. RangeMask inverted() const
  64. {
  65. RangeMask ret(m_all);
  66. T last = m_all.first;
  67. for (auto i: m_ranges)
  68. {
  69. if (i.first != last)
  70. ret.m_ranges[last] = i.first;
  71. last = i.second;
  72. }
  73. if (last != m_all.second)
  74. ret.m_ranges[last] = m_all.second;
  75. return ret;
  76. }
  77. /// Changes the range mask to its complement relative to the ground range and returns a
  78. /// reference to itself.
  79. RangeMask& invert() { return *this = inverted(); }
  80. template <class S> RangeMask operator-(S const& _m) const { auto ret = *this; return ret -= _m; }
  81. template <class S> RangeMask& operator-=(S const& _m) { return invert().unionWith(_m).invert(); }
  82. RangeMask& operator+=(RangeMask const& _m) { return unionWith(_m); }
  83. RangeMask& unionWith(RangeMask const& _m)
  84. {
  85. m_all.first = std::min(_m.m_all.first, m_all.first);
  86. m_all.second = std::max(_m.m_all.second, m_all.second);
  87. for (auto const& i: _m.m_ranges)
  88. unionWith(i);
  89. return *this;
  90. }
  91. RangeMask& operator+=(Range const& _m) { return unionWith(_m); }
  92. /// Modifies this range mask to also include the range _m, which has to be a subset of
  93. /// the ground range.
  94. RangeMask& unionWith(Range const& _m);
  95. /// Adds the single element _i to the range mask.
  96. RangeMask& operator+=(T _m) { return unionWith(_m); }
  97. /// Adds the single element _i to the range mask.
  98. RangeMask& unionWith(T _i)
  99. {
  100. return operator+=(Range(_i, _i + 1));
  101. }
  102. bool contains(T _i) const
  103. {
  104. auto it = m_ranges.upper_bound(_i);
  105. if (it == m_ranges.begin())
  106. return false;
  107. return (--it)->second > _i;
  108. }
  109. bool empty() const
  110. {
  111. return m_ranges.empty();
  112. }
  113. bool full() const
  114. {
  115. return m_all.first == m_all.second || (m_ranges.size() == 1 && m_ranges.begin()->first == m_all.first && m_ranges.begin()->second == m_all.second);
  116. }
  117. void clear()
  118. {
  119. m_ranges.clear();
  120. }
  121. void reset()
  122. {
  123. m_ranges.clear();
  124. m_all = std::make_pair(0, 0);
  125. }
  126. /// @returns the ground range.
  127. std::pair<T, T> const& all() const { return m_all; }
  128. /// Extends the ground range to include _i.
  129. void extendAll(T _i) { m_all = std::make_pair(std::min(m_all.first, _i), std::max(m_all.second, _i + 1)); }
  130. class const_iterator: public std::iterator<std::forward_iterator_tag, T>
  131. {
  132. friend class RangeMask;
  133. public:
  134. const_iterator() {}
  135. T operator*() const { return m_value; }
  136. const_iterator& operator++() { if (m_owner) m_value = m_owner->next(m_value); return *this; }
  137. const_iterator operator++(int) { auto ret = *this; if (m_owner) m_value = m_owner->next(m_value); return ret; }
  138. bool operator==(const_iterator const& _i) const { return m_owner == _i.m_owner && m_value == _i.m_value; }
  139. bool operator!=(const_iterator const& _i) const { return !operator==(_i); }
  140. bool operator<(const_iterator const& _i) const { return m_value < _i.m_value; }
  141. private:
  142. const_iterator(RangeMask const& _m, bool _end): m_owner(&_m), m_value(_m.m_ranges.empty() || _end ? _m.m_all.second : _m.m_ranges.begin()->first) {}
  143. RangeMask const* m_owner = nullptr;
  144. T m_value = 0;
  145. };
  146. const_iterator begin() const { return const_iterator(*this, false); }
  147. const_iterator end() const { return const_iterator(*this, true); }
  148. /// @returns the smallest element in the range mask that is larger than _t or the end of the
  149. /// base range if such an element does not exist.
  150. T next(T _t) const
  151. {
  152. _t++;
  153. // find next item in range at least _t
  154. auto uit = m_ranges.upper_bound(_t); // > _t
  155. auto it = uit == m_ranges.begin() ? m_ranges.end() : std::prev(uit);
  156. if (it != m_ranges.end() && it->first <= _t && it->second > _t)
  157. return _t;
  158. return uit == m_ranges.end() ? m_all.second : uit->first;
  159. }
  160. /// @returns the number of elements (not ranges) in the range mask.
  161. size_t size() const
  162. {
  163. size_t c = 0;
  164. for (auto const& r: this->m_ranges)
  165. c += r.second - r.first;
  166. return c;
  167. }
  168. size_t firstOut() const
  169. {
  170. if (m_ranges.empty() || !m_ranges.count(m_all.first))
  171. return m_all.first;
  172. return m_ranges.at(m_all.first);
  173. }
  174. size_t lastIn() const
  175. {
  176. if (m_ranges.empty())
  177. return m_all.first;
  178. return m_ranges.rbegin()->second - 1;
  179. }
  180. private:
  181. /// The ground range.
  182. UnsignedRange m_all;
  183. /// Mapping begin -> end containing the ranges.
  184. std::map<T, T> m_ranges;
  185. };
  186. template <class T> inline std::ostream& operator<<(std::ostream& _out, RangeMask<T> const& _r)
  187. {
  188. _out << _r.m_all.first << "{ ";
  189. for (auto const& i: _r.m_ranges)
  190. _out << "[" << i.first << ", " << i.second << ") ";
  191. _out << "}" << _r.m_all.second;
  192. return _out;
  193. }
  194. template <class T>
  195. RangeMask<T>& RangeMask<T>::unionWith(typename RangeMask<T>::Range const& _m)
  196. {
  197. for (auto i = _m.first; i < _m.second;)
  198. {
  199. assert(i >= m_all.first);
  200. assert(i < m_all.second);
  201. // For each number, we find the element equal or next lower. this, if any, must contain the value.
  202. // First range that starts after i.
  203. auto rangeAfter = m_ranges.upper_bound(i);
  204. // Range before rangeAfter or "end" if the rangeAfter is the first ever...
  205. auto it = rangeAfter == m_ranges.begin() ? m_ranges.end() : std::prev(rangeAfter);
  206. if (it == m_ranges.end() || it->second < i)
  207. {
  208. // i is either before the first range or between two ranges (with some distance
  209. // so that we cannot merge it onto "it").
  210. // lower range is too low to merge.
  211. // if the next higher range is too high.
  212. if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second)
  213. {
  214. // just create a new range
  215. m_ranges[i] = _m.second;
  216. break;
  217. }
  218. else
  219. {
  220. if (rangeAfter->first == i)
  221. // move i to end of range
  222. i = rangeAfter->second;
  223. else
  224. {
  225. // merge with the next higher range
  226. // move i to end of range
  227. i = m_ranges[i] = rangeAfter->second;
  228. m_ranges.erase(rangeAfter);
  229. }
  230. }
  231. }
  232. else if (it->second == i)
  233. {
  234. // The range before i ends with i.
  235. // if the next higher range is too high.
  236. if (rangeAfter == m_ranges.end() || rangeAfter->first > _m.second)
  237. {
  238. // merge with the next lower range
  239. m_ranges[it->first] = _m.second;
  240. break;
  241. }
  242. else
  243. {
  244. // merge with both next lower & next higher.
  245. i = m_ranges[it->first] = rangeAfter->second;
  246. m_ranges.erase(rangeAfter);
  247. }
  248. }
  249. else
  250. i = it->second;
  251. }
  252. return *this;
  253. }
  254. }