1 #ifndef OLIGOFAR_CTRANSCRIPT__HPP
2 #define OLIGOFAR_CTRANSCRIPT__HPP
3 
4 #include "debug.hpp"
5 #include "defs.hpp"
6 
7 BEGIN_OLIGOFAR_SCOPES
8 
9 class CTrBase
10 {
11 public:
12     enum EEvent {
13         eEvent_Match     = 0x01, // bases match
14         eEvent_Replaced  = 0x02, // replacement
15         eEvent_Insertion = 0x03, // query has extra base
16         eEvent_Deletion  = 0x04, // subject ahs an extra base
17         eEvent_Splice    = 0x05, // few subject bases are skiped with no penalty
18         eEvent_Overlap   = 0x06, // same subject bases are mathed twice by different bases of the read
19         eEvent_Padding   = 0x07, // CIGAR - for multisequence alignment, no action
20         eEvent_SoftMask  = 0x08, // end of the query is not aligned, but is present in SAM/BAM
21         eEvent_HardMask  = 0x09, // end of the query is not aligned and is not present in SAM/BAM
22         eEvent_Changed   = 0x0a, // allowed replacement (C->T with bisulfite treatment)
23         eEvent_NULL      = 0,
24     };
25     static EEvent Char2Event( char x );
Event2Char(EEvent x)26     static char Event2Char( EEvent x ) { return ":MRIDNBPSHC....."[x]; }
27 protected:
28     static char s_char2event[];
29 };
30 
Char2Event(char x)31 inline CTrBase::EEvent CTrBase::Char2Event( char x ) {
32     EEvent y = (EEvent)
33         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
34         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
35         //    A  B  C  D  E  F  G    H  I  J  K  L  M  N  O     P  Q  R  S  T  U  V  W    X  Y  Z
36         "\x0\x0\x6\xa\x4\x0\x0\x0""\x9\x3\x0\x0\x0\x1\x5\x0" "\x7\x0\x2\x8\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
37         "\x0\x0\x6\xa\x4\x0\x0\x0""\x9\x3\x0\x0\x0\x1\x5\x0" "\x7\x0\x2\x8\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
38         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
39         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
40         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
41         "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0" "\x0\x0\x0\x0\x0\x0\x0\x0""\x0\x0\x0\x0\x0\x0\x0\x0"
42         [int( (unsigned char)x)];
43     if( y == eEvent_NULL ) THROW( logic_error, "Unknown CIGAR event char ascii" << int(x) );
44     return y;
45 }
46 
47 
48 template<int bitst = 4, int bitsc = 12>
49 class CTrItemPacked : public CTrBase
50 {
51 public:
CTrItemPacked()52     CTrItemPacked() : m_event(0), m_count(0) {}
CTrItemPacked(EEvent t,unsigned c=1)53     CTrItemPacked( EEvent t, unsigned c = 1 ) : m_event( t ), m_count( c ) { ASSERT( c <= GetMaxCount() ); }
CTrItemPacked(const CTrItemPacked & other,unsigned cnt)54     CTrItemPacked( const CTrItemPacked& other, unsigned cnt ) : m_event( other.GetEvent() ), m_count( cnt ) { ASSERT( cnt <= GetMaxCount() ); }
CTrItemPacked(const CTrItemPacked & other)55     CTrItemPacked( const CTrItemPacked& other ) : m_event( other.GetEvent() ), m_count( other.GetCount() ) {}
56     template<class TOther>
CTrItemPacked(const TOther & other)57     CTrItemPacked( const TOther& other ) : m_event( other.GetEvent() ), m_count( other.GetCount() ) {
58         if( other.GetCount() > (int)GetMaxCount() ) { THROW( logic_error, "Event count limit exceeded: " << other.GetCount() << " > " << (int)GetMaxCount() << " for event " << Event2Char( other.GetEvent() ) ); } }
AddCount(int count)59     int AddCount( int count ) {
60         unsigned ncnt = count + GetCount();
61         if( ncnt > GetMaxCount() ) {
62             m_count = GetMaxCount();
63             return ncnt - GetMaxCount();
64         } else {
65             m_count = ncnt;
66             return 0;
67         }
68     }
69     template<class TOtherItem>
Add(const TOtherItem & o)70     TOtherItem Add( const TOtherItem& o ) {
71         if( GetCount() == 0 ) m_event = o.GetEvent();
72         else if( o.GetEvent() != GetEvent() ) return o;
73         return TOtherItem( o, AddCount( o.GetCount() ) );
74     }
SetEvent(EEvent ev)75     void SetEvent( EEvent ev ) { m_event = ev; }
GetEvent() const76     EEvent GetEvent() const { return EEvent( m_event ); }
GetCount() const77     int GetCount() const { return m_count; }
GetMaxCount()78     static size_t GetMaxCount() { return ~((~size_t(0)) << bitsc); }
GetCigar(EEvent t)79     static char GetCigar( EEvent t ) { return Event2Char( t ); } // considering that NULL can be at the end only
GetCigar() const80     char GetCigar() const { return GetCigar( GetEvent() ); }
DecrCount()81     CTrItemPacked<bitst,bitsc>& DecrCount() { if( m_count == 0 ) THROW( logic_error, "Attempt to decrement count below 0" ); --m_count; return *this; }
IncrCount()82     CTrItemPacked<bitst,bitsc>& IncrCount() { if( m_count == GetMaxCount() ) THROW( logic_error, "Attempt to increment count above max" ); ++m_count; return *this; }
operator ==(const CTrItemPacked<bitst,bitsc> & other) const83     bool operator == ( const CTrItemPacked<bitst,bitsc>& other ) const { return m_event == other.m_event && m_count == other.m_count; }
operator !=(const CTrItemPacked<bitst,bitsc> & other) const84     bool operator != ( const CTrItemPacked<bitst,bitsc>& other ) const { return m_event != other.m_event || m_count != other.m_count; }
85 protected:
86     unsigned int m_event:bitst;
87     unsigned int m_count:bitsc;
88 };
89 
90 template<unsigned bbits, unsigned cbits>
operator <<(std::ostream & out,const CTrItemPacked<bbits,cbits> & ti)91 inline std::ostream& operator << ( std::ostream& out, const CTrItemPacked<bbits,cbits>& ti )
92 {
93     return out << ti.GetCount() << ti.GetCigar();
94 }
95 
96 template<class T>
97 class CTrVector : public CTrBase, public vector<T>
98 {
99 public:
100     typedef T value_type;
101     typedef CTrVector<T> self_type;
102 
GetMaxItemCount()103     static size_t GetMaxItemCount() { return value_type::GetMaxCount(); }
104 
105     template<class TT>
Assign(const TT & tt)106     self_type& Assign( const TT& tt ) { self_type::clear(); return AppendFwd( tt ); }
Reverse()107     self_type& Reverse() { reverse( self_type::begin(), self_type::end() ); return *this; }
108 
AppendItem(EEvent t,unsigned cnt)109     self_type& AppendItem( EEvent t, unsigned cnt ) {
110         if( cnt == 0 ) return *this;
111         //ASSERT( t != eEvent_NULL );
112         if( (!self_type::empty()) && self_type::back().GetEvent() == t ) cnt = self_type::back().AddCount( cnt );
113         for( ; cnt > GetMaxItemCount() ; cnt -= GetMaxItemCount() ) push_back( T( t, GetMaxItemCount() ) );
114         if( cnt ) push_back( T( t, cnt ) );
115         return *this;
116     }
117 
118     template<class TT>
AppendItem(TT tt)119     self_type& AppendItem( TT tt ) {
120         if( tt.GetCount() == 0 ) return *this;
121         //ASSERT( tt.GetEvent() != eEvent_NULL );
122         if( (!self_type::empty()) && self_type::back().GetEvent() == tt.GetEvent() ) tt = self_type::back().Add( tt );
123         for( ; (unsigned)tt.GetCount() > GetMaxItemCount() ; tt = TT( tt, tt.GetCount() - GetMaxItemCount() ) )
124             push_back( T( tt, GetMaxItemCount() ) );
125         if( tt.GetCount() ) push_back( T( tt ) );
126         return *this;
127     }
128 
129     template<class TT>
AppendFwd(const TT & tt)130     self_type& AppendFwd( const TT& tt ) { return Append( tt.begin(), tt.end() ); }
131     template<class TT>
AppendRev(const TT & tt)132     self_type& AppendRev( const TT& tt ) { return Append( tt.rbegin(), tt.rend() ); }
133 
134     template<class Iter>
Append(Iter begin,Iter end)135     self_type& Append( Iter begin, Iter end ) {
136         for( ; begin != end ; ++begin ) AppendItem( *begin );
137         return *this;
138     }
139 
CTrVector()140     CTrVector() {}
CTrVector(const char * cigar)141     CTrVector( const char * cigar ) { Assign( cigar ); }
CTrVector(const string & cigar)142     CTrVector( const string& cigar ) { Assign( cigar ); }
143     template<class Other>
CTrVector(const Other & other)144     CTrVector( const Other& other ) { AppendFwd( other ); }
145 
Assign(const string & cigar)146     self_type& Assign( const string& cigar ) { return Assign( cigar.c_str() ); }
Assign(const char * cigar)147     self_type& Assign( const char * cigar ) {
148         self_type::clear();
149         if( cigar == 0 ) return *this;
150         for( const char * x = cigar; *x; ++x ) {
151             int count = isdigit( *x ) ? strtol( x, const_cast<char**>(&x), 10 ) : 1;
152             EEvent event = Char2Event(*x);
153             if( count > 0 ) AppendItem( event, count );
154         }
155         return *this;
156     }
ComputeLengths() const157     pair<int,int> ComputeLengths() const {
158         int qlen = 0, slen = 0;
159         for( typename self_type::const_iterator iter = self_type::begin(); iter != self_type::end(); ++iter ) {
160             switch( iter->GetEvent() ) {
161             case eEvent_NULL:
162             case eEvent_Padding:
163             case eEvent_SoftMask:
164             case eEvent_HardMask: break;
165             case eEvent_Insertion: qlen += iter->GetCount(); break;
166             case eEvent_Overlap: slen -= iter->GetCount(); break;
167             case eEvent_Splice:
168             case eEvent_Deletion: slen += iter->GetCount(); break;
169             case eEvent_Match:
170             case eEvent_Changed:
171             case eEvent_Replaced: qlen += iter->GetCount(); slen += iter->GetCount(); break;
172             }
173         }
174         return make_pair( qlen, slen );
175     }
ComputeSubjectLength() const176     unsigned ComputeSubjectLength() const {
177         int len = 0;
178         for( typename self_type::const_iterator iter = self_type::begin(); iter != self_type::end(); ++iter ) {
179             switch( iter->GetEvent() ) {
180             case eEvent_NULL:
181             case eEvent_Padding:
182             case eEvent_SoftMask:
183             case eEvent_HardMask:
184             case eEvent_Insertion: break;
185             case eEvent_Overlap: len -= iter->GetCount(); break;
186             case eEvent_Splice:
187             case eEvent_Deletion:
188             case eEvent_Match:
189             case eEvent_Changed:
190             case eEvent_Replaced: len += iter->GetCount(); break;
191             }
192         }
193         ASSERT( len >= 0 );
194         return len;
195     }
196 
197     template<class Iter>
Print(ostream & o,Iter begin,Iter end)198     static ostream& Print( ostream& o, Iter begin, Iter end ) {
199         for( Iter i = begin; i != end; ++i ) {
200             if( i->GetCount() ) o << i->GetCount() << i->GetCigar();
201         }
202         return o;
203     }
PrintFwd(ostream & o) const204     ostream& PrintFwd( ostream& o ) const { return Print( o, self_type::begin(), self_type::end() ); }
PrintRev(ostream & o) const205     ostream& PrintRev( ostream& o ) const { return Print( o, self_type::rbegin(), self_type::rend() ); }
ToString() const206     string ToString() const { ostringstream o; PrintFwd( o ); return o.str(); }
207 };
208 
209 template<unsigned bbits, unsigned cbits>
operator <<(std::ostream & out,const CTrVector<CTrItemPacked<bbits,cbits>> & tr)210 inline std::ostream& operator << ( std::ostream& out, const CTrVector<CTrItemPacked<bbits,cbits> >& tr )
211 {
212     return tr.PrintFwd( out );
213 }
214 
215 template<int bitst = 4, int bitsc = 12>
216 class CTrSequence : public CTrBase
217 {
218 public:
219     // TODO: optimize allocation/deallocation to minimize dry rest
220     typedef CTrSequence<bitst,bitsc> self_type;
221 
222     typedef CTrItemPacked<bitst,bitsc> value_type;
223     typedef CTrItemPacked<bitst,bitsc> data_type;
224 
225     typedef CTrItemPacked<bitst,bitsc> * self_pointer_type;
226     typedef CTrItemPacked<bitst,bitsc> & self_reference_type;
227 
228     typedef const CTrItemPacked<bitst,bitsc> * self_const_pointer_type;
229     typedef const CTrItemPacked<bitst,bitsc> & self_const_reference_type;
230 
231     typedef value_type * pointer_type;
232     typedef value_type & reference_type;
233     typedef const value_type * const_pointer_type;
234     typedef const value_type & const_reference_type;
235 
236     typedef pointer_type iterator;
237     typedef const_pointer_type const_iterator;
238 
239     enum { kSizeIncrement = 4 };
240 
241     template<class Item>
242     class C_ReverseIterator
243     {
244     public:
245         typedef Item value_type;
246         typedef Item * pointer_type;
247         typedef Item & reference_type;
248         typedef C_ReverseIterator<Item> self_type;
249 
C_ReverseIterator(Item * i=0)250         C_ReverseIterator( Item * i = 0 ) : m_item( i ) {}
C_ReverseIterator(const self_type * i)251         C_ReverseIterator( const self_type* i ) : m_item( i->m_item ) {}
C_ReverseIterator(const self_type & i)252         C_ReverseIterator( const self_type& i ) : m_item( i.m_item ) {}
operator pointer_type() const253         operator pointer_type () const { return m_item; }
operator ->() const254         pointer_type operator -> () const { return m_item; }
operator *() const255         reference_type operator * () const { return *m_item; }
operator ++()256         self_type& operator ++ () { --m_item; return *this; }
operator --()257         self_type& operator -- () { ++m_item; return *this; }
operator ++(int)258         self_type  operator ++ ( int ) { self_type ret( *this ); --m_item; return ret; }
operator --(int)259         self_type  operator -- ( int ) { self_type ret( *this ); ++m_item; return ret; }
operator +=(int i)260         self_type& operator += ( int i ) { m_item -= i; return *this; }
operator -=(int i)261         self_type& operator -= ( int i ) { m_item += i; return *this; }
operator ==(const self_type & other) const262         bool operator == ( const self_type& other ) const { return m_item == other.m_item; }
operator !=(const self_type & other) const263         bool operator != ( const self_type& other ) const { return m_item != other.m_item; }
operator <(const self_type & other) const264         bool operator <  ( const self_type& other ) const { return m_item >  other.m_item; }
operator >(const self_type & other) const265         bool operator >  ( const self_type& other ) const { return m_item <  other.m_item; }
operator <=(const self_type & other) const266         bool operator <= ( const self_type& other ) const { return m_item >= other.m_item; }
operator >=(const self_type & other) const267         bool operator >= ( const self_type& other ) const { return m_item <= other.m_item; }
operator -(const self_type & a,const self_type & b)268         friend       int operator - ( const self_type& a, const self_type& b ) { return b.m_item - a.m_item; }
operator -(const self_type & a,int b)269         friend self_type operator - ( const self_type& a, int b ) { return self_type(a.m_item + b); }
operator +(const self_type & a,int b)270         friend self_type operator + ( const self_type& a, int b ) { return self_type(a.m_item - b); }
operator +(int b,const self_type & a)271         friend self_type operator + ( int b, const self_type& a ) { return self_type(a.m_item - b); }
272     protected:
273         Item * m_item;
274     };
275 
276     typedef C_ReverseIterator<value_type> reverse_iterator;
277     typedef C_ReverseIterator<const value_type> const_reverse_iterator;
278 
~CTrSequence()279     ~CTrSequence() { free( m_data ); }
CTrSequence()280     CTrSequence() : m_data(0) {}
CTrSequence(const self_type & other)281     CTrSequence( const self_type& other ) : m_data(0) { Assign( other ); }
CTrSequence(const char * trans)282     CTrSequence( const char *  trans ) : m_data(0) { Assign( trans ); }
CTrSequence(const string & trans)283     CTrSequence( const string& trans ) : m_data(0) { Assign( trans ); }
284 
size() const285     size_t size() const { return m_data ? m_data->GetCount() : 0; }
capacity() const286     size_t capacity() const { return size(); } //m_data ? m_data->GetCount() | (kSizeIncrement - 1) : 0; }
287 
front()288     reference_type front() { return m_data[1]; }
back()289     reference_type back() { return m_data[size()]; } // since size() is always 1 less then allocated, and first element contains size
front() const290     const_reference_type front() const { return m_data[1]; }
back() const291     const_reference_type back() const { return m_data[size()]; }
292 
begin()293     iterator begin() { return m_data ? m_data + 1 : 0; }
end()294     iterator end() { return m_data ? m_data + size() + 1 : 0; }
begin() const295     const_iterator begin() const { return m_data ? m_data + 1 : 0; }
end() const296     const_iterator end() const { return m_data ? m_data + size() + 1 : 0; }
297 
rbegin()298     reverse_iterator rbegin() { return m_data ? m_data + size() : 0; }
rend()299     reverse_iterator rend() { return m_data ? m_data : 0; }
rbegin() const300     const_reverse_iterator rbegin() const { return m_data ? m_data + size() : 0; }
rend() const301     const_reverse_iterator rend() const { return m_data ? m_data : 0; }
302 
clear()303     void clear() { free( m_data ); m_data = 0; } //delete[] m_data; m_data = 0; }
resize(unsigned long x)304     void resize( unsigned long x ) {
305         ASSERT( x <= size() );
306         ASSERT( x >= 0 );
307         if( x == size() ) return;
308         if( x == 0 ) clear();
309         else m_data[0] = value_type( eEvent_NULL, x );
310     }
reserve(unsigned long)311     void reserve( unsigned long ) {}
erase(iterator from,iterator to)312     void erase( iterator from, iterator to ) {
313         copy( to, end(), from );
314         resize( size() - ( to - from ) );
315     }
316 
operator !=(const self_type & other) const317     bool operator != ( const self_type& other ) const { return !operator == ( other ); }
operator ==(const self_type & other) const318     bool operator == ( const self_type& other ) const {
319         const_iterator a = begin(), b = other.begin();
320         const_iterator A = end(), B = other.end();
321         while( a != A && b != B ) if( *a++ != *b++ ) return false;
322         return( a == A && b == B );
323     }
324 
operator =(const self_type & other)325     self_type& operator = ( const self_type& other ) { return Assign( other ); }
326 
operator [](int i)327     reference_type operator [] ( int i ) { return m_data[i + 1]; }
operator [](int i) const328     const_reference_type operator [] ( int i ) const { return m_data[i + 1]; }
329 
AppendItem(const value_type & value)330     self_type& AppendItem( const value_type& value ) {
331         if( value.GetCount() == 0 ) return *this;
332         if( value.GetEvent() == eEvent_NULL ) return *this;
333         if( m_data == 0 ) {
334             m_data = (pointer_type)malloc( sizeof( value_type ) * 2 ); // allocate two items at once - for metadata and for first element
335             //m_data = new value_type[kSizeIncrement];
336             m_data[0] = value_type( eEvent_NULL, 1 );
337             m_data[1] = value;
338         } else {
339             ASSERT( size() > 0 );
340             reference_type b = back();
341             value_type v = b.Add( value );
342             if( v.GetCount() ) {
343                 size_t s = size();
344                 m_data = (pointer_type)realloc( m_data, (s + 2)*sizeof( value_type ) );
345                 m_data[s + 1] = v;
346                 ASSERT( m_data[0].GetCount() == (int)s );
347                 m_data[0].IncrCount();
348             }
349         }
350         return *this;
351     }
AppendItem(EEvent ev,unsigned cnt)352     self_type& AppendItem( EEvent ev, unsigned cnt ) {
353         if( ev == eEvent_NULL ) return *this;
354         if( cnt <= 0 ) return *this;
355         while( cnt > value_type::GetMaxCount() ) {
356             AppendItem( value_type( ev, value_type::GetMaxCount() ) );
357             cnt -= value_type::GetMaxCount();
358         }
359         return AppendItem( value_type( ev, cnt ) );
360     }
361     template<class Iter>
Append(const Iter & begin,const Iter & end)362     self_type& Append( const Iter& begin, const Iter& end ) {
363         for( Iter x = begin, X = end; x != X; ++x ) AppendItem( *x );
364         return *this;
365     }
AppendFwd(const self_type & other)366     self_type& AppendFwd( const self_type& other ) {
367         Append( other.begin(), other.end() );
368         return *this;
369     }
AppendRev(const self_type & other)370     self_type& AppendRev( const self_type& other ) {
371         Append( other.rbegin(), other.rend() );
372         return *this;
373     }
Assign(const string & other)374     self_type& Assign( const string& other ) { return Assign( other.c_str() ); }
Assign(const self_type & other)375     self_type& Assign( const self_type& other ) {
376         if( &other == this ) return *this;
377         //delete[] m_data;
378         if( m_data ) { free( m_data ); m_data = 0; }
379         if( int sz = other.size() ) {
380             m_data = (pointer_type)malloc( (1 + sz) * sizeof( value_type ) );
381             // m_data = new value_type[(sz | (kSizeIncrement - 1)) + 1];
382             copy( other.m_data, other.m_data + sz + 1, m_data );
383         }
384         else m_data = 0;
385         return *this;
386     }
Assign(const CTrVector<value_type> & other)387     self_type& Assign( const CTrVector<value_type>& other ) {
388         if( m_data ) { free( m_data ); m_data = 0; }
389         for( typename CTrVector<value_type>::const_iterator o = other.begin(); o != other.end(); ++o ) AppendItem( *o );
390         return *this;
391     }
Assign(const char * other)392     self_type& Assign( const char * other ) {
393         //delete[] m_data;
394         if( m_data ) { free( m_data ); m_data = 0; }
395         if( !other ) return *this;
396         for( const char * x = other; *x; ++x ) {
397             unsigned cnt = isdigit( *x ) ? strtol( x, const_cast<char**>( &x ), 10 ) : 1;
398             EEvent e = Char2Event( *x );
399             if( e == eEvent_NULL ) THROW( runtime_error, "Undefined CIGAR char " << (isprint( *x ) ? *x : ' ') << " (ascii" << int(*x) << ") in [" << other << "]" );
400             while( cnt > value_type::GetMaxCount() ) AppendItem( value_type( e, value_type::GetMaxCount() ) );
401             if( cnt > 0 ) AppendItem( value_type( e, cnt ) );
402         }
403         return *this;
404     }
Reverse()405     self_type& Reverse() {
406         if( m_data ) reverse( m_data + 1, m_data + 1 + m_data->GetCount() );
407         return *this;
408     }
409     template<class Iter>
Print(ostream & o,Iter begin,Iter end)410     static ostream& Print( ostream& o, Iter begin, Iter end ) {
411         for( Iter i = begin; i != end; ++i ) {
412             if( i->GetCount() ) o << i->GetCount() << i->GetCigar();
413         }
414         return o;
415     }
ComputeSubjectLength() const416     unsigned ComputeSubjectLength() const {
417         int len = 0;
418         for( typename self_type::const_iterator iter = self_type::begin(); iter != self_type::end(); ++iter ) {
419             switch( iter->GetEvent() ) {
420             case eEvent_NULL:
421             case eEvent_Padding:
422             case eEvent_SoftMask:
423             case eEvent_HardMask:
424             case eEvent_Insertion: break;
425             case eEvent_Overlap: len -= iter->GetCount(); break;
426             case eEvent_Splice:
427             case eEvent_Deletion:
428             case eEvent_Match:
429             case eEvent_Changed:
430             case eEvent_Replaced: len += iter->GetCount(); break;
431             }
432         }
433         ASSERT( len >= 0 );
434         return len;
435     }
ComputeLengths() const436     pair<int,int> ComputeLengths() const {
437         int qlen = 0, slen = 0;
438         for( typename self_type::const_iterator iter = self_type::begin(); iter != self_type::end(); ++iter ) {
439             switch( iter->GetEvent() ) {
440             case eEvent_NULL:
441             case eEvent_Padding:
442             case eEvent_SoftMask:
443             case eEvent_HardMask: break;
444             case eEvent_Insertion: qlen += iter->GetCount(); break;
445             case eEvent_Overlap: slen -= iter->GetCount(); break;
446             case eEvent_Splice:
447             case eEvent_Deletion: slen += iter->GetCount(); break;
448             case eEvent_Match:
449             case eEvent_Changed:
450             case eEvent_Replaced: qlen += iter->GetCount(); slen += iter->GetCount(); break;
451             }
452         }
453         return make_pair( qlen, slen );
454     }
PrintFwd(ostream & o) const455     ostream& PrintFwd( ostream& o ) const { return Print( o, self_type::begin(), self_type::end() ); }
PrintRev(ostream & o) const456     ostream& PrintRev( ostream& o ) const { return Print( o, self_type::rbegin(), self_type::rend() ); }
457 
ToString() const458     string ToString() const { ostringstream o; PrintFwd( o ); return o.str(); }
459 protected:
460     // data structure: first item should be NULL with count equal to number of items in list
461     pointer_type m_data;
462 };
463 
464 template<unsigned bbits, unsigned cbits>
operator <<(std::ostream & out,const CTrSequence<bbits,cbits> & tr)465 inline std::ostream& operator << ( std::ostream& out, const CTrSequence<bbits,cbits>& tr )
466 {
467     return tr.PrintFwd( out );
468 }
469 
470 template<class Iter>
ComputeDistance(Iter begin,Iter end)471 int ComputeDistance( Iter begin, Iter end )
472 {
473     int ret = 0;
474     for( ; begin != end; ++begin )
475         switch( begin->GetEvent() ) {
476             case CTrBase::eEvent_Insertion:
477             case CTrBase::eEvent_Deletion:
478             case CTrBase::eEvent_Replaced: ret += begin-> GetCount();
479             default: ;
480         }
481     return ret;
482 }
483 
484 template<class Container>
ComputeDistance(const Container & cont)485 int ComputeDistance( const Container& cont )
486 {
487     return ComputeDistance( cont.begin(), cont.end() );
488 }
489 
490 typedef CTrItemPacked<4,12> TTrItem;
491 typedef CTrVector<TTrItem> TTrVector;
492 //typedef CTrVector<TTrItem> TTrSequence;
493 typedef CTrSequence<4,12> TTrSequence;
494 
495 END_OLIGOFAR_SCOPES
496 
497 #endif
498