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

Last change on this file since 1155 was 1155, checked in by Maciej Komosinski, 3 years ago

Added ParamInterface::findGroupId(const char* name)

  • 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);
[1155]80        int findGroupId(const char* name);
[109]81
[154]82        virtual const char *id(int i) = 0;      ///< get internal name
83        virtual const char *name(int i) = 0;    ///< get the human-readable name
[109]84
[154]85        /** get type description.
86                first character defines basic datatype:
87                - d = integer
88                - f = floating point
89                - s = string
90                - o = ExtObject
91                - x = ExtValue (universal datatype)
92                */
93        virtual const char *type(int i) = 0;
[109]94
[154]95        virtual const char *help(int i) = 0;    ///< get long description (tooltip)
[109]96
[154]97        virtual int flags(int i) = 0;           ///< get flags
[109]98
[154]99        virtual int group(int i) = 0;           ///< get group id for a property
100        virtual const char *grname(int gi) = 0; ///< get group name
101        virtual int grmember(int gi, int n) = 0;        ///< get property id for n'th member of group "gi"
[109]102
[154]103        virtual void call(int i, ExtValue* args, ExtValue *ret) = 0;
[109]104
[154]105        void get(int, ExtValue &retval);        ///< most universal get, can be used for every datatype
[109]106
[154]107        virtual SString getString(int) = 0;     ///< get string value, you can only use this for "s" type property
[247]108        virtual paInt getInt(int) = 0;  ///< get long value, you can only use this for "d" type property
[154]109        virtual double getDouble(int) = 0;      ///< get double value, you can only use this for "f" type property
110        virtual ExtObject getObject(int) = 0;   ///< get object reference, you can only use this for "o" type property
111        virtual ExtValue getExtValue(int) = 0;  ///< get extvalue object, you can only use this for "x" type property
[109]112
[154]113        SString get(int);               ///< old style get, can convert long or double to string
114        SString getText(int);           ///< like getString, returns enumeration label for subtype "d 0 n ~enum1~enum2...
[109]115
[154]116        SString getStringById(const char*prop);  ///< get string value, you can only use this for "s" type property
[247]117        paInt getIntById(const char* prop);    ///< get long value, you can only use this for "d" type property
[154]118        double getDoubleById(const char* prop);///< get double value, you can only use this for "f" type property
119        ExtObject getObjectById(const char* prop);///< get object reference, you can only use this for "o" type property
120        ExtValue getExtValueById(const char* prop);///< get extvalue object, you can only use this for "x" type property
121        ExtValue getById(const char* prop);
[109]122
[743]123        int setIntFromString(int i, const char* str, bool strict = false);
124        int setDoubleFromString(int i, const char* str);
[247]125        virtual int setInt(int, paInt) = 0;             ///< set long value, you can only use this for "d" type prop
[154]126        virtual int setDouble(int, double) = 0; ///< set double value, you can only use this for "f" type prop
127        virtual int setString(int, const SString &) = 0;        ///< set string value, you can only use this for "s" type prop
128        virtual int setObject(int, const ExtObject &) = 0;      ///< set object reference, you can only use this for "o" type prop
129        virtual int setExtValue(int, const ExtValue &) = 0;     ///< 4 in 1
[109]130
[154]131        int set(int, const ExtValue &);///< most universal set, can be used for every datatype
[109]132
[743]133        int setFromString(int, const char*, bool strict = false);               ///< oldstyle set, can convert string to long or double
[109]134
[247]135        int setIntById(const char* prop, paInt);///< set long value, you can only use this for "d" type prop
[154]136        int setDoubleById(const char* prop, double);///< set double value, you can only use this for "f" type prop
137        int setStringById(const char* prop, const SString &);///< set string value, you can only use this for "s" type prop
138        int setObjectById(const char* prop, const ExtObject &);///< set object reference, you can only use this for "o" type prop
139        int setExtValueById(const char* prop, const ExtValue &); ///< for ExtValue types only
140        int setById(const char* prop, const ExtValue &);///< can be used for all property types
[109]141
[154]142        /** get valid minimum, maximum and default value for property 'prop'
143                @return 0 if min/max/def information is not available */
[743]144        int getMinMaxInt(int prop, paInt& minumum, paInt& maximum, paInt& def);
[154]145        /** get valid minimum, maximum and default value for property 'prop'
146                @return 0 if min/max/def information is not available */
[743]147        int getMinMaxDouble(int prop, double& minumum, double& maximum, double& def);
148        int getMinMaxString(int prop, int& minumum, int& maximum, SString& def);
149        static int getMinMaxIntFromTypeDef(const char* type, paInt& minumum, paInt& maximum, paInt& def);
150        static int getMinMaxDoubleFromTypeDef(const char* type, double& minumum, double& maximum, double& def);
151        static int getMinMaxStringFromTypeDef(const char* type, int& minumum, int& maximum, SString& def);
[109]152
[278]153        virtual void setDefault();
154        virtual void setDefault(int i);
[154]155        void setMin();
156        void setMax();
157        void setMin(int i);
158        void setMax(int i);
[109]159
[640]160        /** return the human readable description of the given type */
[743]161        static SString friendlyTypeDescrFromTypeDef(const char* type);
162        SString friendlyTypeDescr(int i) { return friendlyTypeDescrFromTypeDef(type(i)); }
[650]163
[154]164        /** copy all property values from other ParamInterface object */
165        void copyFrom(ParamInterface *src);
[109]166
[154]167        /** Copy all property values from compatible ParamInterface object.
168                This method is more efficient than copyFrom,
169                but can be used only if the other object has the same properties sequence, e.g.:
170                - any two Param objects having common paramtab
171                - any ParamInterface object and the Param with paramtab constructed by ParamObject::makeParamTab
172                */
173        void quickCopyFrom(ParamInterface *src);
[109]174
[720]175        enum FileFormat { FormatMultiLine, FormatSingleLine }; // FormatJSON in the future?
176        struct LoadOptions {
177                bool warn_unknown_fields; bool *abortable; int *linenum; int offset; bool parse_failed;
178                LoadOptions() : warn_unknown_fields(false), abortable(NULL), linenum(NULL), offset(0), parse_failed(false) {}
179        };
180
[745]181        int saveMultiLine(VirtFILE*, const char* altname = NULL, bool force = 0);
[154]182        int saveprop(VirtFILE*, int i, const char* p, bool force = 0);
[109]183
[720]184        int load(FileFormat format, VirtFILE*, LoadOptions *load_options = NULL);///< @return the number of fields loaded
185        int load(FileFormat format, const SString &, LoadOptions *load_options = NULL);///< @return the number of fields loaded
186protected:
187        int loadMultiLine(VirtFILE*, LoadOptions &options);///< @return the number of fields loaded
188        int loadSingleLine(const SString &, LoadOptions &options);///< @return the number of fields loaded
189public:
190
[154]191        static const char* SERIALIZATION_PREFIX;
[230]192
[535]193        static bool isValidTypeDescription(const char* t);
[483]194#ifdef _DEBUG
[230]195        virtual void sanityCheck(int i) {}
196#endif
[950]197        SString nameDotProperty(int prop);
198        SString nameDotPropertyForMessages(int prop);
[109]199};
200
201// implementations:
202
203extern char MakeCodeGuardHappy;
204
205#define PROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
206#define STATICPROCOFFSET(_proc_) ( (void (*)(void*,ExtValue*,ExtValue*)) &(FIELDSTRUCT :: _proc_))
207#define GETOFFSET(_proc_) ( (void (*)(void*,ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
208#define SETOFFSET(_proc_) ( (int (*)(void*,const ExtValue*)) &(FIELDSTRUCT :: _proc_ ## _statrick))
209
[247]210#define FIELDOFFSET(_fld_) ((intptr_t)((char*)(&((FIELDSTRUCT*)&MakeCodeGuardHappy)->_fld_)-((char*)((FIELDSTRUCT*)&MakeCodeGuardHappy))))
[109]211
[483]212#ifdef _DEBUG
[247]213#define PARAM_ILLEGAL_OFFSET ((intptr_t)0xdeadbeef)
[230]214#else
215#define PARAM_ILLEGAL_OFFSET 0
216#endif
217
[109]218#define FIELD(_fld_) FIELDOFFSET(_fld_),0,0
219#define LONGOFFSET(_o_) (_o_),0,0
[230]220#define PROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)PROCOFFSET(_proc_),0
221#define STATICPROCEDURE(_proc_) PARAM_ILLEGAL_OFFSET,(void*)STATICPROCOFFSET(_proc_),0
222#define GETSET(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),(void*)SETOFFSET(set_ ## _proc_)
[109]223#define GETFIELD(_proc_) FIELDOFFSET(_proc_),(void*)GETOFFSET(get_ ## _proc_),0
224#define SETFIELD(_proc_) FIELDOFFSET(_proc_),0,(void*)SETOFFSET(set_ ## _proc_)
[230]225#define GETONLY(_proc_) PARAM_ILLEGAL_OFFSET,(void*)GETOFFSET(get_ ## _proc_),0
226#define SETONLY(_proc_) PARAM_ILLEGAL_OFFSET,0,(void*)SETOFFSET(set_ ## _proc_)
[109]227
228#define PARAMPROCARGS ExtValue* args,ExtValue* ret
229#define PARAMSETARGS const ExtValue* arg
230#define PARAMGETARGS ExtValue* ret
231
232#define PARAMPROCDEF(name) STATRICKDEF2(name,ExtValue*,ExtValue*)
233#define PARAMGETDEF(name) STATRICKDEF1(get_ ## name,ExtValue*)
234#define PARAMSETDEF(name) STATRICKRDEF1(int,set_ ## name,const ExtValue*)
235
236///////////////////////////////
237
238struct ParamEntry
239{
[154]240        const char *id;
[478]241        paInt group, flags;
[154]242        const char *name, *type;
[247]243        intptr_t offset;
[154]244        void *fun1; ///< procedure or get
245        void *fun2; ///< set
246        const char *help;
[109]247};
248
[154]249struct ParamEntryConstructor : public ParamEntry
[109]250{
251public:
[478]252        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]253        {
254                id = _id; group = _group; flags = _flags; name = _name; type = _type; offset = _offset; fun1 = _fun1; fun2 = _fun2; help = _help;
255        }
[109]256};
257
[154]258class SimpleAbstractParam : public virtual ParamInterface
[109]259{
260protected:
[154]261        virtual void *getTarget(int i);
262        const char* myname;
[950]263        const char* mylongname;
[154]264        bool dontcheckchanges;
[109]265
266public:
[154]267        void *object;
[109]268
[154]269        const char* getName() { return myname; }
[950]270        const char* getLongName() { return mylongname ? mylongname : myname; }
271
[154]272        void setName(const char* n) { myname = n; }
[950]273        void setLongName(const char* n) { mylongname = n; }
[109]274
[154]275        /**
276                @param t ParamEntry table
277                @param o controlled object
278                @param n Param's name
279                */
[950]280        SimpleAbstractParam(void* o = 0, const char*n = 0) :myname(n), mylongname(NULL), dontcheckchanges(0), object(o) {}
[154]281        void setDontCheckChanges(bool x) { dontcheckchanges = x; }
[109]282
[154]283        void select(void *o) { object = o; }
284        void* getSelected() { return object; }
[109]285
[253]286        virtual ParamEntry *entry(int i) = 0;
[154]287        const char *id(int i) { return (i >= getPropCount()) ? 0 : entry(i)->id; }
288        const char *name(int i) { return entry(i)->name; }
289        const char *type(int i) { return entry(i)->type; }
290        const char *help(int i) { return entry(i)->help; }
291        int flags(int i) { return entry(i)->flags; }
292        int group(int i) { return entry(i)->group; }
293        void call(int i, ExtValue* args, ExtValue *ret);
[109]294
[154]295        SString getString(int);
[247]296        paInt getInt(int);
[154]297        double getDouble(int);
298        ExtObject getObject(int);
299        ExtValue getExtValue(int);
[109]300
[805]301        void messageOnExceedRange(int i, int setflags, ExtValue& valuetoset);
[247]302        int setInt(int, paInt);
[154]303        int setDouble(int, double);
304        int setString(int, const SString &);
305        int setObject(int, const ExtObject &);
306        int setExtValue(int, const ExtValue &);
[109]307
[154]308        int isequal(int i, void* defdata);
[720]309        void saveSingleLine(SString&, void *defdata, bool addcr = true, bool all_names = true);
[109]310
[278]311        virtual void setDefault();
312        virtual void setDefault(int i);
[230]313
[483]314#ifdef _DEBUG
[230]315        void sanityCheck(int i);
316#endif
[109]317};
318
[154]319class Param : public SimpleAbstractParam
[109]320{
321protected:
[154]322        ParamEntry *entry(int i) { return tab + tab[0].group + i; }
[109]323public:
[154]324        ParamEntry *tab;
325        /**
326                @param t ParamEntry table
327                @param o controlled object
328                @param n Param's name
329                */
[109]330
[154]331        Param(ParamEntry *t = 0, void* o = 0, const char*n = 0) :SimpleAbstractParam(o, n), tab(t)
332        {
333                if (!n&&tab) myname = tab[0].name;
334        }
[109]335
[154]336        Param(const Param& p) :SimpleAbstractParam(p.object, p.myname), tab(p.tab) {}
337        void operator=(const Param&p) { object = p.object; myname = p.myname; tab = p.tab; }
[109]338
[154]339        const char* getDescription() { return tab[0].type; }
[950]340        const char* getLongName() { return tab[0].help ? tab[0].help : SimpleAbstractParam::getLongName(); }
[109]341
[154]342        int getGroupCount() { return tab[0].group; }
343        int getPropCount() { return tab[0].flags; }
344        const char *grname(int i) { return (i < getGroupCount()) ? tab[i].id : 0; }
345        int grmember(int, int);
346        void setParamTab(ParamEntry *t, int dontupdatename = 0) { tab = t; if ((!dontupdatename) && tab) myname = tab[0].name; }
347        ParamEntry *getParamTab() const { return tab; }
[109]348};
349
350extern ParamEntry empty_paramtab[];
351
352#endif
Note: See TracBrowser for help on using the repository browser.