From 9755c3b016d8172428c55b03752e590379fe912e Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Tue, 5 Mar 2013 20:34:35 +0100 Subject: [PATCH] raw structure dump eget option, unspecified argument support --- testApp/remote/eget.cpp | 43 +++++++++++---- testApp/remote/pvutils.cpp | 3 +- testApp/remote/pvutils.h | 1 + testApp/remote/testServer.cpp | 98 ++++++++++++++++++++++++++++++----- 4 files changed, 120 insertions(+), 25 deletions(-) diff --git a/testApp/remote/eget.cpp b/testApp/remote/eget.cpp index f2b2dbd..c019f5b 100644 --- a/testApp/remote/eget.cpp +++ b/testApp/remote/eget.cpp @@ -816,11 +816,11 @@ void usage (void) " -h: Help: Print this message\n" "\noptions:\n" " -s : Service API compliant based RPC service name (accepts NTURI request argument)\n" - " -a : Service argument in form 'name=value'\n" + " -a : Service argument in form 'name[=value]'\n" " -r : Get request string, specifies what fields to return and options, default is '%s'\n" " -w : Wait time, specifies timeout, default is %f second(s)\n" " -q: Pure pvAccess RPC based service (send NTURI.query as request argument)\n" - " -n: Do not format NT types, dump structure instread." + " -n: Do not format NT types, dump structure instead.\n" " -t: Terse mode / transpose vector, table, matrix.\n" " -x: Use column-major order to decode matrix.\n" " -d: Enable debug output\n" @@ -1155,10 +1155,14 @@ int main (int argc, char *argv[]) size_t eqPos = param.find('='); if (eqPos==string::npos) { - fprintf(stderr, "Parameter not specified in name=value form. ('eget -h' for help.)\n"); - return 1; + //fprintf(stderr, "Parameter not specified in name=value form. ('eget -h' for help.)\n"); + //return 1; + parameters.push_back(pair(param, "")); + } + else + { + parameters.push_back(pair(param.substr(0, eqPos), param.substr(eqPos+1, string::npos))); } - parameters.push_back(pair(param.substr(0, eqPos), param.substr(eqPos+1, string::npos))); /* if (urlEncodedRequest.size()) urlEncodedRequest += '&'; @@ -1232,9 +1236,27 @@ int main (int argc, char *argv[]) Requester::shared_pointer requester(new RequesterImpl("eget")); + // parse URI + // try to parse as URI if only one nPvs + URI uri; + bool validURI = + (serviceRequest || nPvs == 1) ? + URI::parse(serviceRequest ? service : argv[optind], uri) : + false; + + // if there is only one nPvs and it's a valid URI that has ? character, + // then it's an service (RPC) request + if (validURI && uri.query_indicated) + { + service = argv[optind]; + serviceRequest = true; + } + // PVs mode if (!serviceRequest) { + // TODO URI support + vector pvs; /* Array of PV structures */ for (int n = 0; optind < argc; n++, optind++) pvs.push_back(argv[optind]); /* Copy PV names from command line */ @@ -1347,8 +1369,6 @@ int main (int argc, char *argv[]) { String authority; - URI uri; - bool validURI = URI::parse(service, uri); if (validURI) { if (uri.protocol != "pva") @@ -1385,10 +1405,11 @@ int main (int argc, char *argv[]) } else { - fprintf(stderr, "Parameter not specified in name=value form. ('eget -h' for help.)\n"); - // TODO - return 1; - } + //fprintf(stderr, "Parameter not specified in name=value form. ('eget -h' for help.)\n"); + //return 1; + string name(begin_i, pair_end_i); + parameters.push_back(pair(name, "")); + } begin_i = pair_end_i; if (begin_i != end_i) diff --git a/testApp/remote/pvutils.cpp b/testApp/remote/pvutils.cpp index 5c5a9b7..aab2432 100644 --- a/testApp/remote/pvutils.cpp +++ b/testApp/remote/pvutils.cpp @@ -314,7 +314,8 @@ bool URI::parse(const string& uri, URI& result) string::const_iterator query_i = find(path_i, fragment_i, '?'); result.path.assign(path_i, query_i); - if( query_i != fragment_i ) + result.query_indicated = (query_i != fragment_i); + if ( result.query_indicated ) result.query.assign(++query_i, fragment_i); return true; diff --git a/testApp/remote/pvutils.h b/testApp/remote/pvutils.h index a71864e..00d3bd7 100644 --- a/testApp/remote/pvutils.h +++ b/testApp/remote/pvutils.h @@ -32,6 +32,7 @@ public: static bool parse(const std::string& uri, URI& result); public: std::string protocol, host, path, query, fragment; + bool query_indicated; }; class RequesterImpl : diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index 2fd01e4..a09c964 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -23,6 +23,7 @@ using namespace epics::pvAccess; using namespace epics::pvData; using namespace std; using std::tr1::static_pointer_cast; +using std::tr1::dynamic_pointer_cast; // TODO temp #include "testNTImage.cpp" @@ -853,7 +854,36 @@ class MockChannelPutGet : public ChannelPutGet +static bool handleHelp( + epics::pvData::PVStructure::shared_pointer const & args, + ChannelRPCRequester::shared_pointer const & channelRPCRequester, + String const & helpText + ) +{ + if (args->getSubField("help")) + { + StringArray fieldNames(1); + FieldConstPtrArray fields(1); + fieldNames[0] = "value"; + fields[0] = getFieldCreate()->createScalar(pvString); + + PVStructure::shared_pointer result( + getPVDataCreate()->createPVStructure( + getFieldCreate()->createStructure( + "uri:ev4:nt/2012/pwd:NTScalar", fieldNames, fields) + ) + ); + + static_pointer_cast(result->getStringField("value"))->put(helpText); + channelRPCRequester->requestDone(Status::Ok, result); + return true; + } + else + { + return false; + } +} PVACCESS_REFCOUNT_MONITOR_DEFINE(mockChannelRPC); @@ -898,12 +928,18 @@ class MockChannelRPC : public ChannelRPC pvArgument ); - // TODO type check, getStringField is verbose - PVStringPtr columns = static_pointer_cast(args->getSubField("columns")); + const String helpText = + "Generates a NTTable structure response with 10 rows and a specified number of columns.\n" + "Columns are labeled 'column' and values are ' + random [0..1)'.\n" + "Arguments:\n\tstring columns\tnumber of table columns\n"; + if (handleHelp(args, m_channelRPCRequester, helpText)) + return; + + PVStringPtr columns = dynamic_pointer_cast(args->getSubField("columns")); if (columns.get() == 0) { PVStructure::shared_pointer nullPtr; - Status errorStatus(Status::STATUSTYPE_ERROR, "no 'columns' argument specified"); + Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'columns' argument specified"); m_channelRPCRequester->requestDone(errorStatus, nullPtr); } else @@ -970,12 +1006,18 @@ class MockChannelRPC : public ChannelRPC pvArgument ); - // TODO type check, getStringField is verbose - PVStringPtr columns = static_pointer_cast(args->getSubField("columns")); + const String helpText = + "Generates a NTNameValue structure response with a specified number of columns.\n" + "Columns are labeled 'name' and values are ' + random [0..1)'.\n" + "Arguments:\n\tstring columns\tnumber of columns\n"; + if (handleHelp(args, m_channelRPCRequester, helpText)) + return; + + PVStringPtr columns = dynamic_pointer_cast(args->getSubField("columns")); if (columns.get() == 0) { PVStructure::shared_pointer nullPtr; - Status errorStatus(Status::STATUSTYPE_ERROR, "no 'columns' argument specified"); + Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'columns' argument specified"); m_channelRPCRequester->requestDone(errorStatus, nullPtr); } else @@ -1025,12 +1067,22 @@ class MockChannelRPC : public ChannelRPC pvArgument ); - PVStringPtr rows = static_pointer_cast(args->getSubField("rows")); - PVStringPtr columns = static_pointer_cast(args->getSubField("columns")); + const String helpText = + "Generates a NTMatrix structure response with a specified number of rows and columns.\n" + "Matrix values are ' + random [0..1)'.\n" + "Arguments:\n" + "\tstring rows\tnumber of matrix rows\n" + "\tstring columns\tnumber of matrix columns\n" + "\t[string bycolumns\torder matrix values in a column-major order]\n"; + if (handleHelp(args, m_channelRPCRequester, helpText)) + return; + + PVStringPtr rows = dynamic_pointer_cast(args->getSubField("rows")); + PVStringPtr columns = dynamic_pointer_cast(args->getSubField("columns")); if (rows.get() == 0 || columns.get() == 0) { PVStructure::shared_pointer nullPtr; - Status errorStatus(Status::STATUSTYPE_ERROR, "no 'rows' and 'columns' arguments specified"); + Status errorStatus(Status::STATUSTYPE_ERROR, "no string 'rows' and 'columns' arguments specified"); m_channelRPCRequester->requestDone(errorStatus, nullPtr); } else @@ -1080,9 +1132,23 @@ class MockChannelRPC : public ChannelRPC pvArgument ); - PVStringPtr file = static_pointer_cast(args->getSubField("file")); - PVStringPtr w = static_pointer_cast(args->getSubField("w")); - PVStringPtr h = static_pointer_cast(args->getSubField("h")); + const String helpText = + "Generates a NTImage structure response that has encoded a specified image.\n" + "Arguments:\n" + "\tstring file\tfile path (relative to a location where the server was started) of a raw encoded image.\n" + "\t\t\tTwo image types are supported:\n" + "\t\t\t\t- RGB888 encoded (file extension '.rgb')\n" + "\t\t\t\t- 8-bit grayscale encoded (any other extension).\n" + "\t\t\tTo generate such encoded images you can use ImageMagick 'convert' tool, e.g.:\n" + "\t\t\t\tconvert my_image.png my_image.rgb\n" + "\tstring w\timage width\n" + "\tstring h\timage height\n"; + if (handleHelp(args, m_channelRPCRequester, helpText)) + return; + + PVStringPtr file = dynamic_pointer_cast(args->getSubField("file")); + PVStringPtr w = dynamic_pointer_cast(args->getSubField("w")); + PVStringPtr h = dynamic_pointer_cast(args->getSubField("h")); if (file.get() == 0 || w.get() == 0 || h.get() == 0) { PVStructure::shared_pointer nullPtr; @@ -1153,7 +1219,13 @@ class MockChannelRPC : public ChannelRPC } else if (m_channelName == "testNTURI") { - if (pvArgument->getStructure()->getID() != "uri:ev4:nt/2012/pwd:NTURI") + const String helpText = + "Returns the NTURI structure response identical the NTURI request.\n" + "Arguments: (none)\n"; + if (handleHelp(pvArgument, m_channelRPCRequester, helpText)) + return; + + if (pvArgument->getStructure()->getID() != "uri:ev4:nt/2012/pwd:NTURI") { PVStructure::shared_pointer nullPtr; Status errorStatus(Status::STATUSTYPE_ERROR, "argument is not a NTURI structure");