From 7d8972de8dafbdac3a0cf95d9613dd2ec4f1307f Mon Sep 17 00:00:00 2001 From: zolliker Date: Mon, 5 Sep 2005 08:25:20 +0000 Subject: [PATCH] - added pardef --- pardef.h | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 pardef.h diff --git a/pardef.h b/pardef.h new file mode 100644 index 0000000..cdcfd36 --- /dev/null +++ b/pardef.h @@ -0,0 +1,234 @@ +/*--------------------------------------------------------------------------- +pardef.h + +my way to define and handle objects and its parameters + +Markus Zolliker, March 2005 +---------------------------------------------------------------------------- +*/ + +#ifndef PARDEF_H +#define PARDEF_H + +#include "sics.h" +#include "logger.h" + +int ParPrintf(void *object, int iOut, const char *fmt, ...); + +typedef enum { PAR_ALWAYS_READY, PAR_NOT_READY, PAR_NOW_READY } ReadyState; + +typedef struct ParInfo { + struct ParInfo *next; + char *name; + Logger *log; + int saveIt; /* bool */ + int saveLog; /* bool */ + ReadyState state; /* enum ReadyState */ + int sugarStatus; /* =1: sugar object made */ +} ParInfo; + +#define PAR_LEVELS 8 +#define PAR_NAN -999999. +#define PAR_LNAN -999999 + +typedef void (*ParDef)(void *); + +typedef struct ParClass { + char *name; + size_t size; + int level; + struct ParClass *base[PAR_LEVELS]; +} ParClass; + +typedef struct ParData { + pObjectDescriptor desc; /* SICS object descriptor */ + ParClass *class; /* class descriptor */ + ParDef pardef; + char *creationCmd; /* the command to create this object */ + char *name; /* object name */ + time_t logTime; /* last logging time */ + int logPending; + int period; /* logging interval */ + ParInfo *infoList; /* list for additional info on parameters */ + pICallBack pCall; /* sics callback function */ + SCStore conn; /* last connection with user or manager priv. */ + int verbose; /* verbosity, mainly for tests */ +} ParData; + +/* + Implementation of an object: + + object data: + + The first member of the objects data struct must be a plain ParData (not a pointer) + The ParData member may also be the first member of an nested struct, the only + condition is, that it is at offset 0, i.e. a cast to ParData is always valid. + + typedef struct { + ParData p; + // object members: + float value; + char *text; + FooSpecialObject *obj; + } FooData; + + a static class object of type ParClass has to be declared and initialized + with its name and the object data size: + + static ParClass fooClass {"Foo", sizeof(FooData) } + + at initialisation, or at least before it is used first, it has + to be initialized with + + ParMakeClass(&fooClass, NULL); + + (NULL as the second argument makes ParData to be the base class, + if more levels of inheritance are used, use the base class as argument) + + parameter definition: + + The parameters definition is within the pardef function, for example + + void FooPardef(void *object) { + FooData *data = ParCast(&fooClass, object); + + ParName("value"); ParFmt("%.3f"); ParFloat(&data->value, 0.0); + ParName("text"); ParList(NULL); ParStr(&data->text, ""); + if (ParAction() == PAR_KILL) { + if (data->obj) { + FreeSpecialObject(data->obj); + data->obj = NULL; + } + } + } + + The first line in FooPardef is a cast converting the anonymous object to + your data type. ParCast does some validity checks, which are strongly recommended. + + The next two lines are parameters definitions. A parameter definition starts always + with ParName, followed by some options, and ends with the parameter type definition. + + FooPardef is called for all operations on data, so do not insert long calculations + inside it. For special actions, code may be inserted for something like killing + members. + + All char arguments in the following functions might be referred even after + the function returned. If they are not a constant, it is the callers responsibility + to make its contents valid whenever they are used. + +*/ + void ParName(char *name); /* name must not change during lifetime of the object, + normally it is a constant */ +/* + Options (to be called before parameter type definitions): +*/ + void ParFmt(char *fmt); /* format (float only) */ + void ParAccess(int access); /* access rights (default usInternal = read only) */ + void ParSave(int save); /* save on status file + (default: 0 for ParAccess(usInternal), 1 for others) */ + void ParEnum(char *list[]); /* automatic keyword to number conversion */ + void ParList(char *group); /* ParList may be repeated with several group arguments, + to appear on a list subcommand. Give NULL + for std list. */ + void ParTail(char *tail); /* comment to appear after list entry (e.g. units). + If ParList is not called, ParTail will force to appear + in standard list. */ + void ParLogAs(char *name); /* switch log on and give sugar name (NULL for default name) */ + +/* + Parameter type definitions: + select one out of these per parameter, with + a pointer to the corresponding object member as argument +*/ + void ParFloat(float *value, float defValue); + void ParInt(int *value, int defValue); + void ParFixedStr(char *value, int maxsize, char *defValue); /* fixed size string */ + void ParStr(char **value, char *defValue); /* dynamic string */ + + typedef int (*ParCommand)(void *object, void *userarg, int argc, char *argv[]); + /* command function to be executed */ + int ParCmd(ParCommand cmd, void *userarg); /* command, returns 0 when not executed + else return value from cmd, default access + is usUser */ +/* + If code has to be executed for a specific to a parameter and and action, + ParActionIs (see below) may be used. Typical usage: + + if (ParActionIs(PAR_SET) > 0) { + things to do when parameter has changed + } + + A parameter definition finishes after these calls. + + There are predefined actions which are all handled by this module: +*/ + typedef enum { + PAR_NOOP, /* no operation */ + PAR_INIT, /* initialize object (called during initialisation) */ + PAR_SHOW, /* show single parameter (1) */ + PAR_SET, /* set a single parameter (1) */ + PAR_GET, /* get a single float parameter (1) */ + PAR_LIST, /* list all or a group of parameters (2) */ + PAR_LOG, /* log all parameters activated for logging (2) */ + PAR_LOGSWITCH, /* (de)activate single parameter for logging (1) */ + PAR_SAVE, /* save all parameters activated for saving (2) */ + PAR_SAVESWITCH,/* (de)activate single parameter for saving (1) */ + PAR_KILL /* kill content (called before remove) */ + } ParAct; + + int ParActionIs(ParAct action); + /* to be called inside the pardef function. + returns 0, when the action is not active. + returns 1 or -1 when the action is active. + the return value -1 is used under following conditions: + - for actions marked with (1), when the name does not match + (for this case ParActionIs may be called between the call to ParName + for the parameter referred and before the next call to ParName) + - for actions marked with (2), when the parameter was not used + (for this case ParActionIs must be called after the parameter definition + for the parameter referred and before the next call to ParName) + */ + + void ParStdDef(void); /* handle the standard parameters "verbose" and "driver" */ + void *ParObject(void); /* get the current object (to be called by functions + called inside pardef, when the object is not in the argument + list */ + void ParLogReady(ReadyState state); /* set ready state for log */ + +/* + functions to be used outside pardef: +*/ + int ParLog(void *object); /* log all parameters of this object, but only if not + already logged in the interval, returns >= 0 when done, + or < 0, when not done (execute PAR_LOG action) */ + void ParKill(void *object); /* free the object (execute PAR_KILL action) */ + void ParGetFloat(SConnection *con, void *object, char *name, float *value); + /* get a float parameter (execute PAR_GET action) */ + void *ParCast(ParClass *class, void *object); + /* returns object, if the object has type "class" or + inherits type "class", returns NULL otherwise */ + void *ParCheck(ParClass *class, void *object) ; + /* dumps core when object has not or does not inherit "class" */ + void *ParMakeClass(ParClass *class, ParClass *base) ; + /* initialize "class". base defines its base class or NULL + when ParData is its direct base class */ + + void *ParMake(SConnection *con, char *name, ParClass *class, ParDef pardef, char *creationCmd); + /* make an object of class "class", and declare its + pardef function. Add it as command "name" to SICS, + and execute pardef with PAR_INIT action. + When creationCmd is not NULL, it is saved in order to + recreate the object. + + The SICS system will execute: + - PAR_SHOW, PAR_SET, PAR_LIST, PAR_LOGSWITCH + from the corresponding command + - PAR_LOG after a PAR_SET action + - PAR_SAVE after a parameter change on any SICS command + - PAR_KILL on RemoveCommand */ + + char *ParArg2Text(int argc, char *argv[], char *res, int maxsize); + /* convert args to text. if res==NULL, the result is + allocated and maxsize is ignored */ +#endif +