This commit is contained in:
Matej Sekoranja
2014-10-15 16:19:36 +02:00
11 changed files with 586 additions and 111 deletions
+2
View File
@@ -18,3 +18,5 @@ d720da04d44ae6ed4a9d548717f453a0fbaa9e56 3.0.4
ceca448e7c62c23388a0c866c905c7080633a875 4.0.0
ceca448e7c62c23388a0c866c905c7080633a875 4.0.0
cf6fc9696904fd1735523a70a4f59b5ad6a3f2d5 4.0.0
cf6fc9696904fd1735523a70a4f59b5ad6a3f2d5 4.0.0
91b7272415af8fdb5b81c98cc6c374558d2ab805 4.0.0
+26 -30
View File
@@ -157,29 +157,7 @@ void formatNTEnum(std::ostream& o, PVStructurePtr const & pvStruct)
return;
}
PVIntPtr index = dynamic_pointer_cast<PVInt>(enumt->getSubField("index"));
if (index.get() == 0)
{
std::cerr << "no int 'value.index' field in NTEnum" << std::endl;
return;
}
PVStringArrayPtr choices = dynamic_pointer_cast<PVStringArray>(enumt->getSubField("choices"));
if (choices.get() == 0)
{
std::cerr << "no string[] 'value.choices' field in NTEnum" << std::endl;
return;
}
int32 ix = index->get();
if (ix < 0 || ix > static_cast<int32>(choices->getLength()))
{
o << ix;
}
else
{
choices->dumpValue(o, ix);
}
printEnumT(o, enumt);
}
size_t getLongestString(shared_vector<const string> const & array)
@@ -886,7 +864,9 @@ void formatNT(std::ostream& o, PVFieldPtr const & pv)
else
{
std::cerr << "non-normative type" << std::endl;
o << *(pv.get()) << std::endl;
//o << *(pv.get()) << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(pv.get()) << std::endl;
}
return;
@@ -894,14 +874,21 @@ void formatNT(std::ostream& o, PVFieldPtr const & pv)
}
// no ID, just dump
o << *(pv.get()) << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(pv.get()) << std::endl;
}
void dumpValue(std::string const & channelName, PVField::shared_pointer const & pv)
{
if (!channelName.empty())
std::cout << channelName << std::endl;
std::cout << *(pv.get()) << std::endl << std::endl;
//std::cout << *(pv.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
if (pv->getField()->getType() == structure)
myos << *(static_pointer_cast<PVStructure>(pv).get()) << std::endl << std::endl;
else
myos << *(pv.get()) << std::endl << std::endl;
}
void printValue(std::string const & channelName, PVStructure::shared_pointer const & pv, bool forceTerseWithName = false)
@@ -1045,7 +1032,7 @@ void usage (void)
" -r <pv request>: Get request string, specifies what fields to return and options, default is '%s'\n"
" -w <sec>: Wait time, specifies timeout, default is %f second(s)\n"
" -z: Pure pvAccess RPC based service (send NTURI.query as request argument)\n"
" -n: Do not format NT types, dump structure instead\n"
" -N: Do not format NT types, dump structure instead\n"
" -t: Terse mode\n"
" -T: Transpose vector, table, matrix\n"
" -m: Monitor mode\n"
@@ -1056,6 +1043,8 @@ void usage (void)
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
" -f <input file>: Use <input file> as an input that provides a list PV name(s) to be read, use '-' for stdin\n"
" -c: Wait for clean shutdown and report used instance count (for expert users)"
" enum format:\n"
" -n: Force enum interpretation of values as numbers (default is enum string)\n"
"\n\nexamples:\n\n"
"#! Get the value of the PV corr:li32:53:bdes\n"
"> eget corr:li32:53:bdes\n"
@@ -1472,7 +1461,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
while ((opt = getopt(argc, argv, ":hr:s:a:w:zntTmxp:qdcF:f:")) != -1) {
while ((opt = getopt(argc, argv, ":hr:s:a:w:zNtTmxp:qdcF:f:n")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -1539,7 +1528,7 @@ int main (int argc, char *argv[])
case 'z': /* pvAccess RPC mode */
onlyQuery = true;
break;
case 'n': /* Do not format NT types */
case 'N': /* Do not format NT types */
dumpStructure = true;
break;
case 't': /* Terse mode */
@@ -1601,6 +1590,9 @@ int main (int argc, char *argv[])
fromStream = true;
break;
}
case 'n':
setEnumPrintMode(NumberEnum);
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('eget -h' for help.)\n",
@@ -2102,7 +2094,11 @@ int main (int argc, char *argv[])
if (rpcRequesterImpl->getLastResponse().get() == 0)
std::cout << "(null)" << std::endl;
else
std::cout << *(rpcRequesterImpl->getLastResponse().get()) << std::endl;
{
//std::cout << *(rpcRequesterImpl->getLastResponse().get()) << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(rpcRequesterImpl->getLastResponse().get()) << std::endl;
}
}
else
formatNT(std::cout, rpcRequesterImpl->getLastResponse());
+51 -12
View File
@@ -57,6 +57,8 @@ void usage (void)
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
" -f <input file>: Use <input file> as an input that provides a list PV name(s) to be read, use '-' for stdin\n"
" -c: Wait for clean shutdown and report used instance count (for expert users)\n"
" enum format:\n"
" -n: Force enum interpretation of values as numbers (default is enum string)\n"
"\nexample: pvget double01\n\n"
, DEFAULT_REQUEST, DEFAULT_TIMEOUT);
}
@@ -69,16 +71,30 @@ void printValue(std::string const & channelName, PVStructure::shared_pointer con
if (value.get() == 0)
{
std::cerr << "no 'value' field" << std::endl;
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
//std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
else
{
Type valueType = value->getField()->getType();
if (valueType != scalar && valueType != scalarArray)
{
// switch to structure mode
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
// switch to structure mode, unless it's NTEnum
if (value->getField()->getID() == "enum_t")
{
std::cout << std::setw(30) << std::left << channelName;
std::cout << fieldSeparator;
printEnumT(std::cout, static_pointer_cast<PVStructure>(value));
std::cout << std::endl;
}
else
{
//std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
}
else
{
if (fieldSeparator == ' ' && value->getField()->getType() == scalar)
@@ -95,7 +111,11 @@ void printValue(std::string const & channelName, PVStructure::shared_pointer con
else if (mode == TerseMode)
terseStructure(std::cout, pv) << std::endl;
else
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
{
//std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
}
@@ -255,17 +275,31 @@ class MonitorRequesterImpl : public MonitorRequester
{
std::cerr << "no 'value' field" << std::endl;
std::cout << m_channelName << std::endl;
std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
//std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(element->pvStructurePtr.get()) << std::endl << std::endl;
}
else
{
Type valueType = value->getField()->getType();
if (valueType != scalar && valueType != scalarArray)
{
// switch to structure mode
std::cout << m_channelName << std::endl;
std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
}
// switch to structure mode, unless it's NTEnum
if (value->getField()->getID() == "enum_t")
{
std::cout << std::setw(30) << std::left << m_channelName;
std::cout << fieldSeparator;
printEnumT(std::cout, static_pointer_cast<PVStructure>(value));
std::cout << std::endl;
}
else
{
std::cout << m_channelName << std::endl;
//std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(element->pvStructurePtr.get()) << std::endl << std::endl;
}
}
else
{
if (fieldSeparator == ' ' && value->getField()->getType() == scalar)
@@ -293,7 +327,9 @@ class MonitorRequesterImpl : public MonitorRequester
else
{
std::cout << m_channelName << std::endl;
std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
//std::cout << *(element->pvStructurePtr.get()) << std::endl << std::endl;
pvutil_ostream myos(std::cout.rdbuf());
myos << *(element->pvStructurePtr.get()) << std::endl << std::endl;
}
monitor->release(element);
@@ -339,7 +375,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
while ((opt = getopt(argc, argv, ":hr:w:tmqdcF:f:")) != -1) {
while ((opt = getopt(argc, argv, ":hr:w:tmqdcF:f:n")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -397,6 +433,9 @@ int main (int argc, char *argv[])
fromStream = true;
break;
}
case 'n':
setEnumPrintMode(NumberEnum);
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('pvget -h' for help.)\n",
+1 -1
View File
@@ -604,7 +604,7 @@ int main (int argc, char *argv[])
if (quiet)
cmd += 'q';
if (printInfo)
cmd += 'n';
cmd += 'N';
cmd += "s pva://" + serverAddress + "/server?op=";
if (printInfo)
cmd += "info";
+182 -49
View File
@@ -28,6 +28,10 @@ using namespace std::tr1;
using namespace epics::pvData;
using namespace epics::pvAccess;
//EnumMode enumMode = AutoEnum;
size_t fromString(PVFieldPtr const & pv, StringArray const & from, size_t fromStartIndex);
size_t fromString(PVScalarArrayPtr const &pv, StringArray const & from, size_t fromStartIndex = 0)
{
int processed = 0;
@@ -98,68 +102,164 @@ size_t fromString(PVStructureArrayPtr const &pv, StringArray const & from, size_
return processed;
}
size_t fromString(PVUnionArrayPtr const & pvUnionArray, StringArray const & from, size_t fromStartIndex);
size_t fromString(PVUnionPtr const & pvUnion, StringArray const & from, size_t fromStartIndex = 0)
{
if (pvUnion->getUnion()->isVariant())
throw std::runtime_error("cannot handle variant unions");
size_t fromValueCount = from.size();
if (fromStartIndex >= fromValueCount)
throw std::runtime_error("not enough of values");
string selector = from[fromStartIndex++];
PVFieldPtr pv = pvUnion->select(selector);
if (!pv)
throw std::runtime_error("invalid union selector value '" + selector + "'");
size_t processed = fromString(pv, from, fromStartIndex);
return processed + 1;
}
size_t fromString(PVUnionArrayPtr const &pv, StringArray const & from, size_t fromStartIndex = 0)
{
int processed = 0;
size_t fromValueCount = from.size();
// first get count
if (fromStartIndex >= fromValueCount)
throw std::runtime_error("not enough of values");
size_t numberOfUnions;
istringstream iss(from[fromStartIndex]);
iss >> numberOfUnions;
// not fail and entire value is parsed (e.g. to detect 1.2 parsing to 1)
if (iss.fail() || !iss.eof())
throw runtime_error("failed to parse element count value (uint) of field '" + pv->getFieldName() + "' from string value '" + from[fromStartIndex] + "'");
fromStartIndex++;
processed++;
PVUnionArray::svector pvUnions;
pvUnions.reserve(numberOfUnions);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for (size_t i = 0; i < numberOfUnions; ++i)
{
PVUnionPtr pvUnion = pvDataCreate->createPVUnion(pv->getUnionArray()->getUnion());
size_t count = fromString(pvUnion, from, fromStartIndex);
processed += count;
fromStartIndex += count;
pvUnions.push_back(pvUnion);
}
pv->replace(freeze(pvUnions));
return processed;
}
size_t fromString(PVStructurePtr const & pvStructure, StringArray const & from, size_t fromStartIndex = 0)
{
// handle enum in a special way
if (pvStructure->getStructure()->getID() == "enum_t")
{
int32 index = -1;
PVInt::shared_pointer pvIndex = pvStructure->getSubField<PVInt>("index");
if (!pvIndex)
throw std::runtime_error("enum_t structure does not have 'int index' field");
PVStringArray::shared_pointer pvChoices = pvStructure->getSubField<PVStringArray>("choices");
if (!pvChoices)
throw std::runtime_error("enum_t structure does not have 'string choices[]' field");
PVStringArray::const_svector choices(pvChoices->view());
if (enumMode == AutoEnum || enumMode == StringEnum)
{
shared_vector<string>::const_iterator it = std::find(choices.begin(), choices.end(), from[fromStartIndex]);
if (it != choices.end())
index = static_cast<int32>(it - choices.begin());
else if (enumMode == StringEnum)
throw runtime_error("enum string value '" + from[fromStartIndex] + "' invalid");
}
if ((enumMode == AutoEnum && index == -1) || enumMode == NumberEnum)
{
istringstream iss(from[fromStartIndex]);
iss >> index;
// not fail and entire value is parsed (e.g. to detect 1.2 parsing to 1)
if (iss.fail() || !iss.eof())
throw runtime_error("enum value '" + from[fromStartIndex] + "' invalid");
if (index < 0 || index >= static_cast<int32>(choices.size()))
throw runtime_error("index '" + from[fromStartIndex] + "' out of bounds");
}
pvIndex->put(index);
return 1;
}
size_t processed = 0;
size_t fromValueCount = from.size();
PVFieldPtrArray const & fieldsData = pvStructure->getPVFields();
if (fieldsData.size() != 0) {
size_t length = pvStructure->getStructure()->getNumberFields();
for(size_t i = 0; i < length; i++) {
PVFieldPtr fieldField = fieldsData[i];
try
{
Type type = fieldField->getField()->getType();
// TODO union/unionArray support
if(type==structure) {
PVStructurePtr pv = static_pointer_cast<PVStructure>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else if(type==scalarArray) {
PVScalarArrayPtr pv = static_pointer_cast<PVScalarArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else if(type==scalar) {
if (fromStartIndex >= fromValueCount)
throw std::runtime_error("not enough of values");
PVScalarPtr pv = static_pointer_cast<PVScalar>(fieldField);
getConvert()->fromString(pv, from[fromStartIndex++]);
processed++;
}
else if(type==structureArray) {
PVStructureArrayPtr pv = static_pointer_cast<PVStructureArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else {
// union/unionArray not supported
std::ostringstream oss;
oss << "fromString unsupported fieldType " << type;
throw std::logic_error(oss.str());
}
}
catch (std::exception &ex)
{
std::ostringstream os;
os << "failed to parse '" << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << "'";
os << ": " << ex.what();
throw std::runtime_error(os.str());
}
size_t count = fromString(fieldsData[i], from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
}
return processed;
}
size_t fromString(PVFieldPtr const & fieldField, StringArray const & from, size_t fromStartIndex)
{
try
{
switch (fieldField->getField()->getType())
{
case scalar:
{
if (fromStartIndex >= from.size())
throw std::runtime_error("not enough of values");
PVScalarPtr pv = static_pointer_cast<PVScalar>(fieldField);
getConvert()->fromString(pv, from[fromStartIndex]);
return 1;
}
case scalarArray:
return fromString(static_pointer_cast<PVScalarArray>(fieldField), from, fromStartIndex);
case structure:
return fromString(static_pointer_cast<PVStructure>(fieldField), from, fromStartIndex);
case structureArray:
return fromString(static_pointer_cast<PVStructureArray>(fieldField), from, fromStartIndex);
case union_:
return fromString(static_pointer_cast<PVUnion>(fieldField), from, fromStartIndex);
case unionArray:
return fromString(static_pointer_cast<PVUnionArray>(fieldField), from, fromStartIndex);
default:
std::ostringstream oss;
oss << "fromString unsupported fieldType " << fieldField->getField()->getType();
throw std::logic_error(oss.str());
}
}
catch (std::exception &ex)
{
std::ostringstream os;
os << "failed to parse '" << fieldField->getField()->getID() << ' '
<< fieldField->getFieldName() << "'";
os << ": " << ex.what();
throw std::runtime_error(os.str());
}
}
#define DEFAULT_TIMEOUT 3.0
@@ -185,10 +285,15 @@ void usage (void)
" -d: Enable debug output\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
" -f <input file>: Use <input file> as an input that provides a list PV name(s) to be read, use '-' for stdin\n"
" enum format:\n"
" default: Auto - try value as enum string, then as index number\n"
" -n: Force enum interpretation of values as numbers\n"
" -s: Force enum interpretation of values as strings\n"
"\nexample: pvput double01 1.234\n\n"
, DEFAULT_REQUEST, DEFAULT_TIMEOUT);
}
void printValue(std::string const & channelName, PVStructure::shared_pointer const & pv)
{
if (mode == ValueOnlyMode)
@@ -204,6 +309,27 @@ void printValue(std::string const & channelName, PVStructure::shared_pointer con
Type valueType = value->getField()->getType();
if (valueType != scalar && valueType != scalarArray)
{
// special case for enum
if (valueType == structure)
{
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(value);
if (pvStructure->getStructure()->getID() == "enum_t")
{
if (fieldSeparator == ' ')
std::cout << std::setw(30) << std::left << channelName;
else
std::cout << channelName;
std::cout << fieldSeparator;
printEnumT(std::cout, pvStructure);
std::cout << std::endl;
return;
}
}
// switch to structure mode
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
@@ -416,7 +542,7 @@ int main (int argc, char *argv[])
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
putenv(const_cast<char*>("POSIXLY_CORRECT=")); /* Behave correct on GNU getopt systems; e.g. handle negative numbers */
while ((opt = getopt(argc, argv, ":hr:w:tqdF:f:")) != -1) {
while ((opt = getopt(argc, argv, ":hr:w:tqdF:f:ns")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -468,6 +594,12 @@ int main (int argc, char *argv[])
fromStream = true;
break;
}
case 'n':
enumMode = NumberEnum;
break;
case 's':
enumMode = StringEnum;
break;
case '?':
fprintf(stderr,
"Unrecognized option: '-%c'. ('pvput -h' for help.)\n",
@@ -535,6 +667,7 @@ int main (int argc, char *argv[])
std::cout << std::boolalpha;
terseSeparator(fieldSeparator);
setEnumPrintMode(enumMode);
ClientFactory::start();
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
+82
View File
@@ -10,6 +10,7 @@
#include <algorithm>
#include <pv/logger.h>
#include <pv/pvTimeStamp.h>
using namespace std;
using namespace std::tr1;
@@ -68,6 +69,18 @@ void terseArrayCount(bool flag)
arrayCountFlag = flag;
}
EnumMode enumMode = AutoEnum;
void setEnumPrintMode(EnumMode mode)
{
enumMode = mode;
}
bool formatTTypesFlag = true;
void formatTTypes(bool flag)
{
formatTTypesFlag = flag;
}
std::ostream& terse(std::ostream& o, PVField::shared_pointer const & pv)
{
@@ -99,6 +112,59 @@ std::ostream& terse(std::ostream& o, PVField::shared_pointer const & pv)
}
}
std::ostream& printEnumT(std::ostream& o, epics::pvData::PVStructure const & pvEnumT)
{
PVInt::shared_pointer pvIndex = pvEnumT.getSubField<PVInt>("index");
if (!pvIndex)
throw std::runtime_error("enum_t structure does not have 'int index' field");
PVStringArray::shared_pointer pvChoices = pvEnumT.getSubField<PVStringArray>("choices");
if (!pvChoices)
throw std::runtime_error("enum_t structure does not have 'string choices[]' field");
if (enumMode == AutoEnum || enumMode == StringEnum)
{
int32 ix = pvIndex->get();
if (ix < 0 || ix > static_cast<int32>(pvChoices->getLength()))
o << ix;
else
pvChoices->dumpValue(o, ix);
}
else
o << pvIndex->get();
return o;
}
std::ostream& printEnumT(std::ostream& o, epics::pvData::PVStructure::shared_pointer const & pvEnumT)
{
return printEnumT(o, *pvEnumT);
}
std::ostream& printTimeT(std::ostream& o, epics::pvData::PVStructure::shared_pointer const & pvTimeT)
{
#define TIMETEXTLEN 32
char timeText[TIMETEXTLEN];
epicsTimeStamp epicsTS;
PVTimeStamp pvTimeStamp;
if (pvTimeStamp.attach(pvTimeT))
{
TimeStamp ts;
pvTimeStamp.get(ts);
epicsTS.secPastEpoch = ts.getEpicsSecondsPastEpoch();
epicsTS.nsec = ts.getNanoseconds();
}
else
throw std::runtime_error("invalid time_t structure");
epicsTimeToStrftime(timeText, TIMETEXTLEN, "%Y-%m-%dT%H:%M:%S.%03f", &epicsTS);
o << timeText;
return o;
}
std::ostream& terseStructure(std::ostream& o, PVStructure::shared_pointer const & pvStructure)
{
if (!pvStructure)
@@ -107,6 +173,22 @@ std::ostream& terseStructure(std::ostream& o, PVStructure::shared_pointer const
return o;
}
// special t-types support (enum_t and time_t, etc.)
if (formatTTypesFlag)
{
string id = pvStructure->getStructure()->getID();
if (id == "enum_t")
{
printEnumT(o, pvStructure);
return o;
}
else if (id == "time_t")
{
printTimeT(o, pvStructure);
return o;
}
}
PVFieldPtrArray fieldsData = pvStructure->getPVFields();
size_t length = pvStructure->getStructure()->getNumberFields();
bool first = true;
+199
View File
@@ -16,6 +16,15 @@ std::ostream& terseScalarArray(std::ostream& o, epics::pvData::PVScalarArray::sh
std::ostream& terseStructureArray(std::ostream& o, epics::pvData::PVStructureArray::shared_pointer const & pvArray);
std::ostream& terseUnionArray(std::ostream& o, epics::pvData::PVUnionArray::shared_pointer const & pvArray);
enum EnumMode { AutoEnum, NumberEnum, StringEnum };
void setEnumPrintMode(EnumMode mode);
void formatTTypes(bool flag);
std::ostream& printEnumT(std::ostream& o, epics::pvData::PVStructure const & pvEnumT);
//std::ostream& printTimeT(std::ostream& o, epics::pvData::PVStructure const & pvTimeT);
std::ostream& printEnumT(std::ostream& o, epics::pvData::PVStructure::shared_pointer const & pvEnumT);
std::ostream& printTimeT(std::ostream& o, epics::pvData::PVStructure::shared_pointer const & pvTimeT);
/* Converts a hex character to its integer value */
char from_hex(char ch);
@@ -103,3 +112,193 @@ struct dump_stack_only_on_debug
};
std::ostream& operator<<(std::ostream& os, const dump_stack_only_on_debug& d);
#include <ostream>
#include <iostream>
// usage: pvutil_ostream myos(std::cout.rdbuf());
class pvutil_ostream : private std::ostream
{
public:
pvutil_ostream(std::streambuf* sb)
: std::ostream(sb)
{}
template <typename T>
friend pvutil_ostream& operator<<(pvutil_ostream&, const T&);
friend pvutil_ostream& dumpPVStructure(pvutil_ostream&, const epics::pvData::PVStructure &, bool);
// Additional overload to handle ostream specific io manipulators
friend pvutil_ostream& operator<<(pvutil_ostream&, std::ostream& (*)(std::ostream&));
// Accessor function to get a reference to the ostream
std::ostream& get_ostream() { return *this; }
};
template <typename T>
inline pvutil_ostream&
operator<<(pvutil_ostream& out, const T& value)
{
static_cast<std::ostream&>(out) << value;
return out;
}
// overload for std::ostream specific io manipulators
inline pvutil_ostream&
operator<<(pvutil_ostream& out, std::ostream& (*func)(std::ostream&))
{
static_cast<std::ostream&>(out) << func;
return out;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVField::shared_pointer & fieldField);
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVStructure & value);
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVUnion::shared_pointer & value);
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVStructure::shared_pointer & value)
{
std::string id = value->getStructure()->getID();
if (id == "enum_t")
{
o << epics::pvData::format::indent() << id << ' ' << value->getFieldName() << " # ";
printEnumT(o, value);
o << std::endl;
dumpPVStructure(o, *value, false);
return o;
}
else if (id == "time_t")
{
o << epics::pvData::format::indent() << id << ' ' << value->getFieldName() << " # ";
printTimeT(o, value);
o << std::endl;
dumpPVStructure(o, *value, false);
return o;
}
return o << *value;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVStructureArray::shared_pointer & value)
{
o << epics::pvData::format::indent() << value->getStructureArray()->getID()
<< ' ' << value->getFieldName() << std::endl;
size_t length = value->getLength();
if (length > 0)
{
epics::pvData::format::indent_scope s(o);
epics::pvData::PVStructureArray::const_svector data(value->view());
for (size_t i = 0; i < length; i++)
o << data[i];
}
return o;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVUnionArray::shared_pointer & value)
{
o << epics::pvData::format::indent() << value->getUnionArray()->getID()
<< ' ' << value->getFieldName() << std::endl;
size_t length = value->getLength();
if (length > 0)
{
epics::pvData::format::indent_scope s(o);
epics::pvData::PVUnionArray::const_svector data(value->view());
for (size_t i = 0; i < length; i++)
o << data[i];
}
return o;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVUnion::shared_pointer & value)
{
o << epics::pvData::format::indent() << value->getUnion()->getID()
<< ' ' << value->getFieldName() << std::endl;
{
epics::pvData::format::indent_scope s(o);
epics::pvData::PVFieldPtr fieldField = value->get();
if (fieldField.get() == NULL)
o << epics::pvData::format::indent() << "(none)" << std::endl;
else
o << fieldField;
}
return o;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVField::shared_pointer & fieldField)
{
epics::pvData::Type type = fieldField->getField()->getType();
if (type == epics::pvData::scalar || type == epics::pvData::scalarArray)
o << epics::pvData::format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
else if (type == epics::pvData::structure)
o << std::tr1::static_pointer_cast<epics::pvData::PVStructure>(fieldField);
else if (type == epics::pvData::structureArray)
o << std::tr1::static_pointer_cast<epics::pvData::PVStructureArray>(fieldField);
else if (type == epics::pvData::union_)
o << std::tr1::static_pointer_cast<epics::pvData::PVUnion>(fieldField);
else if (type == epics::pvData::unionArray)
o << std::tr1::static_pointer_cast<epics::pvData::PVUnionArray>(fieldField);
else
throw std::runtime_error("unsupported type");
return o;
}
pvutil_ostream&
dumpPVStructure(pvutil_ostream& o, const epics::pvData::PVStructure & value, bool showHeader)
{
if (showHeader)
{
std::string id = value.getStructure()->getID();
o << epics::pvData::format::indent() << id << ' ' << value.getFieldName();
o << std::endl;
}
{
epics::pvData::format::indent_scope s(o);
epics::pvData::PVFieldPtrArray const & fieldsData = value.getPVFields();
if (fieldsData.size() != 0) {
size_t length = value.getStructure()->getNumberFields();
for(size_t i=0; i<length; i++) {
o << fieldsData[i];
}
}
}
return o;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& o, const epics::pvData::PVStructure& value)
{
return dumpPVStructure(o, value, true);
}
+1 -1
View File
@@ -25,7 +25,7 @@
// module version
// TODO to be generated, etc.
#define EPICS_PVA_MAJOR_VERSION 4
#define EPICS_PVA_MINOR_VERSION 1
#define EPICS_PVA_MINOR_VERSION 0
#define EPICS_PVA_MAINTENANCE_VERSION 0
#define EPICS_PVA_DEVELOPMENT_FLAG 1
+40 -16
View File
@@ -451,6 +451,10 @@ public:
return _waitEvent.wait(timeoutSec);
}
void resetEvent() {
_waitEvent.tryWait();
}
private:
epics::pvData::Mutex _waitMutex;
epics::pvData::Event _waitEvent;
@@ -504,24 +508,44 @@ public:
string op = opField->get();
if (op == "channels")
{
ChannelListRequesterImpl::shared_pointer listListener(new ChannelListRequesterImpl());
m_serverContext->getChannelProviders()[0]->channelList(listListener); // TODO multiple channel providers !!!!
if (!listListener->waitForCompletion(TIMEOUT_SEC))
throw RPCRequestException(Status::STATUSTYPE_ERROR, "failed to fetch channel list due to timeout");
Status& status = listListener->status;
if (!status.isSuccess())
{
string errorMessage = "failed to fetch channel list: " + status.getMessage();
if (!status.getStackDump().empty())
errorMessage += "\n" + status.getStackDump();
throw RPCRequestException(Status::STATUSTYPE_ERROR, errorMessage);
}
PVStructure::shared_pointer result =
getPVDataCreate()->createPVStructure(channelListStructure);
PVStringArray::shared_pointer pvArray = result->getSubField<PVStringArray>("value");
pvArray->replace(listListener->channelNames);
PVStringArray::shared_pointer allChannelNames = result->getSubField<PVStringArray>("value");
ChannelListRequesterImpl::shared_pointer listListener(new ChannelListRequesterImpl());
std::vector<ChannelProvider::shared_pointer> providers = m_serverContext->getChannelProviders();
size_t providerCount = providers.size();
for (size_t i = 0; i < providerCount; i++)
{
providers[i]->channelList(listListener);
if (!listListener->waitForCompletion(TIMEOUT_SEC))
throw RPCRequestException(Status::STATUSTYPE_ERROR, "failed to fetch channel list due to timeout");
Status& status = listListener->status;
if (!status.isSuccess())
{
string errorMessage = "failed to fetch channel list: " + status.getMessage();
if (!status.getStackDump().empty())
errorMessage += "\n" + status.getStackDump();
throw RPCRequestException(Status::STATUSTYPE_ERROR, errorMessage);
}
// optimization
if (providerCount == 1)
{
allChannelNames->replace(listListener->channelNames);
}
else
{
PVStringArray::svector list(allChannelNames->reuse());
std::copy(listListener->channelNames.begin(), listListener->channelNames.end(),
back_inserter(list));
allChannelNames->replace(freeze(list));
}
listListener->resetEvent();
}
return result;
}
+1 -1
View File
@@ -645,7 +645,7 @@ void ServerContextImpl::setChannelProviderName(std::string channelProviderName)
_channelProviderNames = channelProviderName;
}
std::vector<ChannelProvider::shared_pointer> ServerContextImpl::getChannelProviders()
std::vector<ChannelProvider::shared_pointer>& ServerContextImpl::getChannelProviders()
{
return _channelProviders;
}
+1 -1
View File
@@ -291,7 +291,7 @@ public:
* Get channel providers.
* @return channel providers.
*/
std::vector<ChannelProvider::shared_pointer> getChannelProviders();
std::vector<ChannelProvider::shared_pointer>& getChannelProviders();
/**
* Return <code>true</code> if channel provider name is provided by configuration (e.g. system env. var.).