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  // test border conditions
125  TEST_EXPECT(PosRange::prior(0) == empty);
126  TEST_EXPECT(PosRange::prior(1).size() == 1);
127 }
128 
129 void TEST_ExplicitRange() {
130  PosRange empty;
131  PosRange whole = PosRange::whole();
132  PosRange till50 = PosRange::till(50);
133  PosRange from30 = PosRange::from(30);
134  PosRange f30t50(30, 50);
135 
136  ExplicitRange wholeOf17(whole, 17);
137  TEST_EXPECT(PosRange(wholeOf17).is_limited());
138 
139  TEST_EXPECT_EQUAL(ExplicitRange(whole, 100).size(), 100);
140  TEST_EXPECT_EQUAL(ExplicitRange(till50, 100).size(), 51); // 0-50
141  TEST_EXPECT_EQUAL(ExplicitRange(till50, 40).size(), 40);
142  TEST_EXPECT_EQUAL(ExplicitRange(from30, 100).size(), 70);
143  TEST_EXPECT_EQUAL(ExplicitRange(from30, 20).size(), 0);
144  TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 100).size(), 21);
145  TEST_EXPECT_EQUAL(ExplicitRange(f30t50, 40).size(), 10); // 30-39
146 
147  TEST_EXPECT_EQUAL(ExplicitRange(empty, 20).size(), 0);
148 }
149 
150 void TEST_range_copying() {
151  char dest[100];
152  const char *source = "0123456789";
153  const size_t source_len = strlen(source);
154 
155  PosRange::till(2).copy_corresponding_part(dest, source, source_len);
156  TEST_EXPECT_EQUAL(dest, "012");
157 
158  PosRange(2, 5).copy_corresponding_part(dest, source, source_len);
159  TEST_EXPECT_EQUAL(dest, "2345");
160 
161  PosRange::from(7).copy_corresponding_part(dest, source, source_len);
162  TEST_EXPECT_EQUAL(dest, "789");
163 
164  PosRange(9, 1000).copy_corresponding_part(dest, source, source_len);
165  TEST_EXPECT_EQUAL(dest, "9");
166 
167  PosRange(900, 1000).copy_corresponding_part(dest, source, source_len);
168  TEST_EXPECT_EQUAL(dest, "");
169 
170  // make sure dest and source may overlap:
171  strcpy(dest, source);
172  PosRange::whole().copy_corresponding_part(dest+1, dest, source_len);
173  TEST_EXPECT_EQUAL(dest+1, source);
174 
175  strcpy(dest, source);
176  PosRange::whole().copy_corresponding_part(dest, dest+1, source_len-1);
177  TEST_EXPECT_EQUAL(dest, source+1);
178 
179  TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange::empty().dup_corresponding_part(source, source_len)), ""); // empty range
180  TEST_EXPECT_EQUAL(&*SmartCharPtr(PosRange(2, 5).dup_corresponding_part(NULp, 0)), ""); // empty source
181 }
182 TEST_PUBLISH(TEST_range_copying);
183 
184 void TEST_range_intersection() {
185  PosRange empty;
186  PosRange whole = PosRange::whole();
187  PosRange till50 = PosRange::till(50);
188  PosRange from30 = PosRange::from(30);
189  PosRange part(30, 50);
190 
191  TEST_EXPECT(intersection(empty, empty) == empty);
192  TEST_EXPECT(intersection(empty, whole) == empty);
193  TEST_EXPECT(intersection(empty, till50) == empty);
194  TEST_EXPECT(intersection(empty, from30) == empty);
195  TEST_EXPECT(intersection(empty, part) == empty);
196 
197  TEST_EXPECT(intersection(whole, empty) == empty);
198  TEST_EXPECT(intersection(whole, whole) == whole);
199  TEST_EXPECT(intersection(whole, till50) == till50);
200  TEST_EXPECT(intersection(whole, from30) == from30);
201  TEST_EXPECT(intersection(whole, part) == part);
202 
203  TEST_EXPECT(intersection(till50, empty) == empty);
204  TEST_EXPECT(intersection(till50, whole) == till50);
205  TEST_EXPECT(intersection(till50, till50) == till50);
206  TEST_EXPECT(intersection(till50, from30) == part);
207  TEST_EXPECT(intersection(till50, part) == part);
208 
209  TEST_EXPECT(intersection(from30, empty) == empty);
210  TEST_EXPECT(intersection(from30, whole) == from30);
211  TEST_EXPECT(intersection(from30, till50) == part);
212  TEST_EXPECT(intersection(from30, from30) == from30);
213  TEST_EXPECT(intersection(from30, part) == part);
214 
215  TEST_EXPECT(intersection(part, empty) == empty);
216  TEST_EXPECT(intersection(part, whole) == part);
217  TEST_EXPECT(intersection(part, till50) == part);
218  TEST_EXPECT(intersection(part, from30) == part);
219  TEST_EXPECT(intersection(part, part) == part);
220 
221  TEST_EXPECT(intersection(PosRange(20, 40), till50) == PosRange(20, 40));
222  TEST_EXPECT(intersection(PosRange(40, 60), till50) == PosRange(40, 50));
223  TEST_EXPECT(intersection(PosRange(60, 80), till50) == empty);
224 
225  TEST_EXPECT(intersection(PosRange(0, 20), from30) == empty);
226  TEST_EXPECT(intersection(PosRange(20, 40), from30) == PosRange(30, 40));
227  TEST_EXPECT(intersection(PosRange(40, 60), from30) == PosRange(40, 60));
228 
229  TEST_EXPECT(intersection(PosRange(40, 60), PosRange(50, 70)) == PosRange(50, 60));
230 }
231 
232 void TEST_range_containment() {
233  PosRange empty;
234  PosRange whole = PosRange::whole();
235  PosRange till50 = PosRange::till(50);
236  PosRange from30 = PosRange::from(30);
237  PosRange part(30, 50);
238 
239  // empty contains nothing
240  TEST_REJECT(empty.contains(empty)); // and empty is contained nowhere!
241  TEST_REJECT(empty.contains(whole));
242  TEST_REJECT(empty.contains(till50));
243  TEST_REJECT(empty.contains(from30));
244  TEST_REJECT(empty.contains(part));
245 
246  // whole contains anything
247  TEST_REJECT(whole.contains(empty)); // except empty
248  TEST_EXPECT(whole.contains(whole));
249  TEST_EXPECT(whole.contains(till50));
250  TEST_EXPECT(whole.contains(from30));
251  TEST_EXPECT(whole.contains(part));
252 
253  TEST_REJECT(till50.contains(empty));
254  TEST_REJECT(till50.contains(whole));
255  TEST_EXPECT(till50.contains(till50));
256  TEST_REJECT(till50.contains(from30));
257  TEST_EXPECT(till50.contains(part));
258 
259  TEST_REJECT(from30.contains(empty));
260  TEST_REJECT(from30.contains(whole));
261  TEST_REJECT(from30.contains(till50));
262  TEST_EXPECT(from30.contains(from30));
263  TEST_EXPECT(from30.contains(part));
264 
265  TEST_REJECT(part.contains(empty));
266  TEST_REJECT(part.contains(whole));
267  TEST_REJECT(part.contains(till50));
268  TEST_REJECT(part.contains(from30));
269  TEST_EXPECT(part.contains(part));
270 }
271 TEST_PUBLISH(TEST_range_containment);
272 
273 #endif // UNIT_TESTS
274 
275 // --------------------------------------------------------------------------------
276 
277 
278 
#define arb_assert(cond)
Definition: arb_assert.h:245
bool is_whole() const
Definition: pos_range.h:71
static PosRange from(int pos)
Definition: pos_range.h:54
PosRange prior() const
Definition: pos_range.h:92
PosRange intersection(PosRange r1, PosRange r2)
Definition: pos_range.h:101
int start() const
Definition: pos_range.h:60
bool is_part() const
Definition: pos_range.h:73
PosRange after() const
Definition: pos_range.h:91
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
int size() const
Definition: pos_range.h:69
static PosRange whole()
Definition: pos_range.h:52
bool is_empty() const
Definition: pos_range.h:72
static PosRange prior(int pos)
Definition: pos_range.h:58
bool is_limited() const
Definition: pos_range.h:77
#define TEST_PUBLISH(testfunction)
Definition: test_unit.h:1517
#define TEST_EXPECT(cond)
Definition: test_unit.h:1328
static PosRange empty()
Definition: pos_range.h:51
bool contains(int pos) const
Definition: pos_range.h:86
#define TEST_REJECT(cond)
Definition: test_unit.h:1330
static PosRange after(int pos)
Definition: pos_range.h:57
bool is_unlimited() const
Definition: pos_range.h:78
static PosRange till(int pos)
Definition: pos_range.h:55
#define NULp
Definition: cxxforward.h:116
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:1294
void copy_corresponding_part(char *dest, const char *source, size_t source_len) const
Definition: pos_range.cxx:15