]> git.tdb.fi Git - r2c2.git/blobdiff - source/libr2c2/trackiter.cpp
Rename the project to R²C²
[r2c2.git] / source / libr2c2 / trackiter.cpp
diff --git a/source/libr2c2/trackiter.cpp b/source/libr2c2/trackiter.cpp
new file mode 100644 (file)
index 0000000..3c6295b
--- /dev/null
@@ -0,0 +1,171 @@
+/* $Id$
+
+This file is part of R²C²
+Copyright © 2010  Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#include <algorithm>
+#include <msp/core/except.h>
+#include "track.h"
+#include "trackiter.h"
+#include "tracktype.h"
+
+using namespace std;
+using namespace Msp;
+
+namespace R2C2 {
+
+TrackIter::TrackIter():
+       _track(0),
+       _entry(0)
+{ }
+
+TrackIter::TrackIter(Track *t, unsigned e):
+       _track(t),
+       _entry(t ? e : 0)
+{
+       if(_track && _entry>_track->get_type().get_endpoints().size())
+               throw InvalidParameterValue("Endpoint index not valid for track");
+}
+
+const TrackType::Endpoint &TrackIter::endpoint() const
+{
+       if(!_track)
+               throw InvalidState("TrackIter is null");
+
+       return _track->get_type().get_endpoint(_entry);
+}
+
+int TrackIter::get_exit(unsigned path) const
+{
+       const vector<TrackType::Endpoint> &eps = _track->get_type().get_endpoints();
+       
+       // Find an endpoint that's connected to the entry and has the requested path
+       for(unsigned i=0; i<eps.size(); ++i)
+               if(i!=_entry && (eps[i].paths&(1<<path)) && (eps[i].paths&eps[_entry].paths))
+                       return i;
+
+       return -1;
+}
+
+TrackIter TrackIter::next() const
+{
+       if(!_track)
+               return TrackIter();
+
+       return next(_track->get_active_path());
+}
+
+TrackIter TrackIter::next(unsigned path) const
+{
+       if(!_track)
+               return TrackIter();
+
+       int exit = get_exit(path);
+       if(exit<0)
+               return TrackIter();
+
+       TrackIter result;
+       result._track = _track->get_link(exit);
+       result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
+
+       return result;
+}
+
+TrackIter TrackIter::reverse() const
+{
+       if(!_track)
+               return TrackIter();
+
+       return reverse(_track->get_active_path());
+}
+
+TrackIter TrackIter::reverse(unsigned path) const
+{
+       if(!_track)
+               return TrackIter();
+
+       int exit = get_exit(path);
+       if(exit<0)
+               return TrackIter();
+
+       return TrackIter(_track, exit);
+}
+
+TrackIter TrackIter::flip() const
+{
+       if(!_track)
+               return TrackIter();
+
+       TrackIter result;
+       result._track = _track->get_link(_entry);
+       result._entry = (result._track ? result._track->get_endpoint_by_link(*_track) : 0);
+
+       return result;
+}
+
+Track &TrackIter::operator*() const
+{
+       if(!_track)
+               throw InvalidState("TrackIter is null");
+
+       return *_track;
+}
+
+bool TrackIter::operator==(const TrackIter &other) const
+{
+       return _track==other._track && _entry==other._entry;
+}
+
+
+TrackLoopIter::TrackLoopIter():
+       _looped(false)
+{ }
+
+TrackLoopIter::TrackLoopIter(Track *t, unsigned e):
+       TrackIter(t, e),
+       _visited(new TrackList()),
+       _last(_visited->insert(_visited->end(), track())),
+       _looped(false)
+{ }
+
+TrackLoopIter::TrackLoopIter(const TrackIter &i):
+       TrackIter(i),
+       _visited(new TrackList()),
+       _last(_visited->insert(_visited->end(), track())),
+       _looped(false)
+{ }
+
+TrackLoopIter::TrackLoopIter(const TrackIter &i, RefPtr<TrackList> v, const TrackList::iterator &l):
+       TrackIter(i),
+       _looped(false)
+{
+       if(track())
+       {
+               _visited = v;
+               _last = l;
+               _looped = (_visited && find(_visited->begin(), _last, track())!=_last);
+
+               ++_last;
+               if(_last!=_visited->end())
+               {
+                       _visited = new TrackList(_visited->begin(), _last);
+                       _last = _visited->end();
+               }
+               _visited->push_back(track());
+               --_last;
+       }
+}
+
+TrackLoopIter TrackLoopIter::next() const
+{
+       return TrackLoopIter(TrackIter::next(), _visited, _last);
+}
+
+TrackLoopIter TrackLoopIter::next(unsigned path) const
+{
+       return TrackLoopIter(TrackIter::next(path), _visited, _last);
+}
+
+} // namespace R2C2