Add basic support and tests for a JSON link address type

This commit is contained in:
Andrew Johnson
2016-04-27 20:47:17 -05:00
parent 778aa18c00
commit 13294f80cc
7 changed files with 75 additions and 19 deletions

View File

@@ -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)

View File

@@ -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")

View File

@@ -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();

View File

@@ -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")

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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,