Long string support:

In dbStatic, split record and field search to make parsing easier.
  In dbAccess, '$' field name suffix makes field an array of DBF_CHAR.
This commit is contained in:
Andrew Johnson
2009-03-25 23:02:28 +00:00
parent 547e9bcfea
commit ed4a2972d6
3 changed files with 213 additions and 147 deletions
+63 -40
View File
@@ -652,30 +652,51 @@ long epicsShareAPI dbNameToAddr(const char *pname, DBADDR *paddr)
dbFldDes *pflddes;
struct rset *prset;
long status = 0;
long no_elements = 1;
short dbfType, dbrType;
if (!pname || !*pname || !pdbbase)
return S_db_notFound;
dbInitEntry(pdbbase, &dbEntry);
status = dbFindRecord(&dbEntry, pname);
if (!status && !dbEntry.pfield)
status = dbFindField(&dbEntry, "VAL");
if (status) {
dbFinishEntry(&dbEntry);
return status;
}
status = dbFindRecordPart(&dbEntry, &pname);
if (status) goto finish;
if (*pname == '.') ++pname;
status = dbFindFieldPart(&dbEntry, &pname);
if (status == S_dbLib_fieldNotFound)
status = dbGetAttributePart(&dbEntry, &pname);
if (status) goto finish;
paddr->precord = dbEntry.precnode->precord;
paddr->pfield = dbEntry.pfield;
pflddes = dbEntry.pflddes;
dbFinishEntry(&dbEntry);
paddr->pfldDes = pflddes;
paddr->field_type = pflddes->field_type;
paddr->dbr_field_type = mapDBFToDBR[pflddes->field_type];
paddr->field_size = pflddes->size;
paddr->special = pflddes->special;
paddr->no_elements = 1;
dbfType = pflddes->field_type;
dbrType = mapDBFToDBR[dbfType];
if (*pname++ == '$') {
/* Some field types can be accessed as char arrays */
if (dbfType == DBF_STRING) {
dbfType = DBF_CHAR;
dbrType = DBR_CHAR;
no_elements = pflddes->size;
} else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) {
/* Clients see a char array, but keep original dbfType */
dbrType = DBR_CHAR;
no_elements = PVNAME_STRINGSZ + 12;
} else {
status = S_dbLib_fieldNotFound;
goto finish;
}
}
paddr->pfldDes = pflddes;
paddr->field_type = dbfType;
paddr->dbr_field_type = dbrType;
paddr->field_size = pflddes->size;
paddr->special = pflddes->special;
paddr->no_elements = no_elements;
if ((paddr->special == SPC_DBADDR) &&
(prset = dbGetRset(paddr)) &&
@@ -685,6 +706,9 @@ long epicsShareAPI dbNameToAddr(const char *pname, DBADDR *paddr)
* dbr_field_type, field_size, and/or special.
*/
status = prset->cvt_dbaddr(paddr);
finish:
dbFinishEntry(&dbEntry);
return status;
}
@@ -740,12 +764,10 @@ unsigned dbNameSizeOfPV ( const dbAddr * paddr )
return recNameLen + fieldNameLen + 1;
}
long epicsShareAPI dbValueSize(
short dbr_type
)
long epicsShareAPI dbValueSize(short dbr_type)
{
/* sizes for value associated with each DBR request type */
static long size[] = {
/* sizes for value associated with each DBR request type */
static long size[] = {
MAX_STRING_SIZE, /* STRING */
sizeof(epicsInt8), /* CHAR */
sizeof(epicsUInt8), /* UCHAR */
@@ -757,30 +779,26 @@ long epicsShareAPI dbValueSize(
sizeof(epicsFloat64), /* DOUBLE */
sizeof(epicsEnum16)}; /* ENUM */
return(size[dbr_type]);
return(size[dbr_type]);
}
long epicsShareAPI dbBufferSize(
short dbr_type,
long options,
long no_elements
)
long epicsShareAPI dbBufferSize(short dbr_type, long options, long no_elements)
{
long nbytes=0;
nbytes += dbValueSize(dbr_type) * no_elements;
if(options & DBR_STATUS) nbytes += dbr_status_size;
if(options & DBR_UNITS) nbytes += dbr_units_size;
if(options & DBR_PRECISION) nbytes += dbr_precision_size;
if(options & DBR_TIME) nbytes += dbr_time_size;
if(options & DBR_ENUM_STRS) nbytes += dbr_enumStrs_size;
if(options & DBR_GR_LONG) nbytes += dbr_grLong_size;
if(options & DBR_GR_DOUBLE) nbytes += dbr_grDouble_size;
if(options & DBR_CTRL_LONG) nbytes += dbr_ctrlLong_size;
if(options & DBR_CTRL_DOUBLE)nbytes += dbr_ctrlDouble_size;
if(options & DBR_AL_LONG) nbytes += dbr_alLong_size;
if(options & DBR_AL_DOUBLE) nbytes += dbr_alDouble_size;
if (options & DBR_STATUS) nbytes += dbr_status_size;
if (options & DBR_UNITS) nbytes += dbr_units_size;
if (options & DBR_PRECISION) nbytes += dbr_precision_size;
if (options & DBR_TIME) nbytes += dbr_time_size;
if (options & DBR_ENUM_STRS) nbytes += dbr_enumStrs_size;
if (options & DBR_GR_LONG) nbytes += dbr_grLong_size;
if (options & DBR_GR_DOUBLE) nbytes += dbr_grDouble_size;
if (options & DBR_CTRL_LONG) nbytes += dbr_ctrlLong_size;
if (options & DBR_CTRL_DOUBLE) nbytes += dbr_ctrlDouble_size;
if (options & DBR_AL_LONG) nbytes += dbr_alLong_size;
if (options & DBR_AL_DOUBLE) nbytes += dbr_alDouble_size;
return(nbytes);
}
int epicsShareAPI dbLoadDatabase(const char *file, const char *path, const char *subs)
@@ -1016,8 +1034,10 @@ long epicsShareAPI dbGet(DBADDR *paddr, short dbrType,
}
/* check for array */
prset = dbGetRset(paddr);
if (no_elements > 1 && prset && prset->get_array_info) {
if (paddr->special == SPC_DBADDR &&
no_elements > 1 &&
(prset = dbGetRset(paddr)) &&
prset->get_array_info) {
status = prset->get_array_info(paddr, &no_elements, &offset);
} else
offset = 0;
@@ -1393,7 +1413,8 @@ long epicsShareAPI dbPut(DBADDR *paddr, short dbrType,
} else {
struct rset *prset = dbGetRset(paddr);
if (prset && prset->get_array_info) {
if (paddr->special == SPC_DBADDR &&
prset && prset->get_array_info) {
long dummy;
status = prset->get_array_info(paddr, &dummy, &offset);
@@ -1405,7 +1426,9 @@ long epicsShareAPI dbPut(DBADDR *paddr, short dbrType,
nRequest, no_elements, offset);
/* update array info */
if (prset && prset->put_array_info && !status) {
if (!status &&
paddr->special == SPC_DBADDR &&
prset && prset->put_array_info) {
status = prset->put_array_info(paddr, nRequest);
}
}
+120 -84
View File
@@ -46,7 +46,6 @@ int dbStaticDebug = 0;
static char *pNullString = "";
#define messagesize 100
#define RPCL_LEN 184
#define MAX_FIELD_NAME_LENGTH 20
static char *ppstring[5]={"NPP","PP","CA","CP","CPP"};
static char *msstring[2]={"NMS","MS"};
@@ -299,24 +298,19 @@ done:
static long putParmString(char **pparm,const char *pstring)
{
size_t size;
if(*pparm && (*pparm != pNullString)){
free((void *)(*pparm));
*pparm = pNullString;
if (*pparm && *pparm != pNullString) {
free(*pparm);
*pparm = pNullString;
}
if(!pstring) return(0);
if(!(pstring = strchr(pstring,'@'))) return(0);
pstring++;
size = strlen(pstring) + 1;
if(size==1) return(0);
*pparm = dbCalloc(size, sizeof(char *));
strcpy(*pparm,pstring);
return(0);
if (!pstring) return 0;
pstring = strchr(pstring, '@');
if (!pstring || !*++pstring) return 0;
*pparm = epicsStrDup(pstring);
return 0;
}
void dbFreeLinkContents(struct link *plink)
{
{
char *parm = NULL;
switch(plink->type) {
@@ -331,7 +325,7 @@ void dbFreeLinkContents(struct link *plink)
case INST_IO: parm = plink->value.instio.string; break;
case BBGPIB_IO: parm = plink->value.bbgpibio.parm;break;
case VXI_IO: parm = plink->value.vxiio.parm; break;
default:
default:
epicsPrintf("dbFreeLink called but link type unknown\n");
}
if(parm && (parm != pNullString)) free((void *)parm);
@@ -1358,25 +1352,33 @@ long epicsShareAPI dbPutRecordAttribute(
return(0);
}
long epicsShareAPI dbGetRecordAttribute(DBENTRY *pdbentry,const char *name)
long dbGetAttributePart(DBENTRY *pdbentry, const char **ppname)
{
dbRecordType *precordType = pdbentry->precordType;
int compare;
dbRecordType *precordType = pdbentry->precordType;
const char *pname = *ppname;
dbRecordAttribute *pattribute;
if(!precordType) return(S_dbLib_recordTypeNotFound);
if (!precordType) return S_dbLib_recordTypeNotFound;
pattribute = (dbRecordAttribute *)ellFirst(&precordType->attributeList);
while(pattribute) {
compare = strcmp(pattribute->name,name);
if(compare==0) {
pdbentry->pflddes = pattribute->pdbFldDes;
pdbentry->pfield = pattribute->value;
return(0);
}
if(compare>=0) break;
pattribute = (dbRecordAttribute *)ellNext(&pattribute->node);
while (pattribute) {
int nameLen = strlen(pattribute->name);
int compare = strncmp(pattribute->name, pname, nameLen);
int ch = pname[nameLen];
if (compare == 0 && !(ch == '_' || isalnum(ch))) {
pdbentry->pflddes = pattribute->pdbFldDes;
pdbentry->pfield = pattribute->value;
*ppname = &pname[nameLen];
return 0;
}
if (compare >= 0) break;
pattribute = (dbRecordAttribute *)ellNext(&pattribute->node);
}
return(S_dbLib_fieldNotFound);
return S_dbLib_fieldNotFound;
}
long dbGetRecordAttribute(DBENTRY *pdbentry, const char *pname)
{
return dbGetAttributePart(pdbentry, &pname);
}
long epicsShareAPI dbFirstField(DBENTRY *pdbentry,int dctonly)
@@ -1614,27 +1616,39 @@ long epicsShareAPI dbFreeRecords(DBBASE *pdbbase)
return(0);
}
long epicsShareAPI dbFindRecord(DBENTRY *pdbentry, const char *name)
long epicsShareAPI dbFindRecordPart(DBENTRY *pdbentry, const char **ppname)
{
dbBase *pdbbase = pdbentry->pdbbase;
const char *field;
const char *pname = *ppname;
const char *pfn;
int lenName;
PVDENTRY *ppvdNode;
zeroDbentry(pdbentry);
field = strchr(name, '.');
if (field) {
lenName = field++ - name;
pfn = strchr(pname, '.');
if (pfn) {
lenName = pfn - pname;
} else {
lenName = strlen(name);
lenName = strlen(pname);
}
ppvdNode = dbPvdFind(pdbbase, name, lenName);
ppvdNode = dbPvdFind(pdbbase, pname, lenName);
if (!ppvdNode)
return S_dbLib_recNotFound;
pdbentry->precnode = ppvdNode->precnode;
pdbentry->precordType = ppvdNode->precordType;
if (field)
return dbFindField(pdbentry, field);
*ppname = pname + lenName;
return 0;
}
long epicsShareAPI dbFindRecord(DBENTRY *pdbentry, const char *pname)
{
long status = dbFindRecordPart(pdbentry, &pname);
if (status) return status;
if (*pname == '.')
return dbFindField(pdbentry, ++pname);
return 0;
}
@@ -1867,64 +1881,86 @@ long epicsShareAPI dbCopyRecord(DBENTRY *pdbentry,const char *newRecordName,int
return(dbFindRecord(pdbentry,newRecordName));
}
long epicsShareAPI dbFindField(DBENTRY *pdbentry,const char *pname)
long epicsShareAPI dbFindFieldPart(DBENTRY *pdbentry,const char **ppname)
{
dbRecordType *precordType = pdbentry->precordType;
dbRecordNode *precnode = pdbentry->precnode;
char *precord;
dbFldDes *pflddes;
short top, bottom, test;
char **papsortFldName;
short *sortFldInd;
int compare,ind;
char fieldName[MAX_FIELD_NAME_LENGTH+1];
char *pfieldName;
dbRecordType *precordType = pdbentry->precordType;
dbRecordNode *precnode = pdbentry->precnode;
const char *pname = *ppname;
char *precord;
short top, bottom, test;
char **papsortFldName;
short *sortFldInd;
int ch;
int nameLen;
if(!precordType) return(S_dbLib_recordTypeNotFound);
if(!precnode) return(S_dbLib_recNotFound);
if (!precordType) return S_dbLib_recordTypeNotFound;
if (!precnode) return S_dbLib_recNotFound;
precord = precnode->precord;
papsortFldName = precordType->papsortFldName;
sortFldInd = precordType->sortFldInd;
/*copy field name. Stop at null or blank or tab*/
pfieldName = &fieldName[0];
for(ind=0; ind<MAX_FIELD_NAME_LENGTH; ind++) {
if(*pname=='\0' || *pname==' ' || *pname=='\t') break;
*pfieldName++ = *pname++;
/* Measure field name length; name is a valid C identifier */
nameLen = 0;
if ((ch = *pname) &&
(ch == '_' || isalpha(ch))) {
while ((ch = pname[++nameLen]))
if (!(ch == '_' || isalnum(ch))) break;
}
*pfieldName = '\0';
pfieldName = &fieldName[0];
/* check for default field name or VAL to be supplied */
if((*pfieldName==0) || (strcmp(pfieldName,"VAL")==0) ) {
if(!(pflddes=precordType->pvalFldDes))
return(S_dbLib_recordTypeNotFound);
pdbentry->pflddes = pflddes;
pdbentry->indfield = precordType->indvalFlddes;
return(dbGetFieldAddress(pdbentry));
/* Handle absent field name */
if (nameLen == 0) {
dbFldDes *pflddes = precordType->pvalFldDes;
if (!pflddes)
return S_dbLib_recordTypeNotFound;
pdbentry->pflddes = pflddes;
pdbentry->indfield = precordType->indvalFlddes;
*ppname = &pname[nameLen];
return dbGetFieldAddress(pdbentry);
}
/* binary search through ordered field names */
top = precordType->no_fields - 1;
bottom = 0;
test = (top + bottom) / 2;
while (1) {
/* check the field name */
compare = strcmp(papsortFldName[test],pfieldName);
if (compare == 0) {
if(!(pflddes=precordType->papFldDes[sortFldInd[test]]))
return(S_dbLib_recordTypeNotFound);
pdbentry->pflddes = pflddes;
pdbentry->indfield = sortFldInd[test];
return(dbGetFieldAddress(pdbentry));
} else if (compare > 0) {
top = test - 1;
if (top < bottom) break;
test = (top + bottom) / 2;
} else {
bottom = test + 1;
if (top < bottom) break;
test = (top + bottom) / 2;
}
int compare = strncmp(papsortFldName[test], pname, nameLen);
if (compare == 0)
compare = strlen(papsortFldName[test]) - nameLen;
if (compare == 0) {
dbFldDes *pflddes = precordType->papFldDes[sortFldInd[test]];
if (!pflddes)
return S_dbLib_recordTypeNotFound;
pdbentry->pflddes = pflddes;
pdbentry->indfield = sortFldInd[test];
*ppname = &pname[nameLen];
return dbGetFieldAddress(pdbentry);
} else if (compare > 0) {
top = test - 1;
if (top < bottom) break;
test = (top + bottom) / 2;
} else {
bottom = test + 1;
if (top < bottom) break;
test = (top + bottom) / 2;
}
}
return(dbGetRecordAttribute(pdbentry,pfieldName));
return S_dbLib_fieldNotFound;
}
long epicsShareAPI dbFindField(DBENTRY *pdbentry,const char *pname)
{
long status = dbFindFieldPart(pdbentry, &pname);
int ch;
if (status == S_dbLib_fieldNotFound)
return dbGetRecordAttribute(pdbentry, pname);
if (status) return status;
ch = *pname;
if (ch == 0 || isspace(ch)) return 0;
return S_dbLib_recNotFound;
}
int epicsShareAPI dbFoundField(DBENTRY *pdbentry)
+30 -23
View File
@@ -111,10 +111,12 @@ epicsShareFunc long epicsShareAPI dbFirstRecordType(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbNextRecordType(DBENTRY *pdbentry);
epicsShareFunc char * epicsShareAPI dbGetRecordTypeName(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbGetNRecordTypes(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbPutRecordAttribute(
DBENTRY *pdbentry,const char *name,const char*value);
epicsShareFunc long epicsShareAPI dbGetRecordAttribute(
DBENTRY *pdbentry,const char *name);
epicsShareFunc long epicsShareAPI dbPutRecordAttribute(DBENTRY *pdbentry,
const char *name, const char*value);
epicsShareFunc long epicsShareAPI dbGetRecordAttribute(DBENTRY *pdbentry,
const char *name);
epicsShareFunc long epicsShareAPI dbGetAttributePart(DBENTRY *pdbentry,
const char **ppname);
epicsShareFunc long epicsShareAPI dbFirstField(DBENTRY *pdbentry,int dctonly);
epicsShareFunc long epicsShareAPI dbNextField(DBENTRY *pdbentry,int dctonly);
@@ -125,46 +127,51 @@ epicsShareFunc char * epicsShareAPI dbGetDefault(DBENTRY *pdbentry);
epicsShareFunc char * epicsShareAPI dbGetPrompt(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbGetPromptGroup(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbCreateRecord(
DBENTRY *pdbentry,const char *precordName);
epicsShareFunc long epicsShareAPI dbCreateRecord(DBENTRY *pdbentry,
const char *pname);
epicsShareFunc long epicsShareAPI dbDeleteRecord(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbFreeRecords(DBBASE *pdbbase);
epicsShareFunc long epicsShareAPI dbFindRecord(
DBENTRY *pdbentry,const char *precordName);
epicsShareFunc long epicsShareAPI dbFirstRecord(
DBENTRY *pdbentry); /*first of record type*/
epicsShareFunc long epicsShareAPI dbFindRecordPart(DBENTRY *pdbentry,
const char **ppname);
epicsShareFunc long epicsShareAPI dbFindRecord(DBENTRY *pdbentry,
const char *pname);
epicsShareFunc long epicsShareAPI dbFirstRecord(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbNextRecord(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbGetNRecords(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbGetNAliases(DBENTRY *pdbentry);
epicsShareFunc char * epicsShareAPI dbGetRecordName(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbRenameRecord(
DBENTRY *pdbentry,const char *newName);
epicsShareFunc long epicsShareAPI dbCopyRecord(
DBENTRY *pdbentry,const char *newRecordName,int overWriteOK);
epicsShareFunc long epicsShareAPI dbRenameRecord(DBENTRY *pdbentry,
const char *newName);
epicsShareFunc long epicsShareAPI dbCopyRecord(DBENTRY *pdbentry,
const char *newRecordName, int overWriteOK);
epicsShareFunc long epicsShareAPI dbVisibleRecord(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbInvisibleRecord(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbIsVisibleRecord(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbCreateAlias(
DBENTRY *pdbentry, const char *paliasName);
epicsShareFunc long epicsShareAPI dbCreateAlias(DBENTRY *pdbentry,
const char *paliasName);
epicsShareFunc int epicsShareAPI dbIsAlias(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbDeleteAliases(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbFindField(
DBENTRY *pdbentry,const char *pfieldName);
epicsShareFunc long epicsShareAPI dbFindFieldPart(DBENTRY *pdbentry,
const char **ppname);
epicsShareFunc long epicsShareAPI dbFindField(DBENTRY *pdbentry,
const char *pfieldName);
epicsShareFunc int epicsShareAPI dbFoundField(DBENTRY *pdbentry);
epicsShareFunc char * epicsShareAPI dbGetString(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbPutString(
DBENTRY *pdbentry,const char *pstring);
epicsShareFunc char * epicsShareAPI dbVerify(
DBENTRY *pdbentry,const char *pstring);
epicsShareFunc long epicsShareAPI dbPutString(DBENTRY *pdbentry,
const char *pstring);
epicsShareFunc char * epicsShareAPI dbVerify(DBENTRY *pdbentry,
const char *pstring);
epicsShareFunc char * epicsShareAPI dbGetRange(DBENTRY *pdbentry);
epicsShareFunc int epicsShareAPI dbIsDefaultValue(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbFirstInfo(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbNextInfo(DBENTRY *pdbentry);
epicsShareFunc long epicsShareAPI dbFindInfo(DBENTRY *pdbentry,const char *name);
epicsShareFunc long epicsShareAPI dbFindInfo(DBENTRY *pdbentry,
const char *name);
epicsShareFunc long epicsShareAPI dbDeleteInfo(DBENTRY *pdbentry);
epicsShareFunc const char * epicsShareAPI dbGetInfoName(DBENTRY *pdbentry);
epicsShareFunc const char * epicsShareAPI dbGetInfoString(DBENTRY *pdbentry);