source: cpp/frams/genetics/geno.cpp @ 196

Last change on this file since 196 was 150, checked in by sz, 11 years ago

Warn against missing converter, convert() caller can differentiate between conversion failure and missing converter.

  • Property svn:eol-style set to native
File size: 5.8 KB
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 2002-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "geno.h"
6#include "genoconv.h"
7#include <frams/model/model.h>
8
9SListTempl<GenoValidator*> Geno::validators;
10GenoConvManager *Geno::converters = NULL;
11
12void Geno::init(const SString& genstring, char genformat, const SString& genname, const SString& comment)
13{
14        refcount = 1;
15        owner = 0;
16        f0gen = 0;
17        mapinshift = 0;
18        mapoutshift = 0;
19        isvalid = -1;
20        SString gencopy(genstring);
21        if (genformat == -1)
22        { // unknown format
23                genformat = '1';
24                if (genstring.charAt(0) == '/')
25                {
26                        int end;
27                        SString newcomment;
28                        switch (genstring.charAt(1))
29                        {
30                        case '/':
31                                genformat = genstring.charAt(2);
32                                if ((end = genstring.indexOf('\n')) >= 0)
33                                {
34                                        newcomment = genstring.substr(2, end - 2);
35                                        gencopy = genstring.substr(end + 1);
36                                        mapinshift = end + 1;
37                                }
38                                else
39                                {
40                                        gencopy = 0;
41                                        mapinshift = genstring.len();
42                                }
43                                break;
44                        case '*':
45                                genformat = genstring.charAt(2);
46                                if ((end = genstring.indexOf("*/")) >= 0)
47                                {
48                                        newcomment = genstring.substr(2, end - 2);
49                                        gencopy = genstring.substr(end + 2);
50                                        mapinshift = end + 2;
51                                }
52                                else
53                                {
54                                        gencopy = 0;
55                                        mapinshift = genstring.len();
56                                }
57                                break;
58                        }
59                        if (newcomment.len() > 0)
60                        {
61                                SString token; int pos = 0;
62                                if (newcomment.getNextToken(pos, token, ';'))
63                                        if (newcomment.getNextToken(pos, token, ';'))
64                                        {
65                                                if (token.len()) txt = token;
66                                                if (newcomment.getNextToken(pos, token, ';'))
67                                                        if (token.len()) name = token;
68                                        }
69                        }
70                }
71        }
72
73        gen = gencopy;
74        format = genformat;
75        if (!name.len()) name = genname;
76        if (!txt.len()) txt = comment;
77        multiline = (strchr((const char*)gen, '\n') != 0);
78        // mapoutshift...?
79}
80
81void Geno::freeF0()
82{
83        if (f0gen) { delete f0gen; f0gen = 0; }
84}
85
86Geno::Geno(const char *genstring, char genformat, const char *genname, const char *comment)
87{
88        init(SString(genstring), genformat, SString(genname), SString(comment));
89}
90
91Geno::Geno(const SString& genstring, char genformat, const SString& genname, const SString& comment)
92{
93        init(genstring, genformat, genname, comment);
94}
95
96Geno::Geno(const Geno& src)
97:gen(src.gen), name(src.name), format(src.format), txt(src.txt), isvalid(src.isvalid),
98f0gen(0), mapinshift(src.mapinshift), mapoutshift(src.mapinshift),
99multiline(src.multiline), owner(0)
100{
101        f0gen = src.f0gen ? new Geno(*src.f0gen) : 0; refcount = 1;
102}
103
104void Geno::operator=(const Geno& src)
105{
106        freeF0();
107        gen = src.gen;
108        name = src.name;
109        format = src.format;
110        txt = src.txt;
111        isvalid = src.isvalid;
112        mapinshift = src.mapinshift;
113        mapoutshift = src.mapinshift;
114        multiline = src.multiline;
115        f0gen = src.f0gen ? new Geno(*src.f0gen) : 0;
116        owner = 0;
117}
118
119Geno::Geno(const SString& src)
120{
121        init(src, -1, SString::empty(), SString::empty());
122}
123
124void Geno::setGene(const SString& g, char newformat)
125{
126        gen = g;
127        isvalid = -1;
128        freeF0();
129        if (newformat >= 0) format = newformat;
130}
131
132void Geno::setString(const SString& g)
133{
134        freeF0();
135        init(g, -1, SString::empty(), SString::empty());
136}
137
138void Geno::setName(const SString& n)
139{
140        name = n;
141}
142
143void Geno::setComment(const SString& c)
144{
145        txt = c;
146}
147
148SString Geno::toString(void) const
149{
150        SString out;
151        int comment = 0;
152        if ((format != '1') || (comment = (txt.len() || name.len())))
153        {
154                if (multiline)
155                        out += "//";
156                else
157                        out += "/*";
158                out += format;
159                if (comment)
160                {
161                        if (txt.len()) { out += ";"; out += txt; }
162                        if (name.len()){ out += ";"; out += name; }
163                }
164                if (multiline)
165                        out += "\n";
166                else
167                        out += "*/";
168        }
169        out += gen;
170        return out;
171}
172
173SString Geno::shortString(void) const
174{
175        SString out;
176        if (format != '1')
177        {
178                if (multiline)
179                        out += "//";
180                else
181                        out += "/*";
182                if (format == 0)
183                        out += "invalid";
184                else
185                        out += format;
186                if (multiline)
187                        out += "\n";
188                else
189                        out += "*/";
190        }
191        out += gen;
192        return out;
193}
194
195int Geno::mapGenToString(int genpos) const
196{
197        if (genpos > gen.len()) return -2;
198        if (genpos<0) return -1;
199        return mapinshift + genpos;
200}
201
202int Geno::mapStringToGen(int stringpos) const
203{
204        stringpos -= mapinshift;
205        if (stringpos>gen.len()) return -2;
206        if (stringpos < 0) return -1;
207        return stringpos;
208}
209
210SString Geno::getGene(void) const { return gen; }
211SString Geno::getName(void) const { return name; }
212char Geno::getFormat(void) const { return format; }
213SString Geno::getComment(void) const { return txt; }
214
215int ModelGenoValidator::testGenoValidity(Geno& g)
216{
217        if (g.getFormat() == '0')
218        {
219                Model mod(g);
220                return mod.isValid();
221        }
222        else
223        {
224                bool converter_missing;
225                Geno f0geno = g.getConverted('0', NULL, &converter_missing);
226                if (converter_missing)
227                        return -1;//no result
228                return f0geno.isValid();
229        }
230}
231
232void Geno::validate()
233{
234        if (isvalid >= 0) return;
235        if (gen.len() == 0) { isvalid = 0; return; }
236        FOREACH(GenoValidator*, v, validators)
237                if ((isvalid = v->testGenoValidity(*this)) >= 0)
238                        return;
239        isvalid = 0;
240        FMprintf("Geno", "validate", FMLV_WARN, "Wrong configuration? No genotype validators defined for genetic format f%c.", format);
241}
242
243bool Geno::isValid(void)
244{
245        if (isvalid<0) validate();
246        return isvalid>0;
247}
248
249Geno Geno::getConverted(char otherformat, MultiMap *m, bool *converter_missing)
250{
251        if (otherformat == getFormat()) { if (converter_missing) *converter_missing = false; return *this; }
252#ifndef NO_GENOCONVMANAGER
253        if (converters)
254        {
255                if ((otherformat == '0') && (!m))
256                {
257                        if (!f0gen)
258                                f0gen = new Geno(converters->convert(*this, otherformat, NULL, converter_missing));
259                        return *f0gen;
260                }
261                else
262                        return converters->convert(*this, otherformat, m, converter_missing);
263        }
264#endif
265        if (converter_missing) *converter_missing = true;
266        return (otherformat == getFormat()) ? *this : Geno(0, 0, 0, "GenConvManager not available");
267}
268
269Geno::~Geno()
270{
271        if (f0gen) delete f0gen;
272}
Note: See TracBrowser for help on using the repository browser.