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

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