// This file is a part of the Framsticks GDK. // Copyright (C) 2002-2014 Maciej Komosinski and Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.framsticks.com/ for further information. #include #include #include #include #include #include #include #include #include "genoconv.h" #include /////////////////////////////////////////////////////////////////////////// GenoConvParam::GenoConvParam(GenoConvManager *g):Param(0),gcm(g) { updatetab(); } void GenoConvParam::freetab() { if (tab) free(tab); tab=0; } const char *GenoConvParam::id(int i) { if (i>=gcm->converters.size()) return 0; sprintf(tmp_id,"genkonw%d",i); return tmp_id; } void GenoConvParam::updatetab() { int i; GenoConverter *gk; ParamEntry *pe; int ile=gcm->converters.size(); freetab(); tab=(ParamEntry*)calloc(2+ile,sizeof(ParamEntry)); tab[0].id="Genetics: Conversions"; tab[0].group=1; tab[0].flags=(short)ile; tab[0].name="gkparam:"; gcnames.clear(); for (i=0,pe=tab+1;gk=(GenoConverter *)gcm->converters(i);pe++,i++) { pe->id="?"; pe->group=0; pe->flags=0; std::string descr="f"; descr+=gk->in_format; descr+=" -> f"; descr+=gk->out_format; descr+=" : "; descr+=gk->name; gcnames.push_back(descr); pe->name=descr.c_str(); pe->type="d 0 1"; pe->help=gk->info; } pe->id=0; } GenoConvParam::~GenoConvParam() { freetab(); } void *GenoConvParam::getTarget(int i) { GenoConverter *gk=(GenoConverter *)gcm->converters(i); return &gk->enabled; } GenoConvManager::GenoConvManager() :param(this) { if (!globalobject) globalobject=this; } GenoConvManager::~GenoConvManager() { GenoConverter *gc; for (converters.start();gc=(GenoConverter*)converters();) delete gc; if (globalobject==this) globalobject=NULL; } GenoConvManager *GenoConvManager::globalobject=NULL; void GenoConvManager::addConverter(GenoConverter *gc) { converters+=gc; param.updatetab(); } void GenoConvManager::removeConverter(GenoConverter *gc) { converters-=gc; param.updatetab(); } GenoConverter *GenoConvManager::findConverters(SListTempl* result,char in,char out,int enabled,char* name) { GenoConverter *gk,*retval=0; int i=0; for (;gk=(GenoConverter*)converters(i);i++) { if ((in!=-1)&&(in!=gk->in_format)) continue; if ((out!=-1)&&(out!=gk->out_format)) continue; if ((enabled!=-1)&&(enabled!=gk->enabled)) continue; if ((name)&&(strcmp(name,gk->name))) continue; if (!retval) {retval=gk; if (!result) break;} if (result) result->append(gk); } return retval; } /// write path into 'path' /// return the last path element (return >= path) /// null -> path not found /// @param mapavailable will receive 1 if conversion map is supported by all converters in path /// (can be NULL if you don't need this information) char *GenoConvManager::getPath(char in,char out,char *path,int maxlen,int *mapavailable) { if (!maxlen) return 0; GenoConverter *gk; int i=0; for (;gk=(GenoConverter*)converters(i);i++) { if ((gk->enabled)&&(gk->in_format == in)) { *path=(char)i; if (gk->out_format == out) { if (mapavailable) *mapavailable=gk->mapsupport; return path; } else { int mapavail; char *ret=getPath(gk->out_format,out,path+1,maxlen-1,&mapavail); if (ret) { if (mapavailable) *mapavailable=gk->mapsupport && mapavail; return ret; } } } } return 0; } char *GenoConvManager::getFormatPath(char in,char out,char *path,int maxlen,int *mapavailable) { char *ret=getPath(in,out,path,maxlen,mapavailable); if (ret) { for (char*t=path;t<=ret;t++) *t=((GenoConverter*)converters(*t))->out_format; } return ret; } Geno GenoConvManager::convert(Geno &in,char format,MultiMap *map) { if (in.getFormat()==format) return in; char path[10]; int dep; char *ret; if (in.isInvalid()) { return Geno("",0,"","invalid genotype cannot be converted"); } int mapavail; for (dep=1;dep<(int)sizeof(path);dep++) // sogenannte iteracyjne poglebianie... if (ret=getPath(in.getFormat(),format,path,dep,&mapavail)) break; if (!ret) { return Geno("",0,"","converter not found"); } if (!map) mapavail=0; char *t=path; SString tmp; tmp=in.getGene(); MultiMap lastmap,tmpmap; int firstmap=1; for (;t<=ret;t++) { GenoConverter *gk=(GenoConverter*)converters(*t); tmp=gk->convert(tmp,mapavail?&tmpmap:0); if (!tmp.len()) { char t[100]; sprintf(t,"f%c->f%c conversion failed (%s)",gk->in_format,gk->out_format,gk->name); return Geno(0,0,0,t); } if (mapavail) { if (firstmap) { lastmap=tmpmap; firstmap=0; } else { MultiMap m; m.addCombined(lastmap,tmpmap); lastmap=m; } tmpmap.clear(); } } if (map) *map=lastmap; return Geno(tmp, format, in.getName(), in.getComment()); } Geno GenoConvManager::globalConvert(Geno &in,char format,MultiMap *map) { if (globalobject) return globalobject->convert(in,format,map); if (format==in.getFormat()) return in; return Geno(0,0,0,"GenConvManager not initialized"); } /////////////////////////////////