// 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. #ifndef _EXTVALUE_H_ #define _EXTVALUE_H_ #include "sstring.h" #include "param.h" #define EXTVALUEUNION #define EXTVALUEUNIONSIZE sizeof(SString) enum ExtPType {TUnknown=0,TInt,TDouble,TString,TObj,TInvalid}; /** destructable object */ class DestrBase { public: int refcount; DestrBase():refcount(0) {} virtual ~DestrBase() {} }; /** object reference. */ class ExtObject { int subtype; //< 0/1=Generic/DPC Object, 0/2=Standalone/Shared Param void incref() const {if (subtype&1) dbobject->refcount++;} void decref() const {if (subtype&1) if (!--dbobject->refcount) delete dbobject;} public: union { void* object; //< generic object, will use param DestrBase *dbobject;}; //< object with refcounting, will be deleted if refcount goes to 0 union { Param* param; //< if object!=0 ParamInterface *paraminterface;}; //< if object==0 void copyFrom(const ExtObject& src) {subtype=src.subtype;object=src.object;param=src.param;} void* operator new(size_t s, void* mem) {return mem;} #ifdef _MSC_VER void operator delete(void* mem,void* t) {} #endif void* operator new(size_t s) {return malloc(sizeof(ExtObject));} void operator delete(void* mem) {free(mem);} ParamInterface *getParamInterface() const {if(subtype&2){param->select(object);return param;} return paraminterface;} const char* interfaceName() const {if (isEmpty()) return "Empty"; return getParamInterface()->getName();} void* getTarget() const {return (subtype&1)?dbobject:object;} void* getTarget(const char* classname) const {return strcmp(interfaceName(),classname)?0:getTarget();} int isEmpty() const {return !param;} ExtObject(const ExtObject& src) {src.incref();copyFrom(src);} void operator=(const ExtObject& src) {src.incref();decref();copyFrom(src);} int operator==(const ExtObject& src) {if (object!=src.object) return 0; return (object==0)?(param==src.param):1;} SString toString() const; ExtObject(Param *p,void *o):subtype(2),object(o),param(p){} ExtObject(ParamInterface *p=0):subtype(0),object(0),paraminterface(p){} ExtObject(Param *p,DestrBase *o):subtype(1+2),dbobject(o),param(p){incref();} ExtObject(ParamInterface *p,DestrBase *o):subtype(1),dbobject(o),paraminterface(p){incref();} ~ExtObject(){decref();} }; class ExtValue { public: ExtPType type; #ifdef EXTVALUEUNION long data[(EXTVALUEUNIONSIZE+sizeof(long)-1)/sizeof(long)]; long& idata() const {return (long&)data[0];}; double& ddata() const {return *(double*)data;}; ExtObject& odata() const {return *(ExtObject*)data;}; SString& sdata() const {return *(SString*)data;}; #else union { long i; double d; SString *s; ExtObject *o; }; long& idata() const {return (long&)i;}; double& ddata() const {return (double&)d;}; ExtObject& odata() const {return *o;}; SString& sdata() const {return *s;}; #endif void* operator new(size_t s, void* mem) {return mem;} void* operator new(size_t s) {return ::operator new(s);} ExtValue():type(TUnknown){} ~ExtValue() {setEmpty();} ExtValue(long v) {seti(v);} ExtValue(double v) {setd(v);} ExtValue(const SString &v) {sets(v);} ExtValue(const ExtObject &srco) {seto(srco);} long compare(const ExtValue& src) const; int operator==(const ExtValue& src) const; void operator+=(const ExtValue& src); void operator-=(const ExtValue& src); void operator*=(const ExtValue& src); void operator/=(const ExtValue& src); void operator%=(const ExtValue& src); void operator=(const ExtValue& src) {setr(src);} ExtValue(const ExtValue& src) :type(TUnknown) {set(src);} void setEmpty(); void setInvalid() {setEmpty();type=TInvalid;} ExtPType getType() {return type;} void *getObjectTarget(const char* classname) {return (type==TObj)?getObject().getTarget(classname):0;} void setInt(long v) {if (type!=TInt) setri(v); else idata()=v;} void setDouble(double v) {if (type!=TDouble) setrd(v); else ddata()=v;} void setString(const SString &v) {if (type!=TString) setrs(v); else sdata()=v;} void setObject(const ExtObject &src) {if (type!=TObj) setro(src); else odata()=src;} long getInt() const; double getDouble() const; SString getString() const; ExtObject getObject() const; ExtValue getExtType(); private: // setrx - release and set, setx - assume released void setr(const ExtValue& src){setEmpty();set(src);} void set(const ExtValue& src); void setri(long v) {setEmpty();seti(v);} void setrd(double v) {setEmpty();setd(v);} void seti(long v) {type=TInt;idata()=v;} void setd(double v) {type=TDouble;ddata()=v;} #ifdef EXTVALUEUNION void setrs(const SString &v) {setEmpty();sets(v);} void setro(const ExtObject &src) {setEmpty();seto(src);} void sets(const SString &v) {type=TString;new(data) SString(v);} void seto(const ExtObject &src) {type=TObj;new(data) ExtObject(src);} #else void setrs(const SString &v) {setEmpty();sets(v);} void setro(const ExtObject &src) {setEmpty();seto(src);} void sets(const SString &v) {type=TString;s=new SString(v);} void seto(const ExtObject &src) {type=TObj;o=new ExtObject(src);} #endif }; #endif