klao@946: // -*- c++ -*-
klao@946: #ifndef LEMON_ITERABLE_GRAPH_EXTENDER_H
klao@946: #define LEMON_ITERABLE_GRAPH_EXTENDER_H
klao@946: 
klao@946: #include <lemon/invalid.h>
alpar@1448: #include <lemon/utility.h>
klao@946: 
klao@946: namespace lemon {
klao@946:   
klao@946:   template <typename _Base>
klao@946:   class IterableGraphExtender : public _Base {
klao@962:   public:
klao@946: 
alpar@1448:     /// Indicates that the graph is undirected.
alpar@1448: 
alpar@1448:     ///\todo Better name?
alpar@1448:     ///
alpar@1448:     ///\bug Should it be here?
alpar@1448:     typedef False UndirTag;
alpar@1448: 
klao@946:     typedef _Base Parent;
klao@946:     typedef IterableGraphExtender<_Base> Graph;
klao@946: 
klao@946:     typedef typename Parent::Node Node;
klao@946:     typedef typename Parent::Edge Edge;
klao@946: 
klao@946: 
klao@946:     class NodeIt : public Node { 
klao@946:       const Graph* graph;
klao@946:     public:
klao@946: 
klao@946:       NodeIt() {}
klao@946: 
klao@946:       NodeIt(Invalid i) : Node(i) { }
klao@946: 
klao@962:       explicit NodeIt(const Graph& _graph) : graph(&_graph) {
klao@946: 	_graph.first(*static_cast<Node*>(this));
klao@946:       }
klao@946: 
klao@946:       NodeIt(const Graph& _graph, const Node& node) 
klao@946: 	: Node(node), graph(&_graph) {}
klao@946: 
klao@946:       NodeIt& operator++() { 
klao@946: 	graph->next(*this);
klao@946: 	return *this; 
klao@946:       }
klao@946: 
klao@946:     };
klao@946: 
klao@946: 
klao@946:     class EdgeIt : public Edge { 
klao@946:       const Graph* graph;
klao@946:     public:
klao@946: 
klao@946:       EdgeIt() { }
klao@946: 
klao@946:       EdgeIt(Invalid i) : Edge(i) { }
klao@946: 
klao@962:       explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
klao@946: 	_graph.first(*static_cast<Edge*>(this));
klao@946:       }
klao@946: 
klao@946:       EdgeIt(const Graph& _graph, const Edge& e) : 
klao@946: 	Edge(e), graph(&_graph) { }
klao@946: 
klao@946:       EdgeIt& operator++() { 
klao@946: 	graph->next(*this);
klao@946: 	return *this; 
klao@946:       }
klao@946: 
klao@946:     };
klao@946: 
klao@946: 
klao@946:     class OutEdgeIt : public Edge { 
klao@946:       const Graph* graph;
klao@946:     public:
klao@946: 
klao@946:       OutEdgeIt() { }
klao@946: 
klao@946:       OutEdgeIt(Invalid i) : Edge(i) { }
klao@946: 
klao@946:       OutEdgeIt(const Graph& _graph, const Node& node) 
klao@962: 	: graph(&_graph) {
klao@946: 	_graph.firstOut(*this, node);
klao@946:       }
klao@946: 
klao@946:       OutEdgeIt(const Graph& _graph, const Edge& edge) 
klao@946: 	: Edge(edge), graph(&_graph) {}
klao@946: 
klao@946:       OutEdgeIt& operator++() { 
klao@946: 	graph->nextOut(*this);
klao@946: 	return *this; 
klao@946:       }
klao@946: 
klao@946:     };
klao@946: 
klao@946: 
klao@946:     class InEdgeIt : public Edge { 
klao@946:       const Graph* graph;
klao@946:     public:
klao@946: 
klao@946:       InEdgeIt() { }
klao@946: 
klao@946:       InEdgeIt(Invalid i) : Edge(i) { }
klao@946: 
klao@946:       InEdgeIt(const Graph& _graph, const Node& node) 
klao@962: 	: graph(&_graph) {
klao@946: 	_graph.firstIn(*this, node);
klao@946:       }
klao@946: 
klao@946:       InEdgeIt(const Graph& _graph, const Edge& edge) : 
klao@946: 	Edge(edge), graph(&_graph) {}
klao@946: 
klao@946:       InEdgeIt& operator++() { 
klao@946: 	graph->nextIn(*this);
klao@946: 	return *this; 
klao@946:       }
klao@946: 
klao@946:     };
klao@946: 
klao@1158:     /// Base node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the base node (ie. the source in this case) of the iterator
klao@1158:     ///
klao@1158:     /// \todo Document in the concept!
klao@1158:     Node baseNode(const OutEdgeIt &e) const {
klao@1158:       return source(e);
klao@1158:     }
klao@1158:     /// Running node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the running node (ie. the target in this case) of the
klao@1158:     /// iterator
klao@1158:     ///
klao@1158:     /// \todo Document in the concept!
klao@1158:     Node runningNode(const OutEdgeIt &e) const {
klao@1158:       return target(e);
klao@1158:     }
klao@1158: 
klao@1158:     /// Base node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the base node (ie. the target in this case) of the iterator
klao@1158:     ///
klao@1158:     /// \todo Document in the concept!
klao@1158:     Node baseNode(const InEdgeIt &e) const {
klao@1158:       return target(e);
klao@1158:     }
klao@1158:     /// Running node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the running node (ie. the source in this case) of the
klao@1158:     /// iterator
klao@1158:     ///
klao@1158:     /// \todo Document in the concept!
klao@1158:     Node runningNode(const InEdgeIt &e) const {
klao@1158:       return source(e);
klao@1158:     }
klao@1158: 
klao@946:     using Parent::first;
klao@946: 
klao@946:   private:
klao@946: 
klao@1230:     // /// \todo When (and if) we change the iterators concept to use operator*,
klao@1230:     // /// then the following shadowed methods will become superfluous.
klao@1230:     // /// But for now these are important safety measures.
klao@946: 
klao@1230:     // void first(NodeIt &) const;
klao@1230:     // void first(EdgeIt &) const;
klao@1230:     // void first(OutEdgeIt &) const;
klao@1230:     // void first(InEdgeIt &) const;
klao@946: 
klao@946:   };
klao@1158: 
klao@1158: 
klao@1158: 
klao@1158: 
klao@1158: 
klao@946:   
klao@962:   template <typename _Base>
klao@962:   class IterableUndirGraphExtender : public IterableGraphExtender<_Base> {
klao@962:   public:
klao@962: 
alpar@1448:     /// Indicates that the graph is undirected.
alpar@1448: 
alpar@1448:     ///\todo Better name?
alpar@1448:     ///
alpar@1448:     ///\bug Should it be here?
alpar@1448:     ///\bug Should be tested in the concept checker whether it is defined
alpar@1448:     ///correctly.
alpar@1448:     typedef True UndirTag;
alpar@1448: 
klao@962:     typedef IterableGraphExtender<_Base> Parent;
klao@962:     typedef IterableUndirGraphExtender<_Base> Graph;
klao@1021:     typedef typename Parent::Node Node;
klao@962: 
klao@962:     typedef typename Parent::UndirEdge UndirEdge;
klao@962: 
klao@1230:     class UndirEdgeIt : public Parent::UndirEdge { 
klao@962:       const Graph* graph;
klao@962:     public:
klao@962: 
klao@962:       UndirEdgeIt() { }
klao@962: 
klao@962:       UndirEdgeIt(Invalid i) : UndirEdge(i) { }
klao@962: 
klao@962:       explicit UndirEdgeIt(const Graph& _graph) : graph(&_graph) {
klao@962: 	_graph.first(*static_cast<UndirEdge*>(this));
klao@962:       }
klao@962: 
klao@962:       UndirEdgeIt(const Graph& _graph, const UndirEdge& e) : 
klao@962: 	UndirEdge(e), graph(&_graph) { }
klao@962: 
klao@962:       UndirEdgeIt& operator++() { 
klao@962: 	graph->next(*this);
klao@962: 	return *this; 
klao@962:       }
klao@962: 
klao@962:     };
klao@962: 
klao@1230:     class IncEdgeIt : public Parent::UndirEdge { 
klao@1021:       const Graph* graph;
klao@1021:       bool forward;
klao@1021:       friend class IterableUndirGraphExtender;
klao@1021:       template <typename G>
klao@1021:       friend class UndirGraphExtender;
klao@1021:     public:
klao@1021: 
klao@1030:       IncEdgeIt() { }
klao@1021: 
klao@1030:       IncEdgeIt(Invalid i) : UndirEdge(i), forward(false) { }
klao@1021: 
klao@1158:       IncEdgeIt(const Graph& _graph, const Node &n)
klao@1021: 	: graph(&_graph)
klao@1021:       {
klao@1021: 	_graph._dirFirstOut(*this, n);
klao@1021:       }
klao@1021: 
klao@1158:       IncEdgeIt(const Graph& _graph, const UndirEdge &ue, const Node &n)
klao@1158: 	: graph(&_graph), UndirEdge(ue)
klao@1158:       {
klao@1158: 	forward = (_graph.source(ue) == n);
klao@1158:       }
klao@1021: 
klao@1030:       IncEdgeIt& operator++() {
klao@1021: 	graph->_dirNextOut(*this);
klao@1021: 	return *this; 
klao@1021:       }
klao@1021:     };
klao@1021: 
klao@1158:     using Parent::baseNode;
klao@1158:     using Parent::runningNode;
klao@1158: 
klao@1158:     /// Base node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the base node of the iterator
klao@1158:     Node baseNode(const IncEdgeIt &e) const {
klao@1021:       return _dirSource(e);
klao@1021:     }
klao@1158:     /// Running node of the iterator
klao@1158:     ///
klao@1158:     /// Returns the running node of the iterator
klao@1158:     Node runningNode(const IncEdgeIt &e) const {
klao@1021:       return _dirTarget(e);
klao@1021:     }
klao@1021: 
klao@962:   };
klao@946: }
klao@946: 
klao@946: #endif // LEMON_GRAPH_EXTENDER_H