PVUnion/PVUnionArray support and tests
This commit is contained in:
@@ -66,6 +66,8 @@ LIBSRCS += PVArray.cpp
|
||||
LIBSRCS += PVScalarArray.cpp
|
||||
LIBSRCS += PVStructure.cpp
|
||||
LIBSRCS += PVStructureArray.cpp
|
||||
LIBSRCS += PVUnion.cpp
|
||||
LIBSRCS += PVUnionArray.cpp
|
||||
LIBSRCS += PVDataCreateFactory.cpp
|
||||
LIBSRCS += Convert.cpp
|
||||
LIBSRCS += pvSubArrayCopy.cpp
|
||||
|
||||
@@ -48,6 +48,16 @@ bool operator==(const Field& a, const Field& b)
|
||||
const StructureArray &B=static_cast<const StructureArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case union_: {
|
||||
const Union &A=static_cast<const Union&>(a);
|
||||
const Union &B=static_cast<const Union&>(b);
|
||||
return A==B;
|
||||
}
|
||||
case unionArray: {
|
||||
const UnionArray &A=static_cast<const UnionArray&>(a);
|
||||
const UnionArray &B=static_cast<const UnionArray&>(b);
|
||||
return A==B;
|
||||
}
|
||||
default:
|
||||
throw std::logic_error("Invalid Field type in comparision");
|
||||
}
|
||||
@@ -94,6 +104,33 @@ bool operator==(const StructureArray& a, const StructureArray& b)
|
||||
return *(a.getStructure().get())==*(b.getStructure().get());
|
||||
}
|
||||
|
||||
bool operator==(const Union& a, const Union& b)
|
||||
{
|
||||
if(&a==&b)
|
||||
return true;
|
||||
if (a.getID()!=b.getID())
|
||||
return false;
|
||||
size_t nflds=a.getNumberFields();
|
||||
if (b.getNumberFields()!=nflds)
|
||||
return false;
|
||||
|
||||
// std::equals does not work, since FieldConstPtrArray is an array of shared_pointers
|
||||
FieldConstPtrArray af = a.getFields();
|
||||
FieldConstPtrArray bf = b.getFields();
|
||||
for (size_t i = 0; i < nflds; i++)
|
||||
if (*(af[i].get()) != *(bf[i].get()))
|
||||
return false;
|
||||
|
||||
StringArray an = a.getFieldNames();
|
||||
StringArray bn = b.getFieldNames();
|
||||
return std::equal( an.begin(), an.end(), bn.begin() );
|
||||
}
|
||||
|
||||
bool operator==(const UnionArray& a, const UnionArray& b)
|
||||
{
|
||||
return *(a.getUnion().get())==*(b.getUnion().get());
|
||||
}
|
||||
|
||||
// PVXXX object comparison
|
||||
|
||||
namespace {
|
||||
@@ -210,6 +247,59 @@ bool compareField(const PVStructureArray* left, const PVStructureArray* right)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool compareField(const PVUnion* left, const PVUnion* right)
|
||||
{
|
||||
UnionConstPtr ls = left->getUnion();
|
||||
|
||||
if(*ls!=*right->getUnion())
|
||||
return false;
|
||||
|
||||
if (ls->isVariant())
|
||||
{
|
||||
PVFieldPtr lval = left->get();
|
||||
if (lval.get() == 0)
|
||||
return right->get().get() == 0;
|
||||
else
|
||||
return *(lval.get()) == *(right->get().get());
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 lix = left->getSelectedIndex();
|
||||
if (lix == right->getSelectedIndex())
|
||||
{
|
||||
if (lix == PVUnion::UNDEFINED_INDEX || *(left->get()) == *(right->get().get()))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compareField(const PVUnionArray* left, const PVUnionArray* right)
|
||||
{
|
||||
if(*left->getUnionArray()->getUnion()
|
||||
!= *right->getUnionArray()->getUnion())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector ld=left->view(), rd=right->view();
|
||||
|
||||
if(ld.size()!=rd.size())
|
||||
return false;
|
||||
|
||||
PVUnionArray::const_svector::const_iterator lit, lend, rit;
|
||||
|
||||
for(lit=ld.begin(), lend=ld.end(), rit=rd.begin();
|
||||
lit!=lend;
|
||||
++lit, ++rit)
|
||||
{
|
||||
if(**lit != **rit)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
// untyped comparison
|
||||
@@ -228,6 +318,8 @@ bool operator==(const PVField& left, const PVField& right)
|
||||
case scalarArray: return compareField(static_cast<const PVScalarArray*>(&left), static_cast<const PVScalarArray*>(&right));
|
||||
case structure: return compareField(static_cast<const PVStructure*>(&left), static_cast<const PVStructure*>(&right));
|
||||
case structureArray: return compareField(static_cast<const PVStructureArray*>(&left), static_cast<const PVStructureArray*>(&right));
|
||||
case union_: return compareField(static_cast<const PVUnion*>(&left), static_cast<const PVUnion*>(&right));
|
||||
case unionArray: return compareField(static_cast<const PVUnionArray*>(&left), static_cast<const PVUnionArray*>(&right));
|
||||
}
|
||||
throw std::logic_error("PVField with invalid type!");
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ size_t Convert::fromString(PVStructurePtr const &pvStructure, StringArray const
|
||||
processed++;
|
||||
}
|
||||
else {
|
||||
// structureArray not supported
|
||||
// union, structureArray, unionArray not supported
|
||||
String message("Convert::fromString unsupported fieldType ");
|
||||
TypeFunc::toString(&message,type);
|
||||
throw std::logic_error(message);
|
||||
@@ -176,6 +176,18 @@ bool Convert::isCopyCompatible(FieldConstPtr const &from, FieldConstPtr const &t
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
return isCopyStructureArrayCompatible(xxx,yyy);
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
return isCopyUnionCompatible(xxx,yyy);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
return isCopyUnionArrayCompatible(xxx,yyy);
|
||||
}
|
||||
}
|
||||
String message("Convert::isCopyCompatible should never get here");
|
||||
throw std::logic_error(message);
|
||||
@@ -211,6 +223,19 @@ void Convert::copy(PVFieldPtr const & from, PVFieldPtr const & to)
|
||||
copyStructureArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(from);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(to);
|
||||
copyUnion(xxx,yyy);
|
||||
return;
|
||||
}
|
||||
case unionArray: {
|
||||
PVUnionArrayPtr fromArray = static_pointer_cast<PVUnionArray>(from);
|
||||
PVUnionArrayPtr toArray = static_pointer_cast<PVUnionArray>(to);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,6 +316,19 @@ bool Convert::isCopyStructureCompatible(
|
||||
StructureArrayConstPtr yyy = static_pointer_cast<const StructureArray>(to);
|
||||
if(!isCopyStructureArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
UnionConstPtr xxx = static_pointer_cast<const Union>(from);
|
||||
UnionConstPtr yyy = static_pointer_cast<const Union>(to);
|
||||
if(!isCopyUnionCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
case unionArray:
|
||||
{
|
||||
UnionArrayConstPtr xxx = static_pointer_cast<const UnionArray>(from);
|
||||
UnionArrayConstPtr yyy = static_pointer_cast<const UnionArray>(to);
|
||||
if(!isCopyUnionArrayCompatible(xxx,yyy)) return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -380,10 +418,60 @@ void Convert::copyStructure(PVStructurePtr const & from, PVStructurePtr const &
|
||||
copyStructureArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr xxx = static_pointer_cast<PVUnion>(fromData);
|
||||
PVUnionPtr yyy = static_pointer_cast<PVUnion>(toData);
|
||||
copyUnion(xxx,yyy);
|
||||
break;
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr fromArray =
|
||||
static_pointer_cast<PVUnionArray>(fromData);
|
||||
PVUnionArrayPtr toArray =
|
||||
static_pointer_cast<PVUnionArray>(toData);
|
||||
copyUnionArray(fromArray,toArray);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyUnionCompatible(
|
||||
UnionConstPtr const &from, UnionConstPtr const &to)
|
||||
{
|
||||
return *(from.get()) == *(to.get());
|
||||
}
|
||||
|
||||
void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to)
|
||||
{
|
||||
if(to->isImmutable()) {
|
||||
if(from==to) return;
|
||||
throw std::invalid_argument("Convert.copyUnion destination is immutable");
|
||||
}
|
||||
if(from==to) return;
|
||||
if(!isCopyUnionCompatible(from->getUnion(), to->getUnion())) {
|
||||
throw std::invalid_argument("Illegal copyUnion");
|
||||
}
|
||||
|
||||
PVFieldPtr fromValue = from->get();
|
||||
if (from->getUnion()->isVariant())
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
to->set(PVFieldPtr());
|
||||
else
|
||||
to->set(getPVDataCreate()->createPVField(fromValue)); // clone value // TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fromValue.get() == 0)
|
||||
to->select(PVUnion::UNDEFINED_INDEX);
|
||||
else
|
||||
copy(fromValue, to->select(from->getSelectedIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
bool Convert::isCopyStructureArrayCompatible(
|
||||
StructureArrayConstPtr const &from, StructureArrayConstPtr const &to)
|
||||
{
|
||||
@@ -403,6 +491,25 @@ void Convert::copyStructureArray(
|
||||
to->replace(from->view());
|
||||
}
|
||||
|
||||
bool Convert::isCopyUnionArrayCompatible(
|
||||
UnionArrayConstPtr const &from, UnionArrayConstPtr const &to)
|
||||
{
|
||||
UnionConstPtr xxx = from->getUnion();
|
||||
UnionConstPtr yyy = to->getUnion();
|
||||
return isCopyUnionCompatible(xxx,yyy);
|
||||
}
|
||||
|
||||
void Convert::copyUnionArray(
|
||||
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to)
|
||||
{
|
||||
if(from==to) {
|
||||
return;
|
||||
} else if(to->isImmutable()) {
|
||||
throw std::invalid_argument("Convert.copyUnionArray destination is immutable");
|
||||
}
|
||||
to->replace(from->view());
|
||||
}
|
||||
|
||||
void Convert::newLine(StringBuilder buffer, int indentLevel)
|
||||
{
|
||||
*buffer += "\n";
|
||||
|
||||
@@ -56,7 +56,7 @@ struct ScalarArrayHashFunction {
|
||||
|
||||
struct StructureHashFunction {
|
||||
size_t operator() (const Structure& /*structure*/) const { return 0; }
|
||||
// TODO
|
||||
// TODO hash
|
||||
// final int PRIME = 31;
|
||||
// return PRIME * Arrays.hashCode(fieldNames) + Arrays.hashCode(fields);
|
||||
};
|
||||
@@ -934,7 +934,7 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
|
||||
if (code == -1)
|
||||
return FieldConstPtr();
|
||||
|
||||
int typeCode = code & 0xE0;
|
||||
int typeCode = code & 0xEF;
|
||||
bool notArray = ((code & 0x10) == 0);
|
||||
if (notArray)
|
||||
{
|
||||
|
||||
@@ -446,6 +446,14 @@ PVFieldPtr PVDataCreate::createPVField(FieldConstPtr const & field)
|
||||
StructureArrayConstPtr xx = static_pointer_cast<const StructureArray>(field);
|
||||
return createPVStructureArray(xx);
|
||||
}
|
||||
case union_: {
|
||||
UnionConstPtr xx = static_pointer_cast<const Union>(field);
|
||||
return createPVUnion(xx);
|
||||
}
|
||||
case unionArray: {
|
||||
UnionArrayConstPtr xx = static_pointer_cast<const UnionArray>(field);
|
||||
return createPVUnionArray(xx);
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVDataCreate::createPVField should never get here");
|
||||
}
|
||||
@@ -482,6 +490,21 @@ PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone)
|
||||
getConvert()->copyStructureArray(from, to);
|
||||
return to;
|
||||
}
|
||||
case union_:
|
||||
{
|
||||
PVUnionPtr pvUnion
|
||||
= static_pointer_cast<PVUnion>(fieldToClone);
|
||||
return createPVUnion(pvUnion);
|
||||
}
|
||||
case unionArray:
|
||||
{
|
||||
PVUnionArrayPtr from
|
||||
= static_pointer_cast<PVUnionArray>(fieldToClone);
|
||||
UnionArrayConstPtr unionArray = from->getUnionArray();
|
||||
PVUnionArrayPtr to = createPVUnionArray(unionArray);
|
||||
getConvert()->copyUnionArray(from, to);
|
||||
return to;
|
||||
}
|
||||
}
|
||||
throw std::logic_error("PVDataCreate::createPVField should never get here");
|
||||
}
|
||||
@@ -614,6 +637,28 @@ PVStructurePtr PVDataCreate::createPVStructure(
|
||||
return PVStructurePtr(new PVStructure(structure));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVUnionArray(
|
||||
UnionArrayConstPtr const & unionArray)
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(unionArray));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(
|
||||
UnionConstPtr const & punion)
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(punion));
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVVariantUnion()
|
||||
{
|
||||
return PVUnionPtr(new PVUnion(getFieldCreate()->createVariantUnion()));
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVDataCreate::createPVVariantUnionArray()
|
||||
{
|
||||
return PVUnionArrayPtr(new PVUnionArray(getFieldCreate()->createVariantUnionArray()));
|
||||
}
|
||||
|
||||
PVStructurePtr PVDataCreate::createPVStructure(
|
||||
StringArray const & fieldNames,PVFieldPtrArray const & pvFields)
|
||||
{
|
||||
@@ -629,6 +674,7 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
{
|
||||
FieldConstPtrArray field;
|
||||
if(structToClone==0) {
|
||||
// is this correct?!
|
||||
FieldConstPtrArray fields(0);
|
||||
StringArray fieldNames(0);
|
||||
StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields);
|
||||
@@ -640,6 +686,14 @@ PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToCl
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone)
|
||||
{
|
||||
PVUnionPtr punion(new PVUnion(unionToClone->getUnion()));
|
||||
// set cloned value
|
||||
punion->set(unionToClone->getSelectedIndex(), createPVField(unionToClone->get()));
|
||||
return punion;
|
||||
}
|
||||
|
||||
PVDataCreatePtr PVDataCreate::getPVDataCreate()
|
||||
{
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
|
||||
@@ -265,7 +265,9 @@ void PVField::computeOffset(const PVField * pvField) {
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray:{
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvField->fieldOffset = offset;
|
||||
pvField->nextFieldOffset = nextOffset;
|
||||
@@ -295,7 +297,9 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) {
|
||||
switch(field->getType()) {
|
||||
case scalar:
|
||||
case scalarArray:
|
||||
case structureArray: {
|
||||
case structureArray:
|
||||
case union_:
|
||||
case unionArray: {
|
||||
nextOffset++;
|
||||
pvSubField->fieldOffset = offset;
|
||||
pvSubField->nextFieldOffset = nextOffset;
|
||||
|
||||
@@ -38,6 +38,8 @@ PVDoublePtr PVStructure::nullPVDouble;
|
||||
PVStringPtr PVStructure::nullPVString;
|
||||
PVStructurePtr PVStructure::nullPVStructure;
|
||||
PVStructureArrayPtr PVStructure::nullPVStructureArray;
|
||||
PVUnionPtr PVStructure::nullPVUnion;
|
||||
PVUnionArrayPtr PVStructure::nullPVUnionArray;
|
||||
PVScalarArrayPtr PVStructure::nullPVScalarArray;
|
||||
|
||||
static PVFieldPtr findSubField(
|
||||
@@ -520,6 +522,24 @@ PVStructurePtr PVStructure::getStructureField(String const &fieldName)
|
||||
return nullPVStructure;
|
||||
}
|
||||
|
||||
PVUnionPtr PVStructure::getUnionField(String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUnion;
|
||||
}
|
||||
if(pvField->getField()->getType()==union_) {
|
||||
return std::tr1::static_pointer_cast<PVUnion>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type union ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUnion;
|
||||
}
|
||||
|
||||
PVScalarArrayPtr PVStructure::getScalarArrayField(
|
||||
String const &fieldName,ScalarType elementType)
|
||||
{
|
||||
@@ -569,6 +589,25 @@ PVStructureArrayPtr PVStructure::getStructureArrayField(
|
||||
return nullPVStructureArray;
|
||||
}
|
||||
|
||||
PVUnionArrayPtr PVStructure::getUnionArrayField(
|
||||
String const &fieldName)
|
||||
{
|
||||
PVFieldPtr pvField = findSubField(fieldName,this);
|
||||
if(pvField.get()==NULL) {
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not exist";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUnionArray;
|
||||
}
|
||||
if(pvField->getField()->getType()==unionArray) {
|
||||
return std::tr1::static_pointer_cast<PVUnionArray>(pvField);
|
||||
}
|
||||
String message("fieldName ");
|
||||
message += fieldName + " does not have type unionArray ";
|
||||
this->message(message, errorMessage);
|
||||
return nullPVUnionArray;
|
||||
}
|
||||
|
||||
String PVStructure::getExtendsStructureName() const
|
||||
{
|
||||
return extendsStructureName;
|
||||
|
||||
208
pvDataApp/factory/PVUnion.cpp
Normal file
208
pvDataApp/factory/PVUnion.cpp
Normal file
@@ -0,0 +1,208 @@
|
||||
/*PVUnion.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mse
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
int32 PVUnion::UNDEFINED_INDEX = -1;
|
||||
PVDataCreatePtr PVUnion::pvDataCreate = getPVDataCreate();
|
||||
|
||||
|
||||
PVUnion::PVUnion(UnionConstPtr const & unionPtr)
|
||||
: PVField(unionPtr),
|
||||
unionPtr(unionPtr),
|
||||
selector(UNDEFINED_INDEX),
|
||||
value(),
|
||||
variant(unionPtr->isVariant())
|
||||
{
|
||||
}
|
||||
|
||||
PVUnion::~PVUnion()
|
||||
{
|
||||
}
|
||||
|
||||
UnionConstPtr PVUnion::getUnion() const
|
||||
{
|
||||
return unionPtr;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::get() const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
int32 PVUnion::getSelectedIndex() const
|
||||
{
|
||||
return selector;
|
||||
}
|
||||
|
||||
String PVUnion::getSelectedFieldName() const
|
||||
{
|
||||
// no name for undefined and for variant unions
|
||||
if (selector == UNDEFINED_INDEX)
|
||||
return String();
|
||||
else
|
||||
return unionPtr->getFieldName(selector);
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(int32 index)
|
||||
{
|
||||
// no change
|
||||
if (selector == index)
|
||||
return value;
|
||||
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
selector = UNDEFINED_INDEX;
|
||||
value.reset();
|
||||
return value;
|
||||
}
|
||||
else if (variant)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
FieldConstPtr field = unionPtr->getField(index);
|
||||
selector = index;
|
||||
value = pvDataCreate->createPVField(field);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
PVFieldPtr PVUnion::select(String const & fieldName)
|
||||
{
|
||||
int32 index = variant ? -1 : unionPtr->getFieldIndex(fieldName);
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
|
||||
return select(index);
|
||||
}
|
||||
|
||||
void PVUnion::set(PVFieldPtr const & value)
|
||||
{
|
||||
set(selector, value);
|
||||
}
|
||||
|
||||
void PVUnion::set(int32 index, PVFieldPtr const & value)
|
||||
{
|
||||
if (variant && index != UNDEFINED_INDEX)
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
else if (!variant)
|
||||
{
|
||||
if (index == UNDEFINED_INDEX)
|
||||
{
|
||||
// for undefined index we accept only null values
|
||||
if (value.get())
|
||||
throw std::invalid_argument("non-null value for index == UNDEFINED_INDEX");
|
||||
}
|
||||
else if (index < 0 || index > static_cast<int32>(unionPtr->getFields().size()))
|
||||
throw std::invalid_argument("index out of bounds");
|
||||
|
||||
// value type must match
|
||||
if (value->getField() != unionPtr->getField(index))
|
||||
throw std::invalid_argument("selected field and its introspection data do not match");
|
||||
}
|
||||
|
||||
selector = index;
|
||||
this->value = value;
|
||||
}
|
||||
|
||||
void PVUnion::set(String const & fieldName, PVFieldPtr const & value)
|
||||
{
|
||||
int32 index = variant ? -1 : unionPtr->getFieldIndex(fieldName);
|
||||
if (index == -1)
|
||||
throw std::invalid_argument("no such fieldName");
|
||||
|
||||
set(index, value);
|
||||
}
|
||||
|
||||
void PVUnion::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
// write introspection data
|
||||
if (value.get() == 0)
|
||||
pbuffer->put((int8)-1);
|
||||
else
|
||||
{
|
||||
pflusher->cachedSerialize(value->getField(), pbuffer);
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// write selector value
|
||||
SerializeHelper::writeSize(selector, pbuffer, pflusher);
|
||||
// write value, no value for UNDEFINED_INDEX
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
value->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
|
||||
void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol)
|
||||
{
|
||||
if (variant)
|
||||
{
|
||||
FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer);
|
||||
if (field.get())
|
||||
{
|
||||
value = pvDataCreate->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
selector = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
if (selector != UNDEFINED_INDEX)
|
||||
{
|
||||
FieldConstPtr field = unionPtr->getField(selector);
|
||||
value = pvDataCreate->createPVField(field);
|
||||
value->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
else
|
||||
value.reset();
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnion::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnion()->getID() << ' ' << getFieldName() << std::endl;
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
PVFieldPtr fieldField = get();
|
||||
if (fieldField.get() == NULL)
|
||||
o << format::indent() << "(none)" << std::endl;
|
||||
else
|
||||
{
|
||||
Type type = fieldField->getField()->getType();
|
||||
if (type == scalar || type == scalarArray)
|
||||
o << format::indent() << fieldField->getField()->getID() << ' ' << fieldField->getFieldName() << ' ' << *(fieldField.get()) << std::endl;
|
||||
else
|
||||
o << *(fieldField.get());
|
||||
}
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
212
pvDataApp/factory/PVUnionArray.cpp
Normal file
212
pvDataApp/factory/PVUnionArray.cpp
Normal file
@@ -0,0 +1,212 @@
|
||||
/*PVUnionArray.cpp*/
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/factory.h>
|
||||
#include <pv/serializeHelper.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
size_t PVUnionArray::append(size_t number)
|
||||
{
|
||||
svector data(reuse());
|
||||
data.resize(data.size()+number);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
|
||||
*it = getPVDataCreate()->createPVUnion(punion);
|
||||
|
||||
size_t newLength = data.size();
|
||||
|
||||
const_svector cdata(freeze(data));
|
||||
swap(cdata);
|
||||
|
||||
return newLength;
|
||||
}
|
||||
|
||||
bool PVUnionArray::remove(size_t offset,size_t number)
|
||||
{
|
||||
if(number==0)
|
||||
return true;
|
||||
else if(offset+number>getLength())
|
||||
return false;
|
||||
|
||||
svector vec(reuse());
|
||||
|
||||
size_t length = vec.size();
|
||||
|
||||
for(size_t i = offset; i+number < length; i++) {
|
||||
vec[i].swap(vec[i + number]);
|
||||
}
|
||||
|
||||
vec.resize(length - number);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PVUnionArray::compress() {
|
||||
svector vec(reuse()); // TODO: check for first NULL before realloc
|
||||
|
||||
size_t length = vec.size();
|
||||
size_t newLength = 0;
|
||||
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(vec[i].get()!=NULL) {
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
// find first non 0
|
||||
size_t notNull = 0;
|
||||
for(size_t j=i+1;j<length;j++) {
|
||||
if(vec[j].get()!=NULL) {
|
||||
notNull = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notNull!=0) {
|
||||
vec[i] = vec[notNull];
|
||||
vec[notNull].reset();
|
||||
newLength++;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vec.resize(newLength);
|
||||
const_svector cdata(freeze(vec));
|
||||
swap(cdata);
|
||||
}
|
||||
|
||||
void PVUnionArray::setCapacity(size_t capacity)
|
||||
{
|
||||
if(this->isCapacityMutable()) {
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(value.capacity()<capacity) {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.reserve(capacity);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
}
|
||||
|
||||
void PVUnionArray::setLength(size_t length)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
const_svector value;
|
||||
swap(value);
|
||||
if(length == value.size()) {
|
||||
// nothing
|
||||
} else if(length < value.size()) {
|
||||
value.slice(0, length);
|
||||
} else {
|
||||
svector mvalue(thaw(value));
|
||||
mvalue.resize(length);
|
||||
value = freeze(mvalue);
|
||||
}
|
||||
swap(value);
|
||||
}
|
||||
|
||||
void PVUnionArray::swap(const_svector &other)
|
||||
{
|
||||
if(this->isImmutable())
|
||||
THROW_EXCEPTION2(std::logic_error,"Immutable");
|
||||
|
||||
value.swap(other);
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const {
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void PVUnionArray::deserialize(ByteBuffer *pbuffer,
|
||||
DeserializableControl *pcontrol) {
|
||||
svector data(reuse());
|
||||
|
||||
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
|
||||
data.resize(size);
|
||||
|
||||
UnionConstPtr punion = unionArray->getUnion();
|
||||
|
||||
for(size_t i = 0; i<size; i++) {
|
||||
pcontrol->ensureData(1);
|
||||
size_t temp = pbuffer->getByte();
|
||||
if(temp==0) {
|
||||
data[i].reset();
|
||||
}
|
||||
else {
|
||||
if(data[i].get()==NULL) {
|
||||
data[i] = getPVDataCreate()->createPVUnion(punion);
|
||||
}
|
||||
data[i]->deserialize(pbuffer, pcontrol);
|
||||
}
|
||||
}
|
||||
replace(freeze(data)); // calls postPut()
|
||||
}
|
||||
|
||||
void PVUnionArray::serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, size_t offset, size_t count) const {
|
||||
|
||||
const_svector temp(view());
|
||||
temp.slice(offset, count);
|
||||
|
||||
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
|
||||
|
||||
for(size_t i = 0; i<count; i++) {
|
||||
if(pbuffer->getRemaining()<1)
|
||||
pflusher->flushSerializeBuffer();
|
||||
|
||||
if(temp[i].get()==NULL) {
|
||||
pbuffer->putByte(0);
|
||||
}
|
||||
else {
|
||||
pbuffer->putByte(1);
|
||||
temp[i]->serialize(pbuffer, pflusher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
|
||||
{
|
||||
o << format::indent() << getUnionArray()->getID() << ' ' << getFieldName() << std::endl;
|
||||
size_t length = getLength();
|
||||
if (length > 0)
|
||||
{
|
||||
format::indent_scope s(o);
|
||||
|
||||
for (size_t i = 0; i < length; i++)
|
||||
dumpValue(o, i);
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
|
||||
{
|
||||
const_svector temp(view());
|
||||
if(index<temp.size())
|
||||
o << temp[index].get();
|
||||
return o;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -22,10 +22,10 @@ namespace epics { namespace pvData {
|
||||
|
||||
namespace TypeFunc {
|
||||
static const char* names[] = {
|
||||
"scalar", "scalarArray", "structure", "structureArray",
|
||||
"scalar", "scalarArray", "structure", "structureArray", "union", "unionArray"
|
||||
};
|
||||
const char* name(Type t) {
|
||||
if (t<int(pvBoolean) || t>int(pvString))
|
||||
if (t<int(scalar) || t>int(unionArray))
|
||||
THROW_EXCEPTION2(std::invalid_argument, "logic error unknown Type");
|
||||
return names[t];
|
||||
}
|
||||
|
||||
@@ -44,7 +44,13 @@ void PrinterBase::endStructure(const PVStructure&) {}
|
||||
void PrinterBase::beginStructureArray(const PVStructureArray&) {}
|
||||
void PrinterBase::endStructureArray(const PVStructureArray&) {}
|
||||
|
||||
void PrinterBase::encodeScalar(const PVScalar& pv) {}
|
||||
void PrinterBase::beginUnion(const PVUnion&) {}
|
||||
void PrinterBase::endUnion(const PVUnion&) {}
|
||||
|
||||
void PrinterBase::beginUnionArray(const PVUnionArray&) {}
|
||||
void PrinterBase::endUnionArray(const PVUnionArray&) {}
|
||||
|
||||
void PrinterBase::encodeScalar(const PVScalar&) {}
|
||||
|
||||
void PrinterBase::encodeArray(const PVScalarArray&) {}
|
||||
|
||||
@@ -81,6 +87,14 @@ void PrinterBase::impl_print(const PVField& pv)
|
||||
endStructureArray(*static_cast<const PVStructureArray *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case union_:
|
||||
endUnion(*static_cast<const PVUnion *>(inprog.back()));
|
||||
break;
|
||||
|
||||
case unionArray:
|
||||
endUnionArray(*static_cast<const PVUnionArray *>(inprog.back()));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(false); // oops!
|
||||
return;
|
||||
@@ -129,6 +143,35 @@ void PrinterBase::impl_print(const PVField& pv)
|
||||
todo.push_back(it->get());
|
||||
}
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case union_: {
|
||||
const PVUnion &fld = *static_cast<const PVUnion*>(next);
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginUnion(fld);
|
||||
PVFieldPtr val = fld.get();
|
||||
if (val.get()) // TODO print "(none)" ?
|
||||
todo.push_back(val.get());
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
case unionArray: {
|
||||
const PVUnionArray &fld = *static_cast<const PVUnionArray*>(next);
|
||||
PVUnionArray::const_svector vals(fld.view());
|
||||
|
||||
inprog.push_back(next);
|
||||
|
||||
beginUnionArray(fld);
|
||||
for(PVUnionArray::const_svector::const_iterator it=vals.begin();
|
||||
it!=vals.end(); ++it)
|
||||
{
|
||||
todo.push_back(it->get());
|
||||
}
|
||||
|
||||
todo.push_back(marker);
|
||||
break;
|
||||
}
|
||||
@@ -168,6 +211,25 @@ void PrinterPlain::beginStructureArray(const PVStructureArray& pv)
|
||||
|
||||
void PrinterPlain::endStructureArray(const PVStructureArray&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginUnion(const PVUnion& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getUnion()->getID() << " " << pv.getFieldName() << std::endl;
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endUnion(const PVUnion&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::beginUnionArray(const PVUnionArray& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
S() << pv.getUnionArray()->getID() << " "
|
||||
<< pv.getFieldName() << "[] ";
|
||||
ilvl++;
|
||||
}
|
||||
|
||||
void PrinterPlain::endUnionArray(const PVUnionArray&) {ilvl--;}
|
||||
|
||||
void PrinterPlain::encodeScalar(const PVScalar& pv)
|
||||
{
|
||||
indentN(S(), ilvl);
|
||||
|
||||
@@ -30,6 +30,8 @@ bool operator==(const Scalar&, const Scalar&);
|
||||
bool operator==(const ScalarArray&, const ScalarArray&);
|
||||
bool operator==(const Structure&, const Structure&);
|
||||
bool operator==(const StructureArray&, const StructureArray&);
|
||||
bool operator==(const Union&, const Union&);
|
||||
bool operator==(const UnionArray&, const UnionArray&);
|
||||
|
||||
static inline bool operator!=(const Field& a, const Field& b)
|
||||
{return !(a==b);}
|
||||
@@ -41,6 +43,10 @@ static inline bool operator!=(const Structure& a, const Structure& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const StructureArray& a, const StructureArray& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const Union& a, const Union& b)
|
||||
{return !(a==b);}
|
||||
static inline bool operator!=(const UnionArray& a, const UnionArray& b)
|
||||
{return !(a==b);}
|
||||
|
||||
|
||||
/**
|
||||
@@ -291,6 +297,38 @@ public:
|
||||
*/
|
||||
void copyStructureArray(
|
||||
PVStructureArrayPtr const & from, PVStructureArrayPtr const & to);
|
||||
/**
|
||||
* Are from and to valid arguments for copyUnion.
|
||||
* They are only compatible if they have the same Union description.
|
||||
* @param from from union.
|
||||
* @param to union.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyUnionCompatible(
|
||||
UnionConstPtr const & from, UnionConstPtr const & to);
|
||||
/**
|
||||
* Copy from a union pv to another union pv.
|
||||
* NOTE: Only compatible nodes are copied.
|
||||
* @param from The source.
|
||||
* @param to The destination.
|
||||
* @throws std::invalid_argument if the arguments are not compatible.
|
||||
*/
|
||||
void copyUnion(PVUnionPtr const & from, PVUnionPtr const & to);
|
||||
/**
|
||||
* Are from and to valid for copyUnionArray.
|
||||
* @param from The from UnionArray.
|
||||
* @param to The to UnionArray.
|
||||
* @return (false,true) If the arguments (are not, are) compatible.
|
||||
*/
|
||||
bool isCopyUnionArrayCompatible(
|
||||
UnionArrayConstPtr const & from, UnionArrayConstPtr const & to);
|
||||
/**
|
||||
* Copy from a union array to another union array.
|
||||
* @param from The source array.
|
||||
* @param to The destination array.
|
||||
*/
|
||||
void copyUnionArray(
|
||||
PVUnionArrayPtr const & from, PVUnionArrayPtr const & to);
|
||||
/**
|
||||
* Convert a PV to a <byte>.
|
||||
* @param pv a PV
|
||||
|
||||
@@ -25,6 +25,12 @@ protected:
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void beginUnion(const PVUnion&);
|
||||
virtual void endUnion(const PVUnion&);
|
||||
|
||||
virtual void beginUnionArray(const PVUnionArray&);
|
||||
virtual void endUnionArray(const PVUnionArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
@@ -46,6 +52,12 @@ protected:
|
||||
virtual void beginStructureArray(const PVStructureArray&);
|
||||
virtual void endStructureArray(const PVStructureArray&);
|
||||
|
||||
virtual void beginUnion(const PVUnion&);
|
||||
virtual void endUnion(const PVUnion&);
|
||||
|
||||
virtual void beginUnionArray(const PVUnionArray&);
|
||||
virtual void endUnionArray(const PVUnionArray&);
|
||||
|
||||
virtual void encodeScalar(const PVScalar&);
|
||||
virtual void encodeArray(const PVScalarArray&);
|
||||
virtual void encodeNull();
|
||||
|
||||
@@ -108,6 +108,9 @@ class PVScalarArray;
|
||||
|
||||
class PVStructure;
|
||||
|
||||
class PVUnion;
|
||||
|
||||
|
||||
|
||||
template<typename T> class PVScalarValue;
|
||||
template<typename T> class PVValueArray;
|
||||
@@ -164,6 +167,29 @@ typedef std::tr1::shared_ptr<PVStructureArray> PVStructureArrayPtr;
|
||||
typedef std::vector<PVStructureArrayPtr> PVStructureArrayPtrArray;
|
||||
typedef std::tr1::shared_ptr<PVStructureArrayPtrArray> PVStructureArrayPtrArrayPtr;
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a PVUnion.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<PVUnion> PVUnionPtr;
|
||||
/**
|
||||
* typedef for a pointer to a array of pointer to PVUnion.
|
||||
*/
|
||||
typedef std::vector<PVUnionPtr> PVUnionPtrArray;
|
||||
typedef std::vector<PVUnionPtr>::iterator PVUnionPtrArray_iterator;
|
||||
typedef std::vector<PVUnionPtr>::const_iterator PVUnionPtrArray_const__iterator;
|
||||
|
||||
/**
|
||||
* typedef for a pointer to a PVUnionArray.
|
||||
*/
|
||||
|
||||
typedef PVValueArray<PVUnionPtr> PVUnionArray;
|
||||
typedef std::tr1::shared_ptr<PVUnionArray> PVUnionArrayPtr;
|
||||
typedef std::vector<PVUnionArrayPtr> PVUnionArrayPtrArray;
|
||||
typedef std::tr1::shared_ptr<PVUnionArrayPtrArray> PVUnionArrayPtrArrayPtr;
|
||||
|
||||
class PVDataCreate;
|
||||
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
|
||||
|
||||
/**
|
||||
* This class provides auxillary information about a PVField.
|
||||
* Each item is stored as a PVScalar.
|
||||
@@ -890,6 +916,12 @@ public:
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructurePtr getStructureField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a union field with the specified name.
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionPtr getUnionField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a scalarArray field with the specified name.
|
||||
* @param fieldName The name of the field to get.
|
||||
@@ -904,6 +936,12 @@ public:
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVStructureArrayPtr getStructureArrayField(String const &fieldName) ;
|
||||
/**
|
||||
* Get a unionArray field with the specified name.
|
||||
* @param fieldName The name of the field to get.
|
||||
* @return Pointer to the field of null if a field with that name and type does not exist.
|
||||
*/
|
||||
PVUnionArrayPtr getUnionArrayField(String const &fieldName) ;
|
||||
/**
|
||||
* Get the name if this structure extends another structure.
|
||||
* @return The string which may be null.
|
||||
@@ -976,6 +1014,8 @@ private:
|
||||
static PVStringPtr nullPVString;
|
||||
static PVStructurePtr nullPVStructure;
|
||||
static PVStructureArrayPtr nullPVStructureArray;
|
||||
static PVUnionPtr nullPVUnion;
|
||||
static PVUnionArrayPtr nullPVUnionArray;
|
||||
static PVScalarArrayPtr nullPVScalarArray;
|
||||
|
||||
PVFieldPtrArray pvFields;
|
||||
@@ -984,6 +1024,142 @@ private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
|
||||
class PVUnion : public PVField
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVUnion);
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVUnion();
|
||||
typedef PVUnion & reference;
|
||||
typedef const PVUnion & const_reference;
|
||||
|
||||
/**
|
||||
* Undefined index.
|
||||
* Default value upon PVUnion construction. Can be set by the user.
|
||||
* Corresponds to {@code null} value.
|
||||
*/
|
||||
static int32 UNDEFINED_INDEX;
|
||||
|
||||
/**
|
||||
* Get the introspection interface
|
||||
* @return The interface.
|
||||
*/
|
||||
UnionConstPtr getUnion() const;
|
||||
|
||||
/**
|
||||
* Get the {@code PVField} value stored in the field.
|
||||
* @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}.
|
||||
*/
|
||||
PVFieldPtr get() const;
|
||||
|
||||
// TODO dynamic vs static cast?
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> get() const {
|
||||
return std::tr1::static_pointer_cast<PVT>(get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select field (set index) and get the field at the index.
|
||||
* @param index index of the field to select.
|
||||
* @return corresponding PVField (of undetermined value), {@code null} if {@code index == UNDEFINED_INDEX}.
|
||||
* @throws {@code std::invalid_argument} if index is invalid (out of range).
|
||||
*/
|
||||
PVFieldPtr select(int32 index);
|
||||
|
||||
// TODO dynamic vs static cast?
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> select(int32 index) {
|
||||
return std::tr1::static_pointer_cast<PVT>(select(index));
|
||||
}
|
||||
|
||||
/**
|
||||
* Select field (set index) and get the field by given name.
|
||||
* @param fieldName the name of the field to select.
|
||||
* @return corresponding PVField (of undetermined value).
|
||||
* @throws {@code std::invalid_argument} if field does not exist.
|
||||
*/
|
||||
PVFieldPtr select(String const & fieldName);
|
||||
|
||||
// TODO dynamic vs static cast?
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> select(String const & fieldName) {
|
||||
return std::tr1::static_pointer_cast<PVT>(select(fieldName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selected field index.
|
||||
* @return selected field index.
|
||||
*/
|
||||
int32 getSelectedIndex() const;
|
||||
|
||||
/**
|
||||
* Get selected field name.
|
||||
* @return selected field name, empty string if field does not exist.
|
||||
*/
|
||||
String getSelectedFieldName() const;
|
||||
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as selected field.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* @param value the field to set.
|
||||
*/
|
||||
void set(PVFieldPtr const & value);
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as field at given index.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* Use {@code select(int)} to put by value.
|
||||
* @param index index of a field to put.
|
||||
* @param value the field to set.
|
||||
* @see #select(int)
|
||||
*/
|
||||
void set(int32 index, PVFieldPtr const & value);
|
||||
/**
|
||||
* Set the {@code PVField} (by reference!) as field by given name.
|
||||
* If a value is not a valid union field an {@code std::invalid_argument} exception is thrown.
|
||||
* Use {@code select(String)} to put by value.
|
||||
* @param fieldName Name of the field to put.
|
||||
* @param value the field to set.
|
||||
* @see #select(String)
|
||||
*/
|
||||
void set(String const & fieldName, PVFieldPtr const & value);
|
||||
|
||||
/**
|
||||
* Serialize.
|
||||
* @param pbuffer The byte buffer.
|
||||
* @param pflusher Interface to call when buffer is full.
|
||||
*/
|
||||
virtual void serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const ;
|
||||
/**
|
||||
* Deserialize
|
||||
* @param pbuffer The byte buffer.
|
||||
* @param pflusher Interface to call when buffer is empty.
|
||||
*/
|
||||
virtual void deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher);
|
||||
/**
|
||||
* Constructor
|
||||
* @param punion The introspection interface.
|
||||
*/
|
||||
PVUnion(UnionConstPtr const & punion);
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
|
||||
private:
|
||||
friend class PVDataCreate;
|
||||
static PVDataCreatePtr pvDataCreate;
|
||||
|
||||
UnionConstPtr unionPtr;
|
||||
|
||||
int32 selector;
|
||||
PVFieldPtr value;
|
||||
bool variant;
|
||||
};
|
||||
|
||||
|
||||
namespace detail {
|
||||
// adaptor to allow epics::pvData::shared_vector to hold a reference
|
||||
// to a shared_ptr<std::vector<> >
|
||||
@@ -1301,6 +1477,105 @@ private:
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This is provided by code that calls get.
|
||||
*/
|
||||
typedef PVArrayData<PVUnionPtr> UnionArrayData;
|
||||
|
||||
/**
|
||||
* Data class for a unionArray
|
||||
*/
|
||||
template<>
|
||||
class PVValueArray<PVUnionPtr> : public detail::PVVectorStorage<PVUnionPtr,PVArray>
|
||||
{
|
||||
typedef detail::PVVectorStorage<PVUnionPtr,PVArray> base_t;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVUnionArray);
|
||||
typedef PVUnionPtr value_type;
|
||||
typedef PVUnionPtr* pointer;
|
||||
typedef const PVUnionPtr* const_pointer;
|
||||
typedef PVArrayData<PVUnionPtr> ArrayDataType;
|
||||
typedef std::vector<PVUnionPtr> vector;
|
||||
typedef const std::vector<PVUnionPtr> const_vector;
|
||||
typedef std::tr1::shared_ptr<vector> shared_vector;
|
||||
typedef PVUnionArray &reference;
|
||||
typedef const PVUnionArray& const_reference;
|
||||
|
||||
//TODO: full namespace can be removed along with local typedef 'shared_vector'
|
||||
typedef ::epics::pvData::shared_vector<PVUnionPtr> svector;
|
||||
typedef ::epics::pvData::shared_vector<const PVUnionPtr> const_svector;
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVValueArray() {}
|
||||
|
||||
virtual size_t getLength() const {return value.size();}
|
||||
virtual size_t getCapacity() const {return value.capacity();}
|
||||
|
||||
/**
|
||||
* Set the array capacity.
|
||||
* @param capacity The length.
|
||||
*/
|
||||
virtual void setCapacity(size_t capacity);
|
||||
/**
|
||||
* Set the array length.
|
||||
* @param length The length.
|
||||
*/
|
||||
virtual void setLength(std::size_t length);
|
||||
|
||||
/**
|
||||
* Get the introspection interface
|
||||
* @return The interface.
|
||||
*/
|
||||
UnionArrayConstPtr getUnionArray() const {return unionArray;}
|
||||
/**
|
||||
* Append new elements to the end of the array.
|
||||
* @param number The number of elements to add.
|
||||
* @return the new length of the array.
|
||||
*/
|
||||
virtual std::size_t append(std::size_t number);
|
||||
/**
|
||||
* Remove elements from the array.
|
||||
* @param offset The offset of the first element to remove.
|
||||
* @param number The number of elements to remove.
|
||||
* @return (false,true) if the elements were removed.
|
||||
*/
|
||||
virtual bool remove(std::size_t offset,std::size_t number);
|
||||
/**
|
||||
* Compress. This removes all null elements from the array.
|
||||
*/
|
||||
virtual void compress();
|
||||
|
||||
virtual const_svector view() const { return value; }
|
||||
virtual void swap(const_svector &other);
|
||||
virtual void replace(const const_svector &other) {
|
||||
value = other;
|
||||
PVField::postPut();
|
||||
}
|
||||
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher) const;
|
||||
virtual void deserialize(ByteBuffer *buffer,
|
||||
DeserializableControl *pflusher);
|
||||
virtual void serialize(ByteBuffer *pbuffer,
|
||||
SerializableControl *pflusher, std::size_t offset, std::size_t count) const ;
|
||||
|
||||
virtual std::ostream& dumpValue(std::ostream& o) const;
|
||||
virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const;
|
||||
|
||||
protected:
|
||||
PVValueArray(UnionArrayConstPtr const & unionArray)
|
||||
:base_t(unionArray)
|
||||
,unionArray(unionArray)
|
||||
{}
|
||||
private:
|
||||
UnionArrayConstPtr unionArray;
|
||||
const_svector value;
|
||||
friend class PVDataCreate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Definitions for the various scalarArray types.
|
||||
*/
|
||||
@@ -1352,8 +1627,6 @@ typedef PVArrayData<String> StringArrayData;
|
||||
typedef PVValueArray<String> PVStringArray;
|
||||
typedef std::tr1::shared_ptr<PVStringArray> PVStringArrayPtr;
|
||||
|
||||
class PVDataCreate;
|
||||
typedef std::tr1::shared_ptr<PVDataCreate> PVDataCreatePtr;
|
||||
/**
|
||||
* This is a singlton class for creating data instances.
|
||||
*/
|
||||
@@ -1439,6 +1712,36 @@ public:
|
||||
* @return The PVStructure implementation.
|
||||
*/
|
||||
PVStructurePtr createPVStructure(PVStructurePtr const & structToClone);
|
||||
/**
|
||||
* Create an implementation of an array with union elements.
|
||||
* @param unionArray The introspection interface.
|
||||
* All elements share the same introspection interface.
|
||||
* @return The PVUnionArray implementation.
|
||||
*/
|
||||
PVUnionArrayPtr createPVUnionArray(UnionArrayConstPtr const & unionArray);
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param union The introspection interface.
|
||||
* @return The PVUnion implementation
|
||||
*/
|
||||
PVUnionPtr createPVUnion(UnionConstPtr const & punion);
|
||||
/**
|
||||
* Create implementation for PVUnion.
|
||||
* @param unionToClone A union. Each subfield is cloned and added to the newly created union.
|
||||
* @return The PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVUnion(PVUnionPtr const & unionToClone);
|
||||
/**
|
||||
* Create variant union implementation.
|
||||
* @return The variant PVUnion implementation.
|
||||
*/
|
||||
PVUnionPtr createPVVariantUnion();
|
||||
/**
|
||||
* Create variant union array implementation.
|
||||
* @return The variant PVUnionArray implementation.
|
||||
*/
|
||||
PVUnionArrayPtr createPVVariantUnionArray();
|
||||
|
||||
private:
|
||||
PVDataCreate();
|
||||
FieldCreatePtr fieldCreate;
|
||||
|
||||
@@ -140,7 +140,7 @@ void serializationTest(PVFieldPtr const & field) {
|
||||
}
|
||||
|
||||
void testEquals() {
|
||||
testDiag("Testing equals...");
|
||||
testDiag("Testing equals..."); // and non-initialized
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
@@ -167,6 +167,59 @@ void testEquals() {
|
||||
PVStructureArrayPtr structureArray1 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure1->getStructure()));
|
||||
PVStructureArrayPtr structureArray2 = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure2->getStructure()));
|
||||
testOk1((*structureArray1)==(*structureArray2));
|
||||
|
||||
// variant union
|
||||
PVUnionPtr variantUnion1 = factory->createPVVariantUnion();
|
||||
PVUnionPtr variantUnion2 = factory->createPVVariantUnion();
|
||||
testOk1((*variantUnion1)==(*variantUnion2));
|
||||
|
||||
variantUnion1->set(structure1);
|
||||
variantUnion2->set(structure1);
|
||||
testOk1((*variantUnion1)==(*variantUnion2));
|
||||
|
||||
variantUnion2->set(structureArray1);
|
||||
testOk1((*variantUnion1)!=(*variantUnion2));
|
||||
|
||||
// variant union array
|
||||
PVUnionArrayPtr variantUnionArray1 = factory->createPVVariantUnionArray();
|
||||
PVUnionArrayPtr variantUnionArray2 = factory->createPVVariantUnionArray();
|
||||
testOk1((*variantUnionArray1)==(*variantUnionArray2));
|
||||
|
||||
// union
|
||||
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
||||
add("double", pvDouble)->
|
||||
add("double2", pvDouble)->
|
||||
addStructureArray("nested")->
|
||||
setId("nestedId")->
|
||||
add("short", pvShort)->
|
||||
add("long", pvLong)->
|
||||
createNested()->
|
||||
addArray("intArray", pvInt)->
|
||||
createUnion();
|
||||
PVUnionPtr union1 = factory->createPVUnion(punion);
|
||||
PVUnionPtr union2 = factory->createPVUnion(punion);
|
||||
testOk1((*union1)==(*union2));
|
||||
|
||||
union1->select<PVDouble>("double")->put(1.2);
|
||||
union2->select<PVDouble>("double")->put(1.2);
|
||||
testOk1((*union1)==(*union2));
|
||||
|
||||
union2->select<PVDouble>("double")->put(2.2);
|
||||
testOk1((*union1)!=(*union2));
|
||||
|
||||
union2->select<PVDouble>("double2")->put(1.2);
|
||||
testOk1((*union1)!=(*union2));
|
||||
|
||||
union2->select("nested");
|
||||
testOk1((*union1)!=(*union2));
|
||||
|
||||
testOk1((*union1)!=(*variantUnion2));
|
||||
|
||||
PVUnionArrayPtr unionArray1 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
||||
PVUnionArrayPtr unionArray2 = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
||||
testOk1((*unionArray1)==(*unionArray2));
|
||||
|
||||
testOk1((*variantUnionArray1)!=(*unionArray2));
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
@@ -322,32 +375,6 @@ void testArray() {
|
||||
testArrayType<PVStringArray>(sdata, NELEMENTS(sdata));
|
||||
}
|
||||
|
||||
void testNonInitialized() {
|
||||
testDiag("Testing non-initialized...");
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
// be sure all is covered
|
||||
for (int i = pvBoolean; i < pvString; i++)
|
||||
{
|
||||
ScalarType scalarType = static_cast<ScalarType>(i);
|
||||
|
||||
PVScalarPtr scalar = factory->createPVScalar(scalarType);
|
||||
serializationTest(scalar);
|
||||
|
||||
PVScalarArrayPtr array = factory->createPVScalarArray(scalarType);
|
||||
serializationTest(array);
|
||||
}
|
||||
|
||||
// and a structure
|
||||
PVStructurePtr structure = factory->createPVStructure(getStandardField()->timeStamp());
|
||||
serializationTest(structure);
|
||||
|
||||
// and a structure array
|
||||
PVStructureArrayPtr structureArray = factory->createPVStructureArray(getFieldCreate()->createStructureArray(structure->getStructure()));
|
||||
serializationTest(structureArray);
|
||||
}
|
||||
|
||||
void testStructure() {
|
||||
testDiag("Testing structure...");
|
||||
|
||||
@@ -371,6 +398,196 @@ void testStructure() {
|
||||
serializationTest(pvStructure);
|
||||
}
|
||||
|
||||
template<typename PVT>
|
||||
std::tr1::shared_ptr<PVT> createPVScalar()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVT>(
|
||||
getPVDataCreate()->createPVScalar(PVT::typeCode)
|
||||
);
|
||||
}
|
||||
|
||||
template<typename PVAT>
|
||||
std::tr1::shared_ptr<PVAT> createPVScalarArray()
|
||||
{
|
||||
return std::tr1::static_pointer_cast<PVAT>(
|
||||
getPVDataCreate()->createPVScalarArray(PVAT::typeCode)
|
||||
);
|
||||
}
|
||||
|
||||
void testUnion() {
|
||||
testDiag("Testing union...");
|
||||
|
||||
PVDataCreatePtr factory = getPVDataCreate();
|
||||
testOk1(factory.get()!=NULL);
|
||||
|
||||
|
||||
PVDoublePtr doubleValue = createPVScalar<PVDouble>();
|
||||
PVIntPtr intValue = createPVScalar<PVInt>();
|
||||
|
||||
testDiag("\tVariant union test");
|
||||
|
||||
PVUnionPtr variant = factory->createPVVariantUnion();
|
||||
testOk1(variant.get()!=NULL);
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
||||
testOk1("" == variant->getSelectedFieldName());
|
||||
serializationTest(variant);
|
||||
|
||||
variant->set(doubleValue);
|
||||
testOk1(doubleValue.get() == variant->get().get());
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
||||
testOk1("" == variant->getSelectedFieldName());
|
||||
serializationTest(variant);
|
||||
|
||||
variant->set(intValue);
|
||||
testOk1(intValue.get() == variant->get().get());
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
||||
testOk1("" == variant->getSelectedFieldName());
|
||||
serializationTest(variant);
|
||||
|
||||
variant->set(PVUnion::UNDEFINED_INDEX, doubleValue);
|
||||
testOk1(doubleValue.get() == variant->get().get());
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == variant->getSelectedIndex());
|
||||
|
||||
variant->set(PVFieldPtr());
|
||||
testOk1(NULL == variant->get().get());
|
||||
|
||||
testDiag("\tVariant union array test");
|
||||
|
||||
PVUnionArrayPtr variantArray = factory->createPVVariantUnionArray();
|
||||
testOk1(variantArray.get()!=NULL);
|
||||
|
||||
variantArray->setLength(6);
|
||||
PVUnionArray::svector data;
|
||||
|
||||
PVUnionPtr u = factory->createPVVariantUnion();
|
||||
data.push_back(u);
|
||||
|
||||
u = factory->createPVVariantUnion();
|
||||
u->set(factory->createPVStructure(getStandardField()->timeStamp()));
|
||||
data.push_back(u);
|
||||
|
||||
u = factory->createPVVariantUnion();
|
||||
u->set(factory->createPVStructure(getStandardField()->control()));
|
||||
data.push_back(u);
|
||||
|
||||
data.push_back(PVUnionPtr());
|
||||
|
||||
variantArray->replace(freeze(data));
|
||||
serializationTest(variantArray);
|
||||
|
||||
testDiag("\tVariant union test");
|
||||
|
||||
UnionConstPtr punion = getFieldCreate()->createFieldBuilder()->
|
||||
add("doubleValue", pvDouble)->
|
||||
add("intValue", pvInt)->
|
||||
createUnion();
|
||||
|
||||
u = factory->createPVUnion(punion);
|
||||
testOk1(NULL!=u.get());
|
||||
|
||||
// null union test
|
||||
testOk1(NULL==u->get().get());
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
||||
testOk1("" == u->getSelectedFieldName());
|
||||
serializationTest(u);
|
||||
|
||||
u->select<PVDouble>("doubleValue")->put(12);
|
||||
testOk1(12 == u->get<PVDouble>()->get());
|
||||
testOk1(0 == u->getSelectedIndex());
|
||||
testOk1("doubleValue" == u->getSelectedFieldName());
|
||||
serializationTest(u);
|
||||
|
||||
u->select<PVInt>("intValue")->put(543);
|
||||
testOk1(543 == u->get<PVInt>()->get());
|
||||
testOk1(1 == u->getSelectedIndex());
|
||||
testOk1("intValue" == u->getSelectedFieldName());
|
||||
serializationTest(u);
|
||||
|
||||
u->select<PVInt>(1)->put(5432);
|
||||
testOk1(5432 == u->get<PVInt>()->get());
|
||||
serializationTest(u);
|
||||
|
||||
testOk1(NULL==u->select(PVUnion::UNDEFINED_INDEX).get());
|
||||
testOk1(NULL==u->get().get());
|
||||
testOk1(PVUnion::UNDEFINED_INDEX == u->getSelectedIndex());
|
||||
testOk1("" == u->getSelectedFieldName());
|
||||
serializationTest(u);
|
||||
|
||||
u->set("doubleValue", doubleValue);
|
||||
testOk1(doubleValue.get() == u->get().get());
|
||||
testOk1(0 == u->getSelectedIndex());
|
||||
serializationTest(u);
|
||||
|
||||
try
|
||||
{
|
||||
u->set(1, doubleValue);
|
||||
testFail("field type does not match, but set allowed");
|
||||
}
|
||||
catch (std::invalid_argument& ia)
|
||||
{
|
||||
// expected
|
||||
testPass("PVUnion.set(int32, PVFieldPtr const&) field type does not match test");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
u->select(120);
|
||||
testFail("index out of bounds allowed");
|
||||
}
|
||||
catch (std::invalid_argument& ia)
|
||||
{
|
||||
// expected
|
||||
testPass("PVUnion.select(int32) index out of bounds test");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
u->select(-2);
|
||||
testFail("index out of bounds allowed");
|
||||
}
|
||||
catch (std::invalid_argument& ia)
|
||||
{
|
||||
// expected
|
||||
testPass("PVUnion.select(int32) index out of bounds test");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
u->set(120, doubleValue);
|
||||
testFail("index out of bounds allowed");
|
||||
}
|
||||
catch (std::invalid_argument& ia)
|
||||
{
|
||||
// expected
|
||||
testPass("PVUnion.set(int32, PVFieldPtr const&) index out of bounds test");
|
||||
}
|
||||
|
||||
testDiag("\tUnion array test");
|
||||
|
||||
PVUnionArrayPtr unionArray = factory->createPVUnionArray(getFieldCreate()->createUnionArray(punion));
|
||||
testOk1(unionArray.get()!=NULL);
|
||||
|
||||
unionArray->setLength(6);
|
||||
data.clear();
|
||||
|
||||
u = factory->createPVUnion(punion);
|
||||
data.push_back(u);
|
||||
|
||||
u = factory->createPVUnion(punion);
|
||||
u->select<PVDouble>(0)->put(12);
|
||||
data.push_back(u);
|
||||
|
||||
u = factory->createPVUnion(punion);
|
||||
u->select<PVInt>(1)->put(421);
|
||||
data.push_back(u);
|
||||
|
||||
data.push_back(PVUnionPtr());
|
||||
|
||||
unionArray->replace(freeze(data));
|
||||
serializationTest(unionArray);
|
||||
|
||||
}
|
||||
|
||||
void testStructureArray() {
|
||||
testDiag("Testing structure array...");
|
||||
|
||||
@@ -461,7 +678,7 @@ void testIntrospectionSerialization()
|
||||
|
||||
ScalarArrayConstPtr array = factory->createScalarArray(scalarType);
|
||||
serializatioTest(array);
|
||||
}
|
||||
}
|
||||
|
||||
// and a structure
|
||||
StructureConstPtr structure = getStandardField()->timeStamp();
|
||||
@@ -470,7 +687,31 @@ void testIntrospectionSerialization()
|
||||
// and a structure array
|
||||
StructureArrayConstPtr structureArray = factory->createStructureArray(structure);
|
||||
serializatioTest(structureArray);
|
||||
}
|
||||
|
||||
// variant union
|
||||
UnionConstPtr variant = factory->createVariantUnion();
|
||||
serializatioTest(variant);
|
||||
|
||||
// variant array union
|
||||
UnionArrayConstPtr variantArray = factory->createVariantUnionArray();
|
||||
serializatioTest(variantArray);
|
||||
|
||||
// union
|
||||
UnionConstPtr punion = factory->createFieldBuilder()->
|
||||
add("double", pvDouble)->
|
||||
addStructureArray("nested")->
|
||||
setId("nestedId")->
|
||||
add("short", pvShort)->
|
||||
add("long", pvLong)->
|
||||
createNested()->
|
||||
addArray("intArray", pvInt)->
|
||||
createUnion();
|
||||
serializatioTest(punion);
|
||||
|
||||
// union array
|
||||
UnionArrayConstPtr punionArray = factory->createUnionArray(punion);
|
||||
serializatioTest(punionArray);
|
||||
}
|
||||
|
||||
void testStringCopy() {
|
||||
String s1 = "abc";
|
||||
@@ -483,7 +724,7 @@ void testStringCopy() {
|
||||
|
||||
MAIN(testSerialization) {
|
||||
|
||||
testPlan(175);
|
||||
testPlan(213);
|
||||
|
||||
flusher = new SerializableControlImpl();
|
||||
control = new DeserializableControlImpl();
|
||||
@@ -493,12 +734,13 @@ MAIN(testSerialization) {
|
||||
|
||||
testIntrospectionSerialization();
|
||||
testEquals();
|
||||
testNonInitialized();
|
||||
|
||||
testScalar();
|
||||
testArray();
|
||||
testStructure();
|
||||
testStructureArray();
|
||||
|
||||
testUnion();
|
||||
|
||||
|
||||
delete buffer;
|
||||
|
||||
Reference in New Issue
Block a user