Dirk Zimoch has proposed merging ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0.
Commit message:
Improved channel filter plugin interface
Requested reviews:
EPICS Core Developers (epics-core)
For more details, see:
https://code.launchpad.net/~dirk.zimoch/epics-base/+git/epics-base/+merge/399636
Allow string arguments with arbitrarily long strings.
In addition to the chfPluginArgString argument type which works on fixed size char array members, chfPluginArgStringAlloc works on char* members. It performs the following actions:
* If a chfPluginArgStringAlloc is provided by the user, the char* member is first NULLed, then filled with a dynamically allocated string (which may fail due to memory shortage)
* If the same char* member may be provided multiple times (maybe under different names), the old value is freed before a new value is written.
* When the structure is released (before freePvt is called), the allocated strings are automatically freed and the char* member NULLed.
* If the parameter is optional and not provided my the user, the pointer is left untouched, allowing to initialize the char* member with a static string as a default value.
--
Your team EPICS Core Developers is requested to review the proposed merge of ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0.
diff --git a/modules/database/src/ioc/db/chfPlugin.c b/modules/database/src/ioc/db/chfPlugin.c
index b4ab72c..a15fd35 100644
--- a/modules/database/src/ioc/db/chfPlugin.c
+++ b/modules/database/src/ioc/db/chfPlugin.c
@@ -71,6 +71,7 @@ store_integer_value(const chfPluginArgDef *opt, char *user, epicsInt32 val)
const chfPluginEnumType *emap;
double *dval;
char *sval;
+ char **psval;
int ret;
char buff[22]; /* 2^64 = 1.8e+19, so 20 digits plus sign max */
@@ -105,6 +106,12 @@ store_integer_value(const chfPluginArgDef *opt, char *user, epicsInt32 val)
strncpy(sval, buff, opt->size-1);
sval[opt->size-1]='\0';
break;
+ case chfPluginArgStringAlloc:
+ psval = (char **) (user + opt->dataOffset);
+ sprintf(buff, "%ld", (long)val);
+ free(*psval);
+ *psval = epicsStrDup(buff);
+ break;
case chfPluginArgEnum:
eval = (int*) (user + opt->dataOffset);
for (emap = opt->enums; emap && emap->name; emap++) {
@@ -117,7 +124,7 @@ store_integer_value(const chfPluginArgDef *opt, char *user, epicsInt32 val)
return -1;
}
break;
- case chfPluginArgInvalid:
+ default:
return -1;
}
return 0;
@@ -132,6 +139,7 @@ static int store_boolean_value(const chfPluginArgDef *opt, char *user, int val)
epicsInt32 *ival;
double *dval;
char *sval;
+ char **psval;
#ifdef DEBUG_CHF
printf("Got a boolean for %s (type %d): %d\n",
@@ -163,8 +171,12 @@ static int store_boolean_value(const chfPluginArgDef *opt, char *user, int val)
strncpy(sval, val ? "true" : "false", opt->size - 1);
sval[opt->size - 1] = '\0';
break;
- case chfPluginArgEnum:
- case chfPluginArgInvalid:
+ case chfPluginArgStringAlloc:
+ psval = (char **) (user + opt->dataOffset);
+ free(*psval);
+ *psval = epicsStrDup(val ? "true" : "false");
+ break;
+ default:
return -1;
}
return 0;
@@ -181,6 +193,7 @@ store_double_value(const chfPluginArgDef *opt, void *vuser, double val)
epicsInt32 *ival;
double *dval;
char *sval;
+ char **psval;
int i;
#ifdef DEBUG_CHF
@@ -218,8 +231,12 @@ store_double_value(const chfPluginArgDef *opt, void *vuser, double val)
return -1;
}
break;
- case chfPluginArgEnum:
- case chfPluginArgInvalid:
+ case chfPluginArgStringAlloc:
+ psval = (char **) (user + opt->dataOffset);
+ *psval = realloc(psval, 24);
+ if (*psval) epicsSnprintf(*psval, 24, "%.17g", val);
+ break;
+ default:
return -1;
}
return 0;
@@ -238,6 +255,7 @@ store_string_value(const chfPluginArgDef *opt, char *user, const char *val,
const chfPluginEnumType *emap;
double *dval;
char *sval;
+ char **psval;
char *end;
size_t i;
@@ -247,6 +265,7 @@ store_string_value(const chfPluginArgDef *opt, char *user, const char *val,
#endif
if (!opt->convert && opt->optType != chfPluginArgString &&
+ opt->optType != chfPluginArgStringAlloc &&
opt->optType != chfPluginArgEnum) {
return -1;
}
@@ -280,6 +299,11 @@ store_string_value(const chfPluginArgDef *opt, char *user, const char *val,
strncpy(sval, val, i);
sval[i] = '\0';
break;
+ case chfPluginArgStringAlloc:
+ psval = (char **) (user + opt->dataOffset);
+ free(*psval);
+ *psval = epicsStrnDup(val, len);
+ break;
case chfPluginArgEnum:
eval = (int*) (user + opt->dataOffset);
for (emap = opt->enums; emap && emap->name; emap++) {
@@ -292,7 +316,7 @@ store_string_value(const chfPluginArgDef *opt, char *user, const char *val,
return -1;
}
break;
- case chfPluginArgInvalid:
+ default:
return -1;
}
return 0;
@@ -352,13 +376,30 @@ static parse_result parse_start(chFilter *filter)
return parse_stop;
}
+static void freePvt(chFilter *filter) {
+ chfPlugin *p = (chfPlugin*) filter->plug->puser;
+ chfFilter *f = (chfFilter*) filter->puser;
+ int i;
+
+ /* free all chfPluginArgStringAlloc options we had allocated */
+ for(i = 0; i < p->nopts; i++) {
+ if (p->opts[i].optType == chfPluginArgStringAlloc &&
+ (f->found[i/32] & (1<<(i%32)))) {
+ char **psval = (char **) ((char*) f->puser + p->opts[i].dataOffset);
+ free(*psval);
+ *psval = NULL;
+ }
+ }
+ if (p->pif->freePvt) p->pif->freePvt(f->puser);
+}
+
static void parse_abort(chFilter *filter) {
chfPlugin *p = (chfPlugin*) filter->plug->puser;
chfFilter *f = (chfFilter*) filter->puser;
/* Call the plugin to tell it we're aborting */
if (p->pif->parse_error) p->pif->parse_error(f->puser);
- if (p->pif->freePvt) p->pif->freePvt(f->puser);
+ freePvt(filter);
freeInstanceData(f);
}
@@ -372,7 +413,7 @@ static parse_result parse_end(chFilter *filter)
for(i = 0; i < (p->nopts/32)+1; i++) {
if ((f->found[i] & p->required[i]) != p->required[i]) {
if (p->pif->parse_error) p->pif->parse_error(f->puser);
- if (p->pif->freePvt) p->pif->freePvt(f->puser);
+ freePvt(filter);
freeInstanceData(f);
return parse_stop;
}
@@ -381,7 +422,7 @@ static parse_result parse_end(chFilter *filter)
/* Call the plugin to tell it we're done */
if (p->pif->parse_ok) {
if (p->pif->parse_ok(f->puser)) {
- if (p->pif->freePvt) p->pif->freePvt(f->puser);
+ freePvt(filter);
freeInstanceData(f);
return parse_stop;
}
@@ -486,6 +527,11 @@ parse_map_key(chFilter *filter, const char *key, size_t stringLen)
|| cur->dataOffset == opts[i].dataOffset)
f->found[j/32] |= 1<<(j%32);
}
+ /* NULL all found chfPluginArgStringAlloc options */
+ if (opts[i].optType == chfPluginArgStringAlloc) {
+ char **psval = (char **) ((char*) f->puser + opts[i].dataOffset);
+ *psval = NULL;
+ }
return parse_continue;
}
@@ -546,7 +592,7 @@ static void channel_close(chFilter *filter)
chfFilter *f = (chfFilter*) filter->puser;
if (p->pif->channel_close) p->pif->channel_close(filter->chan, f->puser);
- if (p->pif->freePvt) p->pif->freePvt(f->puser);
+ freePvt(filter);
free(f->found);
free(f); /* FIXME: Use a free-list */
}
@@ -650,7 +696,16 @@ chfPluginRegister(const char* key, const chfPluginIf *pif,
return -1;
}
break;
- case chfPluginArgInvalid:
+ case chfPluginArgStringAlloc:
+ if (cur->size != sizeof(char*)) {
+ /* Catch if someone has given us a something else than a pointer
+ */
+ errlogPrintf("Plugin %s: %d bytes not a pointer type for string %s\n",
+ key, cur->size, cur->name);
+ return -1;
+ }
+ break;
+ default:
errlogPrintf("Plugin %s: storage type for %s is not defined\n",
key, cur->name);
return -1;
diff --git a/modules/database/src/ioc/db/chfPlugin.h b/modules/database/src/ioc/db/chfPlugin.h
index 8fe156f..e3dced0 100644
--- a/modules/database/src/ioc/db/chfPlugin.h
+++ b/modules/database/src/ioc/db/chfPlugin.h
@@ -52,6 +52,7 @@ struct db_field_log;
* epicsInt32 ival2;
* int enumval;
* char strval[20];
+ * char* str;
* char boolval;
* } myStruct;
*
@@ -64,6 +65,7 @@ struct db_field_log;
* chfInt32 (myStruct, ival2, "Second" , 1, 0),
* chfDouble (myStruct, dval, "Double" , 1, 0),
* chfString (myStruct, strval , "String" , 1, 0),
+ * chfStringAlloc(myStruct, str , "String" , 1, 0),
* chfEnum (myStruct, enumval, "Color" , 1, 0, colorEnum),
* chfBoolean (myStruct, boolval, "Bool" , 1, 0),
* chfPluginEnd
@@ -225,7 +227,8 @@ typedef enum chfPluginArg {
chfPluginArgInt32,
chfPluginArgDouble,
chfPluginArgString,
- chfPluginArgEnum
+ chfPluginArgEnum,
+ chfPluginArgStringAlloc
} chfPluginArg;
typedef struct chfPluginEnumType {
@@ -268,6 +271,10 @@ typedef struct chfPluginArgDef {
{Name, chfPluginArgEnum, Req, Conv, 0, 0, 0, \
OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), Enums}
+#define chfStringAlloc(Struct, Member, Name, Req, Conv) \
+ {Name, chfPluginArgStringAlloc, Req, Conv, 0, 0, 0, \
+ OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
+
/* Tagged arguments */
#define chfTagInt32(Struct, Member, Name, Tag, Choice, Req, Conv) \
@@ -290,6 +297,10 @@ typedef struct chfPluginArgDef {
{Name, chfPluginArgEnum, Req, Conv, 1, OFFSET(Struct, Tag), Choice, \
OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), Enums}
+#define chfTagStringAlloc(Struct, Member, Name, Tag, Choice, Req, Conv) \
+ {Name, chfPluginArgStringAlloc, Req, Conv, 1, OFFSET(Struct, Tag), Choice, \
+ OFFSET(Struct, Member), sizeof( ((Struct*)0)->Member ), NULL}
+
#define chfPluginArgEnd {0}
/* Extra output when parsing and converting */
- Replies:
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Navigate by Date:
- Prev:
Build failed: EPICS Base 7 base-7.0-248 AppVeyor via Core-talk
- Next:
Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
<2021>
2022
2023
2024
- Navigate by Thread:
- Prev:
Build failed: EPICS Base 7 base-7.0-248 AppVeyor via Core-talk
- Next:
Re: [Merge] ~dirk.zimoch/epics-base:chfPluginImprovements into epics-base:7.0 Dirk Zimoch via Core-talk
- Index:
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
<2021>
2022
2023
2024
|