34 static inline string one_pos_as_string(
char uc,
long p) {
36 if (uc !=
'=') s += uc;
42 : pos1(p1), pos2(p2), uncertain1(u1), uncertain2(u2)
47 : pos1(p), pos2(p), uncertain1(u), uncertain2(u)
56 return p1 <= pos1 && pos2 <= p2;
61 pos->start_pos[p] =
pos1;
62 pos->stop_pos[p] =
pos2;
63 pos->complement[p] =
char(complementary);
64 pos->start_uncertain[p] = uncertain1;
65 pos->stop_uncertain[p] = uncertain2;
71 if (uncertain1 ==
'+') {
72 if (uncertain2 !=
'-' || pos2 != (pos1+1))
throw "Invalid uncertainties";
76 string s = one_pos_as_string(uncertain1, pos1);
78 s +=
".."+one_pos_as_string(uncertain2, pos2);
94 throw "order() and join() cannot be mixed";
96 locations.push_back(loc);
103 LocationVectorCIter e = locations.end();
104 for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
105 Count += (*i)->count();
111 LocationVectorCIter e = locations.end();
112 for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
113 if (!(*i)->isInRange(p1, p2)) {
122 LocationVectorCRIter e = locations.rend();
123 for (LocationVectorCRIter i = locations.rbegin(); i != e; ++i) {
124 (*i)->save(pos, complementary);
128 LocationVectorCIter e = locations.end();
129 for (LocationVectorCIter i = locations.begin(); i != e; ++i) {
130 (*i)->save(pos, complementary);
137 case LJT_JOIN: joined =
"join";
break;
139 default:
throw "Unhandled join type";
break;
143 LocationVectorCIter e = locations.end();
144 LocationVectorCIter i = locations.begin();
146 joined += (*i++)->as_string();
147 for (; i != e; ++i) {
149 joined += (*i)->as_string();
175 const char *
s = source.c_str();
176 size_t slen = source.length();
178 if (s[0] ==
'>' or s[0] ==
'<') {
188 size_t pos = strtoul(s, &end, 10);
190 size_t converted = end-
s;
191 if (converted<slen) {
192 throw string(
"Unexpected char '")+end[0]+
"' in '"+source+
"'";
199 size_t comma = source.find_first_of(
"(,", startPos);
201 while (comma != string::npos && source[comma] ==
'(') {
202 size_t pos = comma+1;
203 size_t paren_count = 1;
205 while (paren_count>0) {
206 size_t paren = source.find_first_of(
"()", pos);
207 if (paren == string::npos) {
208 throw GBS_global_string(
"Expected %zu closing parenthesis in '%s'", paren_count, source.c_str());
210 if (source[paren] ==
')') paren_count--;
215 comma = source.find_first_of(
"(,", pos);
218 if (comma == string::npos) {
223 locvec.push_back(
parseLocation(source.substr(startPos, comma-startPos)));
228 static bool parseInfix(
const string &
str,
const string& prefix,
const string& postfix,
string& foundInfix) {
231 size_t strlen = str.length();
232 size_t prelen = prefix.length();
233 size_t postlen = postfix.length();
235 if (strlen >= (prelen+postlen)) {
236 foundInfix = str.substr(prelen, strlen-(prelen+postlen));
244 char first = source[0];
247 if (
parseInfix(source,
"complement(",
")", infix)) {
251 else if (first ==
'j' || first ==
'o') {
255 if (
parseInfix(source,
"join(",
")", infix)) {
258 else if (
parseInfix(source,
"order(",
")", infix)) {
269 LocationVectorCIter e = locvec.end();
270 for (LocationVectorCIter i = locvec.begin(); i != e; ++i) {
276 else if (isdigit(first) || strchr(
"<>", first)) {
277 size_t dots = source.find(
"..");
278 if (dots != string::npos) {
279 char uncertain1, uncertain2;
286 size_t in_between = source.find(
"^");
287 if (in_between != string::npos) {
288 char uncertain1, uncertain2;
292 if (uncertain1 ==
'=' && uncertain2 ==
'=' && pos2 == pos1+1) {
295 throw string(
"Can only handle 'pos^pos+1'. Can't parse location '"+source+
"'");
301 if (uncertain !=
'=')
throw "No uncertainty allowed for single positions";
306 throw string(
"Unparsable location '"+source+
"'");
313 #if defined(ASSERTION_USED)
314 int org_parts = pos->
parts;
315 #endif // ASSERTION_USED
327 if (contradicted(pos->
complement[i], inverseComplement)) {;
337 if (gp->
parts == 1) {
341 int complemented = 0;
347 if (2*complemented > gp->
parts) {
349 for (
int p = gp->
parts-1; p >= 0; --p) {
351 joined->push_back(ploc);
356 for (
int p = 0; p<gp->
parts; ++p) {
358 joined->push_back(ploc);
369 static GB_ERROR perform_conversions(
const string& in,
string& out,
string& out2) {
388 #define DO_LOCONV_NOERR(str) string reverse, convReverse; TEST_EXPECT_NO_ERROR(perform_conversions(str, reverse, convReverse));
399 #define TEST_EXPECT___CONV_IDENT(str) do { \
400 DO_LOCONV_NOERR(str); \
401 TEST_EXPECT_EQUAL(str, reverse.c_str()); \
402 TEST_EXPECT_EQUAL(str, convReverse.c_str()); \
405 #define TEST_EXPECT___CONV_IDENT__BROKEN(str) do { \
406 DO_LOCONV_NOERR(str); \
407 TEST_EXPECT_EQUAL__BROKEN(str, reverse.c_str()); \
410 #define TEST_EXPECT___CONV__INTO(str,res) do { \
411 DO_LOCONV_NOERR(str); \
412 TEST_EXPECT_EQUAL(res, reverse.c_str()); \
413 TEST_EXPECT_EQUAL(res, convReverse.c_str()); \
416 #define TEST_EXPECT_RECONV__INTO(str,res) do { \
418 DO_LOCONV_NOERR(str); \
419 TEST_EXPECT_EQUAL(str, reverse.c_str()); \
420 TEST_EXPECT_EQUAL(res, convReverse.c_str()); \
421 TEST_EXPECT_MORE_EQUAL(reverse.length(), convReverse.length()); \
423 TEST_EXPECT___CONV_IDENT(res); \
426 #define TEST_EXPECT_RECONV_INTO2(str,res1,res2) do { \
427 DO_LOCONV_NOERR(str); \
428 TEST_EXPECT_EQUAL(res1, reverse.c_str()); \
429 TEST_EXPECT_EQUAL(res2, convReverse.c_str()); \
430 TEST_EXPECT_MORE_EQUAL(reverse.length(), convReverse.length()); \
433 #define TEST_EXPECT__PARSE_ERROR(str,err) do { \
434 string reverse, convReverse; \
435 TEST_EXPECT_EQUAL(perform_conversions(str, reverse, convReverse), err); \
441 TEST_EXPECT___CONV_IDENT(
"1725");
442 TEST_EXPECT__PARSE_ERROR(
"3-77",
"Unexpected char '-' in '3-77'");
443 TEST_EXPECT___CONV_IDENT(
"3..77");
444 TEST_EXPECT___CONV_IDENT(
"77..3");
446 TEST_EXPECT___CONV_IDENT(
"<3..77");
447 TEST_EXPECT___CONV_IDENT(
"3..>77");
448 TEST_EXPECT___CONV_IDENT(
">3..<77");
450 TEST_EXPECT___CONV_IDENT(
"7^8");
451 TEST_EXPECT__PARSE_ERROR(
"7^9",
"Can only handle 'pos^pos+1'. Can't parse location '7^9'");
453 TEST_EXPECT___CONV_IDENT(
"complement(3..77)");
454 TEST_EXPECT___CONV_IDENT(
"complement(77..3)");
455 TEST_EXPECT___CONV_IDENT(
"complement(77)");
457 TEST_EXPECT___CONV_IDENT(
"join(3..77,100..200)");
458 TEST_EXPECT_RECONV__INTO(
"join(3..77)",
"3..77");
459 TEST_EXPECT___CONV_IDENT(
"join(3..77,100,130..177)");
460 TEST_EXPECT__PARSE_ERROR(
"join(3..77,100..200, 130..177)",
"Unparsable location ' 130..177'");
462 TEST_EXPECT_RECONV__INTO(
"order(1)",
"1");
463 TEST_EXPECT___CONV_IDENT(
"order(0,8,15)");
464 TEST_EXPECT___CONV_IDENT(
"order(10..12,7..9,1^2)");
465 TEST_EXPECT_RECONV__INTO(
"order(complement(1^2),complement(7..9),complement(10..12))",
466 "complement(order(10..12,7..9,1^2))");
467 TEST_EXPECT___CONV_IDENT(
"order(10..12,complement(7..9),1^2)");
468 TEST_EXPECT_RECONV__INTO(
"order(complement(1^2),7..9,complement(10..12))",
469 "complement(order(10..12,complement(7..9),1^2))");
471 TEST_EXPECT__PARSE_ERROR(
"join(order(0,8,15),order(3,2,1))",
"order() and join() cannot be mixed");
473 TEST_EXPECT_RECONV__INTO(
"join(complement(3..77),complement(100..200))",
474 "complement(join(100..200,3..77))");
475 TEST_EXPECT_RECONV__INTO(
"join(complement(join(3..77,74..83)),complement(100..200))",
476 "complement(join(100..200,3..77,74..83))");
477 TEST_EXPECT_RECONV__INTO(
"complement(complement(complement(100..200)))",
478 "complement(100..200)");
479 TEST_EXPECT_RECONV__INTO(
"join(complement(join(complement(join(1)))))",
483 TEST_EXPECT__PARSE_ERROR(
"join(abc()",
"Expected 1 closing parenthesis in 'abc('");
486 TEST_EXPECT___CONV__INTO(
"",
"0");
487 TEST_EXPECT_RECONV_INTO2(
"join()",
"join(0)",
"0");
488 TEST_EXPECT___CONV__INTO(
"complement()",
"complement(0)");
489 TEST_EXPECT_RECONV_INTO2(
"complement(complement())",
"complement(complement(0))",
"0");
static bool parseInfix(const string &str, const string &prefix, const string &postfix, string &foundInfix)
void push_back(const LocationPtr &loc)
SimpleLocation(long p, char u)
unsigned char * complement
LocationJoinType getJoinType() const OVERRIDE
vector< LocationPtr > LocationVector
string as_string() const OVERRIDE
return string(buffer, length)
int count() const OVERRIDE
void GEN_free_position(GEN_position *pos)
virtual bool isInRange(long pos1, long pos2) const =0
int count() const OVERRIDE
int count() const OVERRIDE
string as_string() const OVERRIDE
const char * GBS_global_string(const char *templat,...)
LocationPtr parseLocation(const string &source)
void GEN_use_uncertainties(GEN_position *pos)
LocationPtr part2SimpleLocation(const GEN_position *pos, int i, bool inverseComplement)
DEFINE_ITERATORS(LocationVector)
static void parseLocationList(const string &source, size_t startPos, LocationVector &locvec)
void save(GEN_position *pos, bool complementary) const OVERRIDE
void save(GEN_position *pos, bool complementary) const OVERRIDE
SmartPtr< Location > LocationPtr
unsigned char * start_uncertain
virtual void save(GEN_position *into, bool complementary) const =0
virtual std::string as_string() const =0
void save(GEN_position *pos, bool complementary) const OVERRIDE
LocationPtr to_Location(const GEN_position *gp)
#define TEST_REJECT_NULL(n)
static void error(const char *msg)
bool isInRange(long p1, long p2) const OVERRIDE
ComplementLocation(const LocationPtr &loc)
LocationJoinType getJoinType() const OVERRIDE
GEN_position * create_GEN_position() const
string as_string() const OVERRIDE
bool beginsWith(const std::string &str, const std::string &start)
#define __ATTR__REDUCED_OPTIMIZE
GEN_position * GEN_new_position(int parts, bool joinable)
bool endsWith(const std::string &str, const std::string &postfix)
JoinedLocation(LocationJoinType jtype)
LocationJoinType getJoinType() const OVERRIDE
static size_t parsePosition(const string &source, char &uncertain)
virtual int count() const =0
const char * GBS_static_string(const char *str)
virtual LocationJoinType getJoinType() const =0
bool isInRange(long p1, long p2) const OVERRIDE
bool isInRange(long p1, long p2) const OVERRIDE
unsigned char * stop_uncertain
SimpleLocation(long p1, long p2, char u1, char u2)
GB_write_int const char s