// This file is a part of Framsticks GDK library. // Copyright (C) 2002-2006 Szymon Ulatowski. See LICENSE.txt for details. // Refer to http://www.frams.alife.pl/ for further information. #include "nonstd.h" #include #include #include #include #include #include #include #include "genoconv.h" #include "multimap.h" /////////////////////////////////////////////////////////////////////////// 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; static char t[20]; sprintf(t,"genkonw%d",i); return t; } 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=ile; tab[0].name="gkparam:"; for (i=0,pe=tab+1;gk=(GenoConverter *)gcm->converters(i);pe++,i++) { pe->id="?"; pe->group=0; pe->flags=0; pe->name=gk->name; 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=0; } GenoConvManager *GenoConvManager::globalobject=0; void GenoConvManager::addConverter(GenoConverter *gc) { converters+=gc; param.updatetab(); } void GenoConvManager::removeConverter(GenoConverter *gc) { converters-=gc; param.updatetab(); } /// 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=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; static char path[10]; int dep; char *ret; if (in.isInvalid()) { return Geno("",0,"","invalid genotype cannot be converted"); } int mapavail; for (dep=1;depconvert(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"); } /////////////////////////////////