X-Git-Url: http://git.tdb.fi/?p=r2c2.git;a=blobdiff_plain;f=source%2Flibr2c2%2Fzone.cpp;h=eb5d102b8414570ff6d01578b04994d675701205;hp=30b60e99aa65865a0960afc113e3d5f5fedfbd7f;hb=d990c03a06a494ce3596862ce61e2a5684dea7e1;hpb=1ac853ffc606b29ffd88b923ed3551ee6282afb2 diff --git a/source/libr2c2/zone.cpp b/source/libr2c2/zone.cpp index 30b60e9..eb5d102 100644 --- a/source/libr2c2/zone.cpp +++ b/source/libr2c2/zone.cpp @@ -12,7 +12,9 @@ namespace R2C2 { Zone::Zone(Layout &l): TrackChain(l), - number(0) + number(0), + up_end(-1), + preferred_dir(UNSPECIFIED) { layout.add(*this); } @@ -54,6 +56,124 @@ void Zone::update_name() TrackChain::set_name(full_name); } +void Zone::on_track_added(Track &track) +{ + if(preferred_dir) + { + TrackIter iter = iter_for(track, preferred_dir==UP ? DOWN : UP); + track.set_preferred_exit(iter.entry()); + } +} + +void Zone::set_direction_towards(Track &track, Direction dir) +{ + if(dir==UNSPECIFIED) + throw invalid_argument("Zone::set_direction_towards"); + if(tracks.empty()) + throw logic_error("no tracks"); + if(tracks.count(&track)) + throw invalid_argument("Zone::set_direction_towards"); + + Validity valid = check_validity(track); + if(valid!=VALID) + throw_bad_chain(valid); + + for(unsigned i=0; i<2; ++i) + if(ends[i] && ends[i]->get_link_slot(track)>=0) + { + up_end = (dir==UP ? i : 1-i); + return; + } + + throw logic_error("internal error (valid track not linked to ends)"); +} + +void Zone::set_preferred_direction(Direction d) +{ + if(up_end<0) + throw logic_error("no direction"); + + preferred_dir = d; + + if(preferred_dir) + { + TrackIter iter = get_end(preferred_dir).reverse(); + while(iter && tracks.count(iter.track())) + { + iter->set_preferred_exit(iter.entry()); + iter = next_iter(iter); + } + } + else + { + for(TrackSet::iterator i=tracks.begin(); i!=tracks.end(); ++i) + (*i)->set_preferred_exit(-1); + } +} + +void Zone::clear_direction() +{ + up_end = -1; + preferred_dir = UNSPECIFIED; +} + +TrackIter Zone::iter_for(Track &track, Direction dir) const +{ + if(!tracks.count(&track)) + return TrackIter(); + else if(dir==UNSPECIFIED) + return TrackIter(&track, 0); + else if(up_end<0) + return TrackIter(); + + for(int i=0; i<2; ++i) + if(&track==ends[i].track()) + { + if((i==up_end)==(dir==UP)) + return ends[i]; + else + return ends[i].reverse(); + } + + TrackIter iter = ends[up_end^(dir==UP)].reverse(); + while(iter && tracks.count(iter.track())) + { + if(iter.track()==&track) + return iter; + + iter = next_iter(iter); + } + + return TrackIter(); +} + +TrackIter Zone::next_iter(const TrackIter &iter) const +{ + TrackIter next_outside; + const TrackType::Endpoint &ep = iter.endpoint(); + for(unsigned i=0; ep.paths>>i; ++i) + if(ep.has_path(i)) + if(TrackIter next = iter.next(i)) + { + if(tracks.count(next.track())) + return next; + else + next_outside = next; + } + + return next_outside; +} + +TrackIter Zone::get_end(Direction dir) const +{ + if(dir==UNSPECIFIED) + return ends[0]; + if(up_end<0) + return TrackIter(); + + return ends[up_end^(dir==DOWN)]; +} + void Zone::save(list &st) const { st.push_back((DataFile::Statement("group"), group)); @@ -62,17 +182,44 @@ void Zone::save(list &st) const if(number) st.push_back((DataFile::Statement("number"), number)); - set block_ids; - for(TrackSet::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) - block_ids.insert((*i)->get_block().get_id()); + unsigned last_block = 0; + TrackIter iter = ends[0].reverse(); + while(iter && tracks.count(iter.track())) + { + unsigned block_id = iter->get_block().get_id(); + if(block_id!=last_block) + { + st.push_back((DataFile::Statement("block"), block_id)); + last_block = block_id; + } - for(set::const_iterator i=block_ids.begin(); i!=block_ids.end(); ++i) - st.push_back((DataFile::Statement("block"), *i)); + iter = next_iter(iter); + } + + if(up_end>=0) + { + for(unsigned i=0; i<2; ++i) + { + TrackIter hint = next_iter(ends[up_end^i]); + if(hint && !tracks.count(hint.track())) + { + st.push_back((DataFile::Statement("direction_hint"), hint->get_block().get_id(), (i==0 ? UP : DOWN))); + break; + } + } + + if(preferred_dir) + st.push_back((DataFile::Statement("preferred_direction"), preferred_dir)); + } } DataFile::Statement Zone::save_reference() const { - return (DataFile::Statement("zone"), group, number); + DataFile::Statement st("zone"); + st.append(group); + if(number) + st.append(number); + return st; } @@ -80,8 +227,10 @@ Zone::Loader::Loader(Zone &z): DataFile::ObjectLoader(z) { add("block", &Loader::block); + add("direction_hint", &Loader::direction_hint); add("group", &Zone::group); add("number", &Zone::number); + add("preferred_direction", &Loader::preferred_direction); add("qualifier", &Zone::qualifier); } @@ -93,8 +242,26 @@ void Zone::Loader::finish() void Zone::Loader::block(unsigned b) { Block &blk = obj.layout.get_block(b); - const set &btracks = blk.get_tracks(); - obj.tracks.insert(btracks.begin(), btracks.end()); + obj.add_tracks(blk.get_tracks()); +} + +void Zone::Loader::direction_hint(unsigned b, Direction d) +{ + Block &blk = obj.layout.get_block(b); + const TrackSet &btracks = blk.get_tracks(); + for(TrackSet::const_iterator i=btracks.begin(); i!=btracks.end(); ++i) + if(obj.check_validity(**i)==VALID) + { + obj.set_direction_towards(**i, d); + return; + } + + throw invalid_argument("Zone::Loader::direction_hint"); +} + +void Zone::Loader::preferred_direction(Direction d) +{ + obj.set_preferred_direction(d); } } // namespace R2C2