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

Last change on this file since 150 was 150, checked in by sz, 6 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.