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

Last change on this file since 1000 was 950, checked in by Maciej Komosinski, 4 years ago

Improved error messages (display longer names of the relevant object and field when available)

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