Union/UnionArray implemented, PVUnion/PVUnionArray not yet implemented; also implemented reuse of scalar/scalarArray instances in FieldCreate

This commit is contained in:
Matej Sekoranja
2013-11-05 16:15:12 +01:00
parent c56c976a22
commit cbf7b69ef0
3 changed files with 590 additions and 38 deletions

View File

@@ -69,7 +69,7 @@ struct StructureArrayHashFunction {
Scalar::Scalar(ScalarType scalarType)
: Field(scalar),scalarType(scalarType)
{
if(scalarType<pvBoolean || scalarType>pvString)
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
}
@@ -170,10 +170,49 @@ static StructureConstPtr deserializeStructureField(const FieldCreate* fieldCreat
return fieldCreate->createStructure(id, fieldNames, fields);
}
static void serializeUnionField(const Union* punion, ByteBuffer* buffer, SerializableControl* control)
{
// to optimize default (non-empty) IDs optimization
// empty IDs are not allowed
String id = punion->getID();
if (id == Union::DEFAULT_ID) // TODO slow comparison
SerializeHelper::serializeString(emptyString, buffer, control);
else
SerializeHelper::serializeString(id, buffer, control);
FieldConstPtrArray const & fields = punion->getFields();
StringArray const & fieldNames = punion->getFieldNames();
std::size_t len = fields.size();
SerializeHelper::writeSize(len, buffer, control);
for (std::size_t i = 0; i < len; i++)
{
SerializeHelper::serializeString(fieldNames[i], buffer, control);
control->cachedSerialize(fields[i], buffer);
}
}
static UnionConstPtr deserializeUnionField(const FieldCreate* fieldCreate, ByteBuffer* buffer, DeserializableControl* control)
{
String id = SerializeHelper::deserializeString(buffer, control);
const std::size_t size = SerializeHelper::readSize(buffer, control);
FieldConstPtrArray fields; fields.reserve(size);
StringArray fieldNames; fieldNames.reserve(size);
for (std::size_t i = 0; i < size; i++)
{
fieldNames.push_back(SerializeHelper::deserializeString(buffer, control));
fields.push_back(control->cachedDeserialize(buffer));
}
if (id.empty())
return fieldCreate->createUnion(fieldNames, fields);
else
return fieldCreate->createUnion(id, fieldNames, fields);
}
ScalarArray::ScalarArray(ScalarType elementType)
: Field(scalarArray),elementType(elementType)
{
if(elementType<pvBoolean || elementType>pvString)
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
}
@@ -265,6 +304,44 @@ void StructureArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl *
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
UnionArray::UnionArray(UnionConstPtr const & _punion)
: Field(unionArray),punion(_punion)
{
}
UnionArray::~UnionArray() {
if(debugLevel==highDebug) printf("~UnionArray\n");
}
String UnionArray::getID() const
{
return punion->getID() + "[]";
}
void UnionArray::toString(StringBuilder buffer,int indentLevel) const {
*buffer += getID();
newLine(buffer,indentLevel + 1);
punion->toString(buffer,indentLevel + 1);
}
void UnionArray::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
if (punion->isVariant())
{
// unrestricted/variant union
buffer->putByte(0x92);
}
else
{
buffer->putByte(0x91);
control->cachedSerialize(punion, buffer);
}
}
void UnionArray::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
String Structure::DEFAULT_ID = "structure";
Structure::Structure (
@@ -357,6 +434,17 @@ void Structure::toStringCommon(StringBuilder buffer,int indentLevel) const{
newLine(buffer,indentLevel +1);
pfield->toString(buffer,indentLevel +1);
break;
case union_:
{
Field const *xxx = pfield.get();
Union const *pstruct = static_cast<Union const*>(xxx);
pstruct->toStringCommon(buffer,indentLevel + 1);
break;
}
case unionArray:
newLine(buffer,indentLevel +1);
pfield->toString(buffer,indentLevel +1);
break;
}
if(i<numberFields-1) newLine(buffer,indentLevel);
}
@@ -372,6 +460,149 @@ void Structure::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*con
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
String Union::DEFAULT_ID = "union";
String Union::ANY_ID = "any";
Union::Union ()
: Field(union_),
fieldNames(),
fields(),
id(ANY_ID)
{
}
Union::Union (
StringArray const & fieldNames,
FieldConstPtrArray const & infields,
String const & inid)
: Field(union_),
fieldNames(fieldNames),
fields(infields),
id(inid)
{
if(inid.empty()) {
throw std::invalid_argument("id is empty");
}
if(fieldNames.size()!=fields.size()) {
throw std::invalid_argument("fieldNames.size()!=fields.size()");
}
if(fields.size()==0 && inid!=ANY_ID) {
throw std::invalid_argument("no fields but id is different than " + ANY_ID);
}
size_t number = fields.size();
for(size_t i=0; i<number; i++) {
const String& name = fieldNames[i];
if(name.empty()) {
throw std::invalid_argument("fieldNames has a zero length string");
}
if(fields[i].get()==NULL)
throw std::invalid_argument("Can't construct Union with NULL Field");
// look for duplicates
for(size_t j=i+1; j<number; j++) {
String otherName = fieldNames[j];
int result = name.compare(otherName);
if(result==0) {
String message("duplicate fieldName ");
message += name;
throw std::invalid_argument(message);
}
}
}
}
Union::~Union() { }
String Union::getID() const
{
return id;
}
FieldConstPtr Union::getField(String const & fieldName) const {
size_t numberFields = fields.size();
for(size_t i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName.compare(fieldNames[i]);
if(result==0) return pfield;
}
return FieldConstPtr();
}
size_t Union::getFieldIndex(String const &fieldName) const {
size_t numberFields = fields.size();
for(size_t i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
int result = fieldName.compare(fieldNames[i]);
if(result==0) return i;
}
return -1;
}
void Union::toString(StringBuilder buffer,int indentLevel) const{
*buffer += getID();
toStringCommon(buffer,indentLevel+1);
}
void Union::toStringCommon(StringBuilder buffer,int indentLevel) const{
newLine(buffer,indentLevel);
size_t numberFields = fields.size();
if (numberFields == 0) // variant support
return;
for(size_t i=0; i<numberFields; i++) {
FieldConstPtr pfield = fields[i];
*buffer += pfield->getID() + " " + fieldNames[i];
switch(pfield->getType()) {
case scalar:
case scalarArray:
break;
case structure:
{
Field const *xxx = pfield.get();
Structure const *pstruct = static_cast<Structure const*>(xxx);
pstruct->toStringCommon(buffer,indentLevel + 1);
break;
}
case structureArray:
newLine(buffer,indentLevel +1);
pfield->toString(buffer,indentLevel +1);
break;
case union_:
{
Field const *xxx = pfield.get();
Union const *pstruct = static_cast<Union const*>(xxx);
pstruct->toStringCommon(buffer,indentLevel + 1);
break;
}
case unionArray:
newLine(buffer,indentLevel +1);
pfield->toString(buffer,indentLevel +1);
break;
}
if(i<numberFields-1) newLine(buffer,indentLevel);
}
}
void Union::serialize(ByteBuffer *buffer, SerializableControl *control) const {
control->ensureBuffer(1);
if (fields.size() == 0)
{
// unrestricted/variant union
buffer->putByte(0x82);
}
else
{
buffer->putByte(0x81);
serializeUnionField(this, buffer, control);
}
}
void Union::deserialize(ByteBuffer */*buffer*/, DeserializableControl */*control*/) {
throw std::runtime_error("not valid operation, use FieldCreate::deserialize instead");
}
FieldBuilder::FieldBuilder() : fieldCreate(getFieldCreate()), idSet(false) {}
FieldBuilder::FieldBuilder(FieldBuilderPtr const & _parentBuilder,
@@ -425,9 +656,9 @@ FieldBuilderPtr FieldBuilder::addArray(std::string const & name, FieldConstPtr c
case structure:
fields.push_back(fieldCreate->createStructureArray(static_pointer_cast<const Structure>(element)));
break;
// TODO case union:
// fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
// break;
case union_:
fields.push_back(fieldCreate->createUnionArray(static_pointer_cast<const Union>(element)));
break;
case scalar:
fields.push_back(fieldCreate->createScalarArray(static_pointer_cast<const Scalar>(element)->getScalarType()));
break;
@@ -441,25 +672,22 @@ FieldBuilderPtr FieldBuilder::addArray(std::string const & name, FieldConstPtr c
FieldConstPtr FieldBuilder::createFieldInternal(Type type)
{
/* TODO
// minor optimization
if (fieldNames.size() == 0 && type == union)
if (fieldNames.size() == 0 && type == union_)
return fieldCreate->createVariantUnion();
*/
if (type == structure)
{
return (idSet) ?
fieldCreate->createStructure(id, fieldNames, fields) :
fieldCreate->createStructure(fieldNames, fields);
}
/* TODO
else if (type == union)
else if (type == union_)
{
return (idSet) ?
fieldCreate->createUnion(id, fieldNames, fields) :
fieldCreate->createUnion(fieldNames, fields);
}
*/
else
throw std::invalid_argument("unsupported type: " + type);
}
@@ -475,42 +703,37 @@ StructureConstPtr FieldBuilder::createStructure()
return field;
}
/*
UnionConstPtr FieldBuilder::createUnion()
{
if (parentBuilder.get())
throw std::runtime_error("createUnion() called in nested FieldBuilder");
UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union)));
UnionConstPtr field(static_pointer_cast<const Union>(createFieldInternal(union_)));
reset();
return field;
}
*/
FieldBuilderPtr FieldBuilder::addStructure(std::string const & name)
{
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, structure, false));
}
/*
FieldBuilderPtr FieldBuilder::addUnion(std::string const & name)
{
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union, false));
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union_, false));
}
*/
FieldBuilderPtr FieldBuilder::addStructureArray(std::string const & name)
{
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, structure, true));
}
/*
FieldBuilderPtr FieldBuilder::addUnionArray(std::string const & name)
{
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union, true));
return FieldBuilderPtr(new FieldBuilder(shared_from_this(), name, union_, true));
}
*/
FieldBuilderPtr FieldBuilder::createNested()
{
@@ -529,22 +752,23 @@ FieldBuilderPtr FieldBuilder::createNested()
FieldBuilderPtr FieldCreate::createFieldBuilder() const
{
FieldBuilderPtr builder(new FieldBuilder());
return builder;
return FieldBuilderPtr(new FieldBuilder());
}
ScalarConstPtr FieldCreate::createScalar(ScalarType scalarType) const
{
// TODO use singleton instance
ScalarConstPtr scalar(new Scalar(scalarType), Field::Deleter());
return scalar;
if(scalarType<0 || scalarType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct Scalar from invalid ScalarType");
return scalars[scalarType];
}
ScalarArrayConstPtr FieldCreate::createScalarArray(ScalarType elementType) const
{
// TODO use singleton instance
ScalarArrayConstPtr scalarArray(new ScalarArray(elementType), Field::Deleter());
return scalarArray;
if(elementType<0 || elementType>MAX_SCALAR_TYPE)
throw std::invalid_argument("Can't construct ScalarArray from invalid ScalarType");
return scalarArrays[elementType];
}
StructureConstPtr FieldCreate::createStructure (
@@ -573,6 +797,42 @@ StructureArrayConstPtr FieldCreate::createStructureArray(
return structureArray;
}
UnionConstPtr FieldCreate::createUnion (
StringArray const & fieldNames,FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields), Field::Deleter());
return punion;
}
UnionConstPtr FieldCreate::createUnion (
String const & id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const
{
UnionConstPtr punion(
new Union(fieldNames,fields,id), Field::Deleter());
return punion;
}
UnionConstPtr FieldCreate::createVariantUnion () const
{
return variantUnion;
}
UnionArrayConstPtr FieldCreate::createUnionArray(
UnionConstPtr const & punion) const
{
UnionArrayConstPtr unionArray(
new UnionArray(punion), Field::Deleter());
return unionArray;
}
UnionArrayConstPtr FieldCreate::createVariantUnionArray () const
{
return variantUnionArray;
}
StructureConstPtr FieldCreate::appendField(
StructureConstPtr const & structure,
String const & fieldName,
@@ -684,13 +944,23 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
int scalarType = decodeScalar(code);
if (scalarType == -1)
throw std::invalid_argument("invalid scalar type encoding");
return FieldConstPtr(new Scalar(static_cast<ScalarType>(scalarType)), Field::Deleter());
return scalars[scalarType];
}
else if (typeCode == 0x80)
{
// Type type = Type.structure;
return deserializeStructureField(this, buffer, control);
}
else if (typeCode == 0x81)
{
// Type type = Type.union;
return deserializeUnionField(this, buffer, control);
}
else if (typeCode == 0x82)
{
// Type type = Type.union; variant union (aka any type)
return variantUnion;
}
else
throw std::invalid_argument("invalid type encoding");
}
@@ -702,7 +972,7 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
int scalarType = decodeScalar(code);
if (scalarType == -1)
throw std::invalid_argument("invalid scalarArray type encoding");
return FieldConstPtr(new ScalarArray(static_cast<ScalarType>(scalarType)), Field::Deleter());
return scalarArrays[scalarType];
}
else if (typeCode == 0x80)
{
@@ -710,6 +980,17 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl
StructureConstPtr elementStructure = std::tr1::static_pointer_cast<const Structure>(control->cachedDeserialize(buffer));
return FieldConstPtr(new StructureArray(elementStructure), Field::Deleter());
}
else if (typeCode == 0x81)
{
// Type type = Type.unionArray;
UnionConstPtr elementUnion = std::tr1::static_pointer_cast<const Union>(control->cachedDeserialize(buffer));
return FieldConstPtr(new UnionArray(elementUnion), Field::Deleter());
}
else if (typeCode == 0x82)
{
// Type type = Type.unionArray; variant union (aka any type)
return variantUnionArray;
}
else
throw std::invalid_argument("invalid type encoding");
}
@@ -726,7 +1007,16 @@ FieldCreatePtr FieldCreate::getFieldCreate()
return fieldCreate;
}
FieldCreate::FieldCreate(){}
FieldCreate::FieldCreate()
{
for (int i = 0; i <= MAX_SCALAR_TYPE; i++)
{
scalars.push_back(ScalarConstPtr(new Scalar(static_cast<ScalarType>(i)), Field::Deleter()));
scalarArrays.push_back(ScalarArrayConstPtr(new ScalarArray(static_cast<ScalarType>(i)), Field::Deleter()));
}
variantUnion = UnionConstPtr(new Union(), Field::Deleter());
variantUnionArray = UnionArrayConstPtr(new UnionArray(variantUnion), Field::Deleter());
}
FieldCreatePtr getFieldCreate() {
return FieldCreate::getFieldCreate();

View File

@@ -11,7 +11,6 @@
#define PVINTROSPECT_H
#include <string>
#include <stdexcept>
#include <map>
#include <pv/noDefaultMethods.h>
#include <pv/pvType.h>
@@ -25,6 +24,8 @@ class Scalar;
class ScalarArray;
class Structure;
class StructureArray;
class Union;
class UnionArray;
/**
* typedef for a shared pointer to an immutable Field.
@@ -50,6 +51,14 @@ typedef std::tr1::shared_ptr<const Structure> StructureConstPtr;
* typedef for a shared pointer to an immutable StructureArray.
*/
typedef std::tr1::shared_ptr<const StructureArray> StructureArrayConstPtr;
/**
* typedef for a shared pointer to an immutable Union.
*/
typedef std::tr1::shared_ptr<const Union> UnionConstPtr;
/**
* typedef for a shared pointer to an immutable UnionArray.
*/
typedef std::tr1::shared_ptr<const UnionArray> UnionArrayConstPtr;
/**
* Definition of support field types.
@@ -70,7 +79,15 @@ enum Type {
/**
* The type is structureArray. Each element is a structure.
*/
structureArray
structureArray,
/**
* The type is an union.
*/
union_,
/**
* The type is an array of unions.
*/
unionArray
};
/**
@@ -145,6 +162,8 @@ enum ScalarType {
pvString
};
#define MAX_SCALAR_TYPE pvString
/**
* Convenience functions for ScalarType.
*/
@@ -382,6 +401,48 @@ private:
friend class FieldCreate;
};
/**
* This class implements introspection object for a unionArray
*/
class UnionArray : public Field{
public:
POINTER_DEFINITIONS(UnionArray);
typedef UnionArray& reference;
typedef const UnionArray& const_reference;
/**
* Get the introspection interface for the array elements.
* @return The introspection interface.
*/
UnionConstPtr getUnion() const {return punion;}
/**
* Convert the scalarType to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel=0) const;
virtual String getID() const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
protected:
/**
* Constructor.
* @param union The introspection interface for the elements.
*/
UnionArray(UnionConstPtr const & _punion);
/**
* Destructor.
*/
virtual ~UnionArray();
private:
UnionConstPtr punion;
friend class FieldCreate;
};
/**
* This class implements introspection object for a structure.
*/
@@ -402,7 +463,7 @@ public:
typedef const Structure& const_reference;
/**
* Get the number of immediate subfields in the structure/
* Get the number of immediate subfields in the structure.
* @return The number of fields.
*/
std::size_t getNumberFields() const {return fieldNames.size();}
@@ -469,6 +530,108 @@ private:
FieldConstPtrArray fields;
String id;
friend class FieldCreate;
friend class Union;
};
/**
* This class implements introspection object for a union.
*/
class Union : public Field {
public:
POINTER_DEFINITIONS(Union);
/**
* Default union ID.
*/
static epics::pvData::String DEFAULT_ID;
/**
* Default variant union ID.
*/
static epics::pvData::String ANY_ID;
/**
* Destructor.
*/
virtual ~Union();
typedef Union& reference;
typedef const Union& const_reference;
/**
* Get the number of immediate subfields in the union.
* @return The number of fields.
*/
std::size_t getNumberFields() const {return fieldNames.size();}
/**
* Get the field for the specified fieldName.
* @param fieldName The name of the field to get;
* @return The introspection interface.
* This will hold a null pointer if the field is not in the union.
*/
FieldConstPtr getField(String const &fieldName) const;
/**
* Get the field for the specified fieldName.
* @param fieldName The index of the field to get;
* @return The introspection interface.
* This will hold a null pointer if the field is not in the union.
*/
FieldConstPtr getField(std::size_t index) const {return fields[index];}
/**
* Get the field index for the specified fieldName.
* @return The introspection interface.
* This will be -1 if the field is not in the union.
*/
std::size_t getFieldIndex(String const &fieldName) const;
/**
* Get the fields in the union.
* @return The array of fields.
*/
FieldConstPtrArray const & getFields() const {return fields;}
/**
* Get the names of the fields in the union.
* @return The array of fieldNames.
*/
StringArray const & getFieldNames() const {return fieldNames;}
void renameField(std::size_t fieldIndex,String const & newName)
{fieldNames[fieldIndex] = newName;}
/**
* Get the name of the field with the specified index;
* @param fieldIndex The index of the desired field.
* @return The fieldName.
*/
String getFieldName(std::size_t fieldIndex) const {return fieldNames[fieldIndex];}
/**
* Check if this union is variant union (aka any type).
* @return <code>true</code> if this union is variant union, otherwise <code>false</code>.
*/
bool isVariant() const {return (fieldNames.size() == 0);}
/**
* Convert the union to a string and add it to builder.
* @param builder The string builder.
*/
virtual void toString(StringBuilder buf) const{toString(buf,0);}
/**
* Convert the union to a string and add it to builder.
* @param builder The string builder.
* @param indentLevel The number of blanks at the beginning of new lines.
*/
virtual void toString(StringBuilder buf,int indentLevel) const;
virtual String getID() const;
virtual void serialize(ByteBuffer *buffer, SerializableControl *control) const;
virtual void deserialize(ByteBuffer *buffer, DeserializableControl *control);
protected:
Union();
Union(StringArray const & fieldNames, FieldConstPtrArray const & fields, String const & id = DEFAULT_ID);
private:
void toStringCommon(StringBuilder buf,int indentLevel) const;
StringArray fieldNames;
FieldConstPtrArray fields;
String id;
friend class FieldCreate;
friend class Structure;
};
/**
@@ -541,7 +704,7 @@ public:
* This resets this instance state and allows new {@code Field} instance to be created.
* @return a new instance of an {@code Union}.
*/
//UnionConstPtr createUnion();
UnionConstPtr createUnion();
/**
* Add new nested {@code Structure}.
@@ -581,7 +744,7 @@ public:
* @return a new instance of a {@code FieldBuilder} is returned.
* @see #createNested()
*/
//FieldBuilderPtr addUnionArray(std::string const & name);
FieldBuilderPtr addUnionArray(std::string const & name);
/**
* Complete the creation of a nested object.
@@ -666,6 +829,43 @@ public:
String const & id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
/**
* Create an {@code Array} field that is has element type <i>Union</i>
* @param fieldName The field name
* @param elementUnion The {@code Union} for each array element.
* @return An {@code Array} Interface for the newly created object.
*/
UnionArrayConstPtr createUnionArray(UnionConstPtr const & punion) const;
/**
* Create a variant {@code UnionArray} (aka any type) field.
* @return a {@code UnionArray} interface for the newly created object.
*/
UnionArrayConstPtr createVariantUnionArray() const;
/**
* Create a variant {@code Union} (aka any type) field.
* @return a {@code Union} interface for the newly created object.
*/
UnionConstPtr createVariantUnion() const;
/**
* Create a {@code Union} field.
* @param fieldNames The array of {@code fieldNames} for the union.
* @param fields The array of {@code fields} for the union.
* @return a {@code Union} interface for the newly created object.
*/
UnionConstPtr createUnion (
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
/**
* Create a {@code Union} field with identification string.
* @param id The identification string for the union.
* @param fieldNames The array of {@code fieldNames} for the union.
* @param fields The array of {@code fields} for the union.
* @return a {@code Union} interface for the newly created object.
*/
UnionConstPtr createUnion (
String const & id,
StringArray const & fieldNames,
FieldConstPtrArray const & fields) const;
/**
* Append a field to a structure.
* @param structure The structure to which the field is appended.
@@ -697,6 +897,11 @@ public:
private:
FieldCreate();
std::vector<ScalarConstPtr> scalars;
std::vector<ScalarArrayConstPtr> scalarArrays;
UnionConstPtr variantUnion;
UnionArrayConstPtr variantUnionArray;
};
/**

View File

@@ -128,6 +128,62 @@ static void testStructure()
testOk1(struct1arr->getID()=="structure[]");
}
static void testUnion()
{
testDiag("testUnion");
StringArray names1(2);
names1[0] = "innerA";
names1[1] = "innerB";
FieldConstPtrArray fields1(2);
fields1[0] = fieldCreate->createScalar(pvDouble);
fields1[1] = fieldCreate->createScalarArray(pvString);
UnionConstPtr union1 = fieldCreate->createUnion(names1, fields1);
testOk1(union1->getNumberFields()==2);
testOk1(union1->getField("innerA")==fields1[0]);
testOk1(union1->getField("innerB")==fields1[1]);
testOk1(union1->getFieldIndex("innerA")==0);
testOk1(union1->getFieldIndex("innerB")==1);
testOk1(union1->getField(0)==fields1[0]);
testOk1(union1->getField(1)==fields1[1]);
testOk1(union1->getFieldName(0)==names1[0]);
testOk1(union1->getFieldName(1)==names1[1]);
testOk1(union1->getID() == Union::DEFAULT_ID);
testOk1(fields1 == union1->getFields()); // vector equality
StringArray names2(2);
names2[0] = "outerA";
names2[1] = "outerB";
FieldConstPtrArray fields2(2);
fields2[0] = fieldCreate->createScalar(pvInt);
fields2[1] = std::tr1::static_pointer_cast<const Field>(union1);
UnionConstPtr union2 = fieldCreate->createUnion(names2, fields2);
testOk1(union2->getNumberFields()==2); // not recursive
testOk1(union2->getField(1)==fields2[1]);
UnionArrayConstPtr union1arr = fieldCreate->createUnionArray(union1);
testOk1(union1arr->getUnion()==union1);
testOk1(union1arr->getID()=="union[]");
UnionConstPtr variantUnion1 = fieldCreate->createVariantUnion();
testOk1(variantUnion1->getNumberFields()==0);
testOk1(variantUnion1->getID() == Union::ANY_ID);
UnionArrayConstPtr variantUnion1arr = fieldCreate->createVariantUnionArray();
testOk1(variantUnion1arr->getUnion()==variantUnion1);
testOk1(variantUnion1arr->getID()=="any[]");
}
#define testExcept(EXCEPT, CMD) try{ CMD; testFail( "No exception from: " #CMD); } \
catch(EXCEPT& e) {testPass("Got expected exception from: " #CMD);} \
catch(std::exception& e) {testFail("Got wrong exception %s(%s) from: " #CMD, typeid(e).name(),e.what());} \
@@ -198,13 +254,14 @@ static void testMapping()
MAIN(testIntrospect)
{
testPlan(161);
testPlan(180);
fieldCreate = getFieldCreate();
pvDataCreate = getPVDataCreate();
standardField = getStandardField();
testScalar();
testScalarArray();
testStructure();
testUnion();
testError();
testMapping();
return testDone();