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

Last change on this file since 241 was 230, checked in by Maciej Komosinski, 11 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
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
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
35// the result of param::set() is a combination of bits:
36
37// read-only: cannot modify
38#define PSET_RONLY      1
39
40// value has been modified
41#define PSET_CHANGED    2
42
43//value has been adjusted because it tried to exceed min or max
44#define PSET_HITMIN     4
45#define PSET_HITMAX     8
46
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
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:
58        virtual int getGroupCount() = 0; ///< @return the number of property groups
59        virtual int getPropCount() = 0; ///< @return the number of properties
60
61        virtual const char* getName() = 0;
62        virtual const char* getDescription() { return 0; }
63        virtual ParamEntry *getParamTab() const { return NULL; }
64
65        int findId(const char *n);      ///< find id number for internal name
66        int findIdn(const char *naz, int n);
67
68        virtual const char *id(int i) = 0;      ///< get internal name
69        virtual const char *name(int i) = 0;    ///< get the human-readable name
70
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;
80
81        virtual const char *help(int i) = 0;    ///< get long description (tooltip)
82
83        virtual int flags(int i) = 0;           ///< get flags
84
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"
88
89        virtual void call(int i, ExtValue* args, ExtValue *ret) = 0;
90
91        void get(int, ExtValue &retval);        ///< most universal get, can be used for every datatype
92
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
98
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...
101
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);
108
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
116
117        int set(int, const ExtValue &);///< most universal set, can be used for every datatype
118
119        int set(int, const char*);              ///< oldstyle set, can convert string to long or double
120
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
127
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);
134
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);
141
142        /** copy all property values from other ParamInterface object */
143        void copyFrom(ParamInterface *src);
144
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);
152
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
157
158        static const char* SERIALIZATION_PREFIX;
159
160#ifdef DEBUG
161        virtual void sanityCheck(int i) {}
162#endif
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
176#ifdef DEBUG
177#define PARAM_ILLEGAL_OFFSET ((long)0xdeadbeef)
178#else
179#define PARAM_ILLEGAL_OFFSET 0
180#endif
181
182#define FIELD(_fld_) FIELDOFFSET(_fld_),0,0
183#define LONGOFFSET(_o_) (_o_),0,0
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_)
187#define GETFIELD(_proc_) FIELDOFFSET(_proc_),(void*)GETOFFSET(get_ ## _proc_),0
188#define SETFIELD(_proc_) FIELDOFFSET(_proc_),0,(void*)SETOFFSET(set_ ## _proc_)
189#define GETONLY(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),0
190#define SETONLY(_proc_) PARAM_ILLEGAL_OFFSET,0,(void*)SETOFFSET(set_ ## _proc_)
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{
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;
211};
212
213struct ParamEntryConstructor : public ParamEntry
214{
215public:
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        }
220};
221
222class SimpleAbstractParam : public virtual ParamInterface
223{
224protected:
225        virtual void *getTarget(int i);
226        virtual ParamEntry *entry(int i) = 0;
227        const char* myname;
228        bool dontcheckchanges;
229
230public:
231        void *object;
232
233        const char* getName() { return myname; }
234        void setName(const char* n) { myname = n; }
235
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; }
243
244        void select(void *o) { object = o; }
245        void* getSelected() { return object; }
246
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);
254
255        SString getString(int);
256        long getInt(int);
257        double getDouble(int);
258        ExtObject getObject(int);
259        ExtValue getExtValue(int);
260
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        }
271
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 &);
277
278        int isequal(int i, void* defdata);
279        void save2(SString&, void *defdata, bool addcr = true, bool all_names = true);
280
281        virtual void setDefault(bool numericonly = false);
282        virtual void setDefault(int i, bool numericonly = false);
283
284#ifdef DEBUG
285        void sanityCheck(int i);
286#endif
287};
288
289class Param : public SimpleAbstractParam
290{
291protected:
292        ParamEntry *entry(int i) { return tab + tab[0].group + i; }
293public:
294        ParamEntry *tab;
295        /**
296                @param t ParamEntry table
297                @param o controlled object
298                @param n Param's name
299                */
300
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        }
305
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; }
308
309        const char* getDescription() { return tab[0].type; }
310
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; }
317};
318
319extern ParamEntry empty_paramtab[];
320
321#endif
Note: See TracBrowser for help on using the repository browser.