11#include <Sawyer/Interval.h>
12#include <Sawyer/Optional.h>
13#include <Sawyer/Sawyer.h>
14#include <boost/range/iterator_range.hpp>
16#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
17#include <boost/serialization/map.hpp>
20#ifdef SAWYER_HAVE_CEREAL
21#include <cereal/types/map.hpp>
70 class Cmp = std::less<K>,
71 class Alloc = std::allocator<std::pair<const K, T> > >
80 typedef std::map<Key, Value, Comparator, Alloc> StlMap;
83#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
85 friend class boost::serialization::access;
88 void serialize(S &s,
const unsigned ) {
89 s & BOOST_SERIALIZATION_NVP(map_);
93#ifdef SAWYER_HAVE_CEREAL
95 friend class cereal::access;
97 template<
class Archive>
98 void CEREAL_SERIALIZE_FUNCTION_NAME(Archive &archive) {
99 archive(CEREAL_NVP(map_));
107 class Node:
private std::pair<const Key, Value> {
110 explicit Node(
const std::pair<const Key, Value> &pair): std::pair<const Key, Value>(pair) {}
116 const Key&
key()
const {
return this->first; }
132 template<
class Derived,
class Value,
class BaseIterator>
133 class BidirectionalIterator {
137 using iterator_category = std::bidirectional_iterator_tag;
138 using value_type =
Value;
139 using difference_type = std::ptrdiff_t;
140 using pointer =
Value*;
141 using reference =
Value&;
145 BidirectionalIterator() {}
146 BidirectionalIterator(
const BaseIterator &base): base_(base) {}
147 BidirectionalIterator(
const BidirectionalIterator &other): base_(other.base_) {}
150 Derived& operator=(
const Derived &other) { base_ = other.base();
return *derived(); }
151 BidirectionalIterator& operator=(
const BidirectionalIterator &other) { base_ = other.base();
return *
this; }
154 Derived& operator++() { ++base_;
return *derived(); }
157 Derived operator++(
int) { Derived old=*derived(); ++*
this;
return old; }
160 Derived& operator--() { --base_;
return *derived(); }
163 Derived operator--(
int) { Derived old=*derived(); --*
this;
return old; }
169 template<
class OtherIter>
bool operator==(
const OtherIter &other)
const {
return base_ == other.base(); }
174 template<
class OtherIter>
bool operator!=(
const OtherIter &other)
const {
return base_ != other.base(); }
176 const BaseIterator& base()
const {
return base_; }
178 Derived* derived() {
return static_cast<Derived*
>(
this); }
179 const Derived* derived()
const {
return static_cast<const Derived*
>(
this); }
187 class NodeIterator:
public BidirectionalIterator<NodeIterator, Node, typename StlMap::iterator> {
188 typedef BidirectionalIterator<NodeIterator, Node, typename StlMap::iterator> Super;
206 NodeIterator(
const typename StlMap::iterator &base): Super(base) {}
213 class ConstNodeIterator:
public BidirectionalIterator<ConstNodeIterator, const Node, typename StlMap::const_iterator> {
214 typedef BidirectionalIterator<ConstNodeIterator, const Node, typename StlMap::const_iterator> Super;
236 ConstNodeIterator(
const typename StlMap::iterator &base): Super(typename StlMap::const_iterator(base)) {}
243 class ConstKeyIterator:
public BidirectionalIterator<ConstKeyIterator, const Key, typename StlMap::const_iterator> {
244 typedef BidirectionalIterator<ConstKeyIterator, const Key, typename StlMap::const_iterator> Super;
271 class ValueIterator:
public BidirectionalIterator<ValueIterator, Value, typename StlMap::iterator> {
272 typedef BidirectionalIterator<ValueIterator, Value, typename StlMap::iterator> Super;
296 class ConstValueIterator:
public BidirectionalIterator<ConstValueIterator, const Value, typename StlMap::const_iterator> {
297 typedef BidirectionalIterator<ConstValueIterator, const Value, typename StlMap::const_iterator> Super;
338 : map_(comparator, allocator) {}
349 template<
class Key2,
class T2,
class Cmp2,
class Alloc2>
352 boost::iterator_range<OtherIterator> otherNodes = other.
nodes();
353 for (OtherIterator otherIter=otherNodes.begin(); otherIter!=otherNodes.end(); ++otherIter)
354 map_.insert(map_.end(), std::make_pair(
Key(otherIter->key()),
Value(otherIter->value())));
357 Map& operator=(
const Map &other) {
359 for (
const auto &node: other.
nodes())
360 map_.
insert(map_.end(), std::make_pair(node.key(), node.value()));
367 template<
class Key2,
class T2,
class Cmp2,
class Alloc2>
371 boost::iterator_range<OtherIterator> otherNodes = other.
nodes();
372 for (OtherIterator otherIter=otherNodes.begin(); otherIter!=otherNodes.end(); ++otherIter)
373 map_.insert(map_.end(), std::make_pair(
Key(otherIter->key()),
Value(otherIter->value())));
387 boost::iterator_range<NodeIterator>
nodes() {
390 boost::iterator_range<ConstNodeIterator>
nodes()
const {
400 boost::iterator_range<ConstKeyIterator>
keys() {
403 boost::iterator_range<ConstKeyIterator>
keys()
const {
414 boost::iterator_range<ValueIterator>
values() {
417 boost::iterator_range<ConstValueIterator>
values()
const {
445 return map_.begin()->first;
451 typename StlMap::const_iterator last = map_.end();
481 return map_.find(key);
484 return map_.find(key);
494 return map_.find(key)!=map_.end();
507 return map_.lower_bound(key);
510 return map_.lower_bound(key);
524 return map_.upper_bound(key);
527 return map_.upper_bound(key);
566 typename StlMap::iterator found = map_.find(key);
567 if (found==map_.end())
568 throw std::domain_error(
"key lookup failure; key is not in map domain");
569 return found->second;
572 typename StlMap::const_iterator found = map_.find(key);
573 if (found==map_.end())
574 throw std::domain_error(
"key lookup failure; key is not in map domain");
575 return found->second;
603 typename StlMap::const_iterator found = map_.find(key);
615 typename StlMap::iterator found = map_.find(key);
616 return found == map_.end() ? dflt : found->second;
619 typename StlMap::const_iterator found = map_.find(key);
620 return found == map_.end() ? dflt : found->second;
630 static const Value dflt;
631 typename StlMap::const_iterator found = map_.find(key);
632 return found==map_.end() ? dflt : found->second;
647 std::pair<typename StlMap::iterator, bool> inserted = map_.
insert(std::make_pair(key, value));
648 if (!inserted.second)
649 inserted.first->second = value;
681 template<
class OtherNodeIterator>
683 for (OtherNodeIterator otherIter=begin; otherIter!=end; ++otherIter)
687 template<
class OtherNodeIterator>
701 return map_.insert(std::make_pair(key, value)).first->second;
712 return map_.insert(std::make_pair(key, T())).first->second;
721 template<
class OtherNodeIterator>
723 for (OtherNodeIterator otherIter=range.begin(); otherIter!=range.end(); ++otherIter)
757 template<
class OtherKeyIterator>
759 for (OtherKeyIterator otherIter=range.begin(); otherIter!=range.end(); ++otherIter)
772 map_.
erase(iter.base());
777 ASSERT_require(iter !=
keys().end());
778 typename StlMap::iterator stdIter = map_.find(*iter);
779 ASSERT_require(stdIter != map_.end());
784 map_.
erase(iter.base());
798 map_.
erase(begin.base(), end.base());
803 map_.
erase(range.begin().base(), range.end().base());
Range of values delimited by endpoints.
static Interval hull(T v1, T v2)
Construct an interval from two endpoints.
Bidirectional iterator over keys.
ConstKeyIterator(const ConstNodeIterator &other)
Copy constructor.
ConstKeyIterator(const NodeIterator &other)
Copy constructor.
const Key * operator->() const
Returns a pointer to the interval of the storage node.
ConstKeyIterator(const ConstKeyIterator &other)
Copy constructor.
ConstKeyIterator & operator=(const ConstKeyIterator &other)
Assignment.
const Key & operator*() const
Dereference iterator to return the interval of the storage node.
Bidirectional iterator over key/value nodes.
const Node & operator*() const
Dereference iterator to return a storage node.
ConstNodeIterator(const NodeIterator &other)
Copy constructor.
const Node * operator->() const
Returns a pointer to a storage node.
ConstNodeIterator & operator=(const ConstNodeIterator &other)
Assignment.
ConstNodeIterator(const ConstNodeIterator &other)
Copy constructor.
Bidirectional iterator over values.
ConstValueIterator(const ConstValueIterator &other)
Copy constructor.
ConstValueIterator(const ConstNodeIterator &other)
Copy constructor.
ConstValueIterator & operator=(const ConstValueIterator &other)
Assignment.
ConstValueIterator(const ValueIterator &other)
Copy constructor.
const Value & operator*() const
Dereference iterator to return the value of the storage node.
ConstValueIterator(const NodeIterator &other)
Copy constructor.
const Value * operator->() const
Returns a pointer to the value of the storage node.
Bidirectional iterator over key/value nodes.
NodeIterator(const NodeIterator &other)
Copy constructor.
NodeIterator & operator=(const NodeIterator &other)
Assignment.
Node * operator->() const
Returns a pointer to a storage node.
Node & operator*() const
Dereference iterator to return a storage node.
const Key & key() const
Key part of key/value node.
const Value & value() const
Value part of key/value node.
Value & value()
Value part of key/value node.
Bidirectional iterator over values.
ValueIterator(const ValueIterator &other)
Copy constructor.
Value & operator*() const
Dereference iterator to return the value of the storage node.
ValueIterator & operator=(const ValueIterator &other)
Assignment.
ValueIterator(const NodeIterator &other)
Copy constructor.
Value * operator->() const
Returns a pointer to the value of the storage node.
Container associating values with keys.
NodeIterator upperBound(const Key &key)
Find a node close to a key.
Map & insertDefault(const Key &key)
Insert or update a key with a default value.
NodeIterator find(const Key &key)
Find a node by key.
const Value & get(const Key &key) const
Lookup and return an existing value.
Map & eraseAt(const NodeIterator &iter)
Remove a node by iterator.
Map & eraseAtMultiple(const boost::iterator_range< Iter > &range)
Remove multiple nodes by iterator range.
boost::iterator_range< ConstNodeIterator > nodes() const
Iterators for container nodes.
Map & eraseAt(const ValueIterator &iter)
Remove a node by iterator.
boost::iterator_range< ConstKeyIterator > keys() const
Iterators for container keys.
Value & operator[](const Key &key)
Return a reference to an existing value.
bool exists(const Key &key) const
Determine if a key exists.
Map & eraseMultiple(const boost::iterator_range< OtherKeyIterator > &range)
Remove keys stored in another Map.
Map & insertMaybeMultiple(const boost::iterator_range< OtherNodeIterator > &range)
Conditionally insert multiple key/value pairs.
Key greatest() const
Returns the maximum key.
const Value & operator[](const Key &key) const
Return a reference to an existing value.
Map & operator=(const Map< Key2, T2, Cmp2, Alloc2 > &other)
Make this map be a copy of another map.
boost::iterator_range< ValueIterator > values()
Iterators for container values.
Map(const Map &other)
Copy constructor.
Map & insertMultiple(const boost::iterator_range< OtherNodeIterator > &range)
Insert multiple values.
ConstNodeIterator find(const Key &key) const
Find a node by key.
size_t size() const
Number of nodes, keys, or values in this container.
Cmp Comparator
Type of comparator, third template argument.
Value & get(const Key &key)
Lookup and return an existing value.
bool isEmpty() const
Determines whether this container is empty.
Optional< Value > getOptional(const Key &key) const
Lookup and return a value or nothing.
Alloc Allocator
Type of allocator, fourth template argument.
Map & erase(const Key &key)
Remove a node with specified key.
const Value & getOrElse(const Key &key, const Value &dflt) const
Lookup and return a value or something else.
NodeIterator lowerBound(const Key &key)
Find a node close to a key.
Value & insertMaybeDefault(const Key &key)
Conditionally insert a new key with default value.
ConstNodeIterator lowerBound(const Key &key) const
Find a node close to a key.
boost::iterator_range< NodeIterator > nodes()
Iterators for container nodes.
Map & eraseAtMultiple(const Iter &begin, const Iter &end)
Remove multiple nodes by iterator range.
Value & insertMaybe(const Key &key, const Value &value)
Conditionally insert a new key/value pair.
Map(const Map< Key2, T2, Cmp2, Alloc2 > &other)
Copy constructor.
boost::iterator_range< ConstKeyIterator > keys()
Iterators for container keys.
Map & insert(const Key &key, const Value &value)
Insert or update a key/value pair.
ConstNodeIterator upperBound(const Key &key) const
Find a node close to a key.
Map & clear()
Remove all nodes.
Value & getOrElse(const Key &key, Value &dflt)
Lookup and return a value or something else.
Map & insertMultiple(const OtherNodeIterator &begin, const OtherNodeIterator &end)
Insert multiple values.
Map(const Comparator &comparator, const Allocator &allocator=Allocator())
Constructs an empty map.
const Value & getOrDefault(const Key &key) const
Lookup and return a value or a default.
Key least() const
Returns the minimum key.
T Value
Type for values associated with each key.
Interval< Key > hull() const
Returns the range of keys in this map.
Map()
Default constructor.
boost::iterator_range< ConstValueIterator > values() const
Iterators for container values.
Map & eraseAt(const ConstKeyIterator &iter)
Remove a node by iterator.
Holds a value or nothing.