// This file is a part of the Framsticks GDK library. // Copyright (C) 2002-2011 Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.framsticks.com/ for further information. #include "geno.h" #include SListTempl Geno::validators; void Geno::init(const SString& genstring,char genformat,const SString& genname,const SString& comment) { refcount=1; owner=0; f0gen=0; mapinshift=0; mapoutshift=0; isvalid=-1; SString gencopy(genstring); if (genformat==-1) { // unknown format genformat='1'; if (genstring.charAt(0)=='/') { int end; SString newcomment; switch(genstring.charAt(1)) { case '/': genformat=genstring.charAt(2); if ((end=genstring.indexOf('\n'))>=0) { newcomment=genstring.substr(2,end-2); gencopy=genstring.substr(end+1); mapinshift=end+1; } else { gencopy=0; mapinshift=genstring.len(); } break; case '*': genformat=genstring.charAt(2); if ((end=genstring.indexOf("*/"))>=0) { newcomment=genstring.substr(2,end-2); gencopy=genstring.substr(end+2); mapinshift=end+2; } else { gencopy=0; mapinshift=genstring.len(); } break; } if (newcomment.len()>0) { SString token; int pos=0; if (newcomment.getNextToken(pos,token,';')) if (newcomment.getNextToken(pos,token,';')) { if (token.len()) txt=token; if (newcomment.getNextToken(pos,token,';')) if (token.len()) name=token; } } } } gen=gencopy; format=genformat; if (!name.len()) name=genname; if (!txt.len()) txt=comment; multiline=(strchr((const char*)gen,'\n')!=0); // mapoutshift...? } void Geno::freeF0() { if (f0gen) {delete f0gen; f0gen=0;} } Geno::Geno(const char *genstring,char genformat,const char *genname,const char *comment) { init(SString(genstring),genformat,SString(genname),SString(comment)); } Geno::Geno(const SString& genstring,char genformat,const SString& genname,const SString& comment) { init(genstring,genformat,genname,comment); } Geno::Geno(const Geno& src) :gen(src.gen),name(src.name),format(src.format),txt(src.txt),isvalid(src.isvalid), f0gen(0),mapinshift(src.mapinshift),mapoutshift(src.mapinshift), multiline(src.multiline),owner(0) {f0gen=src.f0gen?new Geno(*src.f0gen):0; refcount=1;} void Geno::operator=(const Geno& src) { freeF0(); gen=src.gen; name=src.name; format=src.format; txt=src.txt; isvalid=src.isvalid; mapinshift=src.mapinshift; mapoutshift=src.mapinshift; multiline=src.multiline; f0gen=src.f0gen?new Geno(*src.f0gen):0; owner=0; } Geno::Geno(const SString& src) { init(src,-1,SString::empty(),SString::empty()); } void Geno::setGene(const SString& g,char newformat) { gen=g; isvalid=-1; freeF0(); if (newformat>=0) format=newformat; } void Geno::setString(const SString& g) { freeF0(); init(g,-1,SString::empty(),SString::empty()); } void Geno::setName(const SString& n) { name=n; } void Geno::setComment(const SString& c) { txt=c; } SString Geno::toString(void) const { SString out; int comment=0; if ((format!='1')||(comment=(txt.len()||name.len()))) { if (multiline) out+="//"; else out+="/*"; out+=format; if (comment) { if (txt.len()) {out+=";";out+=txt;} if (name.len()){out+=";";out+=name;} } if (multiline) out+="\n"; else out+="*/"; } out+=gen; return out; } SString Geno::shortString(void) const { SString out; if (format!='1') { if (multiline) out+="//"; else out+="/*"; if (format==0) out+="invalid"; else out+=format; if (multiline) out+="\n"; else out+="*/"; } out+=gen; return out; } int Geno::mapGenToString(int genpos) const { if (genpos>gen.len()) return -2; if (genpos<0) return -1; return mapinshift+genpos; } int Geno::mapStringToGen(int stringpos) const { stringpos-=mapinshift; if (stringpos>gen.len()) return -2; if (stringpos<0) return -1; return stringpos; } SString Geno::getGene(void) const {return gen;} SString Geno::getName(void) const {return name;} char Geno::getFormat(void) const {return format;} SString Geno::getComment(void) const {return txt;} class ModelGenoValidator: public GenoValidator { public: ModelGenoValidator(); int testGenoValidity(Geno& g); }; ModelGenoValidator::ModelGenoValidator() { Geno::validators+=this; } int ModelGenoValidator::testGenoValidity(Geno& g) { if (g.getFormat()=='0') { Model mod(g); return mod.isValid(); } else { Geno f0geno=g.getConverted('0'); return f0geno.isValid(); } } static ModelGenoValidator default_validator; void Geno::validate() { if (isvalid>=0) return; if (gen.len()==0) { isvalid=0; return; } FOREACH(GenoValidator*,v,validators) if ((isvalid=v->testGenoValidity(*this))>=0) break; } bool Geno::isValid(void) { if (isvalid<0) validate(); return isvalid>0; } Geno Geno::getConverted(char otherformat,MultiMap *m) { if (otherformat==getFormat()) return *this; #ifndef NO_GENOCONVMANAGER if ((otherformat=='0')&&(!m)) { if (!f0gen) f0gen=new Geno(GenoConvManager::globalConvert(*this,otherformat)); return *f0gen; } else return GenoConvManager::globalConvert(*this,otherformat,m); #else return (otherformat==getFormat())?*this:Geno(0,0,0,"GenConvManager not available"); #endif } Geno::~Geno() { if (f0gen) delete f0gen; }