normativeTypesCPP 6.0.2
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>
17#include <pv/ntutils.h>
18
19using namespace std;
20using namespace epics::pvData;
21
22namespace epics { namespace nt {
23
24namespace detail {
25
26static FieldCreatePtr fieldCreate = getFieldCreate();
27static PVDataCreatePtr pvDataCreate = getPVDataCreate();
28
29static Mutex mutex;
30
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())->
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)->
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
140NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDescriptor()
141{
142 descriptor = true;
143 return shared_from_this();
144}
145
146NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addAlarm()
147{
148 alarm = true;
149 return shared_from_this();
150}
151
152NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addTimeStamp()
153{
154 timeStamp = true;
155 return shared_from_this();
156}
157
158NTNDArrayBuilder::shared_pointer NTNDArrayBuilder::addDisplay()
159{
160 display = true;
161 return shared_from_this();
162}
163
165{
166 return getPVDataCreate()->createPVStructure(createStructure());
167}
168
173
174NTNDArrayBuilder::NTNDArrayBuilder()
175{
176 reset();
177}
178
179void NTNDArrayBuilder::reset()
180{
181 descriptor = false;
182 timeStamp = false;
183 alarm = false;
184 display = false;
185 extraFieldNames.clear();
186 extraFields.clear();
187}
188
189NTNDArrayBuilder::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
197const std::string NTNDArray::URI("epics:nt/NTNDArray:1.0");
198const std::string ntAttrStr("epics:nt/NTAttribute:1.0");
199
200NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & pvStructure)
201{
202 if(!isCompatible(pvStructure)) return shared_pointer();
203 return wrapUnsafe(pvStructure);
204}
205
206NTNDArray::shared_pointer NTNDArray::wrapUnsafe(PVStructurePtr const & pvStructure)
207{
208 return shared_pointer(new NTNDArray(pvStructure));
209}
210
211bool NTNDArray::is_a(StructureConstPtr const & structure)
212{
213 return NTUtils::is_a(structure->getID(), URI);
214}
215
216bool NTNDArray::is_a(PVStructurePtr const & pvStructure)
217{
218 return is_a(pvStructure->getStructure());
219}
220
221namespace {
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
255bool 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
280bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure)
281{
282 if(!pvStructure.get()) return false;
283
284 return isCompatible(pvStructure->getStructure());
285}
286
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
306int64 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
326int64 NTNDArray::getValueSize()
327{
328 int64 size = 0;
329 PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
330 if (storedValue.get())
331 size = storedValue->getLength()*getValueTypeSize();
332 return size;
333}
334
335int64 NTNDArray::getValueTypeSize()
336{
337 int64 typeSize = 0;
338 PVScalarArrayPtr storedValue = getValue()->get<PVScalarArray>();
339 if (storedValue.get())
340 {
341 switch (storedValue->getScalarArray()->getElementType())
342 {
343 case pvBoolean:
344 case pvByte:
345 case pvUByte:
346 typeSize = 1;
347 break;
348
349 case pvShort:
350 case pvUShort:
351 typeSize = 2;
352 break;
353
354 case pvInt:
355 case pvUInt:
356 case pvFloat:
357 typeSize = 4;
358 break;
359
360 case pvLong:
361 case pvULong:
362 case pvDouble:
363 typeSize = 8;
364 break;
365
366 default:
367 break;
368 }
369 }
370 return typeSize;
371}
372
377
378
379bool NTNDArray::attachTimeStamp(PVTimeStamp &pvTimeStamp) const
380{
381 PVStructurePtr ts = getTimeStamp();
382 if (ts)
383 return pvTimeStamp.attach(ts);
384 else
385 return false;
386}
387
388bool NTNDArray::attachDataTimeStamp(PVTimeStamp &pvTimeStamp) const
389{
390 PVStructurePtr ts = getDataTimeStamp();
391 if (ts)
392 return pvTimeStamp.attach(ts);
393 else
394 return false;
395}
396
397bool NTNDArray::attachAlarm(PVAlarm &pvAlarm) const
398{
399 PVStructurePtr al = getAlarm();
400 if (al)
401 return pvAlarm.attach(al);
402 else
403 return false;
404}
405
406bool NTNDArray::attachDisplay(PVDisplay &pvDisplay) const
407{
408 PVStructurePtr dp = getDisplay();
409 if (dp)
410 return pvDisplay.attach(dp);
411 else
412 return false;
413}
414
415PVStructurePtr NTNDArray::getPVStructure() const
416{
417 return pvNTNDArray;
418}
419
420PVUnionPtr NTNDArray::getValue() const
421{
422 return pvNTNDArray->getSubField<PVUnion>("value");
423}
424
425PVStructurePtr NTNDArray::getCodec() const
426{
427 return pvNTNDArray->getSubField<PVStructure>("codec");
428}
429
431{
432 return pvNTNDArray->getSubField<PVLong>("compressedSize");
433}
434
436{
437 return pvNTNDArray->getSubField<PVLong>("uncompressedSize");
438}
439
440PVStructureArrayPtr NTNDArray::getDimension() const
441{
442 return pvNTNDArray->getSubField<PVStructureArray>("dimension");
443}
444
446{
447 return pvNTNDArray->getSubField<PVInt>("uniqueId");
448}
449
450PVStructurePtr NTNDArray::getDataTimeStamp() const
451{
452 return pvNTNDArray->getSubField<PVStructure>("dataTimeStamp");
453}
454
455PVStructureArrayPtr NTNDArray::getAttribute() const
456{
457 return pvNTNDArray->getSubField<PVStructureArray>("attribute");
458}
459
460PVStringPtr NTNDArray::getDescriptor() const
461{
462 return pvNTNDArray->getSubField<PVString>("descriptor");
463}
464
465PVStructurePtr NTNDArray::getTimeStamp() const
466{
467 return pvNTNDArray->getSubField<PVStructure>("timeStamp");
468}
469
470PVStructurePtr NTNDArray::getAlarm() const
471{
472 return pvNTNDArray->getSubField<PVStructure>("alarm");
473}
474
475PVStructurePtr NTNDArray::getDisplay() const
476{
477 return pvNTNDArray->getSubField<PVStructure>("display");
478}
479
480
481NTNDArray::NTNDArray(PVStructurePtr const & pvStructure) :
482 pvNTNDArray(pvStructure)
483{}
484
485
486}}
bool isAlarm(epics::pvData::FieldConstPtr const &field)
bool isDisplay(epics::pvData::FieldConstPtr const &field)
static NTNDArrayAttributeBuilderPtr createBuilder()
Convenience Class for NTNDArray.
Definition ntndarray.h:129
epics::pvData::PVStructurePtr getDataTimeStamp() const
epics::pvData::PVStructureArrayPtr getAttribute() const
bool attachDisplay(epics::pvData::PVDisplay &pvDisplay) const
static NTNDArrayBuilderPtr createBuilder()
epics::pvData::PVLongPtr getUncompressedDataSize() const
epics::pvData::PVLongPtr getCompressedDataSize() const
static shared_pointer wrapUnsafe(epics::pvData::PVStructurePtr const &pvStructure)
epics::pvData::PVStructurePtr getTimeStamp() const
epics::pvData::PVStringPtr getDescriptor() const
bool attachAlarm(epics::pvData::PVAlarm &pvAlarm) const
static bool isCompatible(epics::pvData::StructureConstPtr const &structure)
epics::pvData::PVStructurePtr getAlarm() const
epics::pvData::PVStructurePtr getPVStructure() const
epics::pvData::PVStructurePtr getCodec() const
epics::pvData::PVIntPtr getUniqueId() const
epics::pvData::PVUnionPtr getValue() const
static shared_pointer wrap(epics::pvData::PVStructurePtr const &pvStructure)
bool attachTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const
epics::pvData::PVStructureArrayPtr getDimension() const
bool attachDataTimeStamp(epics::pvData::PVTimeStamp &pvTimeStamp) const
static bool is_a(epics::pvData::StructureConstPtr const &structure)
epics::pvData::PVStructurePtr getDisplay() const
static const std::string URI
Definition ntndarray.h:133
static bool is_a(const std::string &u1, const std::string &u2)
Definition ntutils.cpp:14
Interface for in-line creating of NTNDArray.
Definition ntndarray.h:45
friend class ::epics::nt::NTNDArray
Definition ntndarray.h:116
epics::pvData::StructureConstPtr createStructure()
Definition ntndarray.cpp:31
shared_pointer add(std::string const &name, epics::pvData::FieldConstPtr const &field)
epics::pvData::PVStructurePtr createPVStructure()
const std::string ntAttrStr("epics:nt/NTAttribute:1.0")
std::tr1::shared_ptr< detail::NTNDArrayBuilder > NTNDArrayBuilderPtr
Definition ntndarray.h:121
std::tr1::shared_ptr< NTNDArray > NTNDArrayPtr
Definition ntndarray.h:32