ARB
pos_range.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : pos_range.cxx //
4 // Purpose : range of positions (e.g. part of seq) //
5 // //
6 // Coded by Ralf Westram (coder@reallysoft.de) in October 2011 //
7 // Institute of Microbiology (Technical University Munich) //
8 // http://www.arb-home.de/ //
9 // //
10 // =============================================================== //
11 
12 #include "pos_range.h"
13 #include "arb_mem.h"
14 
15 void PosRange::copy_corresponding_part(char *dest, const char *source, size_t source_len) const {
16  // dest and source may overlap
17 
18  arb_assert((!source && source_len == 0) || (source && source_len == strlen(source)));
19 
20  ExplicitRange range(*this, source_len);
21  int Size = range.size();
22 
23  if (Size) memmove(dest, source+start(), Size);
24  dest[Size] = 0;
25 }
26 
27 char *PosRange::dup_corresponding_part(const char *source, size_t source_len) const {
28  ExplicitRange range(*this, source_len);
29  int Size = range.size();
30  char *dup = ARB_alloc<char>(Size+1);
31 
32  copy_corresponding_part(dup, source, source_len);
33  return dup;
34 }
35 
36 // --------------------------------------------------------------------------------
37 
38 #ifdef UNIT_TESTS
39 
40 #ifndef TEST_UNIT_H
41 #include <test_unit.h>
42 #endif
43 #include "arb_msg.h"
44 #include <climits>
45 #include <smartptr.h>
46 
47 inline bool exactly_one_of(bool b1, bool b2, bool b3) { return (b1+b2+b3) == 1; }
48 inline bool wellDefined(PosRange range) {
49  return
50  exactly_one_of(range.is_empty(), range.is_part(), range.is_whole()) &&
51  contradicted(range.is_limited(), range.is_unlimited());
52 }
53 
54 void TEST_PosRange() {
55  PosRange empty = PosRange::empty();
56  PosRange whole = PosRange::whole();
57  PosRange from7 = PosRange::from(7);
58  PosRange till9 = PosRange::till(9);
59  PosRange seven2nine(7, 9);
60 
61  TEST_REJECT(empty.is_whole()); TEST_REJECT(empty.is_part()); TEST_EXPECT(empty.is_empty());
62  TEST_EXPECT(whole.is_whole()); TEST_REJECT(whole.is_part()); TEST_REJECT(whole.is_empty());
63  TEST_REJECT(from7.is_whole()); TEST_EXPECT(from7.is_part()); TEST_REJECT(from7.is_empty());
64  TEST_REJECT(till9.is_whole()); TEST_EXPECT(till9.is_part()); TEST_REJECT(till9.is_empty());
65  TEST_REJECT(seven2nine.is_whole()); TEST_EXPECT(seven2nine.is_part()); TEST_REJECT(seven2nine.is_empty());
66 
67  TEST_EXPECT(empty.is_limited());
68  TEST_REJECT(whole.is_limited());
69  TEST_REJECT(from7.is_limited());
70  TEST_EXPECT(till9.is_limited());
71  TEST_EXPECT(seven2nine.is_limited());
72 
73  // test size
74  TEST_EXPECT_EQUAL(empty.size(), 0);
75  TEST_EXPECT(whole.size() < 0);
76  TEST_EXPECT(from7.size() < 0);
77  TEST_EXPECT_EQUAL(till9.size(), 10);
78  TEST_EXPECT_EQUAL(seven2nine.size(), 3);
79 
80  TEST_EXPECT(wellDefined(empty));
81  TEST_EXPECT(wellDefined(whole));
82  TEST_EXPECT(wellDefined(from7));
83  TEST_EXPECT(wellDefined(till9));
84  TEST_EXPECT(wellDefined(seven2nine));
85 
86  // test equality
87  TEST_EXPECT(empty == empty);
88  TEST_EXPECT(whole == whole);
89  TEST_EXPECT(from7 == from7);
90  TEST_EXPECT(whole != from7);
91 
92  TEST_EXPECT(from7 == PosRange::after(6));
93  TEST_EXPECT(till9 == PosRange::prior(10));
94 
95  // test containment (see also TEST_range_containment below)
96  for (int pos = -3; pos<12; ++pos) {
97  TEST_ANNOTATE(GBS_global_string("pos=%i", pos));
98 
99  TEST_REJECT(empty.contains(pos));
100  TEST_EXPECT(correlated(whole.contains(pos), pos >= 0));
101  TEST_EXPECT(correlated(from7.contains(pos), pos >= 7));
102  TEST_EXPECT(correlated(till9.contains(pos), pos >= 0 && pos <= 9));
103  TEST_EXPECT(correlated(seven2nine.contains(pos), pos >= 7 && pos <= 9));
104  }
105  TEST_ANNOTATE(NULp);
106 
107  TEST_EXPECT(whole.contains(INT_MAX));
108  TEST_EXPECT(from7.contains(INT_MAX));
109  TEST_REJECT(empty.contains(INT_MAX));
110 
111  // test after/prior
112  TEST_EXPECT(empty.prior() == empty);
113  TEST_EXPECT(whole.prior() == empty);
114  TEST_EXPECT(from7.prior() == PosRange::till(6));
115  TEST_EXPECT(till9.prior() == empty);
116  TEST_EXPECT(seven2nine.prior() == PosRange::till(6));
117 
118  TEST_EXPECT(empty.after() == empty);
119  TEST_EXPECT(whole.after() == empty);
120  TEST_EXPECT(from7.after() == empty);
121  TEST_EXPECT(till9.after() == PosRange::from(10));
122  TEST_EXPECT(seven2nine.after() == PosRange::from(10));
123 }
124 
125 void TEST_ExplicitRange() {
126  PosRange empty;
127  PosRange whole = PosRange::whole();
128  PosRange till50 = PosRange::till(50);
129  PosRange from30 = PosRange::from(30);
130  PosRange f30t50(30, 50);
131 
132  ExplicitRange wholeOf17(whole, 17);
133  TEST_EXPECT(PosRange(wholeOf17).is_limited());
134 
135  TEST_EXPECT_EQUAL(ExplicitRange(whole, 100).size(), 100);
136  TEST_EXPECT_EQUAL(ExplicitRange(till50, 100).size(), 51); // 0-50
137  TEST_EXPECT_EQUAL(ExplicitRange(till50, 40).size(), 40);
138  TEST_EXPECT_EQUAL(ExplicitRange(from30, 100).size(), 70);
139  TEST_EXPECT_EQUAL(ExplicitRange(from30, 20).size(), 0);
140  TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 100).size(), 21);
141  TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 40).size(), 10); // 30-39
142 
143  TEST_EXPECT_EQUAL(ExplicitRange(empty, 20).size(), 0);
144 }
145 
146 void TEST_range_copying() {
147  char dest[100];
148  const char *source = "0123456789";
149  const size_t source_len = strlen(source);
150 
151  PosRange::till(2).copy_corresponding_part(dest, source, source_len);
152  TEST_EXPECT_EQUAL(dest, "012");
153 
154  PosRange(2, 5).copy_corresponding_part(dest, source, source_len);
155  TEST_EXPECT_EQUAL(dest, "2345");
156 
157  PosRange::from(7).copy_corresponding_part(dest, source, source_len);
158  TEST_EXPECT_EQUAL(dest, "789");
159 
160  PosRange(9, 1000).copy_corresponding_part(dest, source, source_len);
161  TEST_EXPECT_EQUAL(dest, "9");
162 
163  PosRange(900, 1000).copy_corresponding_part(dest, source, source_len);
164  TEST_EXPECT_EQUAL(dest, "");
165 
166  // make sure dest and source may overlap:
167  strcpy(dest, source);
168  PosRange::whole().copy_corresponding_part(dest+1, dest, source_len);
169  TEST_EXPECT_EQUAL(dest+1, source);
170 
171  strcpy(dest, source);
172  PosRange::whole().copy_corresponding_part(dest, dest+1, source_len-1);
173  TEST_EXPECT_EQUAL(dest, source+1);
174 
175  TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange::empty().dup_corresponding_part(source, source_len)), ""); // empty range
176  TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange(2, 5).dup_corresponding_part(NULp, 0)), ""); // empty source
177 }
178 TEST_PUBLISH(TEST_range_copying);
179 
180 void TEST_range_intersection() {
181  PosRange empty;
182  PosRange whole = PosRange::whole();
183  PosRange till50 = PosRange::till(50);
184  PosRange from30 = PosRange::from(30);
185  PosRange part(30, 50);
186 
187  TEST_EXPECT(intersection(empty, empty) == empty);
188  TEST_EXPECT(intersection(empty, whole) == empty);
189  TEST_EXPECT(intersection(empty, till50) == empty);
190  TEST_EXPECT(intersection(empty, from30) == empty);
191  TEST_EXPECT(intersection(empty, part) == empty);
192 
193  TEST_EXPECT(intersection(whole, empty) == empty);
194  TEST_EXPECT(intersection(whole, whole) == whole);
195  TEST_EXPECT(intersection(whole, till50) == till50);
196  TEST_EXPECT(intersection(whole, from30) == from30);
197  TEST_EXPECT(intersection(whole, part) == part);
198 
199  TEST_EXPECT(intersection(till50, empty) == empty);
200  TEST_EXPECT(intersection(till50, whole) == till50);
201  TEST_EXPECT(intersection(till50, till50) == till50);
202  TEST_EXPECT(intersection(till50, from30) == part);
203  TEST_EXPECT(intersection(till50, part) == part);
204 
205  TEST_EXPECT(intersection(from30, empty) == empty);
206  TEST_EXPECT(intersection(from30, whole) == from30);
207  TEST_EXPECT(intersection(from30, till50) == part);
208  TEST_EXPECT(intersection(from30, from30) == from30);
209  TEST_EXPECT(intersection(from30, part) == part);
210 
211  TEST_EXPECT(intersection(part, empty) == empty);
212  TEST_EXPECT(intersection(part, whole) == part);
213  TEST_EXPECT(intersection(part, till50) == part);
214  TEST_EXPECT(intersection(part, from30) == part);
215  TEST_EXPECT(intersection(part, part) == part);
216 
217  TEST_EXPECT(intersection(PosRange(20, 40), till50) == PosRange(20, 40));
218  TEST_EXPECT(intersection(PosRange(40, 60), till50) == PosRange(40, 50));
219  TEST_EXPECT(intersection(PosRange(60, 80), till50) == empty);
220 
221  TEST_EXPECT(intersection(PosRange(0, 20), from30) == empty);
222  TEST_EXPECT(intersection(PosRange(20, 40), from30) == PosRange(30, 40));
223  TEST_EXPECT(intersection(PosRange(40, 60), from30) == PosRange(40, 60));
224 
225  TEST_EXPECT(intersection(PosRange(40, 60), PosRange(50, 70)) == PosRange(50, 60));
226 }
227 
228 void TEST_range_containment() {
229  PosRange empty;
230  PosRange whole = PosRange::whole();
231  PosRange till50 = PosRange::till(50);
232  PosRange from30 = PosRange::from(30);
233  PosRange part(30, 50);
234 
235  // empty contains nothing
236  TEST_REJECT(empty.contains(empty)); // and empty is contained nowhere!
237  TEST_REJECT(empty.contains(whole));
238  TEST_REJECT(empty.contains(till50));
239  TEST_REJECT(empty.contains(from30));
240  TEST_REJECT(empty.contains(part));
241 
242  // whole contains anything
243  TEST_REJECT(whole.contains(empty)); // except empty
244  TEST_EXPECT(whole.contains(whole));
245  TEST_EXPECT(whole.contains(till50));
246  TEST_EXPECT(whole.contains(from30));
247  TEST_EXPECT(whole.contains(part));
248 
249  TEST_REJECT(till50.contains(empty));
250  TEST_REJECT(till50.contains(whole));
251  TEST_EXPECT(till50.contains(till50));
252  TEST_REJECT(till50.contains(from30));
253  TEST_EXPECT(till50.contains(part));
254 
255  TEST_REJECT(from30.contains(empty));
256  TEST_REJECT(from30.contains(whole));
257  TEST_REJECT(from30.contains(till50));
258  TEST_EXPECT(from30.contains(from30));
259  TEST_EXPECT(from30.contains(part));
260 
261  TEST_REJECT(part.contains(empty));
262  TEST_REJECT(part.contains(whole));
263  TEST_REJECT(part.contains(till50));
264  TEST_REJECT(part.contains(from30));
265  TEST_EXPECT(part.contains(part));
266 }
267 TEST_PUBLISH(TEST_range_containment);
268 
269 #endif // UNIT_TESTS
270 
271 // --------------------------------------------------------------------------------
272 
273 
274 
#define arb_assert(cond)
Definition: arb_assert.h:245
bool is_whole() const
Definition: pos_range.h:68
static PosRange from(int pos)
Definition: pos_range.h:54
PosRange prior() const
Definition: pos_range.h:89
PosRange intersection(PosRange r1, PosRange r2)
Definition: pos_range.h:98
int start() const
Definition: pos_range.h:57
bool is_part() const
Definition: pos_range.h:70
PosRange after() const
Definition: pos_range.h:88
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:204
int size() const
Definition: pos_range.h:66
static PosRange whole()
Definition: pos_range.h:52
bool is_empty() const
Definition: pos_range.h:69
static PosRange prior(int pos)
Definition: pos_range.h:55
bool is_limited() const
Definition: pos_range.h:74
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1485
#define TEST_EXPECT(cond)
Definition: test_unit.h:1313
static PosRange empty()
Definition: pos_range.h:51
bool contains(int pos) const
Definition: pos_range.h:83
#define TEST_REJECT(cond)
Definition: test_unit.h:1315
static PosRange after(int pos)
Definition: pos_range.h:54
bool is_unlimited() const
Definition: pos_range.h:75
static PosRange till(int pos)
Definition: pos_range.h:55
#define NULp
Definition: cxxforward.h:97
char * dup_corresponding_part(const char *source, size_t source_len) const
Definition: pos_range.cxx:27
#define TEST_EXPECT_EQUAL(expr, want)
Definition: test_unit.h:1283
void copy_corresponding_part(char *dest, const char *source, size_t source_len) const
Definition: pos_range.cxx:15