lnkState: Add support for inverting the flag data

Determine the truthiness of put data in its original data type.
Adjust the link documentation to cover these changes.
This commit is contained in:
Andrew Johnson
2017-12-11 23:45:35 -06:00
parent 8ae34ba01d
commit c0d4835e66
2 changed files with 76 additions and 19 deletions

View File

@@ -137,12 +137,18 @@ link(state, lnkStateIf)
=head3 dbState Link C<"state">
A dbState link is one that reads or writes a boolean value from/to a named
global flag as implemented by the dbState facility in C<dbstate.h>.
global flag as implemented by the dbState facility in C<dbstate.h>. The link
type can invert the sense of the dbState flag if desired.
The value of the named flag is read or written at the time of the link I/O
operation. The boolean flag data is represented as a C<DBF_LONG> that can only
hold the values zero or one; putting any non-zero numeric value to a link sets
the boolean flag value, putting a zero value clears it.
operation. When reading a flag, the value returned by the link will be zero or
one converted to the requested data type. When writing to a flag the boolean
value of the data written is determined in the originating data type. All
strings are regarded as true other than C<""> and C<"0"> which are both false.
A link can be configured to invert the sense of the flag data by putting an
exclamation mark C<!> before the first character of the flag's name in the link
address.
These dbState flags can be accessed from the IOC Shell with various dbState
commands, and are also used by the C<"sync"> Channel-Access server-side filter
@@ -150,11 +156,14 @@ mechanism.
=head4 Parameters
The link address must be a string providing the name of the dbState object,
which will be created when the link is initialized if it doesn't already exist.
The link address must be a string providing the name of the dbState object, with
an optional leading C<!> charater to indicate the flag's value should be
inverted. The dbState object will be created when the link is initialized if it
doesn't already exist.
=head4 Example
=head4 Examples
{state:"redBeam"}
{state:"!simEnable"}
=cut

View File

@@ -40,7 +40,8 @@ typedef long (*FASTCONVERT)();
typedef struct state_link {
jlink jlink; /* embedded object */
char *name;
int val;
short val;
short invert;
dbStateId state;
} state_link;
@@ -58,6 +59,7 @@ static jlink* lnkState_alloc(short dbfType)
slink->name = NULL;
slink->state = NULL;
slink->invert = 0;
slink->val = 0;
IFDEBUG(10)
@@ -84,6 +86,11 @@ static jlif_result lnkState_string(jlink *pjlink, const char *val, size_t len)
IFDEBUG(10)
printf("lnkState_string(state@%p, \"%.*s\")\n", slink, (int) len, val);
if (len > 1 && val[0] == '!') {
slink->invert = 1;
val++; len--;
}
slink->name = epicsStrnDup(val, len);
return jlif_continue;
}
@@ -105,8 +112,8 @@ static void lnkState_report(const jlink *pjlink, int level, int indent)
IFDEBUG(10)
printf("lnkState_report(state@%p)\n", slink);
printf("%*s'state': \"%s\" = %d\n", indent, "",
slink->name, slink->val);
printf("%*s'state': \"%s\" = %s%s\n", indent, "",
slink->name, slink->invert ? "! " : "", slink->val ? "TRUE" : "FALSE");
}
/*************************** lset Routines **************************/
@@ -155,7 +162,7 @@ static int lnkState_getDBFtype(const struct link *plink)
IFDEBUG(10)
printf("lnkState_getDBFtype(state@%p)\n", slink);
return DBF_LONG;
return DBF_SHORT;
}
static long lnkState_getElements(const struct link *plink, long *nelements)
@@ -177,13 +184,15 @@ static long lnkState_getValue(struct link *plink, short dbrType, void *pbuffer,
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
long status;
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_LONG][dbrType];
short flag;
FASTCONVERT conv = dbFastPutConvertRoutine[DBR_SHORT][dbrType];
IFDEBUG(10)
printf("lnkState_getValue(state@%p, %d, ...)\n",
slink, dbrType);
slink->val = dbStateGet(slink->state);
flag = dbStateGet(slink->state);
slink->val = slink->invert ^ flag;
status = conv(&slink->val, pbuffer, NULL);
return status;
@@ -194,20 +203,59 @@ static long lnkState_putValue(struct link *plink, short dbrType,
{
state_link *slink = CONTAINER(plink->value.json.jlink,
struct state_link, jlink);
long status;
FASTCONVERT conv = dbFastPutConvertRoutine[dbrType][DBR_LONG];
short val;
const char *pstr;
IFDEBUG(10)
printf("lnkState_getValue(state@%p, %d, ...)\n",
printf("lnkState_putValue(state@%p, %d, ...)\n",
slink, dbrType);
if (nRequest == 0)
return 0;
status = conv(pbuffer, &slink->val, NULL);
(slink->val ? dbStateSet : dbStateClear)(slink->state);
switch(dbrType) {
case DBR_CHAR:
case DBR_UCHAR:
val = !! *(const epicsInt8 *) pbuffer;
break;
return status;
case DBR_SHORT:
case DBR_USHORT:
val = !! *(const epicsInt16 *) pbuffer;
break;
case DBR_LONG:
case DBR_ULONG:
val = !! *(const epicsInt32 *) pbuffer;
break;
case DBR_INT64:
case DBR_UINT64:
val = !! *(const epicsInt64 *) pbuffer;
break;
case DBR_FLOAT:
val = !! *(const epicsFloat32 *) pbuffer;
break;
case DBR_DOUBLE:
val = !! *(const epicsFloat64 *) pbuffer;
break;
case DBR_STRING: /* Only "" and "0" are FALSE */
pstr = (const char *) pbuffer;
val = (pstr[0] != 0) && ((pstr[0] != '0') || (pstr[1] != 0));
break;
default:
return S_db_badDbrtype;
}
slink->val = val;
val ^= slink->invert;
(val ? dbStateSet : dbStateClear)(slink->state);
return 0;
}
/************************* Interface Tables *************************/