Add lset::loadArray and JSON parsing
Replace lset::loadLink with lset::loadScalar, add lset::loadArray Add dbLoadLinkArray() routine to dbLink.h API New dbConvertJSON.h API for use by dbConstLoadArray()
This commit is contained in:
@@ -21,6 +21,7 @@ INC += dbChannel.h
|
||||
INC += dbConstLink.h
|
||||
INC += dbConvert.h
|
||||
INC += dbConvertFast.h
|
||||
INC += dbConvertJSON.h
|
||||
INC += dbDbLink.h
|
||||
INC += dbExtractArray.h
|
||||
INC += dbEvent.h
|
||||
@@ -68,6 +69,7 @@ dbCore_SRCS += dbBkpt.c
|
||||
dbCore_SRCS += dbChannel.c
|
||||
dbCore_SRCS += dbConstLink.c
|
||||
dbCore_SRCS += dbConvert.c
|
||||
dbCore_SRCS += dbConvertJSON.c
|
||||
dbCore_SRCS += dbDbLink.c
|
||||
dbCore_SRCS += dbFastLinkConv.c
|
||||
dbCore_SRCS += dbExtractArray.c
|
||||
|
||||
@@ -709,8 +709,8 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) {
|
||||
}
|
||||
|
||||
static lset dbCa_lset = {
|
||||
NULL,
|
||||
dbCaRemoveLink,
|
||||
NULL, NULL,
|
||||
isConnected,
|
||||
getDBFtype, getElements,
|
||||
dbCaGetLink,
|
||||
|
||||
@@ -12,24 +12,19 @@
|
||||
* Current Author: Andrew Johnson
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "cvtFast.h"
|
||||
#include "dbDefs.h"
|
||||
#include "errlog.h"
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbAddr.h"
|
||||
#include "dbBase.h"
|
||||
#include "dbCommon.h"
|
||||
#include "dbConvertFast.h"
|
||||
#include "dbConvert.h"
|
||||
#include "dbConvertJSON.h"
|
||||
#include "dbFldTypes.h"
|
||||
#include "dbLink.h"
|
||||
#include "link.h"
|
||||
#include "recGbl.h"
|
||||
|
||||
/***************************** Constant Links *****************************/
|
||||
|
||||
@@ -46,14 +41,14 @@ void dbConstAddLink(struct link *plink)
|
||||
plink->lset = &dbConst_lset;
|
||||
}
|
||||
|
||||
static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer)
|
||||
/**************************** Member functions ****************************/
|
||||
|
||||
static long dbConstLoadScalar(struct link *plink, short dbrType, void *pbuffer)
|
||||
{
|
||||
if (!plink->value.constantStr)
|
||||
return S_db_badField;
|
||||
|
||||
plink->lset = &dbConst_lset;
|
||||
|
||||
/* Constant strings are always numeric */
|
||||
/* Constant scalars are always numeric */
|
||||
if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
|
||||
dbrType = DBF_USHORT;
|
||||
|
||||
@@ -61,6 +56,19 @@ static long dbConstLoadLink(struct link *plink, short dbrType, void *pbuffer)
|
||||
(plink->value.constantStr, pbuffer, NULL);
|
||||
}
|
||||
|
||||
static long dbConstLoadArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnReq)
|
||||
{
|
||||
if (!plink->value.constantStr)
|
||||
return S_db_badField;
|
||||
|
||||
/* No support for arrays of choice types */
|
||||
if (dbrType == DBF_MENU || dbrType == DBF_ENUM || dbrType == DBF_DEVICE)
|
||||
return S_db_badField;
|
||||
|
||||
return dbPutConvertJSON(plink->value.constantStr, dbrType, pbuffer, pnReq);
|
||||
}
|
||||
|
||||
static long dbConstGetNelements(const struct link *plink, long *nelements)
|
||||
{
|
||||
*nelements = 0;
|
||||
@@ -76,8 +84,9 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
}
|
||||
|
||||
static lset dbConst_lset = {
|
||||
dbConstLoadLink,
|
||||
NULL,
|
||||
dbConstLoadScalar,
|
||||
dbConstLoadArray,
|
||||
NULL,
|
||||
NULL, dbConstGetNelements,
|
||||
dbConstGetValue,
|
||||
|
||||
164
src/ioc/db/dbConvertJSON.c
Normal file
164
src/ioc/db/dbConvertJSON.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbConvertJSON.c */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dbDefs.h"
|
||||
#include "yajl_alloc.h"
|
||||
#include "yajl_parse.h"
|
||||
|
||||
#define epicsExportSharedSybols
|
||||
#include "dbAccessDefs.h"
|
||||
#include "dbConvertFast.h"
|
||||
|
||||
typedef long (*FASTCONVERT)();
|
||||
|
||||
typedef struct parseContext {
|
||||
int depth;
|
||||
short dbrType;
|
||||
short dbrSize;
|
||||
void *pdest;
|
||||
int elems;
|
||||
} parseContext;
|
||||
|
||||
static int dbcj_null(void *ctx) {
|
||||
return 0; /* Illegal */
|
||||
}
|
||||
|
||||
static int dbcj_boolean(void *ctx, int val) {
|
||||
return 0; /* Illegal */
|
||||
}
|
||||
|
||||
static int dbcj_integer(void *ctx, long num) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
epicsInt32 val32 = num;
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_LONG][parser->dbrType];
|
||||
|
||||
if (parser->elems > 0) {
|
||||
conv(&val32, parser->pdest, NULL);
|
||||
parser->pdest += parser->dbrSize;
|
||||
parser->elems--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dbcj_double(void *ctx, double num) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
FASTCONVERT conv = dbFastPutConvertRoutine[DBF_DOUBLE][parser->dbrType];
|
||||
|
||||
if (parser->elems > 0) {
|
||||
conv(&num, parser->pdest, NULL);
|
||||
parser->pdest += parser->dbrSize;
|
||||
parser->elems--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dbcj_string(void *ctx, const unsigned char *val, unsigned int len) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
char *pdest = parser->pdest;
|
||||
|
||||
/* Not attempting to handle char-array fields here, they need more
|
||||
* metadata about the field than we have available at the moment.
|
||||
*/
|
||||
if (parser->dbrType != DBF_STRING)
|
||||
return 0; /* Illegal */
|
||||
|
||||
if (parser->elems > 0) {
|
||||
if (len > MAX_STRING_SIZE - 1)
|
||||
len = MAX_STRING_SIZE - 1;
|
||||
strncpy(pdest, (const char *) val, len);
|
||||
pdest[len] = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dbcj_start_map(void *ctx) {
|
||||
return 0; /* Illegal */
|
||||
}
|
||||
|
||||
static int dbcj_map_key(void *ctx, const unsigned char *key, unsigned int len) {
|
||||
return 0; /* Illegal */
|
||||
}
|
||||
|
||||
static int dbcj_end_map(void *ctx) {
|
||||
return 0; /* Illegal */
|
||||
}
|
||||
|
||||
static int dbcj_start_array(void *ctx) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
|
||||
parser->depth++;
|
||||
return (parser->depth == 1);
|
||||
}
|
||||
|
||||
static int dbcj_end_array(void *ctx) {
|
||||
parseContext *parser = (parseContext *) ctx;
|
||||
|
||||
parser->depth--;
|
||||
return (parser->depth == 0);
|
||||
}
|
||||
|
||||
|
||||
static yajl_callbacks dbcj_callbacks = {
|
||||
dbcj_null, dbcj_boolean, dbcj_integer, dbcj_double, NULL, dbcj_string,
|
||||
dbcj_start_map, dbcj_map_key, dbcj_end_map,
|
||||
dbcj_start_array, dbcj_end_array
|
||||
};
|
||||
|
||||
static const yajl_parser_config dbcj_config =
|
||||
{ 0, 0 }; /* allowComments = NO, checkUTF8 = NO */
|
||||
|
||||
long dbPutConvertJSON(const char *json, short dbrType,
|
||||
void *pdest, long *pnRequest)
|
||||
{
|
||||
parseContext context, *parser = &context;
|
||||
yajl_alloc_funcs dbcj_alloc;
|
||||
yajl_handle yh;
|
||||
yajl_status ys;
|
||||
size_t jlen = strlen(json);
|
||||
long status;
|
||||
|
||||
parser->depth = 0;
|
||||
parser->dbrType = dbrType;
|
||||
parser->dbrSize = dbValueSize(dbrType);
|
||||
parser->pdest = pdest;
|
||||
parser->elems = *pnRequest;
|
||||
|
||||
yajl_set_default_alloc_funcs(&dbcj_alloc);
|
||||
yh = yajl_alloc(&dbcj_callbacks, &dbcj_config, &dbcj_alloc, parser);
|
||||
if (!yh)
|
||||
return S_db_noMemory;
|
||||
|
||||
ys = yajl_parse(yh, (const unsigned char *) json, (unsigned int) jlen);
|
||||
if (ys == yajl_status_insufficient_data)
|
||||
ys = yajl_parse_complete(yh);
|
||||
|
||||
switch (ys) {
|
||||
case yajl_status_ok:
|
||||
*pnRequest -= parser->elems;
|
||||
status = 0;
|
||||
break;
|
||||
|
||||
case yajl_status_error: {
|
||||
unsigned char *err = yajl_get_error(yh, 1,
|
||||
(const unsigned char *) json, (unsigned int) jlen);
|
||||
fprintf(stderr, "dbPutConvertJSON: %s\n", err);
|
||||
yajl_free_error(yh, err);
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
status = S_db_badField;
|
||||
}
|
||||
|
||||
yajl_free(yh);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
27
src/ioc/db/dbConvertJSON.h
Normal file
27
src/ioc/db/dbConvertJSON.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2016 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* dbConvertJSON.h */
|
||||
|
||||
#ifndef INC_dbConvertJSON_H
|
||||
#define INC_dbConvertJSON_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This name should probably be changed to inclue "array" */
|
||||
epicsShareFunc long dbPutConvertJSON(const char *json, short dbrType,
|
||||
void *pdest, long *psize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* INC_dbConvertJSON_H */
|
||||
|
||||
@@ -98,7 +98,6 @@ static void dbDbRemoveLink(struct dbLocker *locker, struct link *plink)
|
||||
plink->value.pv_link.pvlMask = 0;
|
||||
plink->value.pv_link.lastGetdbrType = 0;
|
||||
plink->type = PV_LINK;
|
||||
plink->lset = NULL;
|
||||
ellDelete(&pdbAddr->precord->bklnk, &plink->value.pv_link.backlinknode);
|
||||
dbLockSetSplit(locker, plink->precord, pdbAddr->precord);
|
||||
free(pdbAddr);
|
||||
@@ -332,8 +331,8 @@ static void dbDbScanFwdLink(struct link *plink)
|
||||
}
|
||||
|
||||
static lset dbDb_lset = {
|
||||
NULL,
|
||||
dbDbRemoveLink,
|
||||
NULL, NULL,
|
||||
dbDbIsConnected,
|
||||
dbDbGetDBFtype, dbDbGetElements,
|
||||
dbDbGetValue,
|
||||
|
||||
@@ -145,8 +145,20 @@ long dbLoadLink(struct link *plink, short dbrType, void *pbuffer)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (plset->loadLink)
|
||||
return plset->loadLink(plink, dbrType, pbuffer);
|
||||
|
||||
if (plset->loadScalar)
|
||||
return plset->loadScalar(plink, dbrType, pbuffer);
|
||||
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
long dbLoadLinkArray(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (plset->loadArray)
|
||||
return plset->loadArray(plink, dbrType, pbuffer, pnRequest);
|
||||
|
||||
return S_db_notFound;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,10 @@ extern "C" {
|
||||
struct dbLocker;
|
||||
|
||||
typedef struct lset {
|
||||
long (*loadLink)(struct link *plink, short dbrType, void *pbuffer);
|
||||
void (*removeLink)(struct dbLocker *locker, struct link *plink);
|
||||
long (*loadScalar)(struct link *plink, short dbrType, void *pbuffer);
|
||||
long (*loadArray)(struct link *plink, short dbrType, void *pbuffer,
|
||||
long *pnRequest);
|
||||
int (*isConnected)(const struct link *plink);
|
||||
int (*getDBFtype)(const struct link *plink);
|
||||
long (*getElements)(const struct link *plink, long *nelements);
|
||||
@@ -53,11 +55,13 @@ typedef struct lset {
|
||||
dbGetAlarm(link, NULL, sevr)
|
||||
|
||||
epicsShareFunc void dbInitLink(struct link *plink, short dbfType);
|
||||
epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType,
|
||||
DBADDR *ptarget);
|
||||
epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink,
|
||||
short dbfType, DBADDR *ptarget);
|
||||
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink);
|
||||
epicsShareFunc long dbLoadLink(struct link *plink, short dbrType,
|
||||
void *pbuffer);
|
||||
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink);
|
||||
epicsShareFunc long dbLoadLinkArray(struct link *, short dbrType, void *pbuffer,
|
||||
long *pnRequest);
|
||||
|
||||
epicsShareFunc long dbGetNelements(const struct link *plink, long *nelements);
|
||||
epicsShareFunc int dbIsLinkConnected(const struct link *plink);
|
||||
|
||||
Reference in New Issue
Block a user