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

Last change on this file since 393 was 393, checked in by sz, 9 years ago

f0 parsing corrections and enhancements:

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