From 05a7a6923ff7131bb5a283a56df9e380b0b23c1b Mon Sep 17 00:00:00 2001 From: Dave Hickin Date: Tue, 1 Sep 2015 15:53:52 +0100 Subject: [PATCH] Implement NTNDArray::isValid() --- src/nt/ntndarray.cpp | 166 +++++++++++++++++++++++++++++++++++++++++++ src/nt/ntndarray.h | 5 ++ 2 files changed, 171 insertions(+) diff --git a/src/nt/ntndarray.cpp b/src/nt/ntndarray.cpp index 2c4e221..94d1bec 100644 --- a/src/nt/ntndarray.cpp +++ b/src/nt/ntndarray.cpp @@ -19,6 +19,7 @@ namespace epics { namespace nt { static NTFieldPtr ntField = NTField::get(); + namespace detail { const std::string ntAttrStr("epics:nt/NTAttribute:1.0"); @@ -207,6 +208,86 @@ const std::string ntAttrStr("epics:nt/NTAttribute:1.0"); static FieldCreatePtr fieldCreate = getFieldCreate(); static PVDataCreatePtr pvDataCreate = getPVDataCreate(); +class NTValueType +{ +public: + static bool isCompatible(UnionConstPtr const &u) + { + if(!u.get()) return false; + + if (u->getID() != Union::defaultId()) return false; + if (u->isVariant()) return false; + + for (int i = pvBoolean; i != pvString; ++i) + { + ScalarType scalarType = static_cast(i); + std::string name(ScalarTypeFunc::name(scalarType)); + name += "Value"; + ScalarArrayConstPtr scalarField = u->getField(name); + if (scalarField.get() == 0 || + scalarField->getElementType() != scalarType) + return false; + } + + return true; + } +}; + +class NTCodec +{ +public: + static bool isCompatible(StructureConstPtr const &structure) + { + if(!structure.get()) return false; + + if (structure->getID() != "codec_t") return false; + + ScalarConstPtr scalarField = structure->getField("name"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvString) + return false; + + UnionConstPtr paramField = structure->getField("parameters"); + if (paramField.get() == 0 || !paramField->isVariant()) + return false; + + return true; + } +}; + + +class NTDimension +{ +public: + static bool isCompatible(StructureConstPtr const &structure) + { + if(!structure.get()) return false; + + if (structure->getID() != "dimension_t") return false; + + ScalarConstPtr scalarField = structure->getField("size"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) + return false; + + scalarField = structure->getField("offset"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) + return false; + + scalarField = structure->getField("fullSize"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) + return false; + + scalarField = structure->getField("binning"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvInt) + return false; + + scalarField = structure->getField("reverse"); + if (scalarField.get() == 0 || scalarField->getScalarType() != pvBoolean) + return false; + + return true; + } +}; + NTNDArray::shared_pointer NTNDArray::wrap(PVStructurePtr const & structure) { if(!isCompatible(structure)) return shared_pointer(); @@ -311,9 +392,94 @@ bool NTNDArray::isCompatible(PVStructurePtr const & pvStructure) return isCompatible(pvStructure->getStructure()); } + +bool NTNDArray::isValid() +{ + int64 valueSize = getValueSize(); + int64 compressedSize = getCompressedDataSize()->get(); + if (valueSize != compressedSize) + return false; + + long expectedUncompressed = getExpectedUncompressedSize(); + long uncompressedSize = getUncompressedDataSize()->get(); + if (uncompressedSize != expectedUncompressed) + return false; + + std::string codecName = getCodec()->getSubField("name")->get(); + if (codecName == "" && valueSize < uncompressedSize) + return false; + return true; } +int64 NTNDArray::getExpectedUncompressedSize() +{ + int64 size = 0; + PVStructureArrayPtr pvDim = getDimension(); + + if (pvDim->getLength() != 0) + { + PVStructureArray::const_svector data = pvDim->view(); + size = getValueTypeSize(); + for (PVStructureArray::const_svector::const_iterator it = data.begin(); + it != data.end(); ++it ) + { + PVStructurePtr dim = *it; + size *= dim->getSubField("size")->get(); + } + } + + return size; +} + +int64 NTNDArray::getValueSize() +{ + int64 size = 0; + PVScalarArrayPtr storedValue = getValue()->get(); + if (!storedValue.get()) + { + size = storedValue->getLength()*getValueTypeSize(); + } + return size; +} + +int64 NTNDArray::getValueTypeSize() +{ + int64 typeSize = 0; + PVScalarArrayPtr storedValue = getValue()->get(); + if (storedValue.get()) + { + switch (storedValue->getScalarArray()->getElementType()) + { + case pvBoolean: + case pvByte: + case pvUByte: + typeSize = 1; + break; + + case pvShort: + case pvUShort: + typeSize = 2; + break; + + case pvInt: + case pvUInt: + case pvFloat: + typeSize = 4; + break; + + case pvLong: + case pvULong: + case pvDouble: + typeSize = 8; + break; + + default: + break; + } + } + return typeSize; +} NTNDArrayBuilderPtr NTNDArray::createBuilder() { diff --git a/src/nt/ntndarray.h b/src/nt/ntndarray.h index c0490f3..cc65778 100644 --- a/src/nt/ntndarray.h +++ b/src/nt/ntndarray.h @@ -305,6 +305,11 @@ public: private: NTNDArray(epics::pvData::PVStructurePtr const & pvStructure); + + epics::pvData::int64 getExpectedUncompressedSize(); + epics::pvData::int64 getValueSize(); + epics::pvData::int64 getValueTypeSize(); + epics::pvData::PVStructurePtr pvNTNDArray; friend class detail::NTNDArrayBuilder;