source: branches/stable/CORE/pos_range.h

Last change on this file was 9633, checked in by westram, 6 years ago
  • reintegrated branch 'sai'
    • providing basic insert/delete by SAI
File size: 5.3 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : pos_range.h                                       //
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#ifndef POS_RANGE_H
13#define POS_RANGE_H
14
15#ifndef ARB_ASSERT_H
16#include <arb_assert.h>
17#endif
18#ifndef ATTRIBUTES_H
19#include <attributes.h>
20#endif
21#ifndef _GLIBCXX_ALGORITHM
22#include <algorithm>
23#endif
24
25class PosRange { // this is a value-class (i.e. all methods apart from ctors have to be const)
26    int start_pos;
27    int end_pos;
28
29public:
30    PosRange() : start_pos(-1), end_pos(-2) {} // default is empty range
31    PosRange(int From, int to)
32        : start_pos(From<0 ? 0 : From)
33    {
34        if (to<0) end_pos = -2;
35        else {
36            if (start_pos>to) { // empty range
37                start_pos = -1;
38                end_pos = -2;
39            }
40            else {
41                end_pos = to;
42                arb_assert(start_pos <= end_pos);
43            }
44        }
45    }
46
47    // factory functions
48    static PosRange empty() { return PosRange(); }
49    static PosRange whole() { return from(0); }
50
51    static PosRange from(int pos) { return PosRange(pos, -1); } static PosRange after(int pos) { return from(pos+1); }
52    static PosRange till(int pos) { return PosRange(0, pos); }  static PosRange prior(int pos) { return till(pos-1); }
53
54    int start() const {
55        arb_assert(!is_empty());
56        return start_pos;
57    }
58    int end() const {
59        arb_assert(has_end());
60        return end_pos;
61    }
62
63    int size() const { return end_pos-start_pos+1; }
64
65    bool is_whole() const { return start_pos == 0 && end_pos<0; }
66    bool is_empty() const { return size() == 0; }
67    bool is_part() const { return !(is_empty() || is_whole()); }
68
69    bool has_end() const { return size() > 0; }
70
71    bool is_limited() const { return is_empty() || has_end(); }
72    bool is_unlimited() const { return !is_limited(); }
73
74    bool operator == (const PosRange& other) const { return start_pos == other.start_pos && end_pos == other.end_pos; }
75    bool operator != (const PosRange& other) const { return !(*this == other); }
76
77    void copy_corresponding_part(char *dest, const char *source, size_t source_len) const;
78    char *dup_corresponding_part(const char *source, size_t source_len) const;
79
80    bool contains(int pos) const {
81        return !is_empty() && pos >= start_pos && (pos <= end_pos || is_unlimited());
82    }
83    bool contains(const PosRange& other) const;
84
85    PosRange after() const { return has_end() ? after(end()) : empty(); }
86    PosRange prior() const { return !is_empty() && start() ? prior(start()) : empty(); }
87
88#if defined(DEBUG)
89    void dump(FILE *out) const {
90        fprintf(out, "[%i..%i]", start_pos, end_pos);
91    }
92#endif
93};
94
95inline PosRange intersection(PosRange r1, PosRange r2) {
96    if (r1.is_empty()) return r1;
97    if (r2.is_empty()) return r2;
98
99    int start = std::max(r1.start(), r2.start());
100    if (r1.is_limited()) {
101        if (r2.is_limited()) return PosRange(start, std::min(r1.end(), r2.end()));
102        return PosRange(start, r1.end());
103    }
104    if (r2.is_limited()) return PosRange(start, r2.end());
105    return PosRange::from(start);
106}
107
108inline bool PosRange::contains(const PosRange& other) const {
109    return !other.is_empty() && intersection(*this, other) == other;
110}
111
112
113class ExplicitRange : public PosRange {
114
115    // this ctor is private to avoid making ranges repeatedly explicit (if REALLY needed, convert range to PosRange before)
116    ExplicitRange(const ExplicitRange& range, int maxlen);
117
118    bool is_limited() const { // always true -> private to avoid usage
119        arb_assert(PosRange::is_limited());
120        return true;
121    }
122
123public:
124    ExplicitRange(const ExplicitRange& limRange) : PosRange(limRange) {}
125    explicit ExplicitRange(const PosRange& limRange) : PosRange(limRange) { arb_assert(is_limited()); }
126
127    ExplicitRange(const PosRange& range, int maxlen)
128        : PosRange(range.is_empty() || maxlen <= 0
129                   ? PosRange::empty()
130                   : PosRange(range.start(), range.is_limited() ? std::min(range.end(), maxlen-1) : maxlen-1))
131    { arb_assert(is_limited()); }
132
133    ExplicitRange(int start_, int end_)
134        : PosRange(start_, end_)
135    { arb_assert(is_limited()); }
136
137    explicit ExplicitRange(int len)
138        : PosRange(0, len-1)
139    { arb_assert(is_limited()); }
140};
141
142inline ExplicitRange intersection(ExplicitRange r1, ExplicitRange r2) {
143    if (r1.is_empty()) return r1;
144    if (r2.is_empty()) return r2;
145
146    return ExplicitRange(std::max(r1.start(), r2.start()),
147                         std::min(r1.end(), r2.end()));
148}
149
150inline ExplicitRange intersection(ExplicitRange e1, PosRange r2) {
151    return intersection(e1, ExplicitRange(r2, e1.end()+1));
152}
153inline ExplicitRange intersection(PosRange r1, ExplicitRange e2) {
154    return intersection(ExplicitRange(r1, e2.end()+1), e2);
155}
156
157#else
158#error pos_range.h included twice
159#endif // POS_RANGE_H
Note: See TracBrowser for help on using the repository browser.