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