// 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 "extvalue.h" #include "param.h" #include SString ExtObject::toString() { if (isEmpty()) return SString(""); ParamInterface *p=getParamInterface(); int tostr=p->findId("toString"); if (tostr>=0) { return SString(p->getString(tostr)); } else { SString tmp("<"); tmp+=p->getName(); sprintf(tmp.directAppend(30)," object at %p>",object); tmp.endAppend(); return tmp; } } /////////////////////////////////////// void ExtValue::set(const ExtValue& src) { switch(src.type) { case TString: sets(src.sdata()); break; case TInt: seti(src.idata()); break; case TDouble: setd(src.ddata()); break; case TObj: seto(src.odata()); break; } } void ExtValue::setEmpty() { switch(type) { #ifdef EXTVALUEUNION case TString: sdata().~SString(); break; case TObj: odata().~ExtObject(); break; #else case TString: delete s; break; case TObj: delete o; break; #endif } type=TUnknown; } static long longsign(long x) { if (x<0) return -1; if (x>0) return 1; return 0; } long ExtValue::compare(const ExtValue& src) const { if (type==TUnknown) { if (src.type==TDouble) return (src.getDouble()!=0.0); if (src.type==TString) return 1; return src.getInt()?1:0; } else if (src.type==TUnknown) { if (type==TDouble) return (getDouble()!=0.0); if (type==TString) return 1; return getInt()?1:0; } switch(type) { case TInt: { long t=src.getInt(); if (idata()>0) {if (t>0) return longsign(idata()-t); else return +1;} else {if (t<=0) return longsign(idata()-t); else return -1;} } case TDouble: { double t=ddata()-src.getDouble(); if (t<0) return -1; else if (t>0) return 1; return 0; } case TString: { SString t=src.getString(); SString& t2=sdata(); const char* s1=(const char*)t2; const char* s2=(const char*)t; return longsign(strcmp(s1,s2)); } case TObj: { if (src.type==TObj) return !(odata()==src.odata()); return 1; } } return 1; } int ExtValue::operator==(const ExtValue& src) const { if (type!=src.type) return 0; switch(type) { case TInt: return idata()==src.idata(); case TDouble: return ddata()==src.ddata(); case TString: return sdata()==src.sdata(); case TObj: return odata()==src.odata(); } return 1; } void ExtValue::operator+=(const ExtValue& src) { switch(type) { case TInt: idata()+=src.getInt(); break; case TDouble: ddata()+=src.getDouble(); break; case TString: sdata()+=src.getString(); break; } } void ExtValue::operator-=(const ExtValue& src) { switch(type) { case TInt: idata()-=src.getInt(); break; case TDouble: ddata()-=src.getDouble(); break; } } void ExtValue::operator*=(const ExtValue& src) { switch(type) { case TInt: idata()*=src.getInt(); break; case TDouble: ddata()*=src.getDouble(); break; } } #include "framsg.h" /*#include "fpu_control.h" #include static int fpuexception; void mathhandler(int sig) { printf("fpu exception!\n"); fpuexception=1; signal(SIGFPE,SIG_IGN); } */ void ExtValue::operator/=(const ExtValue& src) { switch(type) { case TInt: { int a=src.getInt(); // idata()/=src.getInt(); if (a) idata()/=a; else FMprintf("ExtValue","divide",FMLV_ERROR,"%s/0",(const char*)getString()); } break; case TDouble: // ugly ;-( #ifdef FPU_THROWS_EXCEPTIONS try { ddata()/=src.getDouble(); } catch(...) { FMprintf("ExtValue","divide",FMLV_ERROR,"%s/0.0",(const char*)getString()); } #else { double d=ddata(); d/=src.getDouble(); if (finite(d)) ddata()=d; else FMprintf("ExtValue","divide",FMLV_ERROR,"%s/0.0",(const char*)getString()); } #endif break; } } void ExtValue::operator%=(const ExtValue& src) { switch(type) { case TInt: idata()=idata()%src.getInt(); break; case TDouble: ddata()=fmod(ddata(),src.getDouble()); break; } } long ExtValue::getInt() const { switch(type) { case TInt: return idata(); case TDouble: return (int)ddata(); case TString: { const char* s=(const char*)sdata(); if ((s[0]=='0')&&(s[1]=='x')) { long val; sscanf(s+2,"%lx",&val); return val; } else { if (strchr(s,'e')||(strchr(s,'E'))) return atof(s); else return atol(s); } } case TObj: return (long)odata().param; } return 0; } double ExtValue::getDouble() const { switch(type) { case TDouble: return ddata(); case TInt: return (double)idata(); case TString: { const char* s=(const char*)sdata(); if ((s[0]=='0')&&(s[1]=='x')) { long val; sscanf(s+2,"%lx",&val); return val; } else return atof(s); } case TObj: return (double)(long)odata().param; } return 0.0; } SString ExtValue::getString() const { switch(type) { case TString: return sdata(); case TInt: { SString tmp; sprintf(tmp.directAppend(20),"%d",idata()); tmp.endAppend(); return tmp; } case TDouble: { SString tmp; sprintf(tmp.directAppend(20),"%g",ddata()); tmp.endAppend(); if ((!strchr(tmp,'.'))&&(!strchr(tmp,'e'))) tmp+=".0"; return tmp; } case TObj: return odata().toString(); default: return SString("null"); } } ExtObject ExtValue::getObject() const { if (type==TObj) return odata(); return ExtObject(); } ExtValue ExtValue::getExtType() { if (getType()!=TObj) return ExtValue((long)getType()); ExtObject& o=odata(); return ExtValue(SString(o.isEmpty()?"":o.getParamInterface()->getName())); }