X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Fzone.cpp;h=52e3c281d8175254474cef140ea4217774c3c3e9;hb=1c15570729bbce44f0518373ca5bf8bf41cfa3b3;hp=00edb5799f6d4d9b49f481f7d7ef3f76113666ce;hpb=73edcbd8841752a2722fc8b3927fee2abbbba750;p=r2c2.git diff --git a/source/libr2c2/zone.cpp b/source/libr2c2/zone.cpp index 00edb57..52e3c28 100644 --- a/source/libr2c2/zone.cpp +++ b/source/libr2c2/zone.cpp @@ -1,4 +1,5 @@ #include +#include #include "block.h" #include "layout.h" #include "track.h" @@ -11,14 +12,25 @@ namespace R2C2 { Zone::Zone(Layout &l): TrackChain(l), - number(0) + number(0), + up_end(-1) { - layout.add_zone(*this); + layout.add(*this); } Zone::~Zone() { - layout.remove_zone(*this); + layout.remove(*this); +} + +void Zone::set_name(const string &n) +{ + Regex r_name("(.+) ([^ ]+) ([1-9][0-9]*)"); + RegMatch m = r_name.match(n); + if(!m) + throw invalid_argument("Zone::set_name"); + + set_name(m[1].str, m[2].str, lexical_cast(m[3].str)); } void Zone::set_name(const string &g, const string &q, unsigned n) @@ -27,20 +39,105 @@ void Zone::set_name(const string &g, const string &q, unsigned n) qualifier = q; number = n; - signal_name_changed.emit(group, qualifier, number); + update_name(); } -string Zone::get_name() const +void Zone::update_name() { - string result = group; + string full_name = group; if(!qualifier.empty()) { - result += ' '; - result += qualifier; + full_name += ' '; + full_name += qualifier; } if(number) - result += format(" %d", number); - return result; + full_name += format(" %d", number); + TrackChain::set_name(full_name); +} + +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::clear_direction() +{ + up_end = -1; +} + +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::get_end(Direction dir) const +{ + if(dir==UNSPECIFIED) + return ends[0]; + if(up_end<0) + return TrackIter(); + + return ends[up_end^(dir==DOWN)]; +} + +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; } void Zone::save(list &st) const @@ -51,12 +148,37 @@ 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; + } + + iter = next_iter(iter); + } - for(set::const_iterator i=block_ids.begin(); i!=block_ids.end(); ++i) - st.push_back((DataFile::Statement("block"), *i)); + 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; + } + } + } +} + +DataFile::Statement Zone::save_reference() const +{ + return (DataFile::Statement("zone"), group, number); } @@ -64,16 +186,35 @@ 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("qualifier", &Zone::qualifier); } +void Zone::Loader::finish() +{ + obj.update_name(); +} + 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"); } } // namespace R2C2