This is Unofficial EPICS BASE Doxygen Site
pvaClientData.cpp
Go to the documentation of this file.
1 /* pvaClientData.cpp */
12 #include <typeinfo>
13 #include <sstream>
14 #include <istream>
15 #include <ostream>
16 
17 #include <pv/createRequest.h>
18 #include <pv/convert.h>
19 #include <pv/pvEnumerated.h>
20 
21 #if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
22 # include <pv/json.h>
23 # define USE_JSON
24 #endif
25 
26 #define epicsExportSharedSymbols
27 
28 #include <pv/pvaClient.h>
29 
31 using namespace epics::pvData;
32 using namespace epics::pvAccess;
33 using namespace std;
34 
35 namespace epics { namespace pvaClient {
36 
37 
38 typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
39 static ConvertPtr convert = getConvert();
40 static string noStructure("no pvStructure ");
41 static string noValue("no value field");
42 static string noScalar("value is not a scalar");
43 static string noArray("value is not an array");
44 static string noScalarArray("value is not a scalarArray");
45 static string noAlarm("no alarm");
46 static string noTimeStamp("no timeStamp");
47 
48 PvaClientDataPtr PvaClientData::create(StructureConstPtr const & structure)
49 {
50  if(PvaClient::getDebug()) cout << "PvaClientData::create\n";
51  PvaClientDataPtr epv(new PvaClientData(structure));
52  return epv;
53 }
54 
55 PvaClientData::PvaClientData(StructureConstPtr const & structure)
56 : structure(structure)
57 {
58 }
59 
61 {
62  if(PvaClient::getDebug()) cout << "PvaClientData::getSinglePVField\n";
63  PVStructurePtr pvStructure = getPVStructure();
64  while(true) {
65  const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
66  if(fieldPtrArray.size()==0) {
67  throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for empty structure");
68  }
69  if(fieldPtrArray.size()!=1) {
70  PVFieldPtr pvValue = pvStructure->getSubField("value");
71  if(pvValue) {
72  Type type = pvValue->getField()->getType();
73  if(type!=epics::pvData::structure) return pvValue;
74  }
75  throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for multiple fields");
76  }
77  PVFieldPtr pvField(fieldPtrArray[0]);
78  Type type = pvField->getField()->getType();
79  if(type!=epics::pvData::structure) return pvField;
80  pvStructure = static_pointer_cast<PVStructure>(pvField);
81  }
82 }
83 
85 {
86  if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
87  if(pvValue) return;
88  throw std::runtime_error(messagePrefix + noValue);
89 }
90 
91 void PvaClientData::setMessagePrefix(std::string const & value)
92 {
93  messagePrefix = value + " ";
94 }
95 
97 {
98  return structure;
99 }
100 
102 {
103  if(pvStructure) return pvStructure;
104  throw std::runtime_error(messagePrefix + noStructure);
105 }
106 
108 {
109  if(bitSet)return bitSet;
110  throw std::runtime_error(messagePrefix + noStructure);
111 }
112 
113 std::ostream & PvaClientData::showChanged(std::ostream & out)
114 {
115  if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
116  size_t nextSet = bitSet->nextSetBit(0);
117  PVFieldPtr pvField;
118  while(nextSet!=string::npos) {
119  if(nextSet==0) {
120  pvField = pvStructure;
121  } else {
122  pvField = pvStructure->getSubField(nextSet);
123  }
124  string name = pvField->getFullName();
125  out << name << " = " << pvField << endl;
126  nextSet = bitSet->nextSetBit(nextSet+1);
127  }
128  return out;
129 }
130 
132  PVStructurePtr const & pvStructureFrom,
133  BitSetPtr const & bitSetFrom)
134 {
135  if(PvaClient::getDebug()) cout << "PvaClientData::setData\n";
136  pvStructure = pvStructureFrom;
137  bitSet = bitSetFrom;
138  pvValue = pvStructure->getSubField("value");
139 }
140 
141 
143 {
144  if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
145  if(!pvValue) return false;
146  return true;
147 }
148 
150 {
151  if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalar\n";
152  if(!pvValue) return false;
153  if(pvValue->getField()->getType()==scalar) return true;
154  return false;
155 }
156 
158 {
159  if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalarArray\n";
160  if(!pvValue) return false;
161  if(pvValue->getField()->getType()==scalarArray) return true;
162  return false;
163 }
164 
166 {
167  if(PvaClient::getDebug()) cout << "PvaClientData::getValue\n";
168  checkValue();
169  return pvValue;
170 }
171 
173 {
174  if(PvaClient::getDebug()) cout << "PvaClientData::getScalarValue\n";
175  checkValue();
176  if(pvValue->getField()->getType()!=scalar) {
177  throw std::runtime_error(messagePrefix + noScalar);
178  }
179  return pvStructure->getSubField<PVScalar>("value");
180 }
181 
183 {
184  if(PvaClient::getDebug()) cout << "PvaClientData::getArrayValue\n";
185  checkValue();
186  Type type = pvValue->getField()->getType();
187  if(type!=scalarArray && type!=structureArray && type!=unionArray) {
188  throw std::runtime_error(messagePrefix + noArray);
189  }
190  return pvStructure->getSubField<PVArray>("value");
191 }
192 
194 {
195  if(PvaClient::getDebug()) cout << "PvaClientData::getScalarArrayValue\n";
196  checkValue();
197  Type type = pvValue->getField()->getType();
198  if(type!=scalarArray) {
199  throw std::runtime_error(messagePrefix + noScalarArray);
200  }
201  return pvStructure->getSubField<PVScalarArray>("value");
202 }
203 
205 {
206  if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
207  PVFieldPtr pvField = getSinglePVField();
208  Type type = pvField->getField()->getType();
209  if(type!=scalar) {
210  throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
211  }
212  PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
213  ScalarType scalarType = pvScalar->getScalar()->getScalarType();
214  if(scalarType==pvDouble) {
216  return pvDouble->get();
217  }
218  if(!ScalarTypeFunc::isNumeric(scalarType)) {
219  throw std::logic_error(
220  "PvaClientData::getDouble() did not find a numeric scalar field");
221  }
222  return convert->toDouble(pvScalar);
223 }
224 
226 {
227  if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
228  PVFieldPtr pvField = getSinglePVField();
229  Type type = pvField->getField()->getType();
230  if(type!=scalar) {
231  throw std::logic_error("PvaClientData::getString() did not find a scalar field");
232  }
233  PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
234  return convert->toString(pvScalar);
235 }
236 
238 {
239  if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
240  PVFieldPtr pvField = getSinglePVField();
241  Type type = pvField->getField()->getType();
242  if(type!=scalarArray) {
243  throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
244  }
245  PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
246  ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
247  if(!ScalarTypeFunc::isNumeric(scalarType)) {
248  throw std::logic_error(
249  "PvaClientData::getDoubleArray() did not find a numeric scalarArray field");
250  }
252  pvScalarArray->getAs<const double>(retValue);
253  return retValue;
254 }
255 
257 {
258  if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
259  PVFieldPtr pvField = getSinglePVField();
260  Type type = pvField->getField()->getType();
261  if(type!=scalarArray) {
262  throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
263  }
264  PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
266  pvScalarArray->getAs<const string>(retValue);
267  return retValue;
268 }
269 
271 {
272  if(PvaClient::getDebug()) cout << "PvaClientData::getAlarm\n";
273  if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
274  PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
275  if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
276  pvAlarm.attach(pvs);
277  if(pvAlarm.isAttached()) {
278  Alarm alarm;
279  pvAlarm.get(alarm);
280  pvAlarm.detach();
281  return alarm;
282  }
283  throw std::runtime_error(messagePrefix + noAlarm);
284 }
285 
287 {
288  if(PvaClient::getDebug()) cout << "PvaClientData::getTimeStamp\n";
289  if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
290  PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
291  if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
292  pvTimeStamp.attach(pvs);
293  if(pvTimeStamp.isAttached()) {
294  TimeStamp timeStamp;
295  pvTimeStamp.get(timeStamp);
296  pvTimeStamp.detach();
297  return timeStamp;
298  }
299  throw std::runtime_error(messagePrefix + noTimeStamp);
300 }
301 
303 {
304  if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
305  zeroArrayLength(pvStructure);
306 }
308  const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet)
309 {
310 #ifdef USE_JSON
311  std::istringstream strm(arg);
312  parseJSON(strm, dest,&(*bitSet));
313 #else
314  throw std::runtime_error("JSON support not built");
315 #endif
316 }
317 
319  const std::string &arg,const PVUnionPtr &pvUnion)
320 {
321  if(pvUnion->getUnion()->isVariant()) {
322  throw std::runtime_error(messagePrefix + "varient union not implemented");
323  }
324  size_t iequals = arg.find_first_of('=');
325  string field;
326  string rest;
327  if(iequals==std::string::npos) {
328  string mess(arg);
329  mess += " was expected to start with field=";
330  throw std::runtime_error(messagePrefix + mess);
331  }
332  field = arg.substr(0,iequals);
333  rest = arg.substr(iequals+1);
334  PVFieldPtr pvField(pvUnion->select(field));
335  if(pvField->getField()->getType()==epics::pvData::union_) {
336  PVUnionPtr pvu = static_pointer_cast<PVUnion>(pvField);
337  parse(rest,pvu);
338  return;
339  }
340  BitSetPtr bs;
341  parse(rest,pvField,bs);
342  return;
343 }
344 
345 void PvaClientData::parse(const std::vector<std::string> &args)
346 {
347  if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure);
348  if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
349  size_t num = args.size();
350  if(num<1) throw std::runtime_error(messagePrefix + " no arguments");
351  for(size_t i=0; i<num; ++i)
352  {
353  string val = args[i];
354  size_t iequals = val.find_first_of('=');
355  string field;
356  string rest(val);
357  if(iequals==std::string::npos) {
358  parse(rest,pvStructure,bitSet);
359  continue;
360  }
361  field = val.substr(0,iequals);
362  rest = val.substr(iequals+1);
363  if(field.size()==std::string::npos) {
364  parse(rest,pvStructure,bitSet);
365  continue;
366  }
367  PVFieldPtr pvField(pvStructure->getSubField(field));
368  if(!pvField) throw std::runtime_error(messagePrefix + field +" does not exist");
369  // look for enumerated structure
370  PVEnumerated pvEnumerated;
371  bool result = pvEnumerated.attach(pvField);
372  if(result) {
373  PVStringArray::const_svector choices(pvEnumerated.getChoices());
374  for(size_t i=0; i<choices.size(); ++i) {
375  if(choices[i]==rest) {
376  pvEnumerated.setIndex(i);
377  return;
378  }
379  }
380  }
381  // look for union
382  PVUnionPtr pvUnion(pvStructure->getSubField<PVUnion>(field));
383  if(pvUnion) {
384  parse(rest,pvUnion);
385  bitSet->set(pvUnion->getFieldOffset());
386  return;
387  }
388  parse(rest,pvField,bitSet);
389  }
390 }
391 
393  std::ostream& strm,
394  bool ignoreUnprintable,
395  bool multiLine)
396 {
397 #ifdef USE_JSON
398  JSONPrintOptions opts;
399  opts.ignoreUnprintable = ignoreUnprintable;
400  opts.multiLine = multiLine;
401  printJSON(strm,*pvStructure,*bitSet,opts);
402 #else
403  throw std::runtime_error("JSON support not built");
404 #endif
405 }
406 
407 
409 {
410 const PVFieldPtrArray pvFields(pvStructure->getPVFields());
411  for(size_t i=0; i<pvFields.size(); ++i) {
412  PVFieldPtr pvField = pvFields[i];
413  Type type(pvField->getField()->getType());
414  switch(type) {
416  {
417  PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
418  pvScalarArray->setLength(0);
419  }
420  break;
422  {
423  PVStructureArrayPtr pvStructureArray = static_pointer_cast<PVStructureArray>(pvField);
424  pvStructureArray->setLength(0);
425  }
426  break;
428  {
429  PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
430  zeroArrayLength(pvStructure);
431  }
432  break;
433  default:
434  break;
435  }
436  }
437 }
438 
439 
440 }}
epics::pvData::Alarm getAlarm()
Get the alarm. If the pvStructure has an alarm field it&#39;s values are returned. Otherwise an exception...
double getDouble()
Get the value as a double.
Definition: link.h:174
PVScalar is the base class for each scalar field.
Definition: pvData.h:272
pvac::PutEvent result
Definition: clientSync.cpp:117
void parse(const std::vector< std::string > &args)
parse from args
Methods for manipulating alarm.
Definition: alarm.h:105
bool ignoreUnprintable
ignore union/union array when encountered
Definition: json.h:45
A holder for a contiguous piece of memory.
Definition: sharedVector.h:27
int i
Definition: scan.c:967
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:788
Methods for accessing an enumerated structure.
Definition: pvEnumerated.h:34
bool attach(PVFieldPtr const &pvField)
bool attach(PVFieldPtr const &pvField)
Definition: pvAlarm.cpp:26
pvd::StructureConstPtr type
std::tr1::shared_ptr< epics::pvData::PVArray > getArrayValue()
Get the interface to an array value field.
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
bool isValueScalar()
Is the value field a scalar?
Options used during printing.
Definition: json.h:42
void get(TimeStamp &timeStamp) const
Definition: pvTimeStamp.cpp:61
std::tr1::shared_ptr< PVArray > PVArrayPtr
storage_t::arg_type get() const
Definition: pvData.h:396
epics::pvData::PVScalarPtr getScalarValue()
Return the interface to a scalar value field.
void get(Alarm &alarm) const
Definition: pvAlarm.cpp:59
epics::pvData::BitSetPtr getChangedBitSet()
Get the changed BitSet for the pvStructure.
epics::pvData::shared_vector< const std::string > getStringArray()
Get the value as a string array.
const ScalarConstPtr getScalar() const
Definition: PVScalar.cpp:27
Holds all PVA related.
Definition: pvif.h:34
std::tr1::shared_ptr< PVUnion > PVUnionPtr
Definition: pvData.h:107
epics::pvData::PVFieldPtr getSinglePVField()
pvData
Definition: monitor.h:428
std::tr1::shared_ptr< PVStructureArray > PVStructureArrayPtr
Definition: pvData.h:100
A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData.
Definition: pvaClient.h:569
void streamJSON(std::ostream &strm, bool ignoreUnprintable=true, bool multiLine=false)
generate JSON output from the current PVStructure
bool setIndex(int32 index)
void zeroArrayLength()
set length of all array fields to 0
bool isNumeric(ScalarType type)
Definition: TypeFunc.cpp:53
Base class for a scalarArray.
Definition: pvData.h:618
std::tr1::shared_ptr< PVScalar > PVScalarPtr
Definition: pvData.h:77
epics::pvData::PVStructure::shared_pointer parseJSON(std::istream &strm)
Definition: parseany.cpp:255
PVUnion has a single subfield.
Definition: pvData.h:940
void printJSON(std::ostream &strm, const PVStructure &val, const BitSet &mask, const JSONPrintOptions &opts)
Definition: print.cpp:211
const ScalarArrayConstPtr getScalarArray() const
std::vector< PVFieldPtr > PVFieldPtrArray
Definition: pvData.h:70
Data interface for a structure,.
Definition: pvData.h:712
bool hasValue()
Is there a top level field named value.
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
virtual void setLength(std::size_t length)=0
Data class for a structureArray.
Definition: pvData.h:1236
std::ostream & showChanged(std::ostream &out)
Show the fields that have changed value since the last get.
epics::pvData::PVFieldPtr getValue()
Get the interface to the value field.
epics::pvData::shared_vector< const double > getDoubleArray()
Get the value as a double array.
std::tr1::shared_ptr< epics::pvData::PVScalarArray > getScalarArrayValue()
Get the interface to a scalar array value field.
Class that holds the data for each possible scalar type.
Definition: pvData.h:54
std::tr1::shared_ptr< PVField > PVFieldPtr
Definition: pvData.h:66
std::tr1::shared_ptr< Convert > ConvertPtr
Definition: convert.h:23
void setMessagePrefix(std::string const &value)
Set a prefix for throw messages.
std::tr1::shared_ptr< BitSet > BitSetPtr
Definition: bitSet.h:26
epics::pvData::PVStructurePtr getPVStructure()
Get the pvStructure.
virtual void setLength(std::size_t length) OVERRIDE FINAL
PVStringArray::const_svector getChoices()
Definition: pvEnumerated.h:91
epics::pvData::TimeStamp getTimeStamp()
Get the timeStamp. If the pvStructure has a timeStamp field, it&#39;s values are returned. Otherwise an exception is thrown.
PVArray is the base class for all array types.
Definition: pvData.h:551
std::tr1::shared_ptr< PVScalarArray > PVScalarArrayPtr
Definition: pvData.h:82
static bool getDebug()
Is debug set?
Definition: pvaClient.cpp:97
bool multiLine
include new lines
Definition: json.h:44
epics::pvData::StructureConstPtr getStructure()
Get the structure.
std::tr1::shared_ptr< PVDouble > PVDoublePtr
Definition: pvData.h:514
void setData(epics::pvData::PVStructurePtr const &pvStructureFrom, epics::pvData::BitSetPtr const &bitSetFrom)
New data is present.
bool isValueScalarArray()
Is the value field a scalar array?
bool attach(PVFieldPtr const &pvField)
Definition: pvTimeStamp.cpp:26
Methods for manipulating timeStamp.
Definition: timeStamp.h:43
std::tr1::shared_ptr< PvaClientData > PvaClientDataPtr
Definition: pvaClient.h:48