From b4dbcf2b1a05f20aa077fec3e5411122c8510c5f Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Fri, 27 Apr 2012 13:21:42 -0400 Subject: [PATCH] Don't parse field modifiers in dbChannelTest() dbChannelDelete() returns void update tests. --- src/ioc/db/dbChannel.c | 103 ++++++++++++-------------------- src/ioc/db/dbChannel.h | 2 +- src/ioc/db/test/dbChannelTest.c | 49 +++++++++------ 3 files changed, 70 insertions(+), 84 deletions(-) diff --git a/src/ioc/db/dbChannel.c b/src/ioc/db/dbChannel.c index 97fe9ec91..a8bb291bb 100644 --- a/src/ioc/db/dbChannel.c +++ b/src/ioc/db/dbChannel.c @@ -211,32 +211,30 @@ static const yajl_callbacks chf_callbacks = static const yajl_parser_config chf_config = { 0, 1 }; /* allowComments = NO , checkUTF8 = YES */ -static long json_validate(const char *json) +static void * chf_malloc(void *ctx, unsigned int sz) { - yajl_handle yh = yajl_alloc(NULL, &chf_config, NULL, NULL); - size_t jlen = strlen(json); - yajl_status ys; - - if (!yh) - return S_db_noMemory; - - ys = yajl_parse(yh, (const unsigned char *) json, jlen); - if (ys == yajl_status_insufficient_data) - ys = yajl_parse_complete(yh); - - yajl_free(yh); - - if (ys == yajl_status_ok) - return 0; - - return S_db_notFound; + return malloc(sz); /* FIXME: free-list */ } -static long chf_parse(dbChannel *chan, const char *json) +static void * chf_realloc(void *ctx, void *ptr, unsigned int sz) +{ + return realloc(ptr, sz); /* FIXME: free-list */ +} + +static void chf_free(void *ctx, void *ptr) +{ + return free(ptr); /* FIXME: free-list */ +} + +static const yajl_alloc_funcs chf_alloc = + { chf_malloc, chf_realloc, chf_free }; + +static long chf_parse(dbChannel *chan, const char **pjson) { parseContext parser = { chan, NULL, 0 }; - yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, NULL, &parser); + yajl_handle yh = yajl_alloc(&chf_callbacks, &chf_config, &chf_alloc, &parser); + const char *json = *pjson; size_t jlen = strlen(json); yajl_status ys; long status; @@ -251,13 +249,14 @@ static long chf_parse(dbChannel *chan, const char *json) switch (ys) { case yajl_status_ok: status = 0; + *pjson += yajl_get_bytes_consumed(yh); break; case yajl_status_error: { unsigned char *err; err = yajl_get_error(yh, 1, (const unsigned char *) json, jlen); - printf("dbChannelFind: %s\n", err); + printf("dbChannelCreate: %s\n", err); yajl_free_error(yh, err); } /* fall through */ default: @@ -267,7 +266,7 @@ static long chf_parse(dbChannel *chan, const char *json) if (parser.filter) { assert(status); parser.filter->fif->parse_abort(parser.filter); - free(parser.filter); + free(parser.filter); /* FIXME: free-list */ } yajl_free(yh); return status; @@ -302,37 +301,9 @@ long dbChannelTest(const char *name) return S_db_notFound; status = pvNameLookup(&dbEntry, &name); - if (status) - goto finish; - /* Test field modifiers */ - while (*name) { - switch (*name) { - case '$': - switch (dbEntry.pflddes->field_type) { - case DBF_STRING: - case DBF_INLINK: - case DBF_OUTLINK: - case DBF_FWDLINK: - break; - default: - status = S_dbLib_fieldNotFound; - goto finish; - } - break; - case '{': - status = json_validate(name); - goto finish; - default: - status = S_dbLib_fieldNotFound; - goto finish; - } - name++; - } - - finish: - dbFinishEntry(&dbEntry); - return status; + dbFinishEntry(&dbEntry); + return status; } /* Stolen from dbAccess.c: */ @@ -372,9 +343,9 @@ dbChannel * dbChannelCreate(const char *name) if (status) goto finish; - // FIXME: Use free-list + /* FIXME: Use free-list */ chan = (dbChannel *) callocMustSucceed(1, sizeof(*chan), "dbChannelCreate"); - chan->name = strdup(name); // FIXME? + chan->name = strdup(name); /* FIXME: free-list */ ellInit(&chan->filters); paddr = &chan->addr; @@ -391,9 +362,8 @@ dbChannel * dbChannelCreate(const char *name) paddr->dbr_field_type = mapDBFToDBR[dbfType]; /* Handle field modifiers */ - while (*pname) { - switch (*pname) { - case '$': + if (*pname) { + if (*pname == '$') { /* Some field types can be accessed as char arrays */ if (dbfType == DBF_STRING) { paddr->no_elements = pflddes->size; @@ -409,15 +379,20 @@ dbChannel * dbChannelCreate(const char *name) status = S_dbLib_fieldNotFound; goto finish; } - break; - case '{': - status = chf_parse(chan, pname); - goto finish; - default: + pname++; + } + + /* JSON may follow a $ */ + if (*pname == '{') { + status = chf_parse(chan, &pname); + if (status) goto finish; + } + + /* Make sure there's nothing else */ + if (*pname) { status = S_dbLib_fieldNotFound; goto finish; } - pname++; } if (paddr->special == SPC_DBADDR) { @@ -533,7 +508,7 @@ void dbChannelFilterShow(dbChannel *chan, int level) } } -long dbChannelDelete(dbChannel *chan) +void dbChannelDelete(dbChannel *chan) { chFilter *filter; diff --git a/src/ioc/db/dbChannel.h b/src/ioc/db/dbChannel.h index 3c5d2e2b3..b42f41410 100644 --- a/src/ioc/db/dbChannel.h +++ b/src/ioc/db/dbChannel.h @@ -102,7 +102,7 @@ epicsShareFunc long dbChannelPutField(dbChannel *chan, short type, const void *pbuffer, long nRequest); epicsShareFunc void dbChannelShow(dbChannel *chan, int level); epicsShareFunc void dbChannelFilterShow(dbChannel *chan, int level); -epicsShareFunc long dbChannelDelete(dbChannel *chan); +epicsShareFunc void dbChannelDelete(dbChannel *chan); epicsShareFunc void dbRegisterFilter(const char *key, const chFilterIf *fif); epicsShareFunc const chFilterIf * dbFindFilter(const char *key, size_t len); diff --git a/src/ioc/db/test/dbChannelTest.c b/src/ioc/db/test/dbChannelTest.c index 58db707c5..50543c038 100644 --- a/src/ioc/db/test/dbChannelTest.c +++ b/src/ioc/db/test/dbChannelTest.c @@ -132,31 +132,42 @@ MAIN(dbChannelTest) { dbChannel *pch; - testPlan(64); + testPlan(67); testOk1(!dbReadDatabase(&pdbbase, "dbChannelTest.dbx", ".:..", NULL)); testOk(!!pdbbase, "pdbbase was set"); r = e = 0; - /* Regular record and field names */ - testOk1(!dbChannelTest("x")); + /* dbChannelTest() checks record and field names */ testOk1(!dbChannelTest("x.NAME")); + testOk1(!dbChannelTest("x.VAL")); + testOk1(!dbChannelTest("x.")); + testOk1(!dbChannelTest("x")); + testOk(dbChannelTest("y"), "Test, nonexistent record"); + testOk(dbChannelTest("x.NOFIELD"), "Test, nonexistent field"); - /* Long string field modifier */ + /* dbChannelTest() allows but ignores field modifiers */ testOk1(!dbChannelTest("x.NAME$")); + testOk1(!dbChannelTest("x.{}")); + testOk1(!dbChannelTest("x.VAL{\"json\":true}")); + + /* dbChannelCreate() accepts field modifiers */ + testOk1(!!(pch = dbChannelCreate("x.{}"))); + if (pch) dbChannelDelete(pch); + testOk1(!!(pch = dbChannelCreate("x.VAL{}"))); + if (pch) dbChannelDelete(pch); testOk1(!!(pch = dbChannelCreate("x.NAME$"))); - testOk1(pch->addr.no_elements > 1); - testOk1(!dbChannelDelete(pch)); + testOk1(pch && pch->addr.no_elements > 1); + if (pch) dbChannelDelete(pch); + testOk1(!!(pch = dbChannelCreate("x.NAME${}"))); + testOk1(pch && pch->addr.no_elements > 1); + if (pch) dbChannelDelete(pch); - /* JSON field modifier validation */ - testOk1(!dbChannelTest("x.{\"json\":true}")); - - /* Ensure bad PVs get rejected */ - testOk(dbChannelTest("y"), "Test nonexistent record"); - testOk(dbChannelCreate("y") == NULL, "Create nonexistent record"); - - testOk1(dbChannelTest("x.{not-json}")); - testOk1(!dbChannelCreate("x.{\"none\":null}")); + /* dbChannelCreate() rejects bad PVs */ + testOk(!dbChannelCreate("y"), "Create, bad record"); + testOk(!dbChannelCreate("x.NOFIELD"), "Create, bad field"); + testOk(!dbChannelCreate("x.{not-json}"), "Create, bad JSON"); + testOk(!dbChannelCreate("x.{\"none\":null}"), "Create, bad filter"); dbRegisterFilter("any", &testIf); @@ -177,7 +188,7 @@ MAIN(dbChannelTest) e = e_start | e_null | e_end; testOk1(!!(pch = dbChannelCreate("x.{\"any\":null}"))); e = e_close; - testOk1(!dbChannelDelete(pch)); + if (pch) dbChannelDelete(pch); dbRegisterFilter("scalar", &testIf); @@ -188,19 +199,19 @@ MAIN(dbChannelTest) dbChannelShow(pch, 0); e = e_close; - testOk1(!dbChannelDelete(pch)); + if (pch) dbChannelDelete(pch); e = e_start | e_start_array | e_boolean | e_integer | e_end_array | e_end; testOk1(!!(pch = dbChannelCreate("x.{\"any\":[true,1]}"))); e = e_close; - testOk1(!dbChannelDelete(pch)); + if (pch) dbChannelDelete(pch); e = e_start | e_start_map | e_map_key | e_double | e_string | e_end_map | e_end; testOk1(!!(pch = dbChannelCreate("x.{\"any\":{\"a\":2.7183,\"b\":\"c\"}}"))); e = e_close; - testOk1(!dbChannelDelete(pch)); + if (pch) dbChannelDelete(pch); /* More event rejection */ r = r_scalar;