1 #include <msp/strings/format.h>
2 #include <msp/strings/regex.h>
13 Zone::Zone(Layout &l):
17 preferred_dir(UNSPECIFIED)
27 void Zone::set_name(const string &n)
29 Regex r_name("(.+) ([^ ]+) ([1-9][0-9]*)");
30 RegMatch m = r_name.match(n);
32 throw invalid_argument("Zone::set_name");
34 set_name(m[1].str, m[2].str, lexical_cast<unsigned>(m[3].str));
37 void Zone::set_name(const string &g, const string &q, unsigned n)
46 void Zone::update_name()
48 string full_name = group;
49 if(!qualifier.empty())
52 full_name += qualifier;
55 full_name += format(" %d", number);
56 TrackChain::set_name(full_name);
59 void Zone::on_track_added(Track &track)
63 TrackIter iter = iter_for(track, preferred_dir==UP ? DOWN : UP);
64 track.set_preferred_exit(iter.entry());
68 void Zone::set_direction_towards(Track &track, Direction dir)
71 throw invalid_argument("Zone::set_direction_towards");
73 throw logic_error("no tracks");
74 if(tracks.count(&track))
75 throw invalid_argument("Zone::set_direction_towards");
77 Validity valid = check_validity(track);
79 throw_bad_chain(valid);
81 for(unsigned i=0; i<2; ++i)
82 if(ends[i] && ends[i]->get_link_slot(track)>=0)
84 up_end = (dir==UP ? i : 1-i);
88 throw logic_error("internal error (valid track not linked to ends)");
91 void Zone::set_preferred_direction(Direction d)
94 throw logic_error("no direction");
100 TrackIter iter = get_end(preferred_dir).reverse();
101 while(iter && tracks.count(iter.track()))
103 iter->set_preferred_exit(iter.entry());
104 iter = next_iter(iter);
109 for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i)
110 (*i)->set_preferred_exit(-1);
114 void Zone::clear_direction()
117 preferred_dir = UNSPECIFIED;
120 TrackIter Zone::iter_for(Track &track, Direction dir) const
122 if(!tracks.count(&track))
124 else if(dir==UNSPECIFIED)
125 return TrackIter(&track, 0);
129 for(int i=0; i<2; ++i)
130 if(&track==ends[i].track())
132 if((i==up_end)==(dir==UP))
135 return ends[i].reverse();
138 TrackIter iter = ends[up_end^(dir==UP)].reverse();
139 while(iter && tracks.count(iter.track()))
141 if(iter.track()==&track)
144 iter = next_iter(iter);
150 TrackIter Zone::next_iter(const TrackIter &iter) const
152 TrackIter next_outside;
153 const TrackType::Endpoint &ep = iter.endpoint();
154 for(unsigned i=0; ep.paths>>i; ++i)
156 if(TrackIter next = iter.next(i))
158 if(tracks.count(next.track()))
167 TrackIter Zone::get_end(Direction dir) const
174 return ends[up_end^(dir==DOWN)];
177 void Zone::save(list<DataFile::Statement> &st) const
179 st.push_back((DataFile::Statement("group"), group));
180 if(!qualifier.empty())
181 st.push_back((DataFile::Statement("qualifier"), qualifier));
183 st.push_back((DataFile::Statement("number"), number));
185 unsigned last_block = 0;
186 TrackIter iter = ends[0].reverse();
187 while(iter && tracks.count(iter.track()))
189 unsigned block_id = iter->get_block().get_id();
190 if(block_id!=last_block)
192 st.push_back((DataFile::Statement("block"), block_id));
193 last_block = block_id;
196 iter = next_iter(iter);
201 for(unsigned i=0; i<2; ++i)
203 TrackIter hint = next_iter(ends[up_end^i]);
204 if(hint && !tracks.count(hint.track()))
206 st.push_back((DataFile::Statement("direction_hint"), hint->get_block().get_id(), (i==0 ? UP : DOWN)));
212 st.push_back((DataFile::Statement("preferred_direction"), preferred_dir));
216 DataFile::Statement Zone::save_reference() const
218 return (DataFile::Statement("zone"), group, number);
222 Zone::Loader::Loader(Zone &z):
223 DataFile::ObjectLoader<Zone>(z)
225 add("block", &Loader::block);
226 add("direction_hint", &Loader::direction_hint);
227 add("group", &Zone::group);
228 add("number", &Zone::number);
229 add("preferred_direction", &Loader::preferred_direction);
230 add("qualifier", &Zone::qualifier);
233 void Zone::Loader::finish()
238 void Zone::Loader::block(unsigned b)
240 Block &blk = obj.layout.get_block(b);
241 obj.add_tracks(blk.get_tracks());
244 void Zone::Loader::direction_hint(unsigned b, Direction d)
246 Block &blk = obj.layout.get_block(b);
247 const TrackSet &btracks = blk.get_tracks();
248 for(TrackSet::const_iterator i=btracks.begin(); i!=btracks.end(); ++i)
249 if(obj.check_validity(**i)==VALID)
251 obj.set_direction_towards(**i, d);
255 throw invalid_argument("Zone::Loader::direction_hint");
258 void Zone::Loader::preferred_direction(Direction d)
260 obj.set_preferred_direction(d);