]> git.tdb.fi Git - r2c2.git/blob - source/libmarklin/trackiter.cpp
Make LCD output selectable at runtime through an extra I/O pin
[r2c2.git] / source / libmarklin / trackiter.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 <algorithm>
9 #include <msp/core/except.h>
10 #include "track.h"
11 #include "trackiter.h"
12 #include "tracktype.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 namespace Marklin {
18
19 TrackIter::TrackIter():
20         _track(0),
21         _entry(0)
22 { }
23
24 TrackIter::TrackIter(Track *t, unsigned e):
25         _track(t),
26         _entry(t ? e : 0)
27 {
28         if(_track && _entry>_track->get_type().get_endpoints().size())
29                 throw InvalidParameterValue("Endpoint index not valid for track");
30 }
31
32 const TrackType::Endpoint &TrackIter::endpoint() const
33 {
34         if(!_track)
35                 throw InvalidState("TrackIter is null");
36
37         return _track->get_type().get_endpoint(_entry);
38 }
39
40 int TrackIter::get_exit(unsigned path) const
41 {
42         const vector<TrackType::Endpoint> &eps = _track->get_type().get_endpoints();
43         
44         // Find an endpoint that's connected to the entry and has the requested path
45         for(unsigned i=0; i<eps.size(); ++i)
46                 if(i!=_entry && (eps[i].paths&(1<<path)) && (eps[i].paths&eps[_entry].paths))
47                         return i;
48
49         return -1;
50 }
51
52 TrackIter TrackIter::next() const
53 {
54         if(!_track)
55                 return TrackIter();
56
57         return next(_track->get_active_path());
58 }
59
60 TrackIter TrackIter::next(unsigned path) const
61 {
62         if(!_track)
63                 return TrackIter();
64
65         int exit = get_exit(path);
66         if(exit<0)
67                 return TrackIter();
68
69         TrackIter result;
70         result._track = _track->get_link(exit);
71         result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
72
73         return result;
74 }
75
76 TrackIter TrackIter::reverse() const
77 {
78         if(!_track)
79                 return TrackIter();
80
81         return reverse(_track->get_active_path());
82 }
83
84 TrackIter TrackIter::reverse(unsigned path) const
85 {
86         if(!_track)
87                 return TrackIter();
88
89         int exit = get_exit(path);
90         if(exit<0)
91                 return TrackIter();
92
93         return TrackIter(_track, exit);
94 }
95
96 TrackIter TrackIter::flip() const
97 {
98         if(!_track)
99                 return TrackIter();
100
101         TrackIter result;
102         result._track = _track->get_link(_entry);
103         result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
104
105         return result;
106 }
107
108 Track &TrackIter::operator*() const
109 {
110         if(!_track)
111                 throw InvalidState("TrackIter is null");
112
113         return *_track;
114 }
115
116 bool TrackIter::operator==(const TrackIter &other) const
117 {
118         return _track==other._track && _entry==other._entry;
119 }
120
121
122 TrackLoopIter::TrackLoopIter():
123         _looped(false)
124 { }
125
126 TrackLoopIter::TrackLoopIter(Track *t, unsigned e):
127         TrackIter(t, e),
128         _visited(new TrackList()),
129         _last(_visited->insert(_visited->end(), track())),
130         _looped(false)
131 { }
132
133 TrackLoopIter::TrackLoopIter(const TrackIter &i):
134         TrackIter(i),
135         _visited(new TrackList()),
136         _last(_visited->insert(_visited->end(), track())),
137         _looped(false)
138 { }
139
140 TrackLoopIter::TrackLoopIter(const TrackIter &i, RefPtr<TrackList> v, const TrackList::iterator &l):
141         TrackIter(i),
142         _looped(false)
143 {
144         if(track())
145         {
146                 _visited = v;
147                 _last = l;
148                 _looped = (_visited && find(_visited->begin(), _last, track())!=_last);
149
150                 ++_last;
151                 if(_last!=_visited->end())
152                 {
153                         _visited = new TrackList(_visited->begin(), _last);
154                         _last = _visited->end();
155                 }
156                 _visited->push_back(track());
157                 --_last;
158         }
159 }
160
161 TrackLoopIter TrackLoopIter::next() const
162 {
163         return TrackLoopIter(TrackIter::next(), _visited, _last);
164 }
165
166 TrackLoopIter TrackLoopIter::next(unsigned path) const
167 {
168         return TrackLoopIter(TrackIter::next(path), _visited, _last);
169 }
170
171 } // namespace Marklin