]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/blockiter.cpp
Simplify some interfaces by using track and block iterators
[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         return _block->get_endpoint(_entry).track_iter();
30 }
31
32 const Block::Endpoint &BlockIter::endpoint() const
33 {
34         if(!_block)
35                 throw logic_error("null block");
36
37         return _block->get_endpoint(_entry);
38 }
39
40 int BlockIter::get_exit(const Route *route) const
41 {
42         const vector<Block::Endpoint> &eps = _block->get_endpoints();
43         TrackIter t_iter = track_iter();
44
45         while(t_iter)
46         {
47                 if(!_block->has_track(*t_iter))
48                         throw logic_error("internal error (block traversal escaped the block)");
49
50                 unsigned path = (route ? route->get_path(*t_iter) : t_iter->get_active_path());
51                 TrackIter t_exit = t_iter.reverse(path);
52
53                 for(unsigned i=0; i<eps.size(); ++i)
54                         if(eps[i].track==t_exit.track() && eps[i].track_ep==t_exit.entry())
55                                 return i;
56
57                 t_iter = t_exit.flip();
58         }
59
60         return -1;
61 }
62
63 BlockIter BlockIter::next(const Route *route) const
64 {
65         if(!_block)
66                 return BlockIter();
67
68         int exit = get_exit(route);
69         if(exit<0)
70                 return BlockIter();
71
72         BlockIter result;
73         result._block = _block->get_link(exit);
74         result._entry = (result._block ? result._block->get_endpoint_by_link(*_block) : 0);
75
76         return result;
77 }
78
79 BlockIter BlockIter::reverse(const Route *route) const
80 {
81         if(!_block)
82                 return BlockIter();
83
84         int exit = get_exit(route);
85         if(exit<0)
86                 return BlockIter();
87
88         return BlockIter(_block, exit);
89 }
90
91 BlockIter BlockIter::flip() const
92 {
93         if(!_block)
94                 return BlockIter();
95
96         BlockIter result;
97         result._block = _block->get_link(_entry);
98         result._entry = (result._block ? result._block->get_endpoint_by_link(*_block) : 0);
99
100         return result;
101 }
102
103 Block &BlockIter::operator*() const
104 {
105         if(!_block)
106                 throw logic_error("null block");
107
108         return *_block;
109 }
110
111 bool BlockIter::operator==(const BlockIter &other) const
112 {
113         return _block==other._block && _entry==other._entry;
114 }
115
116 } // namespace R2C2