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

Last change on this file since 268 was 268, checked in by Maciej Komosinski, 9 years ago

ParamInterface::load warns on unknown fields and skips comments

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