merge
This commit is contained in:
@@ -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
@@ -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
@@ -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",
|
||||
|
||||
@@ -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
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.).
|
||||
|
||||
Reference in New Issue
Block a user