commit after merge
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/convert.h>
|
||||
@@ -68,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");
|
||||
}
|
||||
|
||||
@@ -169,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");
|
||||
}
|
||||
|
||||
@@ -264,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 (
|
||||
@@ -356,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);
|
||||
}
|
||||
@@ -371,18 +460,315 @@ 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,
|
||||
std::string const & _nestedName,
|
||||
Type _nestedClassToBuild, bool _nestedArray) :
|
||||
fieldCreate(getFieldCreate()),
|
||||
idSet(false),
|
||||
parentBuilder(_parentBuilder),
|
||||
nestedClassToBuild(_nestedClassToBuild),
|
||||
nestedName(_nestedName),
|
||||
nestedArray(_nestedArray)
|
||||
{}
|
||||
|
||||
void FieldBuilder::reset()
|
||||
{
|
||||
id.erase();
|
||||
idSet = false;
|
||||
fieldNames.clear();
|
||||
fields.clear();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::setId(std::string const & id)
|
||||
{
|
||||
this->id = id;
|
||||
idSet = true;
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::add(std::string const & name, ScalarType scalarType)
|
||||
{
|
||||
fields.push_back(fieldCreate->createScalar(scalarType)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::add(std::string const & name, FieldConstPtr const & field)
|
||||
{
|
||||
fields.push_back(field); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addArray(std::string const & name, ScalarType scalarType)
|
||||
{
|
||||
fields.push_back(fieldCreate->createScalarArray(scalarType)); fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::addArray(std::string const & name, FieldConstPtr const & element)
|
||||
{
|
||||
switch (element->getType())
|
||||
{
|
||||
case structure:
|
||||
fields.push_back(fieldCreate->createStructureArray(static_pointer_cast<const Structure>(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;
|
||||
default:
|
||||
throw std::invalid_argument("unsupported array element type:" + element->getType());
|
||||
}
|
||||
|
||||
fieldNames.push_back(name);
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
FieldConstPtr FieldBuilder::createFieldInternal(Type type)
|
||||
{
|
||||
// minor optimization
|
||||
if (fieldNames.size() == 0 && type == union_)
|
||||
return fieldCreate->createVariantUnion();
|
||||
|
||||
if (type == structure)
|
||||
{
|
||||
return (idSet) ?
|
||||
fieldCreate->createStructure(id, fieldNames, fields) :
|
||||
fieldCreate->createStructure(fieldNames, fields);
|
||||
}
|
||||
else if (type == union_)
|
||||
{
|
||||
return (idSet) ?
|
||||
fieldCreate->createUnion(id, fieldNames, fields) :
|
||||
fieldCreate->createUnion(fieldNames, fields);
|
||||
}
|
||||
else
|
||||
throw std::invalid_argument("unsupported type: " + type);
|
||||
}
|
||||
|
||||
|
||||
StructureConstPtr FieldBuilder::createStructure()
|
||||
{
|
||||
if (parentBuilder.get())
|
||||
throw std::runtime_error("createStructure() called in nested FieldBuilder");
|
||||
|
||||
StructureConstPtr field(static_pointer_cast<const Structure>(createFieldInternal(structure)));
|
||||
reset();
|
||||
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_)));
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
FieldBuilderPtr FieldBuilder::createNested()
|
||||
{
|
||||
if (!parentBuilder.get())
|
||||
throw std::runtime_error("this method can only be called to create nested fields");
|
||||
|
||||
FieldConstPtr nestedField = createFieldInternal(nestedClassToBuild);
|
||||
if (nestedArray)
|
||||
parentBuilder->addArray(nestedName, nestedField);
|
||||
else
|
||||
parentBuilder->add(nestedName, nestedField);
|
||||
|
||||
return parentBuilder;
|
||||
}
|
||||
|
||||
|
||||
FieldBuilderPtr FieldCreate::createFieldBuilder() const
|
||||
{
|
||||
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 (
|
||||
@@ -411,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,
|
||||
@@ -522,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");
|
||||
}
|
||||
@@ -540,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)
|
||||
{
|
||||
@@ -548,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");
|
||||
}
|
||||
@@ -564,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();
|
||||
|
||||
@@ -24,6 +24,8 @@ class Scalar;
|
||||
class ScalarArray;
|
||||
class Structure;
|
||||
class StructureArray;
|
||||
class Union;
|
||||
class UnionArray;
|
||||
|
||||
/**
|
||||
* typedef for a shared pointer to an immutable Field.
|
||||
@@ -49,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.
|
||||
@@ -69,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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -144,6 +162,8 @@ enum ScalarType {
|
||||
pvString
|
||||
};
|
||||
|
||||
#define MAX_SCALAR_TYPE pvString
|
||||
|
||||
/**
|
||||
* Convenience functions for ScalarType.
|
||||
*/
|
||||
@@ -381,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.
|
||||
*/
|
||||
@@ -401,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();}
|
||||
@@ -468,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -476,16 +640,162 @@ private:
|
||||
class FieldCreate;
|
||||
typedef std::tr1::shared_ptr<FieldCreate> FieldCreatePtr;
|
||||
|
||||
class FieldBuilder;
|
||||
typedef std::tr1::shared_ptr<FieldBuilder> FieldBuilderPtr;
|
||||
|
||||
/**
|
||||
* Interface for in-line creating of introspection interfaces.
|
||||
* One instance can be used to create multiple {@code Field} instances.
|
||||
* An instance of this object must not be used concurrently (an object has a state).
|
||||
* @author mse
|
||||
*/
|
||||
class FieldBuilder :
|
||||
public std::tr1::enable_shared_from_this<FieldBuilder>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Set ID of an object to be created.
|
||||
* @param id id to be set.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr setId(std::string const & id);
|
||||
|
||||
/**
|
||||
* Add a {@code Scalar}.
|
||||
* @param name name of the array.
|
||||
* @param scalarType type of a scalar to add.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr add(std::string const & name, ScalarType scalarType);
|
||||
|
||||
/**
|
||||
* Add a {@code Field} (e.g. {@code Structure}, {@code Union}).
|
||||
* @param name name of the array.
|
||||
* @param field a field to add.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr add(std::string const & name, FieldConstPtr const & field);
|
||||
|
||||
/**
|
||||
* Add array of {@code Scalar} elements.
|
||||
* @param name name of the array.
|
||||
* @param scalarType type of a scalar element.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr addArray(std::string const & name, ScalarType scalarType);
|
||||
|
||||
/**
|
||||
* Add array of {@code Field} elements.
|
||||
* @param name name of the array.
|
||||
* @param field a type of an array element.
|
||||
* @return this instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr addArray(std::string const & name, FieldConstPtr const & element);
|
||||
|
||||
/**
|
||||
* Create a {@code Structure}.
|
||||
* This resets this instance state and allows new {@code Field} instance to be created.
|
||||
* @return a new instance of a {@code Structure}.
|
||||
*/
|
||||
StructureConstPtr createStructure();
|
||||
|
||||
/**
|
||||
* Create an {@code Union}.
|
||||
* This resets this instance state and allows new {@code Field} instance to be created.
|
||||
* @return a new instance of an {@code Union}.
|
||||
*/
|
||||
UnionConstPtr createUnion();
|
||||
|
||||
/**
|
||||
* Add new nested {@code Structure}.
|
||||
* {@code createNested()} method must be called
|
||||
* to complete creation of the nested {@code Structure}.
|
||||
* @param name nested structure name.
|
||||
* @return a new instance of a {@code FieldBuilder} is returned.
|
||||
* @see #createNested()
|
||||
*/
|
||||
FieldBuilderPtr addStructure(std::string const & name);
|
||||
|
||||
/**
|
||||
* Add new nested {@code Union}.
|
||||
* {@code createNested()} method must be called
|
||||
* to complete creation of the nested {@code Union}.
|
||||
* @param name nested union name.
|
||||
* @return a new instance of a {@code FieldBuilder} is returned.
|
||||
* @see #createNested()
|
||||
*/
|
||||
FieldBuilderPtr addUnion(std::string const & name);
|
||||
|
||||
/**
|
||||
* Add new nested {@code Structure[]}.
|
||||
* {@code createNested()} method must be called
|
||||
* to complete creation of the nested {@code Structure}.
|
||||
* @param name nested structure name.
|
||||
* @return a new instance of a {@code FieldBuilder} is returned.
|
||||
* @see #createNested()
|
||||
*/
|
||||
FieldBuilderPtr addStructureArray(std::string const & name);
|
||||
|
||||
/**
|
||||
* Add new nested {@code Union[]}.
|
||||
* {@code createNested()} method must be called
|
||||
* to complete creation of the nested {@code Union}.
|
||||
* @param name nested union name.
|
||||
* @return a new instance of a {@code FieldBuilder} is returned.
|
||||
* @see #createNested()
|
||||
*/
|
||||
FieldBuilderPtr addUnionArray(std::string const & name);
|
||||
|
||||
/**
|
||||
* Complete the creation of a nested object.
|
||||
* @see #addStructure(String)
|
||||
* @see #addUnion(String)
|
||||
* @return a previous (parent) {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr createNested();
|
||||
|
||||
private:
|
||||
FieldBuilder();
|
||||
FieldBuilder(FieldBuilderPtr const & parentBuilder,
|
||||
std::string const & nestedName,
|
||||
Type nestedClassToBuild, bool nestedArray);
|
||||
|
||||
void reset();
|
||||
FieldConstPtr createFieldInternal(Type type);
|
||||
|
||||
friend class FieldCreate;
|
||||
|
||||
FieldCreatePtr fieldCreate;
|
||||
|
||||
std::string id;
|
||||
bool idSet;
|
||||
|
||||
// NOTE: this preserves order, however it does not handle duplicates
|
||||
StringArray fieldNames;
|
||||
FieldConstPtrArray fields;
|
||||
|
||||
FieldBuilderPtr parentBuilder;
|
||||
Type nestedClassToBuild;
|
||||
std::string nestedName;
|
||||
bool nestedArray;
|
||||
|
||||
};
|
||||
|
||||
class FieldCreate {
|
||||
public:
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
static FieldCreatePtr getFieldCreate();
|
||||
/**
|
||||
* Create a new instance of in-line {@code Field} builder.
|
||||
* @return a new instance of a {@code FieldBuilder}.
|
||||
*/
|
||||
FieldBuilderPtr createFieldBuilder() const;
|
||||
/**
|
||||
* Create a {@code ScalarField}.
|
||||
* @param scalarType The scalar type.
|
||||
* @return a {@code Scalar} interface for the newly created object.
|
||||
* @throws An {@code IllegalArgumentException} if an illegal type is specified.
|
||||
*/
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const;
|
||||
ScalarConstPtr createScalar(ScalarType scalarType) const;
|
||||
/**
|
||||
* Create an {@code Array} field.
|
||||
* @param elementType The {@code scalarType} for array elements
|
||||
@@ -519,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.
|
||||
@@ -549,7 +896,12 @@ public:
|
||||
FieldConstPtr deserialize(ByteBuffer* buffer, DeserializableControl* control) const;
|
||||
|
||||
private:
|
||||
FieldCreate();
|
||||
FieldCreate();
|
||||
|
||||
std::vector<ScalarConstPtr> scalars;
|
||||
std::vector<ScalarArrayConstPtr> scalarArrays;
|
||||
UnionConstPtr variantUnion;
|
||||
UnionArrayConstPtr variantUnionArray;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -53,6 +53,10 @@ PROD_HOST += testOperators
|
||||
testOperators_SRCS += testOperators.cpp
|
||||
testOperators_LIBS += pvData Com
|
||||
|
||||
PROD_HOST += testFieldBuilder
|
||||
testFieldBuilder_SRCS += testFieldBuilder.cpp
|
||||
testFieldBuilder_LIBS += pvData Com
|
||||
|
||||
TESTSCRIPTS_HOST += $(TESTS:%=%.t)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
239
testApp/pv/testFieldBuilder.cpp
Normal file
239
testApp/pv/testFieldBuilder.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include <string>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
using namespace std::tr1;
|
||||
|
||||
|
||||
void test_factory()
|
||||
{
|
||||
testDiag("Test test_factory()");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
FieldBuilderPtr fb = fieldCreate->createFieldBuilder();
|
||||
testOk1(fb.get() != 0);
|
||||
|
||||
FieldBuilderPtr fb2 = fieldCreate->createFieldBuilder();
|
||||
testOk1(fb.get() != fb2.get());
|
||||
}
|
||||
|
||||
void test_structure()
|
||||
{
|
||||
testDiag("Test test_structure()");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
FieldBuilderPtr fb = fieldCreate->createFieldBuilder();
|
||||
|
||||
// test with simple (non-nested) structure
|
||||
std::string ID = "testStructureID";
|
||||
StructureConstPtr s = fb->setId(ID)->
|
||||
add("double", pvDouble)->
|
||||
addArray("intArray", pvInt)->
|
||||
createStructure();
|
||||
testOk1(s.get() != 0);
|
||||
testOk1(ID == s->getID());
|
||||
testOk1(2 == s->getFields().size());
|
||||
|
||||
FieldConstPtr f0 = s->getField(0);
|
||||
testOk1(scalar == f0->getType());
|
||||
testOk1("double" == s->getFieldName(0));
|
||||
testOk(pvDouble == static_pointer_cast<const Scalar>(f0)->getScalarType(), "f0 scalar type == double");
|
||||
|
||||
FieldConstPtr f1 = s->getField(1);
|
||||
testOk1(scalarArray == f1->getType());
|
||||
testOk1("intArray" == s->getFieldName(1));
|
||||
testOk(pvInt == static_pointer_cast<const ScalarArray>(f1)->getElementType(), "f1 element type == int");
|
||||
|
||||
// test reuse with empty structure
|
||||
StructureConstPtr emptyStructure = fb->createStructure();
|
||||
testOk1(emptyStructure.get() != 0);
|
||||
testOk1(Structure::DEFAULT_ID == emptyStructure->getID());
|
||||
testOk1(0 == emptyStructure->getFields().size());
|
||||
|
||||
// test add/addArray with Field
|
||||
StructureConstPtr s2 = fb->add("s", s)->
|
||||
addArray("sArray", s)->
|
||||
createStructure();
|
||||
testOk1(s2 != 0);
|
||||
testOk1(Structure::DEFAULT_ID == s2->getID());
|
||||
testOk1(2 == s2->getFields().size());
|
||||
|
||||
f0 = s2->getField(0);
|
||||
testOk1(structure == f0->getType());
|
||||
testOk1("s" == s2->getFieldName(0));
|
||||
testOk1(s.get() == f0.get());
|
||||
|
||||
f1 = s2->getField(1);
|
||||
testOk1(structureArray == f1->getType());
|
||||
testOk1("sArray" == s2->getFieldName(1));
|
||||
testOk(s.get() == static_pointer_cast<const StructureArray>(f1)->getStructure().get(), "array element is given structure");
|
||||
}
|
||||
|
||||
|
||||
void test_invalid()
|
||||
{
|
||||
testDiag("Test test_invalid()");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
try
|
||||
{
|
||||
fieldCreate->createFieldBuilder()->
|
||||
add("f1", pvByte)->
|
||||
createNested();
|
||||
testFail("createNested() allowed in non-nested FieldBuilder");
|
||||
}
|
||||
catch (std::runtime_error& re) {
|
||||
// ok
|
||||
testPass("createNested() disallowed in non-nested FieldBuilder");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
fieldCreate->createFieldBuilder()->
|
||||
add("f1", pvByte)->
|
||||
addStructure("nested")->
|
||||
add("n1", pvUInt)->
|
||||
createStructure();
|
||||
testFail("createStructure() allowed in nested FieldBuilder");
|
||||
}
|
||||
catch (std::runtime_error& re) {
|
||||
// ok
|
||||
testPass("createStructure() disallowed in nested FieldBuilder");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test_nestedStructure()
|
||||
{
|
||||
testDiag("Test test_nestedStructure()");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
std::string NESTED_ID = "nestedID";
|
||||
StructureConstPtr s = fieldCreate->createFieldBuilder()->
|
||||
add("double", pvDouble)->
|
||||
addStructure("nested")->
|
||||
setId(NESTED_ID)->
|
||||
add("short", pvShort)->
|
||||
add("long", pvLong)->
|
||||
createNested()->
|
||||
addArray("intArray", pvInt)->
|
||||
createStructure();
|
||||
testOk1(s.get() != 0);
|
||||
testOk1(Structure::DEFAULT_ID == s->getID());
|
||||
testOk1(3 == s->getFields().size());
|
||||
|
||||
FieldConstPtr f0 = s->getField(0);
|
||||
testOk1(scalar == f0->getType());
|
||||
testOk1("double" == s->getFieldName(0));
|
||||
testOk(pvDouble == static_pointer_cast<const Scalar>(f0)->getScalarType(), "f0 scalar type == double");
|
||||
|
||||
FieldConstPtr f1 = s->getField(1);
|
||||
testOk1(structure == f1->getType());
|
||||
testOk1("nested" == s->getFieldName(1));
|
||||
|
||||
{
|
||||
StructureConstPtr s2 = static_pointer_cast<const Structure>(f1);
|
||||
|
||||
testOk1(s2.get() != 0);
|
||||
testOk1(NESTED_ID == s2->getID());
|
||||
testOk1(2 == s2->getFields().size());
|
||||
|
||||
FieldConstPtr f20 = s2->getField(0);
|
||||
testOk1(scalar == f20->getType());
|
||||
testOk1("short" == s2->getFieldName(0));
|
||||
testOk(pvShort == static_pointer_cast<const Scalar>(f20)->getScalarType(), "f20 scalar type == short");
|
||||
|
||||
FieldConstPtr f21 = s2->getField(1);
|
||||
testOk1(scalar == f21->getType());
|
||||
testOk1("long" == s2->getFieldName(1));
|
||||
testOk(pvLong == static_pointer_cast<const Scalar>(f21)->getScalarType(), "f21 element type == long");
|
||||
|
||||
}
|
||||
|
||||
FieldConstPtr f2 = s->getField(2);
|
||||
testOk1(scalarArray == f2->getType());
|
||||
testOk1("intArray" == s->getFieldName(2));
|
||||
testOk(pvInt == static_pointer_cast<const ScalarArray>(f2)->getElementType(), "f2 element type == int");
|
||||
|
||||
}
|
||||
|
||||
|
||||
void test_nestedStructureArray()
|
||||
{
|
||||
testDiag("Test test_nestedStructureArray()");
|
||||
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
|
||||
std::string NESTED_ID = "nestedID";
|
||||
StructureConstPtr s = fieldCreate->createFieldBuilder()->
|
||||
add("double", pvDouble)->
|
||||
addStructureArray("nested")->
|
||||
setId(NESTED_ID)->
|
||||
add("short", pvShort)->
|
||||
add("long", pvLong)->
|
||||
createNested()->
|
||||
addArray("intArray", pvInt)->
|
||||
createStructure();
|
||||
testOk1(s.get() != 0);
|
||||
testOk1(Structure::DEFAULT_ID == s->getID());
|
||||
testOk1(3 == s->getFields().size());
|
||||
|
||||
FieldConstPtr f0 = s->getField(0);
|
||||
testOk1(scalar == f0->getType());
|
||||
testOk1("double" == s->getFieldName(0));
|
||||
testOk(pvDouble == static_pointer_cast<const Scalar>(f0)->getScalarType(), "f0 scalar type == double");
|
||||
|
||||
FieldConstPtr f1 = s->getField(1);
|
||||
testOk1(structureArray == f1->getType());
|
||||
testOk1("nested" == s->getFieldName(1));
|
||||
|
||||
{
|
||||
StructureConstPtr s2 = static_pointer_cast<const StructureArray>(f1)->getStructure();
|
||||
|
||||
testOk1(s2.get() != 0);
|
||||
testOk1(NESTED_ID == s2->getID());
|
||||
testOk1(2 == s2->getFields().size());
|
||||
|
||||
FieldConstPtr f20 = s2->getField(0);
|
||||
testOk1(scalar == f20->getType());
|
||||
testOk1("short" == s2->getFieldName(0));
|
||||
testOk(pvShort == static_pointer_cast<const Scalar>(f20)->getScalarType(), "f20 scalar type == short");
|
||||
|
||||
FieldConstPtr f21 = s2->getField(1);
|
||||
testOk1(scalar == f21->getType());
|
||||
testOk1("long" == s2->getFieldName(1));
|
||||
testOk(pvLong == static_pointer_cast<const Scalar>(f21)->getScalarType(), "f21 element type == long");
|
||||
|
||||
}
|
||||
|
||||
FieldConstPtr f2 = s->getField(2);
|
||||
testOk1(scalarArray == f2->getType());
|
||||
testOk1("intArray" == s->getFieldName(2));
|
||||
testOk(pvInt == static_pointer_cast<const ScalarArray>(f2)->getElementType(), "f2 element type == int");
|
||||
|
||||
}
|
||||
|
||||
|
||||
MAIN(testFieldBuilder)
|
||||
{
|
||||
testPlan(65);
|
||||
testDiag("Tests for FieldBuilder");
|
||||
|
||||
test_factory();
|
||||
test_structure();
|
||||
test_nestedStructure();
|
||||
test_nestedStructureArray();
|
||||
|
||||
|
||||
test_invalid();
|
||||
|
||||
return testDone();
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user