source: branches/stable/CORE/arb_string.cxx

Last change on this file was 11488, checked in by westram, 6 years ago
  • reintegrates 'tree' into 'trunk'
    • implements #417 (multifurcate tree)
    • tree display
      • adds MULTIFURC MODE
      • reordered modes (synchronizes NTREE and PARSIMONY)
    • branch analysis
      • display number of multifurcations in 'mark long branches'
      • display "in-tree-distance" and "per-species-distance"
    • added function to toggle '100%' bootstraps
    • document bug in GBT_remove_leafs (#452)
  • adds:
File size: 13.7 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : arb_string.cxx                                     //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include "arb_string.h"
13
14#include <arb_assert.h>
15
16#include <cstring>
17#include <cstdlib>
18
19#include <ctime>
20#include <sys/time.h>
21
22char *GB_strduplen(const char *p, unsigned len) {
23    // fast replacement for strdup, if len is known
24    if (p) {
25        char *neu;
26
27        arb_assert(strlen(p) == len);
28        // Note: Common reason for failure: a zero-char was manually printed by a GBS_global_string...-function
29
30        neu = (char*)malloc(len+1);
31        memcpy(neu, p, len+1);
32        return neu;
33    }
34    return 0;
35}
36
37char *GB_strpartdup(const char *start, const char *end) {
38    /* strdup of a part of a string (including 'start' and 'end')
39     * 'end' may point behind end of string -> copy only till zero byte
40     * if 'end'=('start'-1) -> return ""
41     * if 'end'<('start'-1) -> return 0
42     * if 'end' == NULL -> copy whole string
43     */
44
45    char *result;
46    if (end) {
47        int len = end-start+1;
48
49        if (len >= 0) {
50            const char *eos = (const char *)memchr(start, 0, len);
51
52            if (eos) len = eos-start;
53            result = (char*)malloc(len+1);
54            memcpy(result, start, len);
55            result[len] = 0;
56        }
57        else {
58            result = 0;
59        }
60    }
61    else { // end = 0 -> return copy of complete string
62        result = nulldup(start);
63    }
64
65    return result;
66}
67
68char *GB_strndup(const char *start, int len) {
69    return GB_strpartdup(start, start+len-1);
70}
71
72const char *GB_date_string() {
73    timeval  date;
74    tm      *p;
75
76    gettimeofday(&date, 0);
77
78#if defined(DARWIN)
79    struct timespec local;
80    TIMEVAL_TO_TIMESPEC(&date, &local); // not avail in time.h of Linux gcc 2.95.3
81    p = localtime(&local.tv_sec);
82#else
83    p = localtime(&date.tv_sec);
84#endif // DARWIN
85
86    char *readable = asctime(p); // points to a static buffer
87    char *cr       = strchr(readable, '\n');
88    arb_assert(cr);
89    cr[0]          = 0;         // cut of \n
90
91    return readable;
92}
93
94
95// --------------------------------------------------------------------------------
96
97
98#ifdef UNIT_TESTS
99
100#include <string>
101#include <climits>
102
103#ifndef TEST_UNIT_H
104#include <test_unit.h>
105#endif
106
107using namespace std;
108
109// ----------------------------------------------
110//      some tests for unit-test-code itself
111
112#define TEST_EXPECT_HEAPCOPY_EQUAL(copy,expected) do {  \
113        char *theCopy = (copy);                         \
114        TEST_EXPECT_EQUAL(theCopy, expected);           \
115        free(theCopy);                                  \
116    } while(0)
117
118void TEST_arbtest_strf() {
119    // tests string formatter from test_unit.h
120    using namespace arb_test;
121    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%i>", 7), "<7>");
122    TEST_EXPECT_HEAPCOPY_EQUAL(StaticCode::strf("<%0*i>", 3, 7), "<007>");
123}
124
125void TEST_arbtest_readable() {
126    using namespace arb_test;
127
128    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy('x')), "'x' (=0x78)");
129    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<unsigned char>('x'))), "'x' (=0x78)");
130    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(static_cast<signed char>('x'))), "'x' (=0x78)");
131
132    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(true)), "true");
133    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(false)), "false");
134   
135    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1)), "1");
136    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(2)), "0x2");
137
138    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(3L)), "3");
139    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(4L)), "0x4");
140
141    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(5U)), "5");
142    TEST_EXPECT_HEAPCOPY_EQUAL(val2hex(make_copy(6U)), "0x6");
143   
144    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("some\ntext\twhich\"special\\chars")), "\"some\\ntext\\twhich\\\"special\\\\chars\"");
145    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy("a\1\2\x1a\x7e\x7f\x80\xfe\xff")), "\"a\\1\\2\\x1a~\\x7f\\x80\\xfe\\xff\"");
146    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const char *)NULL)), "(null)");
147    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const unsigned char *)NULL)), "(null)");
148    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy((const signed char *)NULL)), "(null)");
149
150    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(1.7)), "1.700000");
151    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20)),  "17699999999999998951424.000000");
152    TEST_EXPECT_HEAPCOPY_EQUAL(val2readable(make_copy(177.0e20F)), "17699999967695435988992.000000");
153}
154
155void TEST_arbtest_copyable() {
156    using namespace arb_test;
157
158    int         i = 7;
159    const char *s = "servas";
160
161    TEST_EXPECT(make_copy(i) == make_copy(7));
162    TEST_EXPECT_ZERO(strcmp(make_copy(s), make_copy("servas")));
163}
164
165#define TEST_DESCRIPTIONS(d, tt, tf, ft, ff) do {        \
166        TEST_EXPECT_EQUAL((d).make(true, true), (tt));   \
167        TEST_EXPECT_EQUAL((d).make(true, false), (tf));  \
168        TEST_EXPECT_EQUAL((d).make(false, true), (ft));  \
169        TEST_EXPECT_EQUAL((d).make(false, false), (ff)); \
170    } while(0)
171
172#define TEST_SIMPLE_DESCRIPTIONS(d, ae, nae) TEST_DESCRIPTIONS(d, ae, nae, ae, nae)
173
174void TEST_arbtest_predicate_description() {
175    TEST_SIMPLE_DESCRIPTIONS(predicate_description("similar"), "is similar", "isnt similar");
176    TEST_SIMPLE_DESCRIPTIONS(predicate_description("repairs"), "repairs", "doesnt repair");
177
178    TEST_DESCRIPTIONS(predicate_description("equals", "differs"),
179                      "equals", "doesnt equal",
180                      "doesnt differ", "differs");
181
182    TEST_DESCRIPTIONS(predicate_description("less_than", "more_than"),
183                      "is less_than", "isnt less_than",
184                      "isnt more_than", "is more_than");
185}
186
187void TEST_arbtest_expectations() {
188    // used to TDD expectations
189    using namespace arb_test;
190
191    string apple       = "Apfel";
192    string pear        = "Birne";
193    string boskop      = apple;
194    string pomegranate = "Granatapfel";
195
196    TEST_EXPECTATION(that(apple).is_equal_to("Apfel"));
197   
198    TEST_EXPECTATION(that(apple).does_differ_from(pear));
199    TEST_EXPECTATION(that(apple).is_equal_to(boskop));
200    TEST_EXPECTATION(wrong(that(pomegranate).is_equal_to(apple)));
201
202    match_expectation ff1 = that(1.0).is_equal_to(2-1);
203    match_expectation ff2 = that(boskop).is_equal_to(apple);
204    match_expectation ff3 = that(apple).is_equal_to(apple);
205
206    match_expectation nf1 = that(apple).is_equal_to(pear);
207    match_expectation nf2 = that(pomegranate).is_equal_to(apple);
208    match_expectation nf3 = that(apple).does_differ_from(boskop);
209
210    match_expectation a1 = all().of(ff1);
211    match_expectation a2 = all().of(ff1, ff2);
212    match_expectation a3 = all().of(ff1, ff2, ff3);
213
214    TEST_EXPECTATION(a1);
215    TEST_EXPECTATION(a2);
216    TEST_EXPECTATION(a3);
217
218    match_expectation n1 = none().of(ff1);
219    match_expectation n2 = none().of(ff1, ff2);
220    match_expectation n3 = none().of(ff1, ff2, ff3);
221
222    TEST_EXPECTATION(wrong(none().of(that(boskop).is_equal_to(apple))));
223    TEST_EXPECTATION(wrong(n1));
224    TEST_EXPECTATION(wrong(n2));
225    TEST_EXPECTATION(wrong(n3));
226
227    TEST_EXPECTATION(atleast(1).of(a1));
228    TEST_EXPECTATION(atleast(1).of(a1, n1));
229    TEST_EXPECTATION(atleast(1).of(n2, a1, n1));
230
231    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1, n2)));
232    TEST_EXPECTATION(wrong(atleast(2).of(a1, n1)));
233    TEST_EXPECTATION(wrong(atleast(2).of(a1))); // impossible
234
235    TEST_EXPECTATION(atmost(2).of(a1));
236    TEST_EXPECTATION(atmost(2).of(a1, a2));
237    TEST_EXPECTATION(atmost(2).of(a1, a2, n1));
238    TEST_EXPECTATION(atmost(2).of(a1, n1, n2));
239    TEST_EXPECTATION(atmost(2).of(n1, n2));
240    TEST_EXPECTATION(wrong(atmost(2).of(a1, a2, a3)));
241
242    TEST_EXPECTATION(exactly(1).of(ff1, nf1, nf2));
243    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2)));
244    TEST_EXPECTATION(wrong(exactly(1).of(nf1, nf2, nf3)));
245    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, nf2)));
246    TEST_EXPECTATION(wrong(exactly(1).of(ff1, ff2, ff3)));
247
248}
249
250void TEST_expectation_groups() {
251    using namespace arb_test;
252
253    expectation_group no_expectations;
254    TEST_EXPECTATION(all().ofgroup(no_expectations));
255    TEST_EXPECTATION(none().ofgroup(no_expectations));
256
257    expectation_group fulfilled_expectation  (that(1).is_equal_to(1));
258    expectation_group unfulfilled_expectation(that(1).is_equal_to(0));
259    expectation_group some_fulfilled_expectations(that(1).is_equal_to(0), that(1).is_equal_to(1));
260
261    TEST_EXPECTATION(all().ofgroup(fulfilled_expectation));
262    TEST_EXPECTATION(none().ofgroup(unfulfilled_expectation));
263
264    TEST_EXPECT(none().ofgroup(fulfilled_expectation).unfulfilled());
265    TEST_EXPECT(all().ofgroup(unfulfilled_expectation).unfulfilled());
266   
267    TEST_EXPECT(all().ofgroup(some_fulfilled_expectations).unfulfilled());
268    TEST_EXPECT(none().ofgroup(some_fulfilled_expectations).unfulfilled());
269}
270
271void TEST_replace_old_TEST_EXPECTS_by_expectations() {
272    // test various string-types are matchable (w/o casts)
273    {
274        const char *car_ccp = "Alfa";
275        char       *car_cp  = strdup("Alfa");
276        string      car_str("Alfa");
277
278        TEST_EXPECT_EQUAL(car_ccp, "Alfa");
279        TEST_EXPECT_EQUAL(car_cp, "Alfa");
280        TEST_EXPECT_EQUAL(car_str, "Alfa");
281
282        TEST_EXPECT_EQUAL("Alfa", car_ccp);
283        TEST_EXPECT_EQUAL("Alfa", car_cp);
284        TEST_EXPECT_EQUAL("Alfa", car_str);
285
286        TEST_EXPECT_EQUAL(car_cp, car_ccp);
287        TEST_EXPECT_EQUAL(car_cp, car_str);
288        TEST_EXPECT_EQUAL(car_ccp, car_cp);
289        TEST_EXPECT_EQUAL(car_ccp, car_str);
290        TEST_EXPECT_EQUAL(car_str, car_cp);
291        TEST_EXPECT_EQUAL(car_str, car_ccp);
292
293        char *null = NULL;
294        TEST_EXPECT_NULL((void*)NULL);
295        TEST_EXPECT_NULL(null);
296
297        TEST_EXPECT_CONTAINS(car_ccp, "lf");
298        TEST_EXPECT_CONTAINS(car_cp, "fa");
299        TEST_EXPECT_CONTAINS(car_str, "Al");
300
301        free(car_cp);
302    }
303
304    // test various numeric types are matchable
305
306    {
307        short unsigned su = 7;
308        short          s  = -su;
309
310        unsigned iu = su;
311        int      i  = -iu;
312
313        long unsigned lu = (long unsigned)INT_MAX+3;
314        long          l  = -lu;
315
316        float  f = s;
317        double d = i;
318
319        TEST_EXPECT_EQUAL(s, -7);
320        TEST_EXPECT_EQUAL(i, -7);
321
322        TEST_EXPECT_EQUAL(su, 7);  TEST_EXPECT_EQUAL(iu, 7);
323        TEST_EXPECT_EQUAL(su, 7U); TEST_EXPECT_EQUAL(iu, 7U);
324        TEST_EXPECT_EQUAL(su, 7L); TEST_EXPECT_EQUAL(iu, 7L);
325
326        TEST_EXPECT_EQUAL(s, -su); TEST_EXPECT_EQUAL(s, -iu);
327        TEST_EXPECT_EQUAL(i, -iu); TEST_EXPECT_EQUAL(i, -su);
328        TEST_EXPECT_EQUAL(l, -lu);
329
330        TEST_EXPECT_EQUAL(f, d);
331        TEST_EXPECT_EQUAL(d, f);
332    }
333
334    TEST_EXPECT_ZERO(7-7);
335}
336
337// --- simulate user_type (which may be defined anywhere) ---
338class user_type {
339    int x, y;
340public:
341    user_type(int X, int Y) : x(X), y(Y) {}
342
343    int get_x() const { return x; }
344    int get_y() const { return y; }
345
346    user_type flipped() const { return user_type(y,x); }
347
348    int quadrant() const {
349        if (x == 0 || y == 0) return 0; // on axis
350        if (y>0) return x<0 ? 2 : 1;
351        return x<0 ? 3 : 4;
352    }
353};
354// --- end of user_type ---
355
356// helpers needed for tests:
357inline bool operator == (const user_type& u1, const user_type& u2) { return u1.get_x() == u2.get_x() && u1.get_y() == u2.get_y(); }
358inline char *val2readable(const user_type& u) { return arb_test::StaticCode::strf("user_type(%i,%i)", u.get_x(), u.get_y()); }
359inline bool in_same_quadrant(const user_type& u1, const user_type& u2) { return u1.quadrant() == u2.quadrant(); }
360
361void TEST_user_type_with_expectations() {
362    user_type ut1(3, 4);
363    user_type ut12(4, 4);
364    user_type ut2(-4, 4);
365    user_type ut3(-4, -8);
366    user_type ut4(4, -8);
367
368    TEST_EXPECTATION(that(ut1).does_differ_from(ut12));
369    TEST_EXPECTATION(that(ut12).is_equal_to(ut12.flipped()));
370    TEST_EXPECTATION(that(ut1).does_differ_from(ut1.flipped()));
371
372    TEST_EXPECTATION(that(ut1).fulfills(in_same_quadrant, ut12));
373    TEST_EXPECTATION(none().of(that(ut1).fulfills(in_same_quadrant, ut2),
374                          that(ut2).fulfills(in_same_quadrant, ut3),
375                          that(ut3).fulfills(in_same_quadrant, ut4)));
376}
377
378void TEST_similarity() {
379    double d1      = 0.7531;
380    double epsilon = 0.00001;
381    double d2      = d1-epsilon*0.6;
382    double d3      = d1+epsilon*0.6;
383
384    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d2));
385    TEST_EXPECTATION(that(d1).fulfills(epsilon_similar(epsilon), d3));
386    TEST_EXPECTATION(that(d2).contradicts(epsilon_similar(epsilon), d3));
387
388    TEST_EXPECT_SIMILAR(d1, d2, epsilon);
389    TEST_EXPECT_SIMILAR(d1, d3, epsilon);
390}
391
392void TEST_less_equal() {
393    int x = 7;
394    int y = 8;
395    int z = 9;
396
397    // less/more etc
398
399    TEST_EXPECTATION(that(x).is_less_than(y));
400    TEST_EXPECTATION(that(x).is_less_or_equal(y));
401    TEST_EXPECTATION(that(x).is_less_or_equal(x));
402   
403    TEST_EXPECTATION(that(y).is_more_than(x));
404    TEST_EXPECTATION(that(y).is_more_or_equal(x));
405    TEST_EXPECTATION(that(y).is_more_or_equal(y));
406
407    TEST_EXPECT_LESS_EQUAL(x, y);
408    TEST_EXPECT_LESS_EQUAL(x, x);
409    TEST_EXPECT_LESS(x, y);
410    TEST_EXPECT_IN_RANGE(y, x, z);
411}
412
413#endif // UNIT_TESTS
414
415// --------------------------------------------------------------------------------
416
417
Note: See TracBrowser for help on using the repository browser.