backup commit of CreateRequestFactory only... to be moved out

This commit is contained in:
Matej Sekoranja
2010-12-26 22:50:46 +01:00
parent 37b72b01b0
commit 987d5f56d3

View File

@@ -8,11 +8,245 @@
#include <lock.h>
#include <standardPVField.h>
#include <sstream>
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(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
if(numOpen==1) return closeBrace;
return findMatchingBrace(request,closeBrace,numOpen-1);
}
static bool createFieldRequest(PVStructure* pvParent,std::string request,bool fieldListOK,Requester* requester) {
trim(request);
if(request.length()<=0) return true;
size_t comma = request.find(',');
size_t openBrace = request.find('{');
size_t openBracket = request.find('[');
if(openBrace != std::string::npos || openBracket != std::string::npos) fieldListOK = false;
if(openBrace != std::string::npos && (comma==std::string::npos || comma>openBrace)) {
//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<PVString*>(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<PVString*>(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<PVString*>(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 <epicsAssert.h>
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;
}