--- /dev/null
+#include <stdexcept>
+#include <set>
+#include <algorithm>
+
+#include "seq_span.hpp"
+#include "mussa_exceptions.hpp"
+
+SeqSpan::SeqSpan(const SeqSpan &o)
+ : seq(o.seq),
+ seq_start(o.seq_start),
+ seq_count(o.seq_count),
+ parent(o.parent)
+{
+}
+
+SeqSpan::SeqSpan(const SeqSpan *p)
+ : seq(p->seq),
+ seq_start(p->seq_start),
+ seq_count(p->seq_count),
+ parent(p->parent)
+{
+}
+
+SeqSpan::SeqSpan(const std::string &seq_)
+ : seq(new SeqString(seq_)),
+ seq_start(0),
+ seq_count(seq_.length()),
+ parent()
+{
+}
+
+SeqSpan::SeqSpan(const SeqSpanRef parent_, size_type start_, size_type count_)
+ : seq(parent_->seq),
+ seq_start(parent_->seq_start + start_),
+ parent(parent_)
+{
+ if (count_ == npos)
+ seq_count = parent_->seq_count;
+ else
+ seq_count = count_;
+}
+
+//////
+// Helpful operators
+SeqSpan &SeqSpan::operator=(const SeqSpan& s)
+{
+ if (this != &s) {
+ seq = s.seq;
+ seq_start = s.seq_start;
+ seq_count = s.seq_count;
+ parent = s.parent;
+ }
+ return *this;
+}
+
+std::ostream& operator<<(std::ostream& out, const SeqSpan& s)
+{
+ out << s.sequence();
+}
+
+/* Not implemented yet
+//! compare two spans
+//! \throws sequence_invalid_comparison
+friend bool operator<(const SeqSpan&, const SeqSpan&);
+bool operator<(const SeqSpan& a, const SeqSpan& b)
+{
+ // are we subcomponents of the same sequence region?
+ if (a.seq.get() == b.seq.get()) {
+ if (a.seq_start < b.seq_start)
+ return true;
+ else
+ return false;
+ } else {
+ throw mussa_error("can only compare two spans from the same sequence");
+ }
+}
+*/
+#include <iostream>
+bool operator==(const SeqSpan& a, const SeqSpan& b)
+{
+ if (SeqSpan::isFamily(a, b)) {
+ std::cout << " " << a.seq_start
+ << " " << b.seq_start
+ << " " << a.seq_count
+ << " " << b.seq_count << std::endl;
+ // can do fast comparison
+ if (a.seq_start == b.seq_start and a.seq_count == b.seq_count) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool operator!=(const SeqSpan& a, const SeqSpan& b)
+{
+ return not (a == b);
+}
+
+SeqSpan::const_reference SeqSpan::operator[](SeqSpan::size_type i) const
+{
+ return at(i);
+}
+
+SeqSpan::const_reference SeqSpan::at(SeqSpan::size_type i) const
+{
+ if (!seq) throw std::out_of_range("empty sequence");
+ return seq->at(i+seq_start);
+}
+
+const char *SeqSpan::data() const
+{
+ if (seq) {
+ return seq->c_str()+seq_start;
+ } else
+ return 0;
+}
+
+SeqSpan::const_iterator SeqSpan::begin() const
+{
+ if (seq and seq_count != 0)
+ return seq->begin()+seq_start;
+ else
+ return SeqSpan::const_iterator(0);
+}
+
+SeqSpan::const_iterator SeqSpan::end() const
+{
+ if (seq and seq_count != 0) {
+ return seq->begin() + seq_start + seq_count;
+ } else {
+ return SeqSpan::const_iterator(0);
+ }
+}
+
+SeqSpan::const_reverse_iterator SeqSpan::rbegin() const
+{
+ if (seq and seq_count != 0)
+ return seq->rbegin()+(seq->size()-(seq_start+seq_count));
+ else
+ return SeqSpan::const_reverse_iterator();
+}
+
+SeqSpan::const_reverse_iterator SeqSpan::rend() const
+{
+ if (seq and seq_count != 0) {
+ return rbegin() + seq_count;
+ } else {
+ return SeqSpan::const_reverse_iterator();
+ }
+}
+
+bool SeqSpan::empty() const
+{
+ return (seq_count == 0) ? true : false;
+}
+
+SeqSpan::size_type SeqSpan::find_first_not_of(
+ const std::string& query,
+ SeqSpan::size_type index) const
+{
+ typedef std::set<std::string::value_type> sequence_set;
+ sequence_set match_set;
+
+ for(const_iterator query_item = query.begin();
+ query_item != query.end();
+ ++query_item)
+ {
+ match_set.insert(*query_item);
+ }
+ for(const_iterator base = begin();
+ base != end();
+ ++base)
+ {
+ if(match_set.find(*base) == match_set.end()) {
+ return base-begin();
+ }
+ }
+ return SeqSpan::npos;
+}
+
+void SeqSpan::setStart(SeqSpan::size_type v)
+{
+ if (v > stop()) {
+ // cry
+ throw mussa_error("can't set Start > Stop");
+ }
+ seq_count += seq_start - v;
+ seq_start = v;
+}
+
+void SeqSpan::setStop(SeqSpan::size_type v)
+{
+ if ( v < start() ) {
+ // negative sized sequences are bad
+ throw mussa_error("can't set Stop < Start");
+ }
+ seq_count = std::min<size_type>(v - seq_start, parentSize()-parentStart());
+}
+
+SeqSpan::size_type SeqSpan::parentStart() const
+{
+ if (!parent) {
+ // no parent
+ return start();
+ } else {
+ return start() - parent->start();
+ }
+}
+
+void SeqSpan::setParentStart(SeqSpan::size_type v)
+{
+ setStart(parent->start() + v);
+}
+
+SeqSpan::size_type SeqSpan::parentStop() const
+{
+ if (!parent) {
+ // no parent
+ return stop();
+ } else {
+ return stop() - parent->start();
+ }
+}
+
+void SeqSpan::setParentStop(SeqSpan::size_type v)
+{
+ setStop(parent->start() + v);
+}
+
+SeqSpanRef SeqSpan::subseq(size_type start, size_type count)
+{
+ count = std::min<size_type>(count, seq_count - start);
+
+ SeqSpanRef new_span(new SeqSpan(this->shared_from_this(), start, count));
+ return new_span;
+}
+
+std::string SeqSpan::sequence() const
+{
+ if (seq) {
+ return seq->substr(seq_start, seq_count);
+ } else {
+ return std::string();
+ }
+}
+
+bool SeqSpan::isFamily(const SeqSpan& a, const SeqSpan& b)
+{
+ return a.seq.get() == b.seq.get();
+}