From 987d5f56d3afe74b9b64febe0bf7f4bcf9e5bfa6 Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Sun, 26 Dec 2010 22:50:46 +0100 Subject: [PATCH] backup commit of CreateRequestFactory only... to be moved out --- testApp/client/MockClientImpl.cpp | 350 +++++++++++++++++++++++++++++- 1 file changed, 348 insertions(+), 2 deletions(-) diff --git a/testApp/client/MockClientImpl.cpp b/testApp/client/MockClientImpl.cpp index bc825f2..4a1c75a 100644 --- a/testApp/client/MockClientImpl.cpp +++ b/testApp/client/MockClientImpl.cpp @@ -8,11 +8,245 @@ #include #include +#include + using namespace epics::pvData; using namespace epics::pvAccess; +using std::string; +class CreateRequestFactory { + private: + + static void trim(std::string& str) + { + std::string::size_type pos = str.find_last_not_of(' '); + if(pos != std::string::npos) { + str.erase(pos + 1); + pos = str.find_first_not_of(' '); + if(pos != std::string::npos) str.erase(0, pos); + } + else str.erase(str.begin(), str.end()); + } + + static int findMatchingBrace(string& request, int index, int numOpen) { + size_t openBrace = request.find('{', index+1); + size_t closeBrace = request.find('}', index+1); + if(openBrace == std::string::npos && closeBrace == std::string::npos) return std::string::npos; + if (openBrace != std::string::npos) { + if(openBraceopenBrace)) { + //find matching brace + size_t closeBrace = findMatchingBrace(request,openBrace+1,1); + if(closeBrace==std::string::npos) { + requester->message(request + "mismatched { }", errorMessage); + return false; + } + String fieldName = request.substr(0,openBrace); + PVStructure* pvStructure = getPVDataCreate()->createPVStructure(pvParent, fieldName, 0); + createFieldRequest(pvStructure,request.substr(openBrace+1,closeBrace-openBrace-1),false,requester); + pvParent->appendPVField(pvStructure); + if(request.length()>closeBrace+1) { + if(request.at(closeBrace+1) != ',') { + requester->message(request + "misssing , after }", errorMessage); + return false; + } + if(!createFieldRequest(pvParent,request.substr(closeBrace+2),false,requester)) return false; + } + return true; + } + if(openBracket==std::string::npos && fieldListOK) { + PVString* pvStringField = static_cast(getPVDataCreate()->createPVScalar(pvParent, "fieldList", pvString)); + pvStringField->put(request); + pvParent->appendPVField(pvStringField); + return true; + } + if(openBracket!=std::string::npos && (comma==std::string::npos || comma>openBracket)) { + size_t closeBracket = request.find(']'); + if(closeBracket==std::string::npos) { + requester->message(request + "option does not have matching []", errorMessage); + return false; + } + if(!createLeafFieldRequest(pvParent,request.substr(0, closeBracket+1),requester)) return false; + if(request.rfind(',')>closeBracket) { + int nextComma = request.find(',', closeBracket); + if(!createFieldRequest(pvParent,request.substr(nextComma+1),false,requester)) return false; + } + return true; + } + if(comma!=std::string::npos) { + if(!createLeafFieldRequest(pvParent,request.substr(0, comma),requester)) return false; + return createFieldRequest(pvParent,request.substr(comma+1),false,requester); + } + return createLeafFieldRequest(pvParent,request,requester); + } + + static bool createLeafFieldRequest(PVStructure* pvParent,String request,Requester* requester) { + size_t openBracket = request.find('['); + String fullName = request; + if(openBracket != std::string::npos) fullName = request.substr(0,openBracket); + size_t indLast = fullName.rfind('.'); + String fieldName = fullName; + if(indLast>1 && indLast != std::string::npos) fieldName = fullName.substr(indLast+1); + PVStructure* pvStructure = getPVDataCreate()->createPVStructure(pvParent, fieldName, 0); + PVStructure* pvLeaf = getPVDataCreate()->createPVStructure(pvStructure,"leaf", 0); + PVString* pvStringField = static_cast(getPVDataCreate()->createPVScalar(pvLeaf, "source", pvString)); + pvStringField->put(fullName); + pvLeaf->appendPVField(pvStringField); + if(openBracket != std::string::npos) { + size_t closeBracket = request.find(']'); + if(closeBracket==std::string::npos) { + requester->message("option does not have matching []", errorMessage); + return false; + } + if(!createRequestOptions(pvLeaf,request.substr(openBracket+1, closeBracket-openBracket-1),requester)) return false; + } + pvStructure->appendPVField(pvLeaf); + pvParent->appendPVField(pvStructure); + return true; + } + + static bool createRequestOptions(PVStructure* pvParent,std::string request,Requester* requester) { + trim(request); + if(request.length()<=1) return true; + + std::string token; + std::istringstream iss(request); + while (getline(iss, token, ',')) + { + size_t equalsPos = token.find('='); + size_t equalsRPos = token.rfind('='); + if (equalsPos != equalsRPos) + { + requester->message("illegal option ", errorMessage); + return false; + } + + PVString* pvStringField = static_cast(getPVDataCreate()->createPVScalar(pvParent, token.substr(0, equalsPos), pvString)); + pvStringField->put(token.substr(equalsPos+1)); + pvParent->appendPVField(pvStringField); + } + return true; + } + + public: + + /** + * Create a request structure for the create calls in Channel. + * See the package overview documentation for details. + * @param request The field request. See the package overview documentation for details. + * @param requester The requester; + * @return The request structure if an invalid request was given. + */ + static PVStructure* createRequest(String request, Requester* requester) + { + static String emptyString; + if (!request.empty()) trim(request); + if (request.empty()) + { + return getPVDataCreate()->createPVStructure(0, emptyString, 0); + } + + size_t offsetRecord = request.find("record["); + size_t offsetField = request.find("field("); + size_t offsetPutField = request.find("putField("); + size_t offsetGetField = request.find("getField("); + PVStructure* pvStructure = getPVDataCreate()->createPVStructure(0, emptyString, 0); + if (offsetRecord != std::string::npos) { + size_t offsetBegin = request.find('[', offsetRecord); + size_t offsetEnd = request.find(']', offsetBegin); + if(offsetEnd == std::string::npos) { + delete pvStructure; + requester->message("record[ does not have matching ]", errorMessage); + return 0; + } + PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "record", 0); + if(!createRequestOptions(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),requester)) + { + // TODO is this ok? + delete pvStruct; + delete pvStructure; + return 0; + } + pvStructure->appendPVField(pvStruct); + } + if (offsetField != std::string::npos) { + size_t offsetBegin = request.find('(', offsetField); + size_t offsetEnd = request.find(')', offsetBegin); + if(offsetEnd == std::string::npos) { + delete pvStructure; + requester->message("field( does not have matching )", errorMessage); + return 0; + } + PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "field", 0); + if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester)) + { + delete pvStruct; + delete pvStructure; + return 0; + } + pvStructure->appendPVField(pvStruct); + } + if (offsetPutField != std::string::npos) { + size_t offsetBegin = request.find('(', offsetPutField); + size_t offsetEnd = request.find(')', offsetBegin); + if(offsetEnd == std::string::npos) { + delete pvStructure; + requester->message("putField( does not have matching )", errorMessage); + return 0; + } + PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "putField", 0); + if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester)) + { + delete pvStruct; + delete pvStructure; + return 0; + } + pvStructure->appendPVField(pvStruct); + } + if (offsetGetField != std::string::npos) { + size_t offsetBegin = request.find('(', offsetGetField); + size_t offsetEnd = request.find(')', offsetBegin); + if(offsetEnd == std::string::npos) { + delete pvStructure; + requester->message("getField( does not have matching )", errorMessage); + return 0; + } + PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "getField", 0); + if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester)) + { + delete pvStruct; + delete pvStructure; + return 0; + } + pvStructure->appendPVField(pvStruct); + } + if (pvStructure->getStructure()->getNumberFields()==0) { + if(!createFieldRequest(pvStructure,request,true,requester)) + { + delete pvStructure; + return 0; + } + } + return pvStructure; + } + +}; @@ -1068,7 +1302,7 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester }; - +/* int main(int argc,char *argv[]) { MockClientContext* context = new MockClientContext(); @@ -1079,7 +1313,8 @@ int main(int argc,char *argv[]) context->getProvider()->channelFind("something", &findRequester); ChannelRequesterImpl channelRequester; - /*Channel* noChannel =*/ context->getProvider()->createChannel("test", &channelRequester, ChannelProvider::PRIORITY_DEFAULT, "over the rainbow"); + //Channel* noChannel + context->getProvider()->createChannel("test", &channelRequester, ChannelProvider::PRIORITY_DEFAULT, "over the rainbow"); Channel* channel = context->getProvider()->createChannel("test", &channelRequester); std::cout << channel->getChannelName() << std::endl; @@ -1129,4 +1364,115 @@ int main(int argc,char *argv[]) return(0); } +*/ + +class RequesterImpl : public Requester { + public: + + virtual String getRequesterName() + { + return "RequesterImpl"; + }; + + virtual void message(String message,MessageType messageType) + { + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + } +}; + +#include + +static void testCreateRequest() { + RequesterImpl requester; + String out; + String request = ""; + PVStructure* pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "alarm,timeStamp,power.value"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "record[process=true]field(alarm,timeStamp,power.value)"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{power.value,power.alarm})"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value)"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = String("record[process=true,xxx=yyy]") + + "putField(power.value)" + + "getField(alarm,timeStamp,power{power.value,power.alarm}," + + "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm})"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = String("record[process=true,xxx=yyy]") + + "putField(power.value)" + + "getField(alarm,timeStamp,power{power.value,power.alarm}," + + "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm}," + + "ps0{" + + "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm}," + + "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}}," + + "ps1{" + + "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm}," + + "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}" + + "})"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "a{b{c{d}}}"; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest); + out.clear(); pvRequest->toString(&out); std::cout << out << std::endl; + delete pvRequest; + + request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value"; + std::cout << std::endl << "Error Expected for next call!!" << std::endl; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest==0); + + request = String("record[process=true,xxx=yyy]") + + "putField(power.value)" + + "getField(alarm,timeStamp,power{power.value,power.alarm}," + + "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm}," + + "ps0{" + + "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm}," + + "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}}," + + "ps1{" + + "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm}," + + "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}" + + ")"; + std::cout << std::endl << "Error Expected for next call!!" << std::endl; + pvRequest = CreateRequestFactory::createRequest(request,&requester); + assert(pvRequest==0); +} + +int main(int argc,char *argv[]) +{ + testCreateRequest(); + + std::cout << "-----------------------------------------------------------------------" << std::endl; + getShowConstructDestruct()->constuctDestructTotals(stdout); + return 0; +}