/** * Copyright - See the COPYRIGHT that is included with this distribution. * pvAccessCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #define epicsExportSharedSymbols #include using namespace epics::pvData; using std::tr1::static_pointer_cast; using std::cout; using std::endl; namespace epics { namespace pvData { static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static FieldCreatePtr fieldCreate = getFieldCreate(); class CreateRequestImpl : public CreateRequest { private: void removeBlanks(String& str) { while(true) { String::size_type pos = str.find_first_of(' '); if(pos==String::npos) return; str.erase(pos,1); } } size_t findMatchingBrace(String& request, size_t index, int numOpen) { size_t openBrace = request.find('{', index+1); size_t closeBrace = request.find('}', index+1); if(openBrace == String::npos && closeBrace == std::string::npos){ message = request + " missing }"; return std::string::npos; } if (openBrace != String::npos && openBrace!=0) { if(openBrace=request.size()) return request.size(); ind = closeBrace; continue; } if(ind>=maxind) break; ++ind; } return request.size(); } std::vector split(String const & commaSeparatedList) { String::size_type numValues = 1; String::size_type index=0; while(true) { String::size_type pos = commaSeparatedList.find(',',index); if(pos==String::npos) break; numValues++; index = pos +1; } std::vector valueList(numValues,""); index=0; for(size_t i=0; i items = split(request); size_t nitems = items.size(); StringArray fieldNames(nitems); FieldConstPtrArray fields(nitems); for(size_t j=0; jcreateScalar(pvString); } return fieldCreate->createStructure(fieldNames,fields); } void initRequestOptions( PVStructurePtr const & pvParent, String request) { if(request.length()<=1) return; std::vector items = split(request); size_t nitems = items.size(); for(size_t j=0; jgetSubField(name); pvValue->put(value); } } StructureConstPtr createSubFieldRequest( StructureConstPtr parent, String request) { if(request.length()<=0) return parent; size_t period = request.find('.'); size_t openBracket = request.find('['); size_t openBrace = request.find('{'); // name only if(period==String::npos && openBracket==String::npos && openBrace==String::npos) { StructureConstPtr subField = fieldCreate->createStructure(); parent = fieldCreate->appendField(parent,request,subField); return parent; } // period is first if(period!=String::npos && (openBracket==String::npos || periodcreateStructure(); subField = createSubFieldRequest(subField,request.substr(period+1)); if(subField==NULL) return subField; parent = fieldCreate->appendField(parent,fieldName,subField); return parent; } // brace before [ or . if(openBrace!=String::npos && (openBracket==String::npos || openBrace= request.size()) nextChar = String::npos; if(nextChar!=String::npos) { message = request + " syntax error " + request[nextChar] + " after } illegal"; return StructureConstPtr(); } StructureConstPtr subField = fieldCreate->createStructure(); String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1); subField = createFieldRequest(subField,subRequest); if(subField==NULL) return subField; parent = fieldCreate->appendField(parent,fieldName,subField); return parent; } // [ is before brace or . if(openBracket!=String::npos && (openBrace==String::npos || openBracket= request.size()) nextChar = String::npos; if(nextChar==String::npos) { StringArray fieldNames(1); FieldConstPtrArray fields(1); fieldNames[0] = "_options"; fields[0] = createRequestOptions( request.substr(openBracket+1,closeBracket-openBracket-1)); StructureConstPtr subField = fieldCreate->createStructure(fieldNames,fields); parent = fieldCreate->appendField(parent,fieldName,subField); return parent; } if(request[nextChar]=='.') { StructureConstPtr subField = fieldCreate->createStructure(); subField = createSubFieldRequest(subField,request.substr(nextChar+1)); if(subField==NULL) return StructureConstPtr(); if(subField->getNumberFields()!=1) { message = request + " logic error createSubFieldRequest openBracket subField"; return StructureConstPtr(); } StringArray fieldNames(2); FieldConstPtrArray fields(2); fieldNames[0] = "_options"; fields[0] = createRequestOptions( request.substr(openBracket+1,closeBracket-openBracket-1)); fieldNames[1] = subField->getFieldNames()[0]; fields[1] = subField; subField = fieldCreate->createStructure(fieldNames,fields); parent = fieldCreate->appendField(parent,fieldName,subField); return parent; } if(request[nextChar]=='{') { size_t closeBrace = findMatchingBrace(request,openBrace,1); if(closeBrace==String::npos) return StructureConstPtr(); StructureConstPtr subField = fieldCreate->createStructure(); String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1); subField = createFieldRequest(subField,subRequest); if(subField==NULL) return subField; size_t numSub = subField->getNumberFields(); StringArray fieldNames(numSub + 1); FieldConstPtrArray fields(numSub+1); fieldNames[0] = "_options"; fields[0] = createRequestOptions( request.substr(openBracket+1,closeBracket-openBracket-1)); StringArray subNames = subField->getFieldNames(); FieldConstPtrArray subFields = subField->getFields(); for(size_t i=0; iappendFields(parent,fieldNames,fields); parent = fieldCreate->appendField(parent,fieldName,subField); return parent; } } message = request + " logic error createSubFieldRequest"; return StructureConstPtr(); } StructureConstPtr createFieldRequest( StructureConstPtr parent, String request) { size_t length = request.length(); if(length<=0) return parent; size_t end = findEndField(request); if(end==String::npos) return StructureConstPtr(); StringArray fieldNames; FieldConstPtrArray fields; StructureConstPtr subField = fieldCreate->createStructure(); subField = createSubFieldRequest(subField,request.substr(0,end)); if(subField==NULL) return subField; fieldNames.push_back(subField->getFieldNames()[0]); fields.push_back(subField->getFields()[0]); if(end!=length) { if(request[end]!=',') { message = request; message += " expected char "; message += length; message += " to be ,"; return StructureConstPtr(); } StructureConstPtr nextSubField = fieldCreate->createStructure(); nextSubField = createFieldRequest(nextSubField,request.substr(end+1)); if(nextSubField==NULL) return nextSubField; size_t numFields = nextSubField->getNumberFields(); StringArray subNames = nextSubField->getFieldNames(); FieldConstPtrArray subFields = nextSubField->getFields(); for(size_t i=0; iappendFields(parent,fieldNames,fields); return parent; } void initSubFieldOptions( PVStructurePtr const & pvParent, String request) { if(request.length()<=0) return; size_t period = request.find('.'); size_t openBracket = request.find('['); size_t openBrace = request.find('{'); // name only if(period==String::npos && openBracket==String::npos && openBrace==String::npos) { return; } // period is first if(period!=String::npos && (openBracket==String::npos || period(pvParent->getPVFields()[0]); initSubFieldOptions(pvSubField,request.substr(period+1)); return; } // brace before [ or . if(openBrace!=String::npos && (openBracket==String::npos || openBrace(pvParent->getPVFields()[0]); size_t closeBrace = findMatchingBrace(request,openBrace,1); String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1); initFieldOptions(pvSubField,subRequest); return; } PVStructurePtr pvOptions = pvParent->getSubField("_options"); if(pvOptions==NULL) throw std::logic_error("initSubFieldOptions pvOptions NULL"); size_t closeBracket = findMatchingBracket(request,openBracket); initRequestOptions(pvOptions,request.substr(openBracket+1,closeBracket-openBracket-1)); size_t nextChar = closeBracket+1; if(nextChar>= request.size()) nextChar = String::npos; if(nextChar==String::npos) return; if(request[nextChar]=='.') { PVStructurePtr pvSubField = static_pointer_cast(pvParent->getPVFields()[1]); initSubFieldOptions(pvSubField,request.substr(nextChar+1)); return; } if(request[nextChar]!='{') throw std::logic_error("initSubFieldOptions request[nextChar]!='{'"); size_t closeBrace = findMatchingBrace(request,openBrace,1); const PVFieldPtrArray &pvFields = pvParent->getPVFields(); String subRequest = request.substr(openBrace+1,closeBrace-openBrace-1); for(size_t i=1; i(pvFields[i]); size_t comma = subRequest.find(','); initSubFieldOptions(pvSubField, subRequest.substr(0,comma-1)); subRequest = subRequest.substr(comma+1); } } void initFieldOptions( PVStructurePtr const & pvParent, String request) { if(request.find('[')==String::npos) return; size_t num = pvParent->getStructure()->getNumberFields(); if(num==0) return; if(num==1) { initSubFieldOptions(pvParent,request); return; } size_t end = findEndField(request); size_t start = 0; for(size_t i=0; i(pvParent->getPVFields()[i]); String subRequest = request.substr(start, end - start); initSubFieldOptions(pvSub,subRequest); if(i==num-1) break; start = end +1; String xxx = request.substr(start); end += findEndField(xxx) + 1; } } public: virtual PVStructure::shared_pointer createRequest( String const & crequest) { String request = crequest; StructureConstPtr topStructure = fieldCreate->createStructure(); if (!request.empty()) removeBlanks(request); if (request.empty()) { PVFieldPtrArray pvFields; StringArray fieldNames; return pvDataCreate->createPVStructure(fieldNames,pvFields); } size_t offsetRecord = request.find("record["); size_t offsetField = request.find("field("); size_t offsetPutField = request.find("putField("); size_t offsetGetField = request.find("getField("); if(offsetRecord==String::npos && offsetField==String::npos && offsetPutField==String::npos && offsetGetField==String::npos) { request = "field(" + crequest + ")"; offsetField = request.find("field("); } if (offsetRecord != String::npos) { size_t openBracket = request.find('[', offsetRecord); size_t closeBracket = request.find(']', openBracket); if(closeBracket == String::npos) { message = request.substr(offsetRecord) + " record[ does not have matching ]"; return PVStructurePtr(); } StructureConstPtr structure = createRequestOptions( request.substr(openBracket+1,closeBracket-openBracket-1)); if(structure==NULL) { return PVStructurePtr(); } topStructure = fieldCreate->appendField(topStructure,"record",structure); } if (offsetField != String::npos) { size_t openBrace = request.find('(', offsetField); size_t closeBrace = request.find(')', openBrace); if(closeBrace == String::npos) { message = request.substr(offsetField) + " field( does not have matching )"; return PVStructurePtr(); } StructureConstPtr structure = fieldCreate->createStructure(); structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1)); if(structure==NULL) { return PVStructurePtr(); } topStructure = fieldCreate->appendField(topStructure,"field",structure); } if (offsetPutField != String::npos) { size_t openBrace = request.find('(', offsetPutField); size_t closeBrace = request.find(')', openBrace); if(closeBrace == String::npos) { message = request.substr(offsetField) + " putField( does not have matching )"; return PVStructurePtr(); } StructureConstPtr structure = fieldCreate->createStructure(); structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1)); if(structure==NULL) { return PVStructurePtr(); } topStructure = fieldCreate->appendField(topStructure,"putField",structure); } if (offsetGetField != String::npos) { size_t openBrace = request.find('(', offsetGetField); size_t closeBrace = request.find(')', openBrace); if(closeBrace == String::npos) { message = request.substr(offsetField) + " getField( does not have matching )"; return PVStructurePtr(); } StructureConstPtr structure = fieldCreate->createStructure(); structure = createFieldRequest(structure,request.substr(openBrace+1,closeBrace-openBrace-1)); if(structure==NULL) { return PVStructurePtr(); } topStructure = fieldCreate->appendField(topStructure,"getField",structure); } PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); if (offsetRecord != String::npos) { size_t openBracket = request.find('[', offsetRecord); size_t closeBracket = request.find(']', openBracket); initRequestOptions( pvStructure->getSubField("record"), request.substr(openBracket+1,closeBracket-openBracket-1)); } if (offsetField != String::npos) { size_t openParam = request.find('(', offsetField); size_t closeParam = request.find(')', openParam); PVStructurePtr pvSub = pvStructure->getSubField("field"); if(pvSub->getStructure()->getNumberFields()==1) { pvSub = static_pointer_cast(pvSub->getPVFields()[0]); } if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1)); } if (offsetPutField != String::npos) { size_t openParam = request.find('(', offsetPutField); size_t closeParam = request.find(')', openParam); PVStructurePtr pvSub = pvStructure->getSubField("putField"); if(pvSub->getStructure()->getNumberFields()==1) { pvSub = static_pointer_cast(pvSub->getPVFields()[0]); } if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1)); } if (offsetGetField != String::npos) { size_t openParam = request.find('(', offsetGetField); size_t closeParam = request.find(')', openParam); PVStructurePtr pvSub = pvStructure->getSubField("getField"); if(pvSub->getStructure()->getNumberFields()==1) { pvSub = static_pointer_cast(pvSub->getPVFields()[0]); } if(pvSub!=NULL) initFieldOptions(pvSub,request.substr(openParam+1,closeParam-openParam-1)); } return pvStructure; } }; CreateRequest::shared_pointer CreateRequest::create() { CreateRequest::shared_pointer createRequest(new CreateRequestImpl()); return createRequest; } }}