8 #ifndef Sawyer_IntervalMap_H
9 #define Sawyer_IntervalMap_H
11 #include <boost/cstdint.hpp>
12 #include <Sawyer/Assert.h>
13 #include <Sawyer/Map.h>
14 #include <Sawyer/Optional.h>
15 #include <Sawyer/Sawyer.h>
17 #include <boost/serialization/access.hpp>
18 #include <boost/serialization/nvp.hpp>
24 template<
class IntervalMap>
31 template<
class IntervalMap>
42 template<
typename I,
typename T>
49 friend class boost::serialization::access;
52 void serialize(S&,
const unsigned ) {
61 bool merge(
const Interval &leftInterval, Value &leftValue,
const Interval &rightInterval, Value &rightValue) {
62 SAWYER_ARGUSED(leftInterval);
63 SAWYER_ARGUSED(rightInterval);
64 return leftValue == rightValue;
74 SAWYER_ARGUSED(interval);
75 SAWYER_ARGUSED(splitPoint);
84 SAWYER_ARGUSED(interval);
85 SAWYER_ARGUSED(value);
86 SAWYER_ARGUSED(splitPoint);
170 template<
typename I,
typename T,
class Policy = MergePolicy<I, T> >
180 struct IntervalCompare {
182 return a.greatest() < b.greatest();
186 typedef std::pair<Interval, Interval> IntervalPair;
230 friend class boost::serialization::access;
233 void serialize(S &s,
const unsigned ) {
234 s & BOOST_SERIALIZATION_NVP(map_);
235 s & BOOST_SERIALIZATION_NVP(policy_);
236 s & BOOST_SERIALIZATION_NVP(size_);
252 template<
class Interval2,
class T2,
class Policy2>
255 for (OtherIterator otherIter=other.
nodes().begin(); other!=other.
nodes().end(); ++other)
263 template<
class Interval2,
class T2,
class Policy2>
267 for (OtherIterator otherIter=other.
nodes().begin(); other!=other.
nodes().end(); ++other)
283 boost::iterator_range<NodeIterator>
nodes() {
return map_.
nodes(); }
284 boost::iterator_range<ConstNodeIterator>
nodes()
const {
return map_.
nodes(); }
291 boost::iterator_range<ConstIntervalIterator>
intervals()
const {
return map_.
keys(); }
299 boost::iterator_range<ValueIterator>
values() {
return map_.
values(); }
300 boost::iterator_range<ConstValueIterator>
values()
const {
return map_.
values(); }
323 while (ub!=map_.
nodes().end() && ub->
key().least() <= scalar)
329 while (ub!=map_.
nodes().end() && ub->
key().least() <= scalar)
352 return imap.nodes().end();
353 Iter lb = imap.lowerBound(scalar);
354 if (lb!=imap.nodes().end() && lb->key().least() <= scalar)
356 if (lb==imap.nodes().begin())
357 return imap.nodes().end();
378 Iter found = imap.lowerBound(scalar);
379 if (found==imap.nodes().end() || scalar < found->key().
least())
380 return imap.nodes().end();
398 static boost::iterator_range<typename IntervalMapTraits<IMap>::NodeIterator>
401 if (interval.isEmpty())
402 return boost::iterator_range<Iter>(imap.nodes().end(), imap.nodes().end());
403 Iter begin = imap.lowerBound(interval.least());
404 if (begin==imap.nodes().end() || begin->key().least() > interval.greatest())
405 return boost::iterator_range<Iter>(imap.nodes().end(), imap.nodes().end());
406 return boost::iterator_range<Iter>(begin, imap.upperBound(interval.greatest()));
426 if (interval.isEmpty())
427 return imap.nodes().end();
428 Iter lb = imap.lowerBound(interval.least());
429 return lb!=imap.nodes().end() && interval.isOverlapping(lb->key()) ? lb : imap.nodes().end();
442 template<
typename T2,
class Policy2>
443 std::pair<NodeIterator, typename IntervalMap<Interval, T2, Policy2>::ConstNodeIterator>
448 template<
typename T2,
class Policy2>
449 std::pair<ConstNodeIterator, typename IntervalMap<Interval, T2, Policy2>::ConstNodeIterator>
455 template<
class IMap,
typename T2,
class Policy2>
456 static std::pair<typename IntervalMapTraits<IMap>::NodeIterator,
462 while (thisIter!=imap.nodes().end() && otherIter!=other.
nodes().end()) {
463 if (thisIter->key().isOverlapping(otherIter->
key()))
464 return std::make_pair(thisIter, otherIter);
465 if (thisIter->key().greatest() < otherIter->
key().greatest()) {
471 return std::make_pair(imap.nodes().end(), other.
nodes().end());
497 for (Iter iter=start; iter!=imap.nodes().end(); ++iter) {
498 if (isLarge(iter->key(),
size))
501 return imap.nodes().end();
529 Iter best = imap.nodes().end();
530 for (Iter iter=start; iter!=imap.nodes().end(); ++iter) {
531 if (iter->key().size()==
size &&
size!=0)
533 if (iter->key().size() >
size && (best==imap.nodes().end() || iter->key().size() < best->key().size()))
549 if (minAddr < iter->key().least())
551 if (iter->key().greatest() == all.greatest())
553 minAddr = iter->key().greatest() + 1;
567 if (maxAddr > iter->key().greatest())
569 if (iter->key().least() == all.least())
571 maxAddr = iter->key().least() - 1;
599 if (found==
nodes().end())
600 throw std::domain_error(
"key lookup failure; key is not in map domain");
601 return found->
value();
606 if (found==
nodes().end())
607 throw std::domain_error(
"key lookup failure; key is not in map domain");
608 return found->
value();
639 return found ==
nodes().end() ? dflt : found->
value();
643 return found ==
nodes().end() ? dflt : found->
value();
652 static const Value dflt;
654 return found==
nodes().end() ? dflt : found->
value();
688 return map_.
keys().begin()->least();
695 return last->greatest();
704 if (found==
nodes().end())
706 return std::max(lowerLimit, found->
key().least());
715 if (found==
nodes().end())
717 return std::min(upperLimit, found->
key().greatest());
726 if (lowerLimit < iter->key().least())
728 lowerLimit = iter->key().greatest() + 1;
729 if (lowerLimit <= iter->key().least())
741 if (upperLimit > iter->key().greatest())
743 upperLimit = iter->key().least() - 1;
744 if (upperLimit >= iter->key().greatest())
746 if (iter==
nodes().begin())
771 if (erasure.isEmpty())
779 for (iter=
lowerBound(erasure.least()); iter!=
nodes().end() && !erasure.isLeftOf(iter->
key()); ++iter) {
782 if (erasure.isContaining(foundInterval)) {
784 if (eraseBegin==
nodes().end())
786 size_ -= foundInterval.size();
787 }
else if (erasure.least()>foundInterval.least() && erasure.greatest()<foundInterval.greatest()) {
789 ASSERT_require(eraseBegin==
nodes().end());
791 IntervalPair rt = splitInterval(foundInterval, erasure.greatest()+1);
792 Value rightValue = policy_.split(foundInterval, v , rt.second.least());
793 insertions.
insert(rt.second, rightValue);
794 IntervalPair lt = splitInterval(rt.first, erasure.least());
795 policy_.truncate(rt.first, v , erasure.least());
796 insertions.
insert(lt.first, v);
797 size_ -= erasure.
size();
798 }
else if (erasure.least() > foundInterval.least()) {
800 ASSERT_require(eraseBegin==
nodes().end());
802 IntervalPair halves = splitInterval(foundInterval, erasure.least());
803 policy_.truncate(foundInterval, v , erasure.least());
804 insertions.
insert(halves.first, v);
805 size_ -= halves.second.
size();
806 }
else if (erasure.greatest() < foundInterval.greatest()) {
808 if (eraseBegin==
nodes().end())
810 IntervalPair halves = splitInterval(foundInterval, erasure.greatest()+1);
811 Value rightValue = policy_.split(foundInterval, v , halves.second.least());
812 insertions.
insert(halves.second, rightValue);
813 size_ -= halves.first.
size();
818 if (eraseBegin!=
nodes().end())
826 template<
typename T2,
class Policy2>
828 ASSERT_forbid2((
const void*)&other == (
const void*)
this,
"use clear() instead");
830 for (OtherIter oi=other.
nodes().begin(); oi!=other.
nodes().end(); ++oi)
845 if (found!=
nodes().end() && key.isOverlapping(found->
key()))
850 if (key.least() - 1 < key.least()) {
852 if (left!=
nodes().end() &&
853 left->
key().greatest()+1==key.least() &&
854 policy_.merge(left->
key(), left->
value(), key, value)) {
856 std::swap(value, left->
value());
857 size_ -= left->
key().size();
863 if (key.greatest() + 1 > key.greatest()) {
865 if (right!=
nodes().end() &&
866 key.greatest()+1==right->
key().least() &&
867 policy_.merge(key, value, right->
key(), right->
value())) {
869 size_ -= right->
key().size();
882 template<
typename T2,
class Policy2>
884 ASSERT_forbid2((
const void*)&other == (
const void*)
this,
"cannot insert a container into itself");
886 for (OtherIter oi=other.
nodes().begin(); oi!=other.
nodes().end(); ++oi)
900 bool isOverlapping(
const Interval &interval)
const {
904 template<
typename T2,
class Policy2>
905 bool isOverlapping(
const IntervalMap<Interval, T2, Policy2> &other)
const {
909 bool isDistinct(
const Interval &interval)
const {
910 return !isOverlapping(interval);
913 template<
typename T2,
class Policy2>
914 bool isDistinct(
const IntervalMap<Interval, T2, Policy2> &other)
const {
915 return !isOverlapping(other);
923 if (found==
nodes().end())
925 if (key.least() < found->key().least())
927 ASSERT_require(key.isOverlapping(found->key()));
928 if (key.greatest() <= found->key().greatest())
930 key = splitInterval(key, found->key().greatest()+1).second;
935 template<
typename T2,
class Policy2>
936 bool contains(
const IntervalMap<Interval, T2, Policy2> &other)
const {
937 for (
ConstNodeIterator iter=other.nodes().begin(); iter!=other.nodes().end(); ++iter) {
938 if (!contains(iter->key()))
950 ASSERT_forbid(interval.isEmpty());
951 ASSERT_require(splitPoint > interval.least() && splitPoint <= interval.greatest());
955 return IntervalPair(left, right);
959 static bool isLarge(
const Interval &interval, boost::uint64_t
size) {
960 return !interval.isEmpty() && (interval.size()==0 || interval.size() >=
size);
void eraseMultiple(const IntervalMap< Interval, T2, Policy2 > &other)
Erase intervals specified in another IntervalMap.
static IntervalMapTraits< IMap >::NodeIterator findPriorImpl(IMap &imap, const typename Interval::Value &scalar)
Find the last node whose interval starts at or below the specified scalar key.
Bidirectional iterator over values.
boost::iterator_range< ConstNodeIterator > findAll(const Interval &interval) const
Finds all nodes overlapping the specified interval.
Optional< typename Interval::Value > greatestUnmapped(typename Interval::Value upperLimit) const
Returns the limited-maximum unmapped scalar key.
Map & eraseAt(const NodeIterator &iter)
Remove a node by iterator.
Optional< typename Interval::Value > least(typename Interval::Value lowerLimit) const
Returns the limited-minimum scalar key.
boost::iterator_range< NodeIterator > nodes()
Iterators for traversing nodes.
Map::NodeIterator NodeIterator
Node iterator.
Bidirectional iterator over values.
ConstNodeIterator findPrior(const typename Interval::Value &scalar) const
Find the last node whose interval starts at or below the specified scalar key.
NodeIterator upperBound(const Key &key)
Find a node close to a key.
boost::iterator_range< ValueIterator > values()
Iterators for traversing values.
NodeIterator find(const typename Interval::Value &scalar)
Find the node containing the specified scalar key.
std::pair< ConstNodeIterator, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator > findFirstOverlap(typename IntervalMap::ConstNodeIterator thisIter, const IntervalMap< Interval, T2, Policy2 > &other, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator otherIter) const
Find first interval that overlaps with any in another container.
IntervalMap::Value & ValueReference
Reference to value.
bool isEmpty() const
Determines whether this container is empty.
T Value
Types of values in the interval.
static IntervalMapTraits< IMap >::NodeIterator findImpl(IMap &imap, const typename Interval::Value &scalar)
Find the node containing the specified scalar key.
IntervalMap(const IntervalMap< Interval2, T2, Policy2 > &other)
Copy constructor.
static boost::iterator_range< typename IntervalMapTraits< IMap >::NodeIterator > findAllImpl(IMap &imap, const Interval &interval)
Finds all nodes overlapping the specified interval.
ConstNodeIterator upperBound(const typename Interval::Value &scalar) const
Find the first node whose interval begins above the specified scalar key.
ConstNodeIterator bestFit(const typename Interval::Value &size, ConstNodeIterator start) const
Find the best fit node at or after a starting point.
Map::Node Node
Storage node.
std::pair< NodeIterator, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator > findFirstOverlap(typename IntervalMap::NodeIterator thisIter, const IntervalMap< Interval, T2, Policy2 > &other, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator otherIter)
Find first interval that overlaps with any in another container.
const Key & key() const
Key part of key/value node.
boost::iterator_range< ConstIntervalIterator > intervals() const
Iterators for traversing keys.
Bidirectional iterator over keys.
Optional< Value > getOptional(const typename Interval::Value &scalar) const
Lookup and return a value or nothing.
IntervalMap::ValueIterator ValueIterator
Value iterator.
static Interval whole()
Construct an interval that covers the entire domain.
Map & insertMultiple(const OtherNodeIterator &begin, const OtherNodeIterator &end)
Insert multiple values.
NodeIterator lowerBound(const Key &key)
Find a node close to a key.
Interval::Value greatest() const
Returns the maximum scalar key.
const Value & getOrDefault(const typename Interval::Value &scalar) const
Lookup and return a value or a default.
Value split(const Interval &interval, Value &value, const typename Interval::Value &splitPoint)
Split one value into two values.
Policy indicating how values are merged and split.
ConstNodeIterator firstFit(const typename Interval::Value &size, ConstNodeIterator start) const
Find the first fit node at or after a starting point.
const Value & getOrElse(const typename Interval::Value &scalar, const Value &dflt) const
Lookup and return a value or something else.
Bidirectional iterator over key/value nodes.
Map::ConstKeyIterator ConstIntervalIterator
Interval iterator.
void truncate(const Interval &interval, Value &value, const typename Interval::Value &splitPoint)
Discard the right part of a value.
Map::ConstNodeIterator ConstNodeIterator
Node iterator.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
size_t size() const
Number of nodes, keys, or values in this container.
Map & eraseAtMultiple(const Iter &begin, const Iter &end)
Remove multiple nodes by iterator range.
bool merge(const Interval &leftInterval, Value &leftValue, const Interval &rightInterval, Value &rightValue)
Merge two values if possible.
void erase(const Interval &erasure)
Erase the specified interval.
NodeIterator upperBound(const typename Interval::Value &scalar)
Find the first node whose interval begins above the specified scalar key.
Map::ConstValueIterator ConstValueIterator
Value iterator.
boost::iterator_range< NodeIterator > nodes()
Iterators for container nodes.
Bidirectional iterator over key/value nodes.
Interval lastUnmapped(typename Interval::Value maxAddr) const
Find the last unmapped region.
static std::pair< typename IntervalMapTraits< IMap >::NodeIterator, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator > findFirstOverlapImpl(IMap &imap, typename IntervalMapTraits< IMap >::NodeIterator thisIter, const IntervalMap< Interval, T2, Policy2 > &other, typename IntervalMap< Interval, T2, Policy2 >::ConstNodeIterator otherIter)
Find first interval that overlaps with any in another container.
Interval hull() const
Returns the range of values in this map.
static IntervalMapTraits< IMap >::NodeIterator findFirstOverlapImpl(IMap &imap, const Interval &interval)
Find first interval that overlaps with the specified interval.
NodeIterator lowerBound(const typename Interval::Value &scalar)
Find the first node whose interval ends at or above the specified scalar key.
NodeIterator bestFit(const typename Interval::Value &size, NodeIterator start)
Find the best fit node at or after a starting point.
Value & value()
Value part of key/value node.
NodeIterator findPrior(const typename Interval::Value &scalar)
Find the last node whose interval starts at or below the specified scalar key.
bool exists(const typename Interval::Value &size) const
Returns true if element exists.
ConstNodeIterator lowerBound(const typename Interval::Value &scalar) const
Find the first node whose interval ends at or above the specified scalar key.
Name space for the entire library.
void insert(Interval key, Value value, bool makeHole=true)
Insert a key/value pair.
static Interval hull(T v1, T v2)
Construct an interval from two endpoints.
Container::Map< Interval, Value, IntervalCompare > Map
Type of the underlying map.
IntervalMap & operator=(const IntervalMap< Interval2, T2, Policy2 > &other)
Assignment operator.
Range of values delimited by endpoints.
bool isEmpty() const
Determine if the container is empty.
Interval::Value size() const
Returns the number of values represented by this container.
size_t nIntervals() const
Number of nodes in the container.
ConstNodeIterator findFirstOverlap(const Interval &interval) const
Find first interval that overlaps with the specified interval.
static IntervalMapTraits< IMap >::NodeIterator bestFitImpl(IMap &imap, const typename Interval::Value &size, typename IntervalMapTraits< IMap >::NodeIterator start)
Find the best fit node at or after a starting point.
const Value & operator[](const typename Interval::Value &scalar) const
Returns a reference to an existing value.
ConstNodeIterator find(const typename Interval::Value &scalar) const
Find the node containing the specified scalar key.
Optional< typename Interval::Value > leastUnmapped(typename Interval::Value lowerLimit) const
Returns the limited-minimum unmapped scalar key.
boost::iterator_range< ConstValueIterator > values() const
Iterators for traversing values.
Interval firstUnmapped(typename Interval::Value minAddr) const
Find the first unmapped region.
NodeIterator findFirstOverlap(const Interval &interval)
Find first interval that overlaps with the specified interval.
An associative container whose keys are non-overlapping intervals.
Interval::Value least() const
Returns the minimum scalar key.
IntervalMap()
Default constructor.
const Value & get(const typename Interval::Value &scalar) const
Returns a reference to an existing value.
static IntervalMapTraits< IMap >::NodeIterator firstFitImpl(IMap &imap, const typename Interval::Value &size, typename IntervalMapTraits< IMap >::NodeIterator start)
Find the first fit node at or after a starting point.
boost::iterator_range< ConstKeyIterator > keys()
Iterators for container keys.
void clear()
Empties the container.
void insertMultiple(const IntervalMap< Interval, T2, Policy2 > &other, bool makeHole=true)
Insert values from another container.
boost::iterator_range< ValueIterator > values()
Iterators for container values.
NodeIterator firstFit(const typename Interval::Value &size, NodeIterator start)
Find the first fit node at or after a starting point.
Map::ValueIterator ValueIterator
Value iterator.
Map & clear()
Remove all nodes.
IntervalMap::NodeIterator NodeIterator
Node iterator.
boost::iterator_range< NodeIterator > findAll(const Interval &interval)
Finds all nodes overlapping the specified interval.
boost::iterator_range< ConstNodeIterator > nodes() const
Iterators for traversing nodes.
Optional< typename Interval::Value > greatest(typename Interval::Value upperLimit) const
Returns the limited-maximum scalar key.
Value & getOrElse(const typename Interval::Value &scalar, Value &dflt)
Lookup and return a value or something else.