diff --git a/src/factory/Compare.cpp b/src/factory/Compare.cpp index 19c0230..116e9e9 100644 --- a/src/factory/Compare.cpp +++ b/src/factory/Compare.cpp @@ -12,7 +12,7 @@ #include #define epicsExportSharedSymbols -#include +#include using std::string; diff --git a/src/factory/PVField.cpp b/src/factory/PVField.cpp index 20db350..ee9c911 100644 --- a/src/factory/PVField.cpp +++ b/src/factory/PVField.cpp @@ -180,4 +180,117 @@ void PVField::computeOffset(const PVField * pvField,size_t offset) { xxx->nextFieldOffset = nextOffset; } +void PVField::copy(const PVField& from) +{ + if(isImmutable()) + throw std::invalid_argument("destination is immutable"); + + if (getField()->getType() != from.getField()->getType()) + throw std::invalid_argument("field types do not match"); + + switch(getField()->getType()) + { + case scalar: + { + const PVScalar* fromS = static_cast(&from); + PVScalar* toS = static_cast(this); + toS->copy(*fromS); + break; + } + case scalarArray: + { + const PVScalarArray* fromS = static_cast(&from); + PVScalarArray* toS = static_cast(this); + toS->copy(*fromS); + break; + } + case structure: + { + const PVStructure* fromS = static_cast(&from); + PVStructure* toS = static_cast(this); + toS->copy(*fromS); + break; + } + case structureArray: + { + const PVStructureArray* fromS = static_cast(&from); + PVStructureArray* toS = static_cast(this); + toS->copy(*fromS); + break; + } + case union_: + { + const PVUnion* fromS = static_cast(&from); + PVUnion* toS = static_cast(this); + toS->copy(*fromS); + break; + } + case unionArray: + { + const PVUnionArray* fromS = static_cast(&from); + PVUnionArray* toS = static_cast(this); + toS->copy(*fromS); + break; + } + default: + { + throw std::logic_error("PVField::copy unknown type"); + } + } +} + +void PVField::copyUnchecked(const PVField& from) +{ + switch(getField()->getType()) + { + case scalar: + { + const PVScalar* fromS = static_cast(&from); + PVScalar* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + case scalarArray: + { + const PVScalarArray* fromS = static_cast(&from); + PVScalarArray* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + case structure: + { + const PVStructure* fromS = static_cast(&from); + PVStructure* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + case structureArray: + { + const PVStructureArray* fromS = static_cast(&from); + PVStructureArray* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + case union_: + { + const PVUnion* fromS = static_cast(&from); + PVUnion* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + case unionArray: + { + const PVUnionArray* fromS = static_cast(&from); + PVUnionArray* toS = static_cast(this); + toS->copyUnchecked(*fromS); + break; + } + default: + { + throw std::logic_error("PVField::copy unknown type"); + } + } +} + + }} diff --git a/src/factory/PVStructure.cpp b/src/factory/PVStructure.cpp index e53e25f..e127730 100644 --- a/src/factory/PVStructure.cpp +++ b/src/factory/PVStructure.cpp @@ -382,4 +382,80 @@ std::ostream& PVStructure::dumpValue(std::ostream& o) const return o; } + +void PVStructure::copy(const PVStructure& from) +{ + if(isImmutable()) + throw std::invalid_argument("destination is immutable"); + + // TODO relaxed compare? + if(*getStructure().get() != *from.getStructure().get()) + throw std::invalid_argument("structure definitions do not match"); + + copyUnchecked(from); +} + +void PVStructure::copyUnchecked(const PVStructure& from) +{ + if (this == &from) + return; + + PVFieldPtrArray const & fromPVFields = from.getPVFields(); + PVFieldPtrArray const & toPVFields = getPVFields(); + + size_t fieldsSize = fromPVFields.size(); + for(size_t i = 0; icopyUnchecked(*fromPVFields[i].get()); + } +} + +void PVStructure::copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse) +{ + if (this == &from) + return; + + size_t numberFields = from.getNumberFields(); + size_t offset = from.getFieldOffset(); + int32 next = inverse ? + maskBitSet.nextClearBit(static_cast(offset)) : + maskBitSet.nextSetBit(static_cast(offset)); + + // no more changes or no changes in this structure + if(next<0||next>=static_cast(offset+numberFields)) return; + + // entire structure + if(static_cast(offset)==next) { + copyUnchecked(from); + return; + } + + PVFieldPtrArray const & fromPVFields = from.getPVFields(); + PVFieldPtrArray const & toPVFields = getPVFields(); + + size_t fieldsSize = fromPVFields.size(); + for(size_t i = 0; igetFieldOffset(); + int32 inumberFields = static_cast(pvField->getNumberFields()); + next = inverse ? + maskBitSet.nextClearBit(static_cast(offset)) : + maskBitSet.nextSetBit(static_cast(offset)); + + // no more changes + if(next<0) return; + // no change in this pvField + if(next>=static_cast(offset+inumberFields)) continue; + + // serialize field or fields + if(inumberFields==1) { + toPVFields[i]->copyUnchecked(*pvField.get()); + } else { + PVStructure::shared_pointer fromPVStructure = std::tr1::static_pointer_cast(pvField); + PVStructure::shared_pointer toPVStructure = std::tr1::static_pointer_cast(toPVFields[i]); + toPVStructure->copyUnchecked(*fromPVStructure.get(), maskBitSet, inverse); + } + } +} + + }} diff --git a/src/factory/PVStructureArray.cpp b/src/factory/PVStructureArray.cpp index ffb5a37..9c0722f 100644 --- a/src/factory/PVStructureArray.cpp +++ b/src/factory/PVStructureArray.cpp @@ -242,4 +242,24 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) co return o; } +void PVStructureArray::copy(const PVStructureArray& from) +{ + if(isImmutable()) + throw std::invalid_argument("destination is immutable"); + + // TODO relaxed structure compare? + if(*getStructureArray().get() != *from.getStructureArray().get()) + throw std::invalid_argument("structureArray definitions do not match"); + + copyUnchecked(from); +} + +void PVStructureArray::copyUnchecked(const PVStructureArray& from) +{ + if (this == &from) + return; + + replace(from.view()); +} + }} diff --git a/src/factory/PVUnion.cpp b/src/factory/PVUnion.cpp index 9848cb7..10d3094 100644 --- a/src/factory/PVUnion.cpp +++ b/src/factory/PVUnion.cpp @@ -29,6 +29,8 @@ namespace epics { namespace pvData { #define PVUNION_UNDEFINED_INDEX -1 int32 PVUnion::UNDEFINED_INDEX = PVUNION_UNDEFINED_INDEX; +PVDataCreatePtr PVUnion::pvDataCreate(getPVDataCreate()); + PVUnion::PVUnion(UnionConstPtr const & unionPtr) : PVField(unionPtr), unionPtr(unionPtr), @@ -87,7 +89,7 @@ PVFieldPtr PVUnion::select(int32 index) FieldConstPtr field = unionPtr->getField(index); selector = index; - value = getPVDataCreate()->createPVField(field); + value = pvDataCreate->createPVField(field); return value; } @@ -171,7 +173,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { // try to reuse existing field instance if (!value.get() || *value->getField() != *field) - value = getPVDataCreate()->createPVField(field); + value = pvDataCreate->createPVField(field); value->deserialize(pbuffer, pcontrol); } else @@ -188,7 +190,7 @@ void PVUnion::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) FieldConstPtr field = unionPtr->getField(selector); // try to reuse existing field instance if (!value.get() || *value->getField() != *field) - value = getPVDataCreate()->createPVField(field); + value = pvDataCreate->createPVField(field); } value->deserialize(pbuffer, pcontrol); } @@ -217,4 +219,57 @@ std::ostream& PVUnion::dumpValue(std::ostream& o) const return o; } +void PVUnion::copy(const PVUnion& from) +{ + if(isImmutable()) + throw std::invalid_argument("destination is immutable"); + + if(*getUnion().get() != *from.getUnion().get()) + throw std::invalid_argument("union definitions do not match"); + + copyUnchecked(from); +} + +void PVUnion::copyUnchecked(const PVUnion& from) +{ + + PVFieldPtr fromValue = from.get(); + if (from.getUnion()->isVariant()) + { + if (fromValue.get() == 0) + { + set(PVField::shared_pointer()); + } + else + { + PVFieldPtr toValue = get(); + if (toValue.get() == 0 || *toValue->getField() != *fromValue->getField()) + { + toValue = pvDataCreate->createPVField(fromValue->getField()); + toValue->copyUnchecked(*fromValue.get()); + set(toValue); + } + else + { + toValue->copyUnchecked(*fromValue.get()); + postPut(); + } + } + } + else + { + if (fromValue.get() == 0) + { + select(PVUnion::UNDEFINED_INDEX); + } + else + { + select(from.getSelectedIndex())->copyUnchecked(*fromValue.get()); + } + postPut(); + } + +} + + }} diff --git a/src/factory/PVUnionArray.cpp b/src/factory/PVUnionArray.cpp index ed516c6..425ab82 100644 --- a/src/factory/PVUnionArray.cpp +++ b/src/factory/PVUnionArray.cpp @@ -241,4 +241,25 @@ std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const return o; } +void PVUnionArray::copy(const PVUnionArray& from) +{ + if(isImmutable()) + throw std::invalid_argument("destination is immutable"); + + // TODO relaxed compare? + if(*getUnionArray().get() != *from.getUnionArray().get()) + throw std::invalid_argument("unionArray definitions do not match"); + + copyUnchecked(from); +} + +void PVUnionArray::copyUnchecked(const PVUnionArray& from) +{ + if (this == &from) + return; + + replace(from.view()); +} + + }} diff --git a/src/pv/convert.h b/src/pv/convert.h index 04baac9..4e17b5a 100644 --- a/src/pv/convert.h +++ b/src/pv/convert.h @@ -22,40 +22,6 @@ namespace epics { namespace pvData { -bool epicsShareExtern operator==(const PVField&, const PVField&); - -static inline bool operator!=(const PVField& a, const PVField& b) -{return !(a==b);} - - -bool epicsShareExtern operator==(const Field&, const Field&); -bool epicsShareExtern operator==(const Scalar&, const Scalar&); -bool epicsShareExtern operator==(const ScalarArray&, const ScalarArray&); -bool epicsShareExtern operator==(const Structure&, const Structure&); -bool epicsShareExtern operator==(const StructureArray&, const StructureArray&); -bool epicsShareExtern operator==(const Union&, const Union&); -bool epicsShareExtern operator==(const UnionArray&, const UnionArray&); -bool epicsShareExtern operator==(const BoundedString&, const BoundedString&); - -static inline bool operator!=(const Field& a, const Field& b) -{return !(a==b);} -static inline bool operator!=(const Scalar& a, const Scalar& b) -{return !(a==b);} -static inline bool operator!=(const ScalarArray& a, const ScalarArray& b) -{return !(a==b);} -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);} -static inline bool operator!=(const BoundedString& a, const BoundedString& b) -{return !(a==b);} - - - class Convert; typedef std::tr1::shared_ptr ConvertPtr; diff --git a/src/pv/pvData.h b/src/pv/pvData.h index e045cb1..cddb6a4 100644 --- a/src/pv/pvData.h +++ b/src/pv/pvData.h @@ -233,6 +233,9 @@ public: */ virtual std::ostream& dumpValue(std::ostream& o) const = 0; + void copy(const PVField& from); + void copyUnchecked(const PVField& from); + protected: PVField::shared_pointer getPtrSelf() { @@ -320,6 +323,9 @@ public: virtual void assign(const PVScalar&) = 0; + virtual void copy(const PVScalar& from) = 0; + virtual void copyUnchecked(const PVScalar& from) = 0; + protected: PVScalar(ScalarConstPtr const & scalar); }; @@ -401,12 +407,20 @@ protected: } virtual void assign(const PVScalar& scalar) { - if(this==&scalar) - return; if(isImmutable()) - throw std::invalid_argument("Destination is immutable"); + throw std::invalid_argument("destination is immutable"); + copyUnchecked(scalar); + } + virtual void copy(const PVScalar& from) + { + assign(from); + } + virtual void copyUnchecked(const PVScalar& from) + { + if(this==&from) + return; T result; - scalar.getAs((void*)&result, typeCode); + from.getAs((void*)&result, typeCode); put(result); } @@ -600,9 +614,21 @@ public: * If the types do match then a new refernce to the provided * data is kept. */ - void assign(PVScalarArray& pv) { + void assign(const PVScalarArray& pv) { + if (isImmutable()) + throw std::invalid_argument("destination is immutable"); + copyUnchecked(pv); + } + + void copy(const PVScalarArray& from) { + assign(from); + } + + void copyUnchecked(const PVScalarArray& from) { + if (this==&from) + return; shared_vector temp; - pv._getAsVoid(temp); + from._getAsVoid(temp); _putFromVoid(temp); } @@ -842,6 +868,11 @@ public: virtual std::ostream& dumpValue(std::ostream& o) const; + void copy(const PVStructure& from); + + void copyUnchecked(const PVStructure& from); + void copyUnchecked(const PVStructure& from, const BitSet& maskBitSet, bool inverse = false); + private: static PVFieldPtr nullPVField; static PVBooleanPtr nullPVBoolean; @@ -995,7 +1026,12 @@ public: virtual std::ostream& dumpValue(std::ostream& o) const; + void copy(const PVUnion& from); + void copyUnchecked(const PVUnion& from); + private: + static PVDataCreatePtr pvDataCreate; + friend class PVDataCreate; UnionConstPtr unionPtr; @@ -1238,6 +1274,9 @@ public: virtual std::ostream& dumpValue(std::ostream& o) const; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; + void copy(const PVStructureArray& from); + void copyUnchecked(const PVStructureArray& from); + protected: PVValueArray(StructureArrayConstPtr const & structureArray) :base_t(structureArray) @@ -1335,6 +1374,9 @@ public: virtual std::ostream& dumpValue(std::ostream& o) const; virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; + void copy(const PVUnionArray& from); + void copyUnchecked(const PVUnionArray& from); + protected: PVValueArray(UnionArrayConstPtr const & unionArray) :base_t(unionArray) @@ -1564,6 +1606,11 @@ private: epicsShareExtern PVDataCreatePtr getPVDataCreate(); +bool epicsShareExtern operator==(const PVField&, const PVField&); + +static inline bool operator!=(const PVField& a, const PVField& b) +{return !(a==b);} + }} /** diff --git a/src/pv/pvIntrospect.h b/src/pv/pvIntrospect.h index cde0421..a7a1cfb 100644 --- a/src/pv/pvIntrospect.h +++ b/src/pv/pvIntrospect.h @@ -1219,6 +1219,32 @@ struct StructureArrayHashFunction { size_t operator() (const StructureArray& structureArray) const { StructureHashFunction shf; return (0x10 | shf(*(structureArray.getStructure()))); } }; +bool epicsShareExtern operator==(const Field&, const Field&); +bool epicsShareExtern operator==(const Scalar&, const Scalar&); +bool epicsShareExtern operator==(const ScalarArray&, const ScalarArray&); +bool epicsShareExtern operator==(const Structure&, const Structure&); +bool epicsShareExtern operator==(const StructureArray&, const StructureArray&); +bool epicsShareExtern operator==(const Union&, const Union&); +bool epicsShareExtern operator==(const UnionArray&, const UnionArray&); +bool epicsShareExtern operator==(const BoundedString&, const BoundedString&); + +static inline bool operator!=(const Field& a, const Field& b) +{return !(a==b);} +static inline bool operator!=(const Scalar& a, const Scalar& b) +{return !(a==b);} +static inline bool operator!=(const ScalarArray& a, const ScalarArray& b) +{return !(a==b);} +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);} +static inline bool operator!=(const BoundedString& a, const BoundedString& b) +{return !(a==b);} + }} /**