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