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

Last change on this file since 284 was 284, checked in by Maciej Komosinski, 7 years ago

Wrong sscanf size in 64-bit caused stack damage (in "0x....." conversion)

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