8 #ifndef Sawyer_GraphIteratorMap_H
9 #define Sawyer_GraphIteratorMap_H
11 #include <Sawyer/Graph.h>
12 #include <Sawyer/Optional.h>
13 #include <boost/range/iterator_range.hpp>
28 template<
class K,
class V>
46 const Key&
key()
const {
return key_; }
59 typedef std::vector<Node> StlVector;
60 mutable StlVector items_;
61 mutable bool needsUpdate_;
67 template<
class Derived,
class Value,
class BaseIterator>
68 class BidirectionalIterator {
71 using iterator_category = std::bidirectional_iterator_tag;
72 using value_type =
Value;
73 using difference_type = std::ptrdiff_t;
74 using pointer =
Value*;
75 using reference =
Value&;
79 BidirectionalIterator() {}
80 BidirectionalIterator(
const BaseIterator &base): base_(base) {}
83 Derived& operator=(
const Derived &other) {
89 Derived& operator++() {
95 Derived operator++(
int) {
96 Derived old = *derived();
102 Derived& operator--() {
108 Derived operator--(
int) {
109 Derived old = *derived();
118 template<
class OtherIter>
119 bool operator==(
const OtherIter &other)
const {
120 return base_ == other.base();
124 template<
class OtherIter>
125 bool operator!=(
const OtherIter &other)
const {
126 return base_ != other.base();
129 const BaseIterator& base()
const {
134 return static_cast<Derived*
>(
this);
136 const Derived* derived()
const {
137 return static_cast<const Derived*
>(
this);
146 class NodeIterator:
public BidirectionalIterator<NodeIterator, Node, typename StlVector::iterator> {
147 typedef BidirectionalIterator<NodeIterator, Node, typename StlVector::iterator> Super;
156 return *this->base();
161 return &*this->base();
173 class ConstNodeIterator:
public BidirectionalIterator<ConstNodeIterator, const Node, typename StlVector::const_iterator> {
174 typedef BidirectionalIterator<ConstNodeIterator, const Node, typename StlVector::const_iterator> Super;
184 : Super(typename StlVector::const_iterator(other.base())) {}
188 return *this->base();
193 return &*this->base();
199 ConstNodeIterator(
const typename StlVector::iterator &base)
200 : Super(typename StlVector::const_iterator(base)) {}
207 class ConstKeyIterator:
public BidirectionalIterator<ConstKeyIterator, const Key, typename StlVector::const_iterator> {
208 typedef BidirectionalIterator<ConstKeyIterator, const Key, typename StlVector::const_iterator> Super;
218 : Super(typename StlVector::const_iterator(other.base())) {}
222 : Super(other.base()) {}
226 return this->base()->key();
231 return &this->base()->key();
239 class ValueIterator:
public BidirectionalIterator<ValueIterator, Value, typename StlVector::iterator> {
240 typedef BidirectionalIterator<ValueIterator, Value, typename StlVector::iterator> Super;
250 : Super(other.base()) {}
254 return this->base()->value();
259 return &this->base()->value();
266 class ConstValueIterator:
public BidirectionalIterator<ConstValueIterator, const Value, typename StlVector::const_iterator> {
267 typedef BidirectionalIterator<ConstValueIterator, const Value, typename StlVector::const_iterator> Super;
277 : Super(typename StlVector::const_iterator(other.base())) {}
281 : Super(other.base()) {}
285 : Super(typename StlVector::const_iterator(other.base())) {}
289 return this->base()->value();
294 return &this->base()->value();
301 typedef typename StlVector::value_type value_type;
302 typedef typename StlVector::allocator_type allocator_type;
303 typedef typename StlVector::reference reference;
304 typedef typename StlVector::pointer pointer;
305 typedef typename StlVector::const_pointer const_pointer;
306 typedef typename StlVector::iterator iterator;
307 typedef typename StlVector::const_iterator const_iterator;
308 typedef typename StlVector::reverse_iterator reverse_iterator;
309 typedef typename StlVector::const_reverse_iterator const_reverse_iterator;
310 typedef typename StlVector::difference_type difference_type;
311 typedef typename StlVector::size_type size_type;
319 : needsUpdate_(false) {}
344 Node node(item, value);
345 typename std::vector<Node>::iterator lb = std::lower_bound(items_.begin(), items_.end(), node, sortById);
346 if (items_.end() == lb || lb->key()->id() != item->id()) {
347 items_.insert(lb, node);
359 Node node(item, value);
360 typename std::vector<Node>::iterator lb = std::lower_bound(items_.begin(), items_.end(), node, sortById);
361 if (items_.end() == lb || lb->key()->id() != item->id())
362 lb = items_.insert(lb, node);
377 Node node(item,
Value());
378 typename std::vector<Node>::iterator lb = std::lower_bound(items_.begin(), items_.end(), node, sortById);
379 if (lb != items_.end() && lb->key()->id() == item->id())
386 needsUpdate_ =
false;
396 Node node(item,
Value());
397 typename std::vector<Node>::const_iterator lb = std::lower_bound(items_.begin(), items_.end(), node, sortById);
398 return lb != items_.end() && lb->key()->id() == item->id();
404 Node node(item,
Value());
405 typename std::vector<Node>::const_iterator lb = std::lower_bound(items_.begin(), items_.end(), node, sortById);
406 if (lb != items_.end() && lb->key()->id() == item->id()) {
428 boost::iterator_range<NodeIterator>
nodes() {
430 return boost::iterator_range<NodeIterator>(NodeIterator(items_.begin()), NodeIterator(items_.end()));
432 boost::iterator_range<ConstNodeIterator>
nodes()
const {
434 return boost::iterator_range<ConstNodeIterator>(ConstNodeIterator(items_.begin()), ConstNodeIterator(items_.end()));
443 boost::iterator_range<ConstKeyIterator>
keys() {
445 return boost::iterator_range<ConstKeyIterator>(NodeIterator(items_.begin()), NodeIterator(items_.end()));
447 boost::iterator_range<ConstKeyIterator>
keys()
const {
449 return boost::iterator_range<ConstKeyIterator>(ConstNodeIterator(items_.begin()), ConstNodeIterator(items_.end()));
459 boost::iterator_range<ValueIterator>
values() {
461 return boost::iterator_range<ValueIterator>(NodeIterator(items_.begin()), NodeIterator(items_.end()));
463 boost::iterator_range<ConstValueIterator>
values()
const {
465 return boost::iterator_range<ConstValueIterator>(ConstNodeIterator(items_.begin()), ConstNodeIterator(items_.end()));
470 NodeIterator begin() {
return NodeIterator(items_.begin()); }
471 ConstNodeIterator begin()
const {
return NodeIterator(items_.begin()); }
472 NodeIterator end() {
return NodeIterator(items_.end()); }
473 ConstNodeIterator end()
const {
return NodeIterator(items_.end()); }
479 static bool sortById(
const Node &a,
const Node &b) {
480 return a.key()->id() < b.key()->id();
483 void update()
const {
485 std::sort(items_.begin(), items_.end(), sortById);
486 needsUpdate_ =
false;
493 for (
size_t i = 1; i < items_.size(); ++i)
494 ASSERT_require(sortById(items_[i-1], items_[i]));