pva-tools: added quiet option, compact ouput of a table, transpose vs terse

This commit is contained in:
Matej Sekoranja
2013-06-11 13:39:56 +02:00
parent 6fc58f992d
commit 99f97b440f
5 changed files with 136 additions and 51 deletions
+107 -42
View File
@@ -18,6 +18,7 @@
#include <iomanip>
#include <map>
#include <pv/convert.h>
#include <pv/event.h>
#include <epicsExit.h>
@@ -35,6 +36,8 @@ char fieldSeparator = ' ';
bool columnMajor = false;
bool transpose = false;
void formatNTAny(std::ostream& o, PVStructurePtr const & pvStruct)
{
PVFieldPtr value = pvStruct->getSubField("value");
@@ -125,7 +128,7 @@ void formatNTScalarArray(std::ostream& o, PVStructurePtr const & pvStruct)
//o << *value;
//formatScalarArray(o, value);
formatVector(o, "", value, mode == TerseMode);
formatVector(o, "", value, mode == TerseMode || transpose);
}
void formatNTEnum(std::ostream& o, PVStructurePtr const & pvStruct)
@@ -197,14 +200,14 @@ size_t getLongestString(PVScalarArrayPtr const & array)
void formatTable(std::ostream& o,
vector<String> const & labels,
vector<PVScalarArrayPtr> const & columnData,
bool transpose)
bool showHeader, bool transpose)
{
// array with maximum number of elements
size_t maxValues = 0;
// value with longest string form
size_t maxColumnLength = labels.size() ? getLongestString(labels) : 0;
size_t maxLabelColumnLength = (showHeader && labels.size()) ? getLongestString(labels) : 0;
size_t maxColumnLength = 0;
//
// get maxValue and maxColumnLength
//
@@ -228,6 +231,13 @@ void formatTable(std::ostream& o,
if (!transpose)
{
/* non-compact
maxLabelColumnLength += padding;
// increase maxColumnLength to maxLabelColumnLength
if (maxLabelColumnLength > maxColumnLength)
maxColumnLength = maxLabelColumnLength;
*/
//
// <column0>, <column1>, ...
@@ -235,11 +245,13 @@ void formatTable(std::ostream& o,
//
// first print labels
if (labels.size())
if (showHeader && labels.size())
{
for (size_t i = 0; i < numColumns; i++)
{
o << std::setw(maxColumnLength) << std::right << labels[i];
int width = std::max(labels[i].size()+padding, maxColumnLength);
o << std::setw(width) << std::right << labels[i];
// non-compact o << std::setw(maxColumnLength) << std::right << labels[i];
}
o << std::endl;
}
@@ -249,7 +261,9 @@ void formatTable(std::ostream& o,
{
for (size_t i = 0; i < numColumns; i++)
{
o << std::setw(maxColumnLength) << std::right;
int width = std::max(labels[i].size()+padding, maxColumnLength);
o << setw(width) << std::right;
// non-compact o << std::setw(maxColumnLength) << std::right;
PVScalarArrayPtr array = columnData[i];
if (array.get() && r < array->getLength())
array->dumpValue(o, r);
@@ -271,8 +285,8 @@ void formatTable(std::ostream& o,
for (size_t i = 0; i < numColumns; i++)
{
if (labels.size())
o << std::setw(maxColumnLength) << std::left << labels[i];
if (showHeader && labels.size())
o << std::setw(maxLabelColumnLength) << std::left << labels[i];
for (size_t r = 0; r < maxValues; r++)
{
@@ -331,7 +345,8 @@ void formatNTTable(std::ostream& o, PVStructurePtr const & pvStruct)
StringArrayData labelsData;
labels->get(0, numColumns, labelsData);
formatTable(o, labelsData.data, columnData, mode == TerseMode);
bool showHeader = (mode != TerseMode);
formatTable(o, labelsData.data, columnData, showHeader, transpose);
}
@@ -388,8 +403,7 @@ void formatNTMatrix(std::ostream& o, PVStructurePtr const & pvStruct)
size_t padding = 2;
size_t maxColumnLength = getLongestString(value) + padding;
// TerseMode as Transpose
if (mode != TerseMode)
if (!transpose)
{
//
@@ -471,19 +485,25 @@ void formatNTNameValue(std::ostream& o, PVStructurePtr const & pvStruct)
StringArrayData nameData;
name->get(0, name->getLength(), nameData);
// get max column size
size_t maxColumnLength = getLongestString(nameData.data);
// get max column name size
bool showHeader = (mode != TerseMode);
size_t maxLabelColumnLength = showHeader ? getLongestString(nameData.data) : 0;
size_t valueLen = getLongestString(array);
if (valueLen > maxColumnLength) maxColumnLength = valueLen;
size_t maxColumnLength = getLongestString(array);
// add some space
size_t padding = 2;
maxColumnLength += padding;
bool transpose = (mode == TerseMode);
if (transpose)
{
/* non-compact
maxLabelColumnLength += padding;
// increase maxColumnLength to maxLabelColumnLength
if (maxLabelColumnLength > maxColumnLength)
maxColumnLength = maxLabelColumnLength;
*/
//
// <name0>, <name1>, ...
@@ -491,16 +511,23 @@ void formatNTNameValue(std::ostream& o, PVStructurePtr const & pvStruct)
//
// first print names
for (size_t i = 0; i < numColumns; i++)
if (showHeader)
{
o << std::setw(maxColumnLength) << std::right << nameData.data[i];
for (size_t i = 0; i < numColumns; i++)
{
int width = std::max(nameData.data[i].size()+padding, maxColumnLength);
o << std::setw(width) << std::right << nameData.data[i];
// non-compact o << std::setw(maxColumnLength) << std::right << nameData.data[i];
}
o << std::endl;
}
o << std::endl;
// then values
for (size_t i = 0; i < numColumns; i++)
{
o << std::setw(maxColumnLength) << std::right;
int width = std::max(nameData.data[i].size()+padding, maxColumnLength);
o << std::setw(width) << std::right;
// non-compact o << std::setw(maxColumnLength) << std::right;
array->dumpValue(o, i);
}
o << std::endl;
@@ -516,7 +543,8 @@ void formatNTNameValue(std::ostream& o, PVStructurePtr const & pvStruct)
for (size_t i = 0; i < numColumns; i++)
{
o << std::setw(maxColumnLength) << std::left << nameData.data[i];
if (showHeader)
o << std::setw(maxLabelColumnLength) << std::left << nameData.data[i];
o << std::setw(maxColumnLength) << std::right;
array->dumpValue(o, i);
o << std::endl;
@@ -760,17 +788,28 @@ void formatNT(std::ostream& o, PVFieldPtr const & pv)
o << *(pv.get()) << std::endl;
}
void printValue(String const & channelName, PVStructure::shared_pointer const & pv)
void dumpValue(String const & channelName, PVField::shared_pointer const & pv)
{
if (mode == ValueOnlyMode)
if (!channelName.empty())
std::cout << channelName << std::endl;
std::cout << *(pv.get()) << std::endl << std::endl;
}
void printValue(String const & channelName, PVStructure::shared_pointer const & pv, bool forceTerseWithName = false)
{
if (forceTerseWithName)
{
if (!channelName.empty())
std::cout << channelName << separator;
terseStructure(std::cout, pv) << std::endl;
}
else if (mode == ValueOnlyMode)
{
PVField::shared_pointer value = pv->getSubField("value");
if (value.get() == 0)
{
std::cerr << "no 'value' field" << std::endl;
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
dumpValue(channelName, pv);
}
else
{
@@ -791,17 +830,20 @@ void printValue(String const & channelName, PVStructure::shared_pointer const &
std::cout << std::endl;
}
else
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
dumpValue(channelName, pv);
}
}
}
else if (mode == TerseMode)
terseStructure(std::cout, pv) << std::endl;
else
std::cout << channelName << std::endl << *(pv.get()) << std::endl << std::endl;
dumpValue(channelName, pv);
}
static String emptyString;
// only in ValueOnlyMode
// NOTE: names might be empty
void printValues(vector<string> const & names, vector<PVStructure::shared_pointer> const & values)
{
size_t len = values.size();
@@ -819,11 +861,24 @@ void printValues(vector<string> const & names, vector<PVStructure::shared_pointe
scalarArrays.push_back(dynamic_pointer_cast<PVScalarArray>(value));
else if (type == scalar)
{
scalars.push_back(dynamic_pointer_cast<PVScalar>(value));
PVScalar::shared_pointer scalar = dynamic_pointer_cast<PVScalar>(value);
scalars.push_back(scalar);
// TODO also try to make an PVStringArray out of a scalar
// make an array, i.e. PVStringArray, out of a scalar (since scalar is an array w/ element count == 1)
PVStringArray::shared_pointer stringArray =
dynamic_pointer_cast<PVStringArray>(getPVDataCreate()->createPVScalarArray(pvString));
StringArray values;
values.reserve(1);
values.push_back(getConvert()->toString(scalar));
stringArray->put(0, values.size(), values, 0);
scalarArrays.push_back(stringArray);
}
}
else
{
// a structure detected, break
break;
}
}
if (scalars.size() == len)
@@ -841,14 +896,15 @@ void printValues(vector<string> const & names, vector<PVStructure::shared_pointe
}
else if (scalarArrays.size() == len)
{
// TODO labels switch
formatTable(std::cout, names, scalarArrays, false);
// format as a table
bool showHeader = false; //(mode != TerseMode);
formatTable(std::cout, names, scalarArrays, showHeader, transpose);
}
else
{
// classic output
// force terse mode with names
for (size_t i = 0; i < len; i++)
printValue(names[i], values[i]);
printValue(names[i], values[i], true);
}
}
@@ -868,10 +924,12 @@ void usage (void)
" -a <service arg>: Service argument in form 'name[=value]'\n"
" -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"
" -q: Pure pvAccess RPC based service (send NTURI.query as request argument)\n"
" -z: Pure pvAccess RPC based service (send NTURI.query as request argument)\n"
" -n: Do not format NT types, dump structure instead.\n"
" -t: Terse mode / transpose vector, table, matrix.\n"
" -t: Terse mode.\n"
" -T: Transpose vector, table, matrix.\n"
" -x: Use column-major order to decode matrix.\n"
" -q: Quiet mode, print only error messages\n"
" -d: Enable debug output\n"
" -F <ofs>: Use <ofs> as an alternate output field separator\n"
" -c: Wait for clean shutdown and report used instance count (for expert users)"
@@ -1177,10 +1235,11 @@ int main (int argc, char *argv[])
string service;
//string urlEncodedRequest;
vector< pair<string,string> > parameters;
bool quiet = false;
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
while ((opt = getopt(argc, argv, ":hr:s:a:w:qntxdcF:")) != -1) {
while ((opt = getopt(argc, argv, ":hr:s:a:w:zntTxqdcF:")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -1225,7 +1284,7 @@ int main (int argc, char *argv[])
service = optarg;
serviceRequest = true;
break;
case 'q': /* pvAccess RPC mode */
case 'z': /* pvAccess RPC mode */
onlyQuery = true;
break;
case 'n': /* Do not format NT types */
@@ -1234,9 +1293,15 @@ int main (int argc, char *argv[])
case 't': /* Terse mode */
mode = TerseMode;
break;
case 'T': /* Terse mode */
transpose = true;
break;
case 'x': /* Column-major order mode */
columnMajor = true;
break;
case 'q': /* Quiet mode */
quiet = true;
break;
case 'd': /* Debug log level */
debug = true;
break;
@@ -1396,7 +1461,7 @@ int main (int argc, char *argv[])
vector<Channel::shared_pointer> channels(nPvs);
for (int n = 0; n < nPvs; n++)
{
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl());
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl(quiet));
// TODO to be removed
String providerName = providerNames[n];
@@ -1466,7 +1531,7 @@ int main (int argc, char *argv[])
if (collectValues)
{
collectedValues.push_back(getRequesterImpl->getPVStructure());
// no labels collectedNames.push_back(channel->getChannelName());
collectedNames.push_back(channel->getChannelName());
}
else
{
@@ -1634,7 +1699,7 @@ int main (int argc, char *argv[])
ClientFactory::start();
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pvAccess");
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl());
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl(quiet));
Channel::shared_pointer channel =
authority.empty() ?
provider->createChannel(service, channelRequesterImpl) :