Add basic support and tests for a JSON link address type
This commit is contained in:
@@ -29,6 +29,7 @@ long link_test_noop(void *junk)
|
||||
static dset devxLTest ## LTYPE = {4, NULL, &link_test_init, &link_test_noop, &link_test_noop}; \
|
||||
epicsExportAddress(dset, devxLTest ## LTYPE);
|
||||
|
||||
DEFDSET(JSON_STR)
|
||||
DEFDSET(VME_IO)
|
||||
DEFDSET(CAMAC_IO)
|
||||
DEFDSET(AB_IO)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
device(x, JSON_STR, devxLTestJSON_STR, "Unit Test JSON_STR")
|
||||
device(x, VME_IO, devxLTestVME_IO, "Unit Test VME_IO")
|
||||
device(x, CAMAC_IO, devxLTestCAMAC_IO, "Unit Test CAMAC_IO")
|
||||
device(x, AB_IO, devxLTestAB_IO, "Unit Test AB_IO")
|
||||
|
||||
@@ -60,6 +60,7 @@ static const struct testParseDataT {
|
||||
{"#B11 C12 N13 A14 F15 @cparam", {CAMAC_IO, "cparam", 0, "BCNAF", {11, 12, 13, 14, 15}}},
|
||||
{" #B111 C112 N113 @cparam", {CAMAC_IO, "cparam", 0, "BCN", {111, 112, 113}}},
|
||||
{" @hello world ", {INST_IO, "hello world", 0, "", /*{}*/}},
|
||||
{" {\"x\":{}} ", {JSON_STR, "{\"x\":{}}", 0, "", /*{}*/}},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@@ -239,6 +240,7 @@ typedef struct {
|
||||
} testHWDataT;
|
||||
|
||||
static const testHWDataT testHWData[] = {
|
||||
{"rJSON_STR", JSON_STR, "{\"JSON\":{}}", {0}, "{\"JSON\":{}}"},
|
||||
{"rVME_IO", VME_IO, "#C100 S101 @parm VME_IO", {100, 101}, "parm VME_IO"},
|
||||
{"rCAMAC_IO", CAMAC_IO, "#B11 C12 N13 A14 F15 @parm CAMAC_IO", {11, 12, 13, 14, 15}, "parm CAMAC_IO"},
|
||||
{"rAB_IO", AB_IO, "#L21 A22 C23 S24 @parm AB_IO", {21, 22, 23, 24}, "parm AB_IO"},
|
||||
@@ -255,6 +257,9 @@ static const testHWDataT testHWData[] = {
|
||||
static void testLink(DBLINK *plink, const testHWDataT *td)
|
||||
{
|
||||
switch(td->ltype) {
|
||||
case JSON_STR:
|
||||
testOk1(strcmp(plink->value.json.string, td->parm)==0);
|
||||
break;
|
||||
case VME_IO:
|
||||
testOk1(plink->value.vmeio.card==td->vals[0]);
|
||||
testOk1(plink->value.vmeio.signal==td->vals[1]);
|
||||
@@ -360,6 +365,7 @@ static void testHWInitSet(void)
|
||||
}
|
||||
|
||||
static const testHWDataT testHWData2[] = {
|
||||
{"rJSON_STR", JSON_STR, "{\"json\":{}}", {0}, "{\"json\":{}}"},
|
||||
{"rVME_IO", VME_IO, "#C200 S201 @another VME_IO", {200, 201}, "another VME_IO"},
|
||||
{"rCAMAC_IO", CAMAC_IO, "#B111 C112 N113 A114 F115 @CAMAC_IO", {111, 112, 113, 114, 115}, "CAMAC_IO"},
|
||||
{"rAB_IO", AB_IO, "#L121 A122 C123 S124 @another AB_IO", {121, 122, 123, 124}, "another AB_IO"},
|
||||
@@ -482,9 +488,15 @@ static void testLinkFail(void)
|
||||
/* INST_IO doesn't accept empty string */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rINST_IO.INP", DBR_STRING, "");
|
||||
|
||||
/* INST_IO doesn't accept empty string */
|
||||
/* INST_IO doesn't accept string without @ */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rINST_IO.INP", DBR_STRING, "abc");
|
||||
|
||||
/* JSON_STR doesn't accept empty string */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rJSON_STR.INP", DBR_STRING, "");
|
||||
|
||||
/* JSON_STR doesn't accept string without braces */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rJSON_STR.INP", DBR_STRING, "abc");
|
||||
|
||||
/* syntax errors */
|
||||
testdbPutFieldFail(S_dbLib_badField, "rVME_IO.INP", DBR_STRING, "#S201 C200 @another VME_IO");
|
||||
testdbPutFieldFail(S_dbLib_badField, "rVME_IO.INP", DBR_STRING, "C200 #S201");
|
||||
@@ -504,7 +516,7 @@ static void testLinkFail(void)
|
||||
|
||||
MAIN(dbPutLinkTest)
|
||||
{
|
||||
testPlan(251);
|
||||
testPlan(263);
|
||||
testLinkParse();
|
||||
testLinkFailParse();
|
||||
testCADBSet();
|
||||
|
||||
@@ -3,6 +3,10 @@ record(x, "x2") {}
|
||||
record(x, "x3") {}
|
||||
record(x, "x4") {}
|
||||
|
||||
record(x, "rJSON_STR") {
|
||||
field(DTYP, "Unit Test JSON_STR")
|
||||
field(INP, "{\"JSON\":{}}")
|
||||
}
|
||||
record(x, "rVME_IO") {
|
||||
field(DTYP, "Unit Test VME_IO")
|
||||
field(INP, "#C100 S101 @parm VME_IO")
|
||||
|
||||
@@ -67,6 +67,7 @@ epicsShareDef maplinkType pamaplinkType[LINK_NTYPES] = {
|
||||
{"GPIB_IO",GPIB_IO},
|
||||
{"BITBUS_IO",BITBUS_IO},
|
||||
{"MACRO_LINK",MACRO_LINK},
|
||||
{"JSON_STR",JSON_STR},
|
||||
{"PN_LINK",PN_LINK},
|
||||
{"DB_LINK",DB_LINK},
|
||||
{"CA_LINK",CA_LINK},
|
||||
@@ -121,6 +122,7 @@ void dbFreeLinkContents(struct link *plink)
|
||||
case CONSTANT: free((void *)plink->value.constantStr); break;
|
||||
case MACRO_LINK: free((void *)plink->value.macro_link.macroStr); break;
|
||||
case PV_LINK: free((void *)plink->value.pv_link.pvname); break;
|
||||
case JSON_STR: parm = plink->value.json.string; break;
|
||||
case VME_IO: parm = plink->value.vmeio.parm; break;
|
||||
case CAMAC_IO: parm = plink->value.camacio.parm; break;
|
||||
case AB_IO: parm = plink->value.abio.parm; break;
|
||||
@@ -1918,6 +1920,9 @@ char * dbGetString(DBENTRY *pdbentry)
|
||||
dbMsgCpy(pdbentry, "");
|
||||
}
|
||||
break;
|
||||
case JSON_STR:
|
||||
dbMsgCpy(pdbentry, plink->value.json.string);
|
||||
break;
|
||||
case PN_LINK:
|
||||
dbMsgPrint(pdbentry, "%s%s",
|
||||
plink->value.pv_link.pvname ? plink->value.pv_link.pvname : "",
|
||||
@@ -2169,6 +2174,7 @@ long dbInitRecordLinks(dbRecordType *rtyp, struct dbCommon *prec)
|
||||
*/
|
||||
case CONSTANT: plink->value.constantStr = NULL; break;
|
||||
case PV_LINK: plink->value.pv_link.pvname = callocMustSucceed(1, 1, "init PV_LINK"); break;
|
||||
case JSON_STR: plink->value.json.string = pNullString; break;
|
||||
case VME_IO: plink->value.vmeio.parm = pNullString; break;
|
||||
case CAMAC_IO: plink->value.camacio.parm = pNullString; break;
|
||||
case AB_IO: plink->value.abio.parm = pNullString; break;
|
||||
@@ -2235,6 +2241,12 @@ long dbParseLink(const char *str, short ftype, dbLinkInfo *pinfo)
|
||||
memcpy(pstr, str, len);
|
||||
pstr[len] = '\0';
|
||||
|
||||
/* Check for braces => JSON */
|
||||
if (*str == '{' && str[len-1] == '}') {
|
||||
pinfo->ltype = JSON_STR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for other HW link types */
|
||||
if (*pstr == '#') {
|
||||
int ret;
|
||||
@@ -2336,16 +2348,18 @@ fail:
|
||||
long dbCanSetLink(DBLINK *plink, dbLinkInfo *pinfo, devSup *devsup)
|
||||
{
|
||||
/* consume allocated string pinfo->target on failure */
|
||||
|
||||
int link_type = CONSTANT;
|
||||
if(devsup)
|
||||
|
||||
if (devsup)
|
||||
link_type = devsup->link_type;
|
||||
if(link_type==pinfo->ltype)
|
||||
if (link_type == pinfo->ltype)
|
||||
return 0;
|
||||
switch(pinfo->ltype) {
|
||||
|
||||
switch (pinfo->ltype) {
|
||||
case CONSTANT:
|
||||
case JSON_STR:
|
||||
case PV_LINK:
|
||||
if(link_type==CONSTANT || link_type==PV_LINK)
|
||||
if (link_type == CONSTANT || link_type == PV_LINK)
|
||||
return 0;
|
||||
default:
|
||||
free(pinfo->target);
|
||||
@@ -2373,11 +2387,22 @@ void dbSetLinkPV(DBLINK *plink, dbLinkInfo *pinfo)
|
||||
pinfo->target = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void dbSetLinkJSON(DBLINK *plink, dbLinkInfo *pinfo)
|
||||
{
|
||||
plink->type = JSON_STR;
|
||||
plink->value.json.string = pinfo->target;
|
||||
|
||||
pinfo->target = NULL;
|
||||
}
|
||||
|
||||
static
|
||||
void dbSetLinkHW(DBLINK *plink, dbLinkInfo *pinfo)
|
||||
{
|
||||
|
||||
switch(pinfo->ltype) {
|
||||
case JSON_STR:
|
||||
plink->value.json.string = pinfo->target;
|
||||
break;
|
||||
case INST_IO:
|
||||
plink->value.instio.string = pinfo->target;
|
||||
break;
|
||||
@@ -2456,27 +2481,33 @@ long dbSetLink(DBLINK *plink, dbLinkInfo *pinfo, devSup *devsup)
|
||||
int ret = 0;
|
||||
int link_type = CONSTANT;
|
||||
|
||||
if(devsup)
|
||||
if (devsup)
|
||||
link_type = devsup->link_type;
|
||||
|
||||
if(link_type==CONSTANT || link_type==PV_LINK) {
|
||||
switch(pinfo->ltype) {
|
||||
if (link_type == CONSTANT || link_type == PV_LINK) {
|
||||
switch (pinfo->ltype) {
|
||||
case CONSTANT:
|
||||
dbFreeLinkContents(plink);
|
||||
dbSetLinkConst(plink, pinfo); break;
|
||||
dbSetLinkConst(plink, pinfo);
|
||||
break;
|
||||
case PV_LINK:
|
||||
dbFreeLinkContents(plink);
|
||||
dbSetLinkPV(plink, pinfo); break;
|
||||
dbSetLinkPV(plink, pinfo);
|
||||
break;
|
||||
case JSON_STR:
|
||||
dbFreeLinkContents(plink);
|
||||
dbSetLinkJSON(plink, pinfo);
|
||||
break;
|
||||
default:
|
||||
errlogMessage("Warning: dbSetLink: forgot to test with dbCanSetLink() or logic error");
|
||||
goto fail; /* can't assign HW link */
|
||||
}
|
||||
|
||||
} else if(link_type==pinfo->ltype) {
|
||||
}
|
||||
else if (link_type == pinfo->ltype) {
|
||||
dbFreeLinkContents(plink);
|
||||
dbSetLinkHW(plink, pinfo);
|
||||
|
||||
} else
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -33,7 +33,7 @@ extern "C" {
|
||||
#define GPIB_IO 5
|
||||
#define BITBUS_IO 6
|
||||
#define MACRO_LINK 7
|
||||
|
||||
#define JSON_STR 8
|
||||
#define PN_LINK 9
|
||||
#define DB_LINK 10
|
||||
#define CA_LINK 11
|
||||
@@ -41,7 +41,7 @@ extern "C" {
|
||||
#define BBGPIB_IO 13 /* bitbus -> gpib */
|
||||
#define RF_IO 14
|
||||
#define VXI_IO 15
|
||||
#define LINK_NTYPES 15
|
||||
#define LINK_NTYPES 16
|
||||
typedef struct maplinkType {
|
||||
char *strvalue;
|
||||
int value;
|
||||
@@ -87,6 +87,11 @@ struct pv_link {
|
||||
short lastGetdbrType; /* last dbrType for DB or CA get */
|
||||
};
|
||||
|
||||
struct json_link {
|
||||
char *string;
|
||||
/* ... */
|
||||
};
|
||||
|
||||
/* structure of a VME io channel */
|
||||
struct vmeio {
|
||||
short card;
|
||||
@@ -167,6 +172,7 @@ struct vxiio {
|
||||
union value {
|
||||
char *constantStr; /*constant string*/
|
||||
struct macro_link macro_link; /* link containing macro substitution*/
|
||||
struct json_link json; /* JSON-encoded link */
|
||||
struct pv_link pv_link; /* link to process variable*/
|
||||
struct vmeio vmeio; /* vme io point */
|
||||
struct camacio camacio; /* camac io point */
|
||||
|
||||
@@ -5,6 +5,7 @@ use DBD::Base;
|
||||
my %link_types = (
|
||||
CONSTANT => qr/$RXnum/o,
|
||||
PV_LINK => qr/$RXname \s+ [.NPCAMS ]*/ox,
|
||||
JSON_STR => qr/\{ .* \}/ox,
|
||||
VME_IO => qr/\# (?: \s* [CS] \s* $RXintx)* \s* (?: @ .*)?/ox,
|
||||
CAMAC_IO => qr/\# (?: \s* [BCNAF] \s* $RXintx)* \s* (?: @ .*)?/ox,
|
||||
RF_IO => qr/\# (?: \s* [RMDE] \s* $RXintx)*/ox,
|
||||
|
||||
Reference in New Issue
Block a user