1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #ifndef _hpp_seq_ranges_
28 #define _hpp_seq_ranges_
29
30 #include <list>
31
32 namespace seq_ranges {
33
34 enum e_range_relation {
35 rr_before,
36 rr_begin,
37 rr_span,
38 rr_inside,
39 rr_end,
40 rr_after
41 };
42
43
44 /* -----------------------------------------------------------------------
45 range-relations:
46
47 A |-------------|
48 B |-----|
49 A.range_rel( B ) = rr_before
50
51 A |-------------|
52 B |-----|
53 A.range_rel( B ) = rr_begin
54
55 A |-------------|
56 B |-------------------|
57 A.range_rel( B ) = rr_span
58
59 A |-------------|
60 B |-----|
61 A.range_rel( B ) = rr_inside
62
63 A |-------------|
64 B |-----|
65 A.range_rel( B ) = rr_end
66
67 A |-------------|
68 B |-----|
69 A.range_rel( B ) = rr_after
70
71 ----------------------------------------------------------------------- */
72
73 class range
74 {
75 private :
76 long start;
77 long end;
78
79 public :
range(void)80 range( void ) : start( 0 ), end( 0 ) { }
range(long start_,long end_)81 range( long start_, long end_ ) : start( start_ ), end( end_ ) { }
range(const range & other)82 range( const range &other ) : start( other.start ), end( other.end ) { }
83
range(const std::string & start_,const std::string & end_)84 range( const std::string &start_, const std::string &end_ ) : start( 0 ), end( 0 )
85 {
86 bool valid = ( convert_value( start_, start ) && convert_value( end_, end ) );
87 if ( !valid ) set( 0, 0 );
88 }
89
operator =(const range & other)90 range& operator= ( const range &other )
91 {
92 if ( this == &other ) return *this;
93 start = other.start;
94 end = other.end;
95 return *this;
96 }
97
set(long start_,long end_)98 void set( long start_, long end_ ) { start = start_; end = end_; }
99
convert_value(const std::string value_,long & value)100 static bool convert_value( const std::string value_, long &value )
101 {
102 bool res = true;
103 std::istringstream ( value_ ) >> value;
104 if ( value < 1 )
105 res = false;
106 return res;
107 }
108
109 /* does this range end before the other range starts ? */
ends_before(const range & other) const110 bool ends_before( const range &other ) const { return ( end < other.start ); }
111
112 /* does this range start after the other range ends ? */
starts_after(const range & other) const113 bool starts_after( const range &other ) const { return ( start > other.end ); }
114
intersect(const range & other) const115 bool intersect( const range &other ) const
116 {
117 e_range_relation rr = range_relation( other );
118 return ( rr == rr_begin || rr == rr_span || rr == rr_inside || rr == rr_end );
119 }
120
intersect(const long value) const121 bool intersect( const long value ) const
122 { return ( value >= start && value <= end ); }
123
include(const range & other)124 void include( const range &other )
125 {
126 if ( other.start < start ) start = other.start;
127 if ( other.end > end ) end = other.end;
128 }
129
merge(const range & other)130 bool merge( const range &other )
131 {
132 bool res = intersect( other );
133 if ( res ) include( other );
134 return res;
135 }
136
range_relation(const range & other) const137 enum e_range_relation range_relation( const range &other ) const
138 {
139 enum e_range_relation res;
140 if ( other.start < start )
141 {
142 if ( other.end < start )
143 res = rr_before;
144 else if ( other.end <= end )
145 res = rr_begin;
146 else
147 res = rr_span;
148 }
149 else
150 {
151 if ( other.start <= end )
152 {
153 if ( other.end <= end )
154 res = rr_inside;
155 else
156 res = rr_end;
157 }
158 else
159 res = rr_after;
160 }
161
162 return res;
163 }
164
get_start(void) const165 long get_start( void ) const { return start; }
get_end(void) const166 long get_end( void ) const { return end; }
empty(void) const167 bool empty( void ) const { return ( start == 0 && end == 0 ); }
168
print(std::ostream & stream) const169 void print( std::ostream &stream ) const { stream << "[ " << start << " .. " << end << " ]"; }
170
operator <<(std::ostream & stream,const range & other)171 friend std::ostream& operator<< ( std::ostream &stream, const range &other )
172 {
173 other.print( stream );
174 return stream;
175 }
176
range_relation_2_str(enum e_range_relation rr)177 static std::string range_relation_2_str( enum e_range_relation rr )
178 {
179 switch ( rr )
180 {
181 case rr_before : return std::string( "before" ); break;
182 case rr_begin : return std::string( "begin" ); break;
183 case rr_span : return std::string( "span" ); break;
184 case rr_inside : return std::string( "inside" ); break;
185 case rr_end : return std::string( "end" ); break;
186 case rr_after : return std::string( "after" ); break;
187 }
188 return std::string( "unknown" );
189 }
190
191 };
192
193
compare_ranges(const range * first,const range * second)194 bool compare_ranges ( const range * first, const range * second )
195 {
196 return ( first -> get_start() < second -> get_start() );
197 }
198
199
200 struct ranges_relation
201 {
202 bool has_inside;
203 bool has_partial;
204
clearseq_ranges::ranges_relation205 void clear( void ) { has_inside = has_partial = false; }
206
printseq_ranges::ranges_relation207 void print( std::ostream &stream ) const { stream << "inside: " << has_inside << ", partial: " << has_partial; }
208
operator <<(std::ostream & stream,const ranges_relation & other)209 friend std::ostream& operator<< ( std::ostream &stream, const ranges_relation &other )
210 {
211 other.print( stream );
212 return stream;
213 }
214 };
215
216
217 class ranges
218 {
219 private :
220 std::list< range * > range_list;
221 long count;
222
223 public :
ranges(void)224 ranges( void ) : count( 0 ) {}
~ranges(void)225 ~ranges( void ) { clear(); }
226
clear(void)227 void clear( void )
228 {
229 while ( !range_list.empty() )
230 {
231 range * r = range_list.front();
232 range_list.pop_front();
233 if ( r != NULL ) delete r;
234 }
235 count = 0;
236 }
237
add(range * r)238 void add( range * r ){ if ( r != NULL ) { range_list.push_back( r ); count++; } }
add(const range & r)239 void add( const range &r ){ add( new range( r ) ); }
240
merge(const range & r1)241 void merge( const range &r1 )
242 {
243 bool merged = false;
244 std::list< range * >::iterator it;
245 for ( it = range_list.begin(); it != range_list.end() && !merged; ++it )
246 {
247 range * r = *it;
248 if ( r != NULL )
249 merged = r -> merge( r1 );
250 }
251 if ( !merged ) add( r1 );
252 }
253
sort(void)254 void sort( void ) { range_list.sort( compare_ranges ); }
get_count(void)255 long get_count( void ) { return count; }
256
compare_sample(const ranges & sample,ranges_relation & res) const257 void compare_sample( const ranges &sample, ranges_relation &res ) const
258 {
259 res.clear();
260 bool done = false;
261
262 // we take each range of the sample and compare it against each range of self
263 std::list< range * >::const_iterator sample_it;
264 for ( sample_it = sample.range_list.begin(); sample_it != sample.range_list.end() && !done; ++sample_it )
265 {
266 const range * sample_range = *sample_it;
267 std::list< range * >::const_iterator pattern_it;
268 for ( pattern_it = range_list.begin(); pattern_it != range_list.end() && !done; ++pattern_it )
269 {
270 const range * pattern_range( *pattern_it );
271 enum e_range_relation rr = pattern_range -> range_relation( *sample_range );
272 switch( rr )
273 {
274 case rr_before : break;
275 case rr_begin : res.has_partial = true; break;
276 case rr_span : res.has_partial = true; break;
277 case rr_inside : res.has_inside = true; break;
278 case rr_end : res.has_partial = true; break;
279 case rr_after : break;
280 }
281 done = ( res.has_partial && res.has_inside );
282 }
283 }
284 }
285
print(std::ostream & stream) const286 void print( std::ostream &stream ) const
287 {
288 std::list< range * >::const_iterator it;
289 for ( it = range_list.begin(); it != range_list.end(); ++it )
290 {
291 range * r = *it;
292 if ( r != NULL ) stream << *r << " ";
293 }
294 }
295
operator <<(std::ostream & stream,const ranges & other)296 friend std::ostream& operator<< ( std::ostream &stream, const ranges &other )
297 {
298 other.print( stream );
299 return stream;
300 }
301
302 };
303
304 }; // namespace seq_ranges
305
306 #endif // _hpp_seq_ranges_
307
308