This is Unofficial EPICS BASE Doxygen Site
ntndarray.cpp
Go to the documentation of this file.
1 /* ntndarray.cpp */
2 /*
3  * Copyright information and license terms for this software can be
4  * found in the file LICENSE that is included with the distribution
5  */
6 
7 #include <algorithm>
8 
9 #include <pv/lock.h>
10 #include <pv/sharedPtr.h>
11 
12 #include "validator.h"
13 
14 #define epicsExportSharedSymbols
15 #include <pv/ntndarray.h>
16 #include <pv/ntndarrayAttribute.h>
17 #include <pv/ntutils.h>
18 
19 using namespace std;
20 using namespace epics::pvData;
21 
22 namespace epics { namespace nt {
23 
24 namespace detail {
25 
26 static FieldCreatePtr fieldCreate = getFieldCreate();
27 static PVDataCreatePtr pvDataCreate = getPVDataCreate();
28 
29 static Mutex mutex;
30 
31 StructureConstPtr NTNDArrayBuilder::createStructure()
32 {
33  enum
34  {
35  DISCRIPTOR_INDEX,
36  TIMESTAMP_INDEX,
37  ALARM_INDEX,
38  DISPLAY_INDEX
39  };
40 
41  const size_t NUMBER_OF_INDICES = DISPLAY_INDEX+1;
42  const size_t NUMBER_OF_STRUCTURES = 1 << NUMBER_OF_INDICES;
43 
44  Lock xx(mutex);
45 
46  static StructureConstPtr ntndarrayStruc[NUMBER_OF_STRUCTURES];
47  static UnionConstPtr valueType;
48  static StructureConstPtr codecStruc;
49  static StructureConstPtr dimensionStruc;
50  static StructureConstPtr attributeStruc;
51 
52  StructureConstPtr returnedStruc;
53 
54  size_t index = 0;
55  if (descriptor) index |= 1 << DISCRIPTOR_INDEX;
56  if (timeStamp) index |= 1 << TIMESTAMP_INDEX;
57  if (alarm) index |= 1 << ALARM_INDEX;
58  if (display) index |= 1 << DISPLAY_INDEX;
59 
60  bool isExtended = !extraFieldNames.empty();
61 
62  if (isExtended || !ntndarrayStruc[index])
63  {
64  StandardFieldPtr standardField = getStandardField();
65  FieldBuilderPtr fb = fieldCreate->createFieldBuilder();
66 
67  if (!valueType)
68  {
69  for (int i = pvBoolean; i < pvString; ++i)
70  {
71  ScalarType st = static_cast<ScalarType>(i);
72  fb->addArray(std::string(ScalarTypeFunc::name(st)) + "Value", st);
73  }
74  valueType = fb->createUnion();
75  }
76 
77  if (!codecStruc)
78  {
79  codecStruc = fb->setId("codec_t")->
80  add("name", pvString)->
81  add("parameters", fieldCreate->createVariantUnion())->
82  createStructure();
83  }
84 
85  if (!dimensionStruc)
86  {
87  dimensionStruc = fb->setId("dimension_t")->
88  add("size", pvInt)->
89  add("offset", pvInt)->
90  add("fullSize", pvInt)->
91  add("binning", pvInt)->
92  add("reverse", pvBoolean)->
93  createStructure();
94  }
95 
96  if (!attributeStruc)
97  {
98  attributeStruc = NTNDArrayAttribute::createBuilder()->createStructure();
99  }
100 
101  fb->setId(NTNDArray::URI)->
102  add("value", valueType)->
103  add("codec", codecStruc)->
104  add("compressedSize", pvLong)->
105  add("uncompressedSize", pvLong)->
106  addArray("dimension", dimensionStruc)->
107  add("uniqueId", pvInt)->
108  add("dataTimeStamp", standardField->timeStamp())->
109  addArray("attribute", attributeStruc);
110 
111  if (descriptor)
112  fb->add("descriptor", pvString);
113 
114  if (alarm)
115  fb->add("alarm", standardField->alarm());
116 
117  if (timeStamp)
118  fb->add("timeStamp", standardField->timeStamp());
119 
120  if (display)
121  fb->add("display", standardField->display());
122 
123  size_t extraCount = extraFieldNames.size();
124  for (size_t i = 0; i< extraCount; i++)
125  fb->add(extraFieldNames[i], extraFields[i]);
126 
127  returnedStruc = fb->createStructure();
128 
129  if (!isExtended)
130  ntndarrayStruc[index] = returnedStruc;
131  }
132  else
133  {
134  return ntndarrayStruc[index];
135  }
136 
137  return returnedStruc;
138 }
139 
140 NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor()
141 {
142  descriptor = true;
143  return shared_from_this();
144 }
145 
146 NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm()
147 {
148  alarm = true;
149  return shared_from_this();
150 }
151 
152 NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp()
153 {
154  timeStamp = true;
155  return shared_from_this();
156 }
157 
158 NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay()
159 {
160  display = true;
161  return shared_from_this();
162 }
163 
164 PVStructurePtr NTNDArrayBuilder::createPVStructure()
165 {
166  return getPVDataCreate()->createPVStructure(createStructure());
167 }
168 
169 NTNDArrayPtr NTNDArrayBuilder::create()
170 {
171  return NTNDArrayPtr(new NTNDArray(createPVStructure()));
172 }
173 
174 NTNDArrayBuilder::NTNDArrayBuilder()
175 {
176  reset();
177 }
178 
179 void NTNDArrayBuilder::reset()
180 {
181  descriptor = false;
182  timeStamp = false;
183  alarm = false;
184  display = false;
185  extraFieldNames.clear();
186  extraFields.clear();
187 }
188 
189 NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::add(string const & name, FieldConstPtr const & field)
190 {
191  extraFields.push_back(field); extraFieldNames.push_back(name);
192  return shared_from_this();
193 }
194 
195 }
196 
197 const std::string NTNDArray::URI("epics:nt/NTNDArray:1.0");
198 const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
199 
200 NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & pvStructure)
201 {
202  if(!isCompatible(pvStructure)) return shared_pointer();
203  return wrapUnsafe(pvStructure);
204 }
205 
206 NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & pvStructure)
207 {
208  return shared_pointer(new NTNDArray(pvStructure));
209 }
210 
211 bool NTNDArray::is_a(StructureConstPtr const & structure)
212 {
213  return NTUtils::is_a(structure->getID(), URI);
214 }
215 
216 bool NTNDArray::is_a(PVStructurePtr const & pvStructure)
217 {
218  return is_a(pvStructure->getStructure());
219 }
220 
221 namespace {
222  Result& isValue(Result& result)
223  {
224  result.is<Union>(Union::defaultId());
225 
226  for (int i = pvBoolean; i < pvString; ++i) {
227  ScalarType type = static_cast<ScalarType>(i);
228  string name(ScalarTypeFunc::name(type));
229  result.has<ScalarArray>(name + "Value");
230  }
231 
232  return result;
233  }
234 
235  Result& isCodec(Result& result)
236  {
237  return result
238  .is<Structure>("codec_t")
239  .has<Scalar>("name")
240  .has<Union>("parameters");
241  }
242 
243  Result& isDimension(Result& result)
244  {
245  return result
246  .is<StructureArray>("dimension_t[]")
247  .has<Scalar>("size")
248  .has<Scalar>("offset")
249  .has<Scalar>("fullSize")
250  .has<Scalar>("binning")
251  .has<Scalar>("reverse");
252  }
253 }
254 
255 bool NTNDArray::isCompatible(StructureConstPtr const &structure)
256 {
257  if (!structure)
258  return false;
259 
260  Result result(structure);
261 
262  return result
263  .is<Structure>()
264  .has<&isValue>("value")
265  .has<&isCodec>("codec")
266  .has<Scalar>("compressedSize")
267  .has<Scalar>("uncompressedSize")
268  .has<&isDimension>("dimension")
269  .has<Scalar>("uniqueId")
270  .has<&NTField::isTimeStamp, Structure>("dataTimeStamp")
271  .has<&NTNDArrayAttribute::isAttribute, StructureArray>("attribute")
272  .maybeHas<Scalar>("descriptor")
273  .maybeHas<&NTField::isAlarm, Structure>("alarm")
274  .maybeHas<&NTField::isTimeStamp, Structure>("timeStamp")
275  .maybeHas<&NTField::isDisplay, Structure>("display")
276  .valid();
277 }
278 
279 
280 bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
281 {
282  if(!pvStructure.get()) return false;
283 
284  return isCompatible(pvStructure->getStructure());
285 }
286 
287 bool NTNDArray::isValid()
288 {
289  int64 valueSize = getValueSize();
290  int64 compressedSize = getCompressedDataSize()->get();
291  if (valueSize != compressedSize)
292  return false;
293 
294  long expectedUncompressed = getExpectedUncompressedSize();
295  long uncompressedSize = getUncompressedDataSize()->get();
296  if (uncompressedSize != expectedUncompressed)
297  return false;
298 
299  std::string codecName = getCodec()->getSubField<PVString>("name")->get();
300  if (codecName == "" && valueSize < uncompressedSize)
301  return false;
302 
303  return true;
304 }
305 
306 int64 NTNDArray::getExpectedUncompressedSize()
307 {
308  int64 size = 0;
309  PVStructureArrayPtr pvDim = getDimension();
310 
311  if (pvDim->getLength() != 0)
312  {
313  PVStructureArray::const_svector data = pvDim->view();
314  size = getValueTypeSize();
315  for (PVStructureArray::const_svector::const_iterator it = data.begin();
316  it != data.end(); ++it )
317  {
318  PVStructurePtr dim = *it;
319  size *= dim->getSubField<PVInt>("size")->get();
320  }
321  }
322 
323  return size;
324 }
325 
326 int64 NTNDArray::getValueSize()
327 {
328  int64 size = 0;
329  PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
330  if (!storedValue.get())
331  {
332  size = storedValue->getLength()*getValueTypeSize();
333  }
334  return size;
335 }
336 
337 int64 NTNDArray::getValueTypeSize()
338 {
339  int64 typeSize = 0;
340  PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
341  if (storedValue.get())
342  {
343  switch (storedValue->getScalarArray()->getElementType())
344  {
345  case pvBoolean:
346  case pvByte:
347  case pvUByte:
348  typeSize = 1;
349  break;
350 
351  case pvShort:
352  case pvUShort:
353  typeSize = 2;
354  break;
355 
356  case pvInt:
357  case pvUInt:
358  case pvFloat:
359  typeSize = 4;
360  break;
361 
362  case pvLong:
363  case pvULong:
364  case pvDouble:
365  typeSize = 8;
366  break;
367 
368  default:
369  break;
370  }
371  }
372  return typeSize;
373 }
374 
375 NTNDArrayBuilderPtr NTNDArray::createBuilder()
376 {
378 }
379 
380 
381 bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
382 {
383  PVStructurePtr ts = getTimeStamp();
384  if (ts)
385  return pvTimeStamp.attach(ts);
386  else
387  return false;
388 }
389 
390 bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const
391 {
392  PVStructurePtr ts = getDataTimeStamp();
393  if (ts)
394  return pvTimeStamp.attach(ts);
395  else
396  return false;
397 }
398 
399 bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const
400 {
401  PVStructurePtr al = getAlarm();
402  if (al)
403  return pvAlarm.attach(al);
404  else
405  return false;
406 }
407 
408 bool NTNDArray::attachDisplay(PVDisplay &pvDisplay) const
409 {
410  PVStructurePtr dp = getDisplay();
411  if (dp)
412  return pvDisplay.attach(dp);
413  else
414  return false;
415 }
416 
417 PVStructurePtr NTNDArray::getPVStructure() const
418 {
419  return pvNTNDArray;
420 }
421 
422 PVUnionPtr NTNDArray::getValue() const
423 {
424  return pvNTNDArray->getSubField<PVUnion>("value");
425 }
426 
427 PVStructurePtr NTNDArray::getCodec() const
428 {
429  return pvNTNDArray->getSubField<PVStructure>("codec");
430 }
431 
432 PVLongPtr NTNDArray::getCompressedDataSize() const
433 {
434  return pvNTNDArray->getSubField<PVLong>("compressedSize");
435 }
436 
437 PVLongPtr NTNDArray::getUncompressedDataSize() const
438 {
439  return pvNTNDArray->getSubField<PVLong>("uncompressedSize");
440 }
441 
442 PVStructureArrayPtr NTNDArray::getDimension() const
443 {
444  return pvNTNDArray->getSubField<PVStructureArray>("dimension");
445 }
446 
447 PVIntPtr NTNDArray::getUniqueId() const
448 {
449  return pvNTNDArray->getSubField<PVInt>("uniqueId");
450 }
451 
452 PVStructurePtr NTNDArray::getDataTimeStamp() const
453 {
454  return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp");
455 }
456 
457 PVStructureArrayPtr NTNDArray::getAttribute() const
458 {
459  return pvNTNDArray->getSubField<PVStructureArray>("attribute");
460 }
461 
462 PVStringPtr NTNDArray::getDescriptor() const
463 {
464  return pvNTNDArray->getSubField<PVString>("descriptor");
465 }
466 
467 PVStructurePtr NTNDArray::getTimeStamp() const
468 {
469  return pvNTNDArray->getSubField<PVStructure>("timeStamp");
470 }
471 
472 PVStructurePtr NTNDArray::getAlarm() const
473 {
474  return pvNTNDArray->getSubField<PVStructure>("alarm");
475 }
476 
477 PVStructurePtr NTNDArray::getDisplay() const
478 {
479  return pvNTNDArray->getSubField<PVStructure>("display");
480 }
481 
482 
483 NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) :
484  pvNTNDArray(pvStructure)
485 {}
486 
487 
488 }}
FORCE_INLINE std::tr1::shared_ptr< PVField > getSubField(A a)
Definition: pvData.h:744
bool attach(PVFieldPtr const &pvField)
Definition: pvDisplay.cpp:26
This class implements introspection object for Scalar.
Definition: pvIntrospect.h:397
std::tr1::shared_ptr< PVInt > PVIntPtr
Definition: pvData.h:507
This class implements introspection object for a union.
Definition: pvIntrospect.h:866
pvac::PutEvent result
Definition: clientSync.cpp:117
Result & is(void)
Definition: validator.h:89
std::tr1::shared_ptr< detail::NTNDArrayBuilder > NTNDArrayBuilderPtr
Definition: ntndarray.h:121
int i
Definition: scan.c:967
bool attach(PVFieldPtr const &pvField)
Definition: pvAlarm.cpp:26
Validation methods for NT types.
Definition: validator.h:23
pvd::StructureConstPtr type
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
A lock for multithreading.
Definition: lock.h:36
std::tr1::shared_ptr< PVLong > PVLongPtr
Definition: pvData.h:508
std::tr1::shared_ptr< FieldBuilder > FieldBuilderPtr
std::tr1::shared_ptr< StandardField > StandardFieldPtr
Definition: standardField.h:22
std::tr1::shared_ptr< PVDataCreate > PVDataCreatePtr
Definition: pvData.h:124
PVString is special case, since it implements SerializableArray.
Definition: pvData.h:521
FORCE_INLINE const StandardFieldPtr & getStandardField()
std::tr1::shared_ptr< PVUnion > PVUnionPtr
Definition: pvData.h:107
pvData
Definition: monitor.h:428
std::tr1::shared_ptr< const Union > UnionConstPtr
Definition: pvIntrospect.h:170
virtual std::size_t getLength() const =0
This class implements introspection object for a structure.
Definition: pvIntrospect.h:697
std::tr1::shared_ptr< PVStructureArray > PVStructureArrayPtr
Definition: pvData.h:100
Methods for accessing a timeStamp structure.
Definition: pvTimeStamp.h:38
Base class for a scalarArray.
Definition: pvData.h:618
Methods for accessing an alarm structure.
Definition: pvAlarm.h:37
PVUnion has a single subfield.
Definition: pvData.h:940
Interface for in-line creating of NTNDArray.
Definition: ntndarray.h:43
Data interface for a structure,.
Definition: pvData.h:712
std::tr1::shared_ptr< const Field > FieldConstPtr
Definition: pvIntrospect.h:137
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
This class implements introspection object for scalar array.
Definition: pvIntrospect.h:497
This class implements introspection object for a structureArray.
Definition: pvIntrospect.h:607
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
std::tr1::shared_ptr< NTNDArray > NTNDArrayPtr
Definition: ntndarray.h:31
Result & has(const std::string &name)
Definition: validator.h:132
int64_t int64
Definition: pvType.h:87
std::tr1::shared_ptr< PVString > PVStringPtr
Definition: pvData.h:540
Data class for a structureArray.
Definition: pvData.h:1236
Convenience Class for NTNDArray.
Definition: ntndarray.h:128
const std::string ntAttrStr("epics:nt/NTAttribute:1.0")
Class that holds the data for each possible scalar type.
Definition: pvData.h:54
std::tr1::shared_ptr< FieldCreate > FieldCreatePtr
Methods for accessing an display structure.
Definition: pvDisplay.h:39
epicsMutex Mutex
Definition: lock.h:28
std::tr1::shared_ptr< PVScalarArray > PVScalarArrayPtr
Definition: pvData.h:82
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648
bool attach(PVFieldPtr const &pvField)
Definition: pvTimeStamp.cpp:26