enum_t/time_t print in terse mode

This commit is contained in:
Matej Sekoranja
2014-10-15 12:01:43 +02:00
parent b3e9ceca10
commit 1e2f335c61
6 changed files with 251 additions and 145 deletions

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)
@ -1045,7 +1023,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 +1034,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 +1452,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 +1519,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 +1581,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",

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);
}
@ -95,7 +97,12 @@ 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;
//pvutil_ostream myos(std::cout.rdbuf());
//myos << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
}
}
@ -339,7 +346,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 +404,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",

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";

View File

@ -28,8 +28,9 @@ using namespace std::tr1;
using namespace epics::pvData;
using namespace epics::pvAccess;
enum EnumMode { AutoEnum, NumberEnum, StringEnum };
EnumMode enumMode = AutoEnum;
//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)
{
@ -114,64 +115,12 @@ size_t fromString(PVUnionPtr const & pvUnion, StringArray const & from, size_t f
throw std::runtime_error("not enough of values");
string selector = from[fromStartIndex++];
PVFieldPtr fieldField = pvUnion->select(selector);
if (!fieldField)
PVFieldPtr pv = pvUnion->select(selector);
if (!pv)
throw std::runtime_error("invalid union selector value '" + selector + "'");
size_t processed = 1;
try
{
Type type = fieldField->getField()->getType();
if(type==structure) {
PVStructurePtr pv = static_pointer_cast<PVStructure>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
}
else if(type==scalarArray) {
PVScalarArrayPtr pv = static_pointer_cast<PVScalarArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += 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;
}
else if(type==union_) {
PVUnionPtr pv = static_pointer_cast<PVUnion>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
}
else if(type==unionArray) {
PVUnionArrayPtr pv = static_pointer_cast<PVUnionArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
}
else {
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());
}
return processed;
size_t processed = fromString(pv, from, fromStartIndex);
return processed + 1;
}
size_t fromString(PVUnionArrayPtr const &pv, StringArray const & from, size_t fromStartIndex = 0)
@ -251,76 +200,68 @@ size_t fromString(PVStructurePtr const & pvStructure, StringArray const & from,
}
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();
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++;
fromStartIndex++;
}
else if(type==structureArray) {
PVStructureArrayPtr pv = static_pointer_cast<PVStructureArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else if(type==union_) {
PVUnionPtr pv = static_pointer_cast<PVUnion>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else if(type==unionArray) {
PVUnionArrayPtr pv = static_pointer_cast<PVUnionArray>(fieldField);
size_t count = fromString(pv, from, fromStartIndex);
processed += count;
fromStartIndex += count;
}
else {
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
#define DEFAULT_REQUEST "field(value)"
@ -368,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;
}
@ -705,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");

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,54 @@ std::ostream& terse(std::ostream& o, PVField::shared_pointer const & pv)
}
}
std::ostream& printEnumT(std::ostream& o, epics::pvData::PVStructure::shared_pointer 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& 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 +168,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;

View File

@ -16,6 +16,13 @@ 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::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 +110,69 @@ 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&);
// 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) << '.';
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) << '#';
static_cast<std::ostream&>(out) << func;
return out;
}
// overload for PVField
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& out, const epics::pvData::PVField& value)
{
static_cast<std::ostream&>(out) << '?';
// static_cast<std::ostream&>(out) << value;
value.dumpValue(out);
return out;
}
template <>
inline pvutil_ostream&
operator<<(pvutil_ostream& out, const epics::pvData::PVStructure& value)
{
static_cast<std::ostream&>(out) << '!';
// static_cast<std::ostream&>(out) << value;
value.dumpValue(out);
return out;
}
*/