source: tags/arb_5.3/GENOM_IMPORT/Location.cxx

Last change on this file was 5861, checked in by westram, 15 years ago
  • type fixes; mostly format arguments (warnings from 64bit-compile)
File size: 8.4 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : Location.cxx                                       //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2006   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11#include "Location.h"
12#include "tools.h"
13
14#include <adGene.h>
15
16#include <cctype>
17#include <string>
18
19using namespace std;
20
21typedef SmartPtr<Location>  LocationPtr;
22typedef vector<LocationPtr> LocationVector;
23
24DEFINE_ITERATORS(LocationVector);
25
26class SimpleLocation : public Location {
27    long pos1;
28    long pos2;
29    char uncertain1;
30    char uncertain2;
31
32public:
33    SimpleLocation(long p1, long p2, char u1, char u2)
34        : pos1(p1), pos2(p2), uncertain1(u1), uncertain2(u2) {}
35    SimpleLocation(long p, char u)
36        : pos1(p), pos2(p), uncertain1(u), uncertain2(u)
37    {
38        arb_assert(u == '='); // do not allow uncertainties with single position ctor
39    }
40
41    virtual int count() const { return 1; }
42    virtual LocationJoinType getJoinType() const { return LJT_NOT_JOINED; }
43    virtual bool isInRange(long p1, long p2) const {
44        arb_assert(p1 <= p2);
45        return p1 <= pos1 && pos2 <= p2;
46    }
47    virtual void save(GEN_position *pos, bool complementary) const {
48        int p = pos->parts;
49
50        pos->start_pos[p]       = pos1;
51        pos->stop_pos[p]        = pos2;
52        pos->complement[p]      = char(complementary);
53        pos->start_uncertain[p] = uncertain1;
54        pos->stop_uncertain[p]  = uncertain2;
55
56        ++pos->parts;
57    }
58};
59
60class JoinedLocation : public Location {
61    LocationVector   locations;
62    LocationJoinType joinType;
63
64public:
65    JoinedLocation(LocationJoinType jtype) : joinType(jtype) {}
66
67    void push_back(const LocationPtr&loc) {
68        LocationJoinType loc_type = loc->getJoinType();
69        if (loc_type != LJT_NOT_JOINED && loc_type != joinType) {
70            throw "order() and join() cannot be mixed";
71        }
72        locations.push_back(loc);
73    }
74
75    virtual LocationJoinType getJoinType() const { return joinType; }
76    virtual int count() const {
77        int Count = 0;
78       
79        LocationVectorCIter e = locations.end();
80        for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
81            Count += (*i)->count();
82        }
83        return Count;
84    }
85
86    virtual bool isInRange(long p1, long p2) const {
87        LocationVectorCIter e = locations.end();
88        for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
89            if (!(*i)->isInRange(p1, p2)) {
90                return false;
91            }
92        }
93        return true;
94    }
95
96    virtual void save(GEN_position *pos, bool complementary) const {
97        if (complementary) {
98            LocationVectorCRIter e = locations.rend();
99            for (LocationVectorCRIter i = locations.rbegin(); i != e; ++i) {
100                (*i)->save(pos, complementary);
101            }
102        }
103        else {
104            LocationVectorCIter e = locations.end();
105            for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
106                (*i)->save(pos, complementary);
107            }
108        }
109    }
110};
111
112class ComplementLocation : public Location {
113    LocationPtr location;
114public:
115    ComplementLocation(const LocationPtr& loc) : location(loc) {}
116
117    virtual int count() const { return location->count(); }
118    virtual bool isInRange(long p1, long p2) const { return location->isInRange(p1, p2); }
119    virtual void save(GEN_position *pos, bool complementary) const { location->save(pos, !complementary); }
120    virtual LocationJoinType getJoinType() const { return location->getJoinType(); }
121};
122
123// --------------------------------------------------------------------------------
124
125static size_t parsePosition(const string& source, char& uncertain) {
126    // parses one position and returns the value
127    // if position contains uncertainties, they are stored in 'uncertain' (as '<' or '>')
128
129    const char *s    = source.c_str();
130    size_t      slen = source.length();
131
132    if (s[0] == '>' or s[0] == '<') {
133        uncertain = s[0];
134        s++;
135        slen--;
136    }
137    else {
138        uncertain = '=';
139    }
140
141    char   *end;
142    size_t  pos = strtoul(s, &end, 10);
143
144    size_t converted = end-s;
145    if (converted<slen) {
146        throw string("Unexpected char '")+end[0]+"' in '"+source+"'";
147    }
148
149    return pos;
150}
151
152static void parseLocationList(const string& source, size_t startPos, LocationVector& locvec) {
153    size_t comma = source.find_first_of("(,", startPos);
154
155    while (comma != string::npos && source[comma] == '(') {
156        size_t pos    = comma+1;
157        size_t paren_count = 1;
158
159        while (paren_count>0) {
160            size_t paren = source.find_first_of("()", pos);
161            if (paren == string::npos) {
162                throw GBS_global_string("Expected %zu closing parenthesis in '%s'", paren_count, source.c_str());
163            }
164            if (source[paren] == ')') paren_count--;
165            else paren_count++;
166
167            pos = paren+1;
168        }
169        comma = source.find_first_of("(,", pos);
170    }
171
172    if (comma == string::npos) { // no comma on top level
173        locvec.push_back(parseLocation(source.substr(startPos)));
174    }
175    else {
176        arb_assert(source[comma] == ',');
177        locvec.push_back(parseLocation(source.substr(startPos, comma-startPos)));
178        parseLocationList(source, comma+1, locvec); // continue after comma
179    }
180}
181
182LocationPtr parseLocation(const string& source) {
183    char first = source[0];
184    if (first == 'c') {
185        string infix;
186        if (parseInfix(source, "complement(", ")", infix)) {
187            return new ComplementLocation(parseLocation(infix));
188        }
189    }
190    else if (first == 'j' || first == 'o') {
191        string           infix;
192        LocationJoinType joinType = LJT_UNDEF;
193
194        if (parseInfix(source, "join(", ")", infix)) {
195            joinType = LJT_JOIN;
196        }
197        else if (parseInfix(source, "order(", ")", infix)) {
198            joinType = LJT_ORDER;
199        }
200
201        if (joinType != LJT_UNDEF) {
202            LocationVector locvec;
203            parseLocationList(infix, 0, locvec);
204
205            JoinedLocation      *join = new JoinedLocation(joinType);
206            LocationVectorCIter  e    = locvec.end();
207            for (LocationVectorCIter i = locvec.begin(); i != e; ++i) {
208                join->push_back(*i);
209            }
210            return join;
211        }
212    }
213    else if (isdigit(first) || strchr("<>", first) != 0) {
214        size_t dots = source.find("..");
215        if (dots != string::npos) {
216            char   uncertain1, uncertain2;
217            size_t pos1 = parsePosition(source.substr(0, dots), uncertain1);
218            size_t pos2 = parsePosition(source.substr(dots+2), uncertain2);
219
220            return new SimpleLocation(pos1, pos2, uncertain1, uncertain2);
221        }
222
223        size_t inbetween = source.find("^");
224        if (inbetween != string::npos) {
225            char   uncertain1, uncertain2;
226            size_t pos1 = parsePosition(source.substr(0, inbetween), uncertain1);
227            size_t pos2 = parsePosition(source.substr(inbetween+1), uncertain2);
228
229            if (uncertain1 == '=' && uncertain2 == '=' && pos2 == pos1+1) {
230                return new SimpleLocation(pos1, pos2, '+', '-');
231            }
232            throw string("Can only handle 'pos^pos+1'. Can't parse location '"+source+"'");
233        }
234        else {
235            // single base position
236            char   uncertain;
237            size_t single_pos = parsePosition(source, uncertain);
238            return new SimpleLocation(single_pos, uncertain);
239        }
240    }
241
242#if defined(DEVEL_RALF)
243    arb_assert(0);
244#endif // DEVEL_RALF
245    throw string("Unparsable location '"+source+"'");
246}
247
248GEN_position *Location::create_GEN_position() const {
249    GEN_position *pos = GEN_new_position(count(), GB_BOOL(getJoinType() == LJT_JOIN));
250    GEN_use_uncertainties(pos);
251
252#if defined(DEBUG)
253    int org_parts = pos->parts;
254#endif // DEBUG
255   
256    pos->parts = 0;             // misuse 'parts' as index for filling 'pos'
257    save(pos, false);
258
259    gi_assert(pos->parts == org_parts);
260
261    return pos;
262}
263
264
Note: See TracBrowser for help on using the repository browser.