Store Sequence sequence location in a shared_ptr class
[mussa.git] / alg / seq_span.cpp
diff --git a/alg/seq_span.cpp b/alg/seq_span.cpp
new file mode 100644 (file)
index 0000000..3382bd8
--- /dev/null
@@ -0,0 +1,252 @@
+#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(); 
+}