/** * 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 #define epicsExportSharedSymbols #include #include #include using namespace epics::pvData; using std::tr1::static_pointer_cast; using std::cout; using std::endl; using std::string; using std::vector; namespace epics { namespace pvData { static PVDataCreatePtr pvDataCreate = getPVDataCreate(); static FieldCreatePtr fieldCreate = getFieldCreate(); class CreateRequestImpl : public CreateRequest { private: struct Node { string name; vector nodes; Node(string name) : name(name) {} }; struct OptionPair { string name; string value; OptionPair(string name,string value) : name(name), value(value) {} }; vector optionList; string fullFieldName; public: CreateRequestImpl() { fullFieldName = ""; } 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 == string::npos){ message = request + " mismatched {}"; throw std::logic_error("message"); } if (openBrace != string::npos && openBrace!=0) { if(openBrace=request.size()) return request.size(); ind = closeBrace; continue; } if(request[ind]=='.') { ++ind; continue; } if(ind>=maxind) break; ++ind; } return request.size(); } 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; } vector valueList(numValues,""); index=0; for(size_t i=0; i top; vector items = split(request); size_t nitems = items.size(); for(size_t j=0; j0) subNode.nodes.push_back(optionNode); node.nodes.push_back(subNode); fullFieldName = saveFullName; return; } if(chr==',') { Node subNode(name); if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode); node.nodes.push_back(subNode); string rest = request.substr(end+1); fullFieldName = saveFullName; createSubNode(node,rest); return; } if(chr=='.') { request = request.substr(end+1); if(request.size()==string::npos || request.size()<1) { throw std::logic_error("null field name " + request); } Node subNode(name); if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode); size_t endField = findEndField(request); string subRequest = request.substr(0, endField); createSubNode(subNode,subRequest); node.nodes.push_back(subNode); size_t next = endField+1; if(next>=request.size()) { fullFieldName = saveFullName; return; } request = request.substr(next); fullFieldName = saveFullName; createSubNode(node,request); return; } if(chr=='{') { size_t endBrace = findEndField(request); if((end+1)>=(endBrace-1)) { throw std::logic_error("illegal syntax " + request); } string subRequest = request.substr(end+1,endBrace-1 -end -1); if(subRequest.size()<1) { throw std::logic_error("empty {} " + request); } Node subNode(name); if(optionNode.name.size()>0) subNode.nodes.push_back(optionNode); createSubNode(subNode,subRequest); node.nodes.push_back(subNode); size_t next = endBrace + 1; if(next>=request.size()) { fullFieldName = saveFullName; return; } request = request.substr(next); fullFieldName = saveFullName; createSubNode(node,request); return; } throw std::logic_error("logic error"); } FieldConstPtr createSubStructure(vector & nodes) { size_t num = nodes.size(); StringArray names(num); FieldConstPtrArray fields(num); for(size_t i=0; i subNode = node.nodes; if(subNode.empty()) { fields[i] = fieldCreate->createStructure(); } else { fields[i] = createSubStructure(subNode); } } } StructureConstPtr structure = fieldCreate->createStructure( names, fields); return structure; } StructureConstPtr createOptions(vector &nodes) { size_t num = nodes.size(); StringArray names(num); FieldConstPtrArray fields(num); for(size_t i=0; icreateScalar(pvString); } StructureConstPtr structure = fieldCreate->createStructure(names, fields); return structure; } public: virtual PVStructurePtr createRequest( string const & crequest) { string request = crequest; if (!request.empty()) removeBlanks(request); if (request.empty()) { return pvDataCreate->createPVStructure(fieldCreate->createStructure()); } 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(" + request + ")"; offsetField = request.find("field("); } int numParan = 0; int numBrace = 0; int numBracket = 0; for(size_t i=0; i< request.length() ; ++i) { char chr = request[i]; if(chr=='(') numParan++; if(chr==')') numParan--; if(chr=='{') numBrace++; if(chr=='}') numBrace--; if(chr=='[') numBracket++; if(chr==']') numBracket--; } if(numParan!=0) { std::ostringstream msg("mismatched () "); msg << numParan; message = msg.str(); return PVStructurePtr(); } if(numBrace!=0) { std::ostringstream msg("mismatched {} "); msg << numBrace; message = msg.str(); return PVStructurePtr(); } if(numBracket!=0) { std::ostringstream msg("mismatched [] "); msg << numBracket; message = msg.str(); return PVStructurePtr(); } vector top; try { if(offsetRecord!=string::npos) { fullFieldName = "record"; 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(); } if(closeBracket-openBracket > 3) { Node node("record"); Node optNode = createRequestOptions( request.substr(openBracket+1,closeBracket-openBracket-1)); node.nodes.push_back(optNode); top.push_back(node); } } if(offsetField!=string::npos) { fullFieldName = "field"; Node node("field"); size_t openParan = request.find('(', offsetField); size_t closeParan = request.find(')', openParan); if(closeParan==string::npos) { message = request.substr(offsetField) + " field( does not have matching )"; return PVStructurePtr(); } if(closeParan>openParan+1) { createSubNode(node,request.substr(openParan+1,closeParan-openParan-1)); } top.push_back(node); } if(offsetGetField!=string::npos) { fullFieldName = "getField"; Node node("getField"); size_t openParan = request.find('(', offsetGetField); size_t closeParan = request.find(')', openParan); if(closeParan==string::npos) { message = request.substr(offsetField) + " getField( does not have matching )"; return PVStructurePtr(); } if(closeParan>openParan+1) { createSubNode(node,request.substr(openParan+1,closeParan-openParan-1)); } top.push_back(node); } if(offsetPutField!=string::npos) { fullFieldName = "putField"; Node node("putField"); size_t openParan = request.find('(', offsetPutField); size_t closeParan = request.find(')', openParan); if(closeParan==string::npos) { message = request.substr(offsetField) + " putField( does not have matching )"; return PVStructurePtr(); } if(closeParan>openParan+1) { createSubNode(node,request.substr(openParan+1,closeParan-openParan-1)); } top.push_back(node); } } catch (std::exception &e) { string xxx = e.what(); message = "while creating Structure exception " + xxx; return PVStructurePtr(); } size_t num = top.size(); StringArray names(num); FieldConstPtrArray fields(num); for(size_t i=0; i subNode = node.nodes; if(subNode.empty()) { fields[i] = fieldCreate->createStructure(); } else { fields[i] = createSubStructure(subNode); } } StructureConstPtr structure = fieldCreate->createStructure(names, fields); PVStructurePtr pvStructure = pvDataCreate->createPVStructure(structure); for(size_t i=0; igetSubField(name); pvField->put(value); } optionList.clear(); return pvStructure; } }; CreateRequest::shared_pointer CreateRequest::create() { CreateRequest::shared_pointer createRequest(new CreateRequestImpl()); return createRequest; } }}