diff --git a/pvDataApp/factory/Convert.cpp b/pvDataApp/factory/Convert.cpp index 763b13b..73620ad 100644 --- a/pvDataApp/factory/Convert.cpp +++ b/pvDataApp/factory/Convert.cpp @@ -461,7 +461,7 @@ void Convert::copyUnion(PVUnionPtr const & from, PVUnionPtr const & to) if (fromValue.get() == 0) to->set(PVFieldPtr()); else - to->set(getPVDataCreate()->createPVField(fromValue)); // clone value // TODO + to->set(getPVDataCreate()->createPVField(fromValue)); // clone value // TODO cache getPVDataCreate() } else { diff --git a/pvDataApp/factory/FieldCreateFactory.cpp b/pvDataApp/factory/FieldCreateFactory.cpp index bc78bf2..eb9fdc7 100644 --- a/pvDataApp/factory/FieldCreateFactory.cpp +++ b/pvDataApp/factory/FieldCreateFactory.cpp @@ -460,18 +460,21 @@ 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"; + +#define UNION_ANY_ID "any" +String Union::ANY_ID = UNION_ANY_ID; Union::Union () : Field(union_), fieldNames(), fields(), - id(ANY_ID) + id(UNION_ANY_ID) { } +#undef UNION_ANY_ID + Union::Union ( StringArray const & fieldNames, FieldConstPtrArray const & infields, @@ -996,6 +999,7 @@ FieldConstPtr FieldCreate::deserialize(ByteBuffer* buffer, DeserializableControl } } +// TODO replace with non-locking singleton pattern FieldCreatePtr FieldCreate::getFieldCreate() { LOCAL_STATIC_LOCK; diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index 4123962..a3a485f 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -651,12 +651,12 @@ PVUnionPtr PVDataCreate::createPVUnion( PVUnionPtr PVDataCreate::createPVVariantUnion() { - return PVUnionPtr(new PVUnion(getFieldCreate()->createVariantUnion())); + return PVUnionPtr(new PVUnion(fieldCreate->createVariantUnion())); } PVUnionArrayPtr PVDataCreate::createPVVariantUnionArray() { - return PVUnionArrayPtr(new PVUnionArray(getFieldCreate()->createVariantUnionArray())); + return PVUnionArrayPtr(new PVUnionArray(fieldCreate->createVariantUnionArray())); } PVStructurePtr PVDataCreate::createPVStructure( @@ -694,6 +694,8 @@ PVUnionPtr PVDataCreate::createPVUnion(PVUnionPtr const & unionToClone) return punion; } +// TODO not thread-safe (local static initializers) +// TODO replace with non-locking singleton pattern PVDataCreatePtr PVDataCreate::getPVDataCreate() { static PVDataCreatePtr pvDataCreate; diff --git a/pvDataApp/factory/PVStructureArray.cpp b/pvDataApp/factory/PVStructureArray.cpp index c22ca1c..2f2ac52 100644 --- a/pvDataApp/factory/PVStructureArray.cpp +++ b/pvDataApp/factory/PVStructureArray.cpp @@ -28,8 +28,9 @@ size_t PVStructureArray::append(size_t number) StructureConstPtr structure = structureArray->getStructure(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number) - *it = getPVDataCreate()->createPVStructure(structure); + *it = pvDataCreate->createPVStructure(structure); size_t newLength = data.size(); @@ -148,6 +149,8 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer, StructureConstPtr structure = structureArray->getStructure(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + for(size_t i = 0; iensureData(1); size_t temp = pbuffer->getByte(); @@ -156,7 +159,7 @@ void PVStructureArray::deserialize(ByteBuffer *pbuffer, } else { if(data[i].get()==NULL) { - data[i] = getPVDataCreate()->createPVStructure(structure); + data[i] = pvDataCreate->createPVStructure(structure); } data[i]->deserialize(pbuffer, pcontrol); } diff --git a/pvDataApp/factory/PVUnion.cpp b/pvDataApp/factory/PVUnion.cpp index 4591eaa..7ea71df 100644 --- a/pvDataApp/factory/PVUnion.cpp +++ b/pvDataApp/factory/PVUnion.cpp @@ -23,19 +23,20 @@ using std::size_t; namespace epics { namespace pvData { -int32 PVUnion::UNDEFINED_INDEX = -1; -PVDataCreatePtr PVUnion::pvDataCreate = getPVDataCreate(); - +#define PVUNION_UNDEFINED_INDEX -1 +int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX; PVUnion::PVUnion(UnionConstPtr const & unionPtr) : PVField(unionPtr), unionPtr(unionPtr), - selector(UNDEFINED_INDEX), + selector(PVUNION_UNDEFINED_INDEX), // to allow out-of-order static initialization value(), variant(unionPtr->isVariant()) { } +#undef PVUNION_UNDEFINED_INDEX + PVUnion::~PVUnion() { } @@ -83,8 +84,8 @@ PVFieldPtr PVUnion::select(int32 index) FieldConstPtr field = unionPtr->getField(index); selector = index; - value = pvDataCreate->createPVField(field); - + value = getPVDataCreate()->createPVField(field); + return value; } @@ -93,7 +94,6 @@ 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); } @@ -165,7 +165,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) FieldConstPtr field = pcontrol->cachedDeserialize(pbuffer); if (field.get()) { - value = pvDataCreate->createPVField(field); + value = getPVDataCreate()->createPVField(field); value->deserialize(pbuffer, pcontrol); } else @@ -177,7 +177,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) if (selector != UNDEFINED_INDEX) { FieldConstPtr field = unionPtr->getField(selector); - value = pvDataCreate->createPVField(field); + value = getPVDataCreate()->createPVField(field); value->deserialize(pbuffer, pcontrol); } else diff --git a/pvDataApp/factory/PVUnionArray.cpp b/pvDataApp/factory/PVUnionArray.cpp index 44e598e..8768246 100644 --- a/pvDataApp/factory/PVUnionArray.cpp +++ b/pvDataApp/factory/PVUnionArray.cpp @@ -28,8 +28,9 @@ size_t PVUnionArray::append(size_t number) UnionConstPtr punion = unionArray->getUnion(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number) - *it = getPVDataCreate()->createPVUnion(punion); + *it = pvDataCreate->createPVUnion(punion); size_t newLength = data.size(); @@ -148,6 +149,8 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer, UnionConstPtr punion = unionArray->getUnion(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + for(size_t i = 0; iensureData(1); size_t temp = pbuffer->getByte(); @@ -156,7 +159,7 @@ void PVUnionArray::deserialize(ByteBuffer *pbuffer, } else { if(data[i].get()==NULL) { - data[i] = getPVDataCreate()->createPVUnion(punion); + data[i] = pvDataCreate->createPVUnion(punion); } data[i]->deserialize(pbuffer, pcontrol); } diff --git a/pvDataApp/pv/pvData.h b/pvDataApp/pv/pvData.h index 01dcd2e..2bd1f88 100644 --- a/pvDataApp/pv/pvData.h +++ b/pvDataApp/pv/pvData.h @@ -814,12 +814,34 @@ public: * @return Pointer to the field or null if field does not exist. */ PVFieldPtr getSubField(String const &fieldName) const; + + template + std::tr1::shared_ptr getSubField(String const &fieldName) const + { + PVFieldPtr pvField = getSubField(fieldName); + if (pvField.get()) + return std::tr1::dynamic_pointer_cast(pvField); + else + return std::tr1::shared_ptr(); + } + /** * Get the subfield with the specified offset. * @param fieldOffset The offset. * @return Pointer to the field or null if field does not exist. */ PVFieldPtr getSubField(std::size_t fieldOffset) const; + + template + std::tr1::shared_ptr getSubField(std::size_t fieldOffset) const + { + PVFieldPtr pvField = getSubField(fieldOffset); + if (pvField.get()) + return std::tr1::dynamic_pointer_cast(pvField); + else + return std::tr1::shared_ptr(); + } + /** * Append a field to the structure. * @param fieldName The name of the field to append. @@ -910,6 +932,7 @@ public: * @return Pointer to the field of null if a field with that name and type does not exist. */ PVStringPtr getStringField(String const &fieldName) ; + /** * Get a structure field with the specified name. * @param fieldName The name of the field to get. @@ -1054,11 +1077,10 @@ public: * @return {@code PVField} value of field, {@code null} if {@code getSelectedIndex() == UNDEFINED_INDEX}. */ PVFieldPtr get() const; - - // TODO dynamic vs static cast? + template std::tr1::shared_ptr get() const { - return std::tr1::static_pointer_cast(get()); + return std::tr1::dynamic_pointer_cast(get()); } /** @@ -1068,11 +1090,10 @@ public: * @throws {@code std::invalid_argument} if index is invalid (out of range). */ PVFieldPtr select(int32 index); - - // TODO dynamic vs static cast? + template std::tr1::shared_ptr select(int32 index) { - return std::tr1::static_pointer_cast(select(index)); + return std::tr1::dynamic_pointer_cast(select(index)); } /** @@ -1082,11 +1103,10 @@ public: * @throws {@code std::invalid_argument} if field does not exist. */ PVFieldPtr select(String const & fieldName); - - // TODO dynamic vs static cast? + template std::tr1::shared_ptr select(String const & fieldName) { - return std::tr1::static_pointer_cast(select(fieldName)); + return std::tr1::dynamic_pointer_cast(select(fieldName)); } /** @@ -1150,7 +1170,6 @@ public: private: friend class PVDataCreate; - static PVDataCreatePtr pvDataCreate; UnionConstPtr unionPtr; @@ -1741,6 +1760,29 @@ public: * @return The variant PVUnionArray implementation. */ PVUnionArrayPtr createPVVariantUnionArray(); + + + template + std::tr1::shared_ptr createPVScalar() + { + return std::tr1::static_pointer_cast(createPVScalar(PVT::typeCode)); + } + + template + std::tr1::shared_ptr createPVScalarArray() + { + return std::tr1::static_pointer_cast(createPVScalarArray(PVAT::typeCode)); + } + + PVStructureArrayPtr createPVStructureArray(StructureConstPtr const & structure) + { + return createPVStructureArray(fieldCreate->createStructureArray(structure)); + } + + PVUnionArrayPtr createPVUnionArray(UnionConstPtr const & punion) + { + return createPVUnionArray(fieldCreate->createUnionArray(punion)); + } private: PVDataCreate(); diff --git a/testApp/misc/testSerialization.cpp b/testApp/misc/testSerialization.cpp index 1fc6b86..63e972d 100644 --- a/testApp/misc/testSerialization.cpp +++ b/testApp/misc/testSerialization.cpp @@ -398,22 +398,6 @@ void testStructure() { serializationTest(pvStructure); } -template -std::tr1::shared_ptr createPVScalar() -{ - return std::tr1::static_pointer_cast( - getPVDataCreate()->createPVScalar(PVT::typeCode) - ); -} - -template -std::tr1::shared_ptr createPVScalarArray() -{ - return std::tr1::static_pointer_cast( - getPVDataCreate()->createPVScalarArray(PVAT::typeCode) - ); -} - void testUnion() { testDiag("Testing union..."); @@ -421,8 +405,8 @@ void testUnion() { testOk1(factory.get()!=NULL); - PVDoublePtr doubleValue = createPVScalar(); - PVIntPtr intValue = createPVScalar(); + PVDoublePtr doubleValue = factory->createPVScalar(); + PVIntPtr intValue = factory->createPVScalar(); testDiag("\tVariant union test");