source: cpp/frams/param/param.h @ 230

Last change on this file since 230 was 230, checked in by Maciej Komosinski, 10 years ago

Detects invalid ParamEntry? when accessing ParamEntry?-based Params in DEBUG mode

  • Property svn:eol-style set to native
File size: 12.1 KB
RevLine 
[121]1// This file is a part of the Framsticks GDK.
[197]2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
[109]3// Refer to http://www.framsticks.com/ for further information.
4
5#ifndef _PARAM_H_
6#define _PARAM_H_
7
8#include <stdio.h>
9#include <frams/util/sstring.h>
10#include <frams/util/list.h>
11#include <frams/util/statrick.h>
12#include <frams/virtfile/virtfile.h>
13#include <common/framsg.h>
14
15class ExtValue;
16class ExtObject;
17
18// ParamInterface flags:
19#define PARAM_READONLY  1
20#define PARAM_DONTSAVE  2
21#define PARAM_SETLEVEL(x) (((x)&3)<<2)
22#define PARAM_LEVEL(x) (((x)>>2)&3)
23#define PARAM_USERREADONLY 16
24#define PARAM_USERHIDDEN 32
25// for mutableparam (private!)
26#define MUTPARAM_ALLOCENTRY 64
27#define MUTPARAM_ALLOCDATA 128
28#define PARAM_NOSTATIC 256
29#define PARAM_CONST 512
30#define PARAM_CANOMITNAME 1024
31#define PARAM_DONTLOAD  2048
32#define PARAM_NOISOLATION       4096
33#define PARAM_DEPRECATED        8192
34
[154]35// the result of param::set() is a combination of bits:
[109]36
[154]37// read-only: cannot modify
[109]38#define PSET_RONLY      1
39
[154]40// value has been modified
[109]41#define PSET_CHANGED    2
42
[154]43//value has been adjusted because it tried to exceed min or max
[109]44#define PSET_HITMIN     4
45#define PSET_HITMAX     8
46
[154]47// useful combination: need to get and display the value so that a user knows that the value they tried to set has been rejected or changed
[109]48#define PSET_WARN (PSET_RONLY | PSET_HITMIN | PSET_HITMAX)
49
50#define PSET_NOPROPERTY 16
51
52struct ParamEntry;
53
54/** Property get/set interface - runtime access to named properties */
55class ParamInterface
56{
57public:
[154]58        virtual int getGroupCount() = 0; ///< @return the number of property groups
59        virtual int getPropCount() = 0; ///< @return the number of properties
[109]60
[154]61        virtual const char* getName() = 0;
62        virtual const char* getDescription() { return 0; }
63        virtual ParamEntry *getParamTab() const { return NULL; }
[109]64
[154]65        int findId(const char *n);      ///< find id number for internal name
66        int findIdn(const char *naz, int n);
[109]67
[154]68        virtual const char *id(int i) = 0;      ///< get internal name
69        virtual const char *name(int i) = 0;    ///< get the human-readable name
[109]70
[154]71        /** get type description.
72                first character defines basic datatype:
73                - d = integer
74                - f = floating point
75                - s = string
76                - o = ExtObject
77                - x = ExtValue (universal datatype)
78                */
79        virtual const char *type(int i) = 0;
[109]80
[154]81        virtual const char *help(int i) = 0;    ///< get long description (tooltip)
[109]82
[154]83        virtual int flags(int i) = 0;           ///< get flags
[109]84
[154]85        virtual int group(int i) = 0;           ///< get group id for a property
86        virtual const char *grname(int gi) = 0; ///< get group name
87        virtual int grmember(int gi, int n) = 0;        ///< get property id for n'th member of group "gi"
[109]88
[154]89        virtual void call(int i, ExtValue* args, ExtValue *ret) = 0;
[109]90
[154]91        void get(int, ExtValue &retval);        ///< most universal get, can be used for every datatype
[109]92
[154]93        virtual SString getString(int) = 0;     ///< get string value, you can only use this for "s" type property
94        virtual long getInt(int) = 0;   ///< get long value, you can only use this for "d" type property
95        virtual double getDouble(int) = 0;      ///< get double value, you can only use this for "f" type property
96        virtual ExtObject getObject(int) = 0;   ///< get object reference, you can only use this for "o" type property
97        virtual ExtValue getExtValue(int) = 0;  ///< get extvalue object, you can only use this for "x" type property
[109]98
[154]99        SString get(int);               ///< old style get, can convert long or double to string
100        SString getText(int);           ///< like getString, returns enumeration label for subtype "d 0 n ~enum1~enum2...
[109]101
[154]102        SString getStringById(const char*prop);  ///< get string value, you can only use this for "s" type property
103        long getIntById(const char* prop);    ///< get long value, you can only use this for "d" type property
104        double getDoubleById(const char* prop);///< get double value, you can only use this for "f" type property
105        ExtObject getObjectById(const char* prop);///< get object reference, you can only use this for "o" type property
106        ExtValue getExtValueById(const char* prop);///< get extvalue object, you can only use this for "x" type property
107        ExtValue getById(const char* prop);
[109]108
[154]109        int setInt(int i, const char* str);
110        int setDouble(int i, const char* str);
111        virtual int setInt(int, long) = 0;              ///< set long value, you can only use this for "d" type prop
112        virtual int setDouble(int, double) = 0; ///< set double value, you can only use this for "f" type prop
113        virtual int setString(int, const SString &) = 0;        ///< set string value, you can only use this for "s" type prop
114        virtual int setObject(int, const ExtObject &) = 0;      ///< set object reference, you can only use this for "o" type prop
115        virtual int setExtValue(int, const ExtValue &) = 0;     ///< 4 in 1
[109]116
[154]117        int set(int, const ExtValue &);///< most universal set, can be used for every datatype
[109]118
[154]119        int set(int, const char*);              ///< oldstyle set, can convert string to long or double
[109]120
[154]121        int setIntById(const char* prop, long);///< set long value, you can only use this for "d" type prop
122        int setDoubleById(const char* prop, double);///< set double value, you can only use this for "f" type prop
123        int setStringById(const char* prop, const SString &);///< set string value, you can only use this for "s" type prop
124        int setObjectById(const char* prop, const ExtObject &);///< set object reference, you can only use this for "o" type prop
125        int setExtValueById(const char* prop, const ExtValue &); ///< for ExtValue types only
126        int setById(const char* prop, const ExtValue &);///< can be used for all property types
[109]127
[154]128        /** get valid minimum, maximum and default value for property 'prop'
129                @return 0 if min/max/def information is not available */
130        int getMinMax(int prop, long& minumum, long& maximum, long& def);
131        /** get valid minimum, maximum and default value for property 'prop'
132                @return 0 if min/max/def information is not available */
133        int getMinMax(int prop, double& minumum, double& maximum, double& def);
[109]134
[154]135        virtual void setDefault(bool numericonly = false);
136        virtual void setDefault(int i, bool numericonly = false);
137        void setMin();
138        void setMax();
139        void setMin(int i);
140        void setMax(int i);
[109]141
[154]142        /** copy all property values from other ParamInterface object */
143        void copyFrom(ParamInterface *src);
[109]144
[154]145        /** Copy all property values from compatible ParamInterface object.
146                This method is more efficient than copyFrom,
147                but can be used only if the other object has the same properties sequence, e.g.:
148                - any two Param objects having common paramtab
149                - any ParamInterface object and the Param with paramtab constructed by ParamObject::makeParamTab
150                */
151        void quickCopyFrom(ParamInterface *src);
[109]152
[154]153        int save(VirtFILE*, const char* altname = NULL, bool force = 0);
154        int saveprop(VirtFILE*, int i, const char* p, bool force = 0);
155        int load(VirtFILE*);///< @return the number of fields loaded
156        int load2(const SString &, int &);///< @return the number of fields loaded
[109]157
[154]158        static const char* SERIALIZATION_PREFIX;
[230]159
160#ifdef DEBUG
161        virtual void sanityCheck(int i) {}
162#endif
[109]163};
164
165// implementations:
166
167extern char MakeCodeGuardHappy;
168
169#define PROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
170#define STATICPROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_))
171#define GETOFFSET(_proc_) ( (void (*)(void*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
172#define SETOFFSET(_proc_) ( (int (*)(void*,const ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
173
174#define FIELDOFFSET(_fld_) ((long)((char*)(&((FIELDSTRUCT*)&MakeCodeGuardHappy)->_fld_)-((char*)((FIELDSTRUCT*)&MakeCodeGuardHappy))))
175
[230]176#ifdef DEBUG
177#define PARAM_ILLEGAL_OFFSET ((long)0xdeadbeef)
178#else
179#define PARAM_ILLEGAL_OFFSET 0
180#endif
181
[109]182#define FIELD(_fld_) FIELDOFFSET(_fld_),0,0
183#define LONGOFFSET(_o_) (_o_),0,0
[230]184#define PROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)PROCOFFSET(_proc_),0
185#define STATICPROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)STATICPROCOFFSET(_proc_),0
186#define GETSET(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),(void*)SETOFFSET(set_ ## _proc_)
[109]187#define GETFIELD(_proc_) FIELDOFFSET(_proc_),(void*)GETOFFSET(get_ ## _proc_),0
188#define SETFIELD(_proc_) FIELDOFFSET(_proc_),0,(void*)SETOFFSET(set_ ## _proc_)
[230]189#define GETONLY(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),0
190#define SETONLY(_proc_) PARAM_ILLEGAL_OFFSET,0,(void*)SETOFFSET(set_ ## _proc_)
[109]191
192#define PARAMPROCARGS ExtValue* args,ExtValue* ret
193#define PARAMSETARGS const ExtValue* arg
194#define PARAMGETARGS ExtValue* ret
195
196#define PARAMPROCDEF(name) STATRICKDEF2(name,ExtValue*,ExtValue*)
197#define PARAMGETDEF(name) STATRICKDEF1(get_ ## name,ExtValue*)
198#define PARAMSETDEF(name) STATRICKRDEF1(int,set_ ## name,const ExtValue*)
199
200///////////////////////////////
201
202struct ParamEntry
203{
[154]204        const char *id;
205        short group, flags;
206        const char *name, *type;
207        long offset;
208        void *fun1; ///< procedure or get
209        void *fun2; ///< set
210        const char *help;
[109]211};
212
[154]213struct ParamEntryConstructor : public ParamEntry
[109]214{
215public:
[154]216        ParamEntryConstructor(const char *_id, short _group = 0, short _flags = 0, const char *_name = 0, const char *_type = 0, long _offset = 0, void *_fun1 = 0, void *_fun2 = 0, const char *_help = 0)
217        {
218                id = _id; group = _group; flags = _flags; name = _name; type = _type; offset = _offset; fun1 = _fun1; fun2 = _fun2; help = _help;
219        }
[109]220};
221
[154]222class SimpleAbstractParam : public virtual ParamInterface
[109]223{
224protected:
[154]225        virtual void *getTarget(int i);
226        virtual ParamEntry *entry(int i) = 0;
227        const char* myname;
228        bool dontcheckchanges;
[109]229
230public:
[154]231        void *object;
[109]232
[154]233        const char* getName() { return myname; }
234        void setName(const char* n) { myname = n; }
[109]235
[154]236        /**
237                @param t ParamEntry table
238                @param o controlled object
239                @param n Param's name
240                */
241        SimpleAbstractParam(void* o = 0, const char*n = 0) :myname(n), dontcheckchanges(0), object(o) {}
242        void setDontCheckChanges(bool x) { dontcheckchanges = x; }
[109]243
[154]244        void select(void *o) { object = o; }
245        void* getSelected() { return object; }
[109]246
[154]247        const char *id(int i) { return (i >= getPropCount()) ? 0 : entry(i)->id; }
248        const char *name(int i) { return entry(i)->name; }
249        const char *type(int i) { return entry(i)->type; }
250        const char *help(int i) { return entry(i)->help; }
251        int flags(int i) { return entry(i)->flags; }
252        int group(int i) { return entry(i)->group; }
253        void call(int i, ExtValue* args, ExtValue *ret);
[109]254
[154]255        SString getString(int);
256        long getInt(int);
257        double getDouble(int);
258        ExtObject getObject(int);
259        ExtValue getExtValue(int);
[109]260
[154]261        template<typename T> void messageOnExceedRange(int i, int setflags, T valuetoset) ///< prints a warning when setflags indicates that allowed param range has been exceeded during set
262        {
263                if (setflags & (PSET_HITMIN | PSET_HITMAX))
264                {
265                        SString svaluetoset = SString::valueOf(valuetoset); //converts any type to SString
266                        SString actual = get(i);
267                        FMprintf("Param", "set", FMLV_WARN, "Setting '%s.%s = %s' exceeded allowed range (too %s). Adjusted to %s.",
268                                getName(), id(i), (const char*)svaluetoset, (setflags&PSET_HITMAX) ? "big" : "small", (const char*)actual);
269                }
270        }
[109]271
[154]272        int setInt(int, long);
273        int setDouble(int, double);
274        int setString(int, const SString &);
275        int setObject(int, const ExtObject &);
276        int setExtValue(int, const ExtValue &);
[109]277
[154]278        int isequal(int i, void* defdata);
279        void save2(SString&, void *defdata, bool addcr = true, bool all_names = true);
[109]280
[154]281        virtual void setDefault(bool numericonly = false);
282        virtual void setDefault(int i, bool numericonly = false);
[230]283
284#ifdef DEBUG
285        void sanityCheck(int i);
286#endif
[109]287};
288
[154]289class Param : public SimpleAbstractParam
[109]290{
291protected:
[154]292        ParamEntry *entry(int i) { return tab + tab[0].group + i; }
[109]293public:
[154]294        ParamEntry *tab;
295        /**
296                @param t ParamEntry table
297                @param o controlled object
298                @param n Param's name
299                */
[109]300
[154]301        Param(ParamEntry *t = 0, void* o = 0, const char*n = 0) :SimpleAbstractParam(o, n), tab(t)
302        {
303                if (!n&&tab) myname = tab[0].name;
304        }
[109]305
[154]306        Param(const Param& p) :SimpleAbstractParam(p.object, p.myname), tab(p.tab) {}
307        void operator=(const Param&p) { object = p.object; myname = p.myname; tab = p.tab; }
[109]308
[154]309        const char* getDescription() { return tab[0].type; }
[109]310
[154]311        int getGroupCount() { return tab[0].group; }
312        int getPropCount() { return tab[0].flags; }
313        const char *grname(int i) { return (i < getGroupCount()) ? tab[i].id : 0; }
314        int grmember(int, int);
315        void setParamTab(ParamEntry *t, int dontupdatename = 0) { tab = t; if ((!dontupdatename) && tab) myname = tab[0].name; }
316        ParamEntry *getParamTab() const { return tab; }
[109]317};
318
319extern ParamEntry empty_paramtab[];
320
321#endif
Note: See TracBrowser for help on using the repository browser.