]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/blockiter.cpp
c39f88ed55ca595ac5e67c69d75b995c16ffac80
[r2c2.git] / source / libr2c2 / blockiter.cpp
1 #include <msp/core/except.h>
2 #include "block.h"
3 #include "blockiter.h"
4 #include "route.h"
5 #include "trackiter.h"
6
7 using namespace std;
8 using namespace Msp;
9
10 namespace R2C2 {
11
12 BlockIter::BlockIter():
13         _block(0),
14         _entry(0)
15 { }
16
17 BlockIter::BlockIter(Block *b, unsigned e):
18         _block(b),
19         _entry(b ? e : 0)
20 {
21         if(_block && _entry>_block->get_endpoints().size())
22                 throw InvalidParameterValue("Endpoint index not valid for block");
23 }
24
25 TrackIter BlockIter::track_iter() const
26 {
27         if(!_block)
28                 return TrackIter();
29
30         const Block::Endpoint &ep = _block->get_endpoint(_entry);
31         return TrackIter(ep.track, ep.track_ep);
32 }
33
34 const Block::Endpoint &BlockIter::endpoint() const
35 {
36         if(!_block)
37                 throw InvalidState("BlockIter is null");
38
39         return _block->get_endpoint(_entry);
40 }
41
42 int BlockIter::get_exit(const Route *route) const
43 {
44         const vector<Block::Endpoint> &eps = _block->get_endpoints();
45         TrackIter t_iter = track_iter();
46
47         while(t_iter)
48         {
49                 if(!_block->has_track(*t_iter))
50                         throw LogicError("Block traversal strayed out of the block");
51
52                 unsigned path = (route ? route->get_path(*t_iter) : t_iter->get_active_path());
53                 TrackIter t_exit = t_iter.reverse(path);
54
55                 for(unsigned i=0; i<eps.size(); ++i)
56                         if(eps[i].track==t_exit.track() && eps[i].track_ep==t_exit.entry())
57                                 return i;
58
59                 t_iter = t_exit.flip();
60         }
61
62         return -1;
63 }
64
65 BlockIter BlockIter::next(const Route *route) const
66 {
67         if(!_block)
68                 return BlockIter();
69
70         int exit = get_exit(route);
71         if(exit<0)
72                 return BlockIter();
73
74         BlockIter result;
75         result._block = _block->get_link(exit);
76         result._entry = (result._block ? result._block->get_endpoint_by_link(*_block) : 0);
77
78         return result;
79 }
80
81 BlockIter BlockIter::reverse(const Route *route) const
82 {
83         if(!_block)
84                 return BlockIter();
85
86         int exit = get_exit(route);
87         if(exit<0)
88                 return BlockIter();
89
90         return BlockIter(_block, exit);
91 }
92
93 BlockIter BlockIter::flip() const
94 {
95         if(!_block)
96                 return BlockIter();
97
98         BlockIter result;
99         result._block = _block->get_link(_entry);
100         result._entry = (result._block ? result._block->get_endpoint_by_link(*_block) : 0);
101
102         return result;
103 }
104
105 Block &BlockIter::operator*() const
106 {
107         if(!_block)
108                 throw InvalidState("BlockIter is null");
109
110         return *_block;
111 }
112
113 bool BlockIter::operator==(const BlockIter &other) const
114 {
115         return _block==other._block && _entry==other._entry;
116 }
117
118 } // namespace R2C2