Various improvements
* Added new lset::openLink() method, called on JSON_LINKs only * Cleanup in dbJLink.c to prevent memory leaks. * Removed jlif::start_parse() method. * Renamed jlif::end_parse() to end_child, which will be called on the parent link when a child link has succesfully finished parsing.
This commit is contained in:
@@ -714,7 +714,7 @@ static void scanLinkOnce(dbCommon *prec, caLink *pca) {
|
||||
|
||||
static lset dbCa_lset = {
|
||||
0, 1, /* not Constant, Volatile */
|
||||
dbCaRemoveLink,
|
||||
NULL, dbCaRemoveLink,
|
||||
NULL, NULL, NULL,
|
||||
isConnected,
|
||||
getDBFtype, getElements,
|
||||
|
||||
@@ -124,7 +124,7 @@ static long dbConstGetValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
|
||||
static lset dbConst_lset = {
|
||||
1, 0, /* Constant, not Volatile */
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
dbConstLoadScalar,
|
||||
dbConstLoadLS,
|
||||
dbConstLoadArray,
|
||||
|
||||
@@ -337,7 +337,7 @@ static void dbDbScanFwdLink(struct link *plink)
|
||||
|
||||
static lset dbDb_lset = {
|
||||
0, 0, /* not Constant, not Volatile */
|
||||
dbDbRemoveLink,
|
||||
NULL, dbDbRemoveLink,
|
||||
NULL, NULL, NULL,
|
||||
dbDbIsConnected,
|
||||
dbDbGetDBFtype, dbDbGetElements,
|
||||
|
||||
@@ -43,17 +43,13 @@ typedef struct parseContext {
|
||||
unsigned key_is_link:1;
|
||||
} parseContext;
|
||||
|
||||
#define CALLIF(routine) !routine ? jlif_stop : routine
|
||||
#define CALL_OR_STOP(routine) !(routine) ? jlif_stop : (routine)
|
||||
|
||||
|
||||
static int dbjl_value(parseContext *parser, jlif_result result) {
|
||||
static int dbjl_return(parseContext *parser, jlif_result result) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_value(%s@%p, %d)\n", pjlink->pif->name, pjlink, result);
|
||||
printf(" jsonDepth=%d, linkDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, parser->linkDepth, parser->key_is_link);
|
||||
}
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_return(%s@%p, %d)\n", pjlink->pif->name, pjlink, result);
|
||||
|
||||
if (result == jlif_stop && pjlink) {
|
||||
jlink *parent;
|
||||
@@ -65,19 +61,35 @@ static int dbjl_value(parseContext *parser, jlif_result result) {
|
||||
pjlink->pif->free_jlink(pjlink);
|
||||
}
|
||||
|
||||
if (result == jlif_stop || parser->linkDepth > 0)
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int dbjl_value(parseContext *parser, jlif_result result) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
jlink *parent;
|
||||
|
||||
IFDEBUG(10) {
|
||||
printf("dbjl_value(%s@%p, %d)\n", pjlink->pif->name, pjlink, result);
|
||||
printf(" jsonDepth=%d, linkDepth=%d, key_is_link=%d\n",
|
||||
parser->jsonDepth, parser->linkDepth, parser->key_is_link);
|
||||
}
|
||||
|
||||
if (result == jlif_stop || parser->linkDepth > 0)
|
||||
return dbjl_return(parser, result);
|
||||
|
||||
parent = pjlink->parent;
|
||||
if (!parent)
|
||||
parser->product = pjlink;
|
||||
else if (parent->pif->end_child)
|
||||
parent->pif->end_child(parent, pjlink);
|
||||
|
||||
parser->product = pjlink;
|
||||
parser->key_is_link = 0;
|
||||
if (pjlink)
|
||||
parser->pjlink = pjlink->parent;
|
||||
parser->pjlink = parent;
|
||||
|
||||
IFDEBUG(8)
|
||||
printf("dbjl_value: product = %p\n", pjlink);
|
||||
|
||||
return pjlink->pif->end_parse ? pjlink->pif->end_parse(pjlink)
|
||||
: jlif_continue;
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static int dbjl_null(void *ctx) {
|
||||
@@ -88,7 +100,8 @@ static int dbjl_null(void *ctx) {
|
||||
printf("dbjl_null(%s@%p)\n", pjlink->pif->name, pjlink);
|
||||
|
||||
assert(pjlink);
|
||||
return dbjl_value(parser, CALLIF(pjlink->pif->parse_null)(pjlink));
|
||||
return dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_null)(pjlink));
|
||||
}
|
||||
|
||||
static int dbjl_boolean(void *ctx, int val) {
|
||||
@@ -96,7 +109,8 @@ static int dbjl_boolean(void *ctx, int val) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
|
||||
assert(pjlink);
|
||||
return dbjl_value(parser, CALLIF(pjlink->pif->parse_boolean)(pjlink, val));
|
||||
return dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_boolean)(pjlink, val));
|
||||
}
|
||||
|
||||
static int dbjl_integer(void *ctx, long num) {
|
||||
@@ -104,10 +118,12 @@ static int dbjl_integer(void *ctx, long num) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_integer(%s@%p, %ld)\n", pjlink->pif->name, pjlink, num);
|
||||
printf("dbjl_integer(%s@%p, %ld)\n",
|
||||
pjlink->pif->name, pjlink, num);
|
||||
|
||||
assert(pjlink);
|
||||
return dbjl_value(parser, CALLIF(pjlink->pif->parse_integer)(pjlink, num));
|
||||
return dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_integer)(pjlink, num));
|
||||
}
|
||||
|
||||
static int dbjl_double(void *ctx, double num) {
|
||||
@@ -115,10 +131,12 @@ static int dbjl_double(void *ctx, double num) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_double(%s@%p, %g)\n", pjlink->pif->name, pjlink, num);
|
||||
printf("dbjl_double(%s@%p, %g)\n",
|
||||
pjlink->pif->name, pjlink, num);
|
||||
|
||||
assert(pjlink);
|
||||
return dbjl_value(parser, CALLIF(pjlink->pif->parse_double)(pjlink, num));
|
||||
return dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_double)(pjlink, num));
|
||||
}
|
||||
|
||||
static int dbjl_string(void *ctx, const unsigned char *val, unsigned len) {
|
||||
@@ -126,11 +144,12 @@ static int dbjl_string(void *ctx, const unsigned char *val, unsigned len) {
|
||||
jlink *pjlink = parser->pjlink;
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_string(%s@%p, \"%.*s\")\n", pjlink->pif->name, pjlink, len, val);
|
||||
printf("dbjl_string(%s@%p, \"%.*s\")\n",
|
||||
pjlink->pif->name, pjlink, len, val);
|
||||
|
||||
assert(pjlink);
|
||||
return dbjl_value(parser,
|
||||
CALLIF(pjlink->pif->parse_string)(pjlink, (const char *) val, len));
|
||||
CALL_OR_STOP(pjlink->pif->parse_string)(pjlink, (const char *) val, len));
|
||||
}
|
||||
|
||||
static int dbjl_start_map(void *ctx) {
|
||||
@@ -159,8 +178,9 @@ static int dbjl_start_map(void *ctx) {
|
||||
|
||||
parser->linkDepth++;
|
||||
parser->jsonDepth++;
|
||||
result = CALLIF(pjlink->pif->parse_start_map)(pjlink);
|
||||
if (result == jlif_key_embed_link) {
|
||||
|
||||
result = CALL_OR_STOP(pjlink->pif->parse_start_map)(pjlink);
|
||||
if (result == jlif_key_child_link) {
|
||||
parser->key_is_link = 1;
|
||||
result = jlif_continue;
|
||||
}
|
||||
@@ -168,7 +188,7 @@ static int dbjl_start_map(void *ctx) {
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_start_map -> %d\n", result);
|
||||
|
||||
return result;
|
||||
return dbjl_return(parser, result);
|
||||
}
|
||||
|
||||
static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) {
|
||||
@@ -178,13 +198,12 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) {
|
||||
size_t lnlen = len;
|
||||
linkSup *linkSup;
|
||||
jlif *pjlif;
|
||||
jlif_result result;
|
||||
|
||||
if (!parser->key_is_link) {
|
||||
if (!pjlink) {
|
||||
errlogPrintf("dbJLinkInit: Illegal second link key '%.*s'\n",
|
||||
len, key);
|
||||
return jlif_stop;
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
|
||||
IFDEBUG(10) {
|
||||
@@ -195,7 +214,9 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) {
|
||||
}
|
||||
|
||||
assert(parser->linkDepth > 0);
|
||||
return CALLIF(pjlink->pif->parse_map_key)(pjlink, (const char *) key, len);
|
||||
return dbjl_return(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_map_key)(pjlink,
|
||||
(const char *) key, len));
|
||||
}
|
||||
|
||||
IFDEBUG(10) {
|
||||
@@ -213,44 +234,35 @@ static int dbjl_map_key(void *ctx, const unsigned char *key, unsigned len) {
|
||||
if (!linkSup) {
|
||||
errlogPrintf("dbJLinkInit: Link type '%s' not found\n",
|
||||
link_name);
|
||||
return jlif_stop;
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
|
||||
pjlif = linkSup->pjlif;
|
||||
if (!pjlif) {
|
||||
errlogPrintf("dbJLinkInit: Support for Link type '%s' not loaded\n",
|
||||
link_name);
|
||||
return jlif_stop;
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
|
||||
pjlink = pjlif->alloc_jlink(parser->dbfType);
|
||||
if (!pjlink) {
|
||||
errlogPrintf("dbJLinkInit: Out of memory\n");
|
||||
return jlif_stop;
|
||||
return dbjl_return(parser, jlif_stop);
|
||||
}
|
||||
pjlink->pif = pjlif;
|
||||
|
||||
if (parser->pjlink) {
|
||||
/* This is an embedded link */
|
||||
/* We're starting a child link, save its parent */
|
||||
pjlink->parent = parser->pjlink;
|
||||
}
|
||||
parser->pjlink = pjlink;
|
||||
|
||||
result = pjlif->start_parse ? pjlif->start_parse(pjlink) : jlif_continue;
|
||||
if (result == jlif_continue) {
|
||||
parser->pjlink = pjlink;
|
||||
IFDEBUG(8)
|
||||
printf("dbjl_map_key: New %s@%p\n", pjlink->pif->name, pjlink);
|
||||
|
||||
IFDEBUG(8)
|
||||
printf("dbjl_map_key: New %s@%p\n", pjlink->pif->name, pjlink);
|
||||
}
|
||||
else {
|
||||
pjlif->free_jlink(pjlink);
|
||||
}
|
||||
// FIXME Ensure link map has only one link key...
|
||||
// FIXME How to ensure a link map has only one key/value pair?
|
||||
|
||||
IFDEBUG(10)
|
||||
printf("dbjl_map_key -> %d\n", result);
|
||||
|
||||
return result;
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static int dbjl_end_map(void *ctx) {
|
||||
@@ -269,7 +281,8 @@ static int dbjl_end_map(void *ctx) {
|
||||
if (parser->linkDepth > 0) {
|
||||
parser->linkDepth--;
|
||||
|
||||
result = dbjl_value(parser, CALLIF(pjlink->pif->parse_end_map)(pjlink));
|
||||
result = dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_end_map)(pjlink));
|
||||
}
|
||||
else {
|
||||
result = jlif_continue;
|
||||
@@ -290,7 +303,9 @@ static int dbjl_start_array(void *ctx) {
|
||||
assert(pjlink);
|
||||
parser->linkDepth++;
|
||||
parser->jsonDepth++;
|
||||
return CALLIF(pjlink->pif->parse_start_array)(pjlink);
|
||||
|
||||
return dbjl_return(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_start_array)(pjlink));
|
||||
}
|
||||
|
||||
static int dbjl_end_array(void *ctx) {
|
||||
@@ -306,9 +321,12 @@ static int dbjl_end_array(void *ctx) {
|
||||
assert(pjlink);
|
||||
parser->linkDepth--;
|
||||
parser->jsonDepth--;
|
||||
return dbjl_value(parser, CALLIF(pjlink->pif->parse_end_array)(pjlink));
|
||||
|
||||
return dbjl_value(parser,
|
||||
CALL_OR_STOP(pjlink->pif->parse_end_array)(pjlink));
|
||||
}
|
||||
|
||||
|
||||
static yajl_callbacks dbjl_callbacks = {
|
||||
dbjl_null, dbjl_boolean, dbjl_integer, dbjl_double, NULL, dbjl_string,
|
||||
dbjl_start_map, dbjl_map_key, dbjl_end_map, dbjl_start_array, dbjl_end_array
|
||||
@@ -380,7 +398,8 @@ long dbJLinkInit(struct link *plink)
|
||||
pjlink = plink->value.json.jlink;
|
||||
|
||||
if (pjlink)
|
||||
plink->lset = pjlink->pif->get_lset(pjlink, plink);
|
||||
plink->lset = pjlink->pif->get_lset(pjlink);
|
||||
|
||||
dbLinkOpen(plink);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
jlif_key_stop = jlif_stop,
|
||||
jlif_key_continue = jlif_continue,
|
||||
jlif_key_embed_link
|
||||
jlif_key_child_link
|
||||
} jlif_key_result;
|
||||
|
||||
struct link;
|
||||
@@ -44,7 +44,6 @@ typedef struct jlif {
|
||||
const char *name;
|
||||
jlink* (*alloc_jlink)(short dbfType);
|
||||
void (*free_jlink)(jlink *);
|
||||
jlif_result (*start_parse)(jlink *);
|
||||
jlif_result (*parse_null)(jlink *);
|
||||
jlif_result (*parse_boolean)(jlink *, int val);
|
||||
jlif_result (*parse_integer)(jlink *, long num);
|
||||
@@ -55,8 +54,8 @@ typedef struct jlif {
|
||||
jlif_result (*parse_end_map)(jlink *);
|
||||
jlif_result (*parse_start_array)(jlink *);
|
||||
jlif_result (*parse_end_array)(jlink *);
|
||||
jlif_result (*end_parse)(jlink *);
|
||||
struct lset* (*get_lset)(const jlink *, struct link *);
|
||||
void (*end_child)(jlink *parent, jlink *child);
|
||||
struct lset* (*get_lset)(const jlink *);
|
||||
void (*report)(const jlink *);
|
||||
} jlif;
|
||||
|
||||
|
||||
@@ -160,6 +160,14 @@ void dbAddLink(struct dbLocker *locker, struct link *plink, short dbfType,
|
||||
}
|
||||
}
|
||||
|
||||
void dbLinkOpen(struct link *plink)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
if (plset && plset->openLink)
|
||||
plset->openLink(plink);
|
||||
}
|
||||
|
||||
void dbRemoveLink(struct dbLocker *locker, struct link *plink)
|
||||
{
|
||||
lset *plset = plink->lset;
|
||||
|
||||
@@ -32,6 +32,9 @@ typedef struct lset {
|
||||
const unsigned isConstant:1;
|
||||
const unsigned isVolatile:1;
|
||||
|
||||
/* Activation */
|
||||
void (*openLink)(struct link *plink);
|
||||
|
||||
/* Destructor */
|
||||
void (*removeLink)(struct dbLocker *locker, struct link *plink);
|
||||
|
||||
@@ -76,6 +79,8 @@ typedef struct lset {
|
||||
epicsShareFunc void dbInitLink(struct link *plink, short dbfType);
|
||||
epicsShareFunc void dbAddLink(struct dbLocker *locker, struct link *plink,
|
||||
short dbfType, DBADDR *ptarget);
|
||||
|
||||
epicsShareFunc void dbLinkOpen(struct link *plink);
|
||||
epicsShareFunc void dbRemoveLink(struct dbLocker *locker, struct link *plink);
|
||||
|
||||
epicsShareFunc int dbLinkIsDefined(const struct link *plink); /* 0 or 1 */
|
||||
|
||||
@@ -275,9 +275,9 @@ static jlif_result lnkConst_end_array(jlink *pjlink) {
|
||||
return jlif_continue;
|
||||
}
|
||||
|
||||
static struct lset* lnkConst_get_lset(const jlink *pjlink, struct link *plink) {
|
||||
static struct lset* lnkConst_get_lset(const jlink *pjlink) {
|
||||
IFDEBUG(10)
|
||||
printf("lnkConst_get_lset(const@%p, %p)\n", pjlink, plink);
|
||||
printf("lnkConst_get_lset(const@%p)\n", pjlink);
|
||||
|
||||
return &lnkConst_lset;
|
||||
}
|
||||
@@ -466,7 +466,8 @@ static long lnkConst_getValue(struct link *plink, short dbrType, void *pbuffer,
|
||||
|
||||
static lset lnkConst_lset = {
|
||||
1, 0, /* Constant, not Volatile */
|
||||
NULL, lnkConst_loadScalar, lnkConst_loadLS, lnkConst_loadArray, NULL,
|
||||
NULL, NULL,
|
||||
lnkConst_loadScalar, lnkConst_loadLS, lnkConst_loadArray, NULL,
|
||||
NULL, lnkConst_getNelements, lnkConst_getValue,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
@@ -476,7 +477,7 @@ static lset lnkConst_lset = {
|
||||
};
|
||||
|
||||
static jlif lnkConstIf = {
|
||||
"const", lnkConst_alloc, lnkConst_free, NULL,
|
||||
"const", lnkConst_alloc, lnkConst_free,
|
||||
NULL, lnkConst_boolean, lnkConst_integer, lnkConst_double, lnkConst_string,
|
||||
NULL, NULL, NULL, lnkConst_start_array, lnkConst_end_array,
|
||||
NULL, lnkConst_get_lset, lnkConst_report
|
||||
|
||||
Reference in New Issue
Block a user