diff --git a/src/factory/PVDataCreateFactory.cpp b/src/factory/PVDataCreateFactory.cpp index 96a773f..6a899ad 100644 --- a/src/factory/PVDataCreateFactory.cpp +++ b/src/factory/PVDataCreateFactory.cpp @@ -59,135 +59,50 @@ template<> const ScalarType PVFloatArray::typeCode = pvFloat; template<> const ScalarType PVDoubleArray::typeCode = pvDouble; template<> const ScalarType PVStringArray::typeCode = pvString; -/** Default storage for scalar values - */ template -class BasePVScalar : public PVScalarValue { -public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - - BasePVScalar(ScalarConstPtr const & scalar); - virtual ~BasePVScalar(); - virtual T get() const ; - virtual void put(T val); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) const; - virtual void deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher); -private: - T value; -}; - -template -BasePVScalar::BasePVScalar(ScalarConstPtr const & scalar) - : PVScalarValue(scalar),value(0) -{} -//Note: '0' is a suitable default for all POD types (not string) - -template -BasePVScalar::~BasePVScalar() {} - -template -T BasePVScalar::get() const { return value;} - -template -void BasePVScalar::put(T val) -{ - value = val; - PVField::postPut(); -} - -template -void BasePVScalar::serialize(ByteBuffer *pbuffer, +void PVScalarValue::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { pflusher->ensureBuffer(sizeof(T)); - pbuffer->put(value); + pbuffer->put(storage.value); +} + +template<> +void PVScalarValue::serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher) const { + SerializeHelper::serializeString(storage.value, pbuffer, pflusher); } template -void BasePVScalar::deserialize(ByteBuffer *pbuffer, +void PVScalarValue::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { pflusher->ensureData(sizeof(T)); - value = pbuffer->GET(T); + storage.value = pbuffer->GET(T); } -typedef BasePVScalar BasePVBoolean; -typedef BasePVScalar BasePVByte; -typedef BasePVScalar BasePVShort; -typedef BasePVScalar BasePVInt; -typedef BasePVScalar BasePVLong; -typedef BasePVScalar BasePVUByte; -typedef BasePVScalar BasePVUShort; -typedef BasePVScalar BasePVUInt; -typedef BasePVScalar BasePVULong; -typedef BasePVScalar BasePVFloat; -typedef BasePVScalar BasePVDouble; +template<> +void PVScalarValue::deserialize(ByteBuffer *pbuffer, + DeserializableControl *pflusher) +{ + storage.value = SerializeHelper::deserializeString(pbuffer, pflusher); + // TODO: check for violations of maxLength? +} -// BasePVString is special case, since it implements SerializableArray -class BasePVString : public PVString { -public: - typedef string value_type; - typedef string* pointer; - typedef const string* const_pointer; - - BasePVString(ScalarConstPtr const & scalar); - virtual ~BasePVString(); - virtual string get() const ; - virtual void put(string val); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) const; - virtual void deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, size_t offset, size_t count) const; -private: - string value; - std::size_t maxLength; -}; - -BasePVString::BasePVString(ScalarConstPtr const & scalar) - : PVString(scalar),value() +PVString::PVString(ScalarConstPtr const & scalar) + : PVScalarValue(scalar) { BoundedStringConstPtr boundedString = std::tr1::dynamic_pointer_cast(scalar); if (boundedString.get()) - maxLength = boundedString->getMaximumLength(); + storage.maxLength = boundedString->getMaximumLength(); else - maxLength = 0; + storage.maxLength = 0; } -BasePVString::~BasePVString() {} - -string BasePVString::get() const { return value;} - -void BasePVString::put(string val) -{ - if (maxLength > 0 && val.length() > maxLength) - throw std::overflow_error("string too long"); - - value = val; - postPut(); -} - -void BasePVString::serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) const -{ - SerializeHelper::serializeString(value, pbuffer, pflusher); -} - -void BasePVString::deserialize(ByteBuffer *pbuffer, - DeserializableControl *pflusher) -{ - value = SerializeHelper::deserializeString(pbuffer, pflusher); -} - -void BasePVString::serialize(ByteBuffer *pbuffer, +void PVString::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { // check bounds - const size_t length = /*(value == null) ? 0 :*/ value.length(); + const size_t length = storage.value.length(); /*if (offset < 0) offset = 0; else*/ if (offset > length) offset = length; //if (count < 0) count = length; @@ -197,10 +112,10 @@ void BasePVString::serialize(ByteBuffer *pbuffer, count = maxCount; // write - SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher); + SerializeHelper::serializeSubstring(storage.value, offset, count, pbuffer, pflusher); } -void PVArray::checkLength(size_t len) +void PVArray::checkLength(size_t len) const { Array::ArraySizeType type = getArray()->getArraySizeType(); if (type != Array::variable) @@ -213,61 +128,26 @@ void PVArray::checkLength(size_t len) } } -/** Default storage for arrays - */ template -class DefaultPVArray : public PVValueArray { -public: - typedef T* pointer; - typedef const T* const_pointer; - typedef std::vector vector; - typedef const std::vector const_vector; - typedef std::tr1::shared_ptr shared_vector; - - typedef ::epics::pvData::shared_vector svector; - typedef ::epics::pvData::shared_vector const_svector; - - DefaultPVArray(ScalarArrayConstPtr const & scalarArray); - virtual ~DefaultPVArray(); - - virtual size_t getLength() const {return value.size();} - virtual size_t getCapacity() const {return value.capacity();} - - virtual void setCapacity(size_t capacity); - virtual void setLength(size_t length); - - virtual const_svector view() const {return value;} - virtual void swap(const_svector &other); - virtual void replace(const const_svector& next); - - // from Serializable - virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const; - virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, size_t offset, size_t count) const; -private: - const_svector value; -}; - -template -DefaultPVArray::DefaultPVArray(ScalarArrayConstPtr const & scalarArray) -: PVValueArray(scalarArray), - value() +PVValueArray::PVValueArray(ScalarArrayConstPtr const & scalarArray) + :base_t(scalarArray) + ,value() -{ - ArrayConstPtr array = this->getArray(); - if (array->getArraySizeType() == Array::fixed) - { - // this->setLength(array->getMaximumCapacity()); - this->setCapacityMutable(false); - } -} +{} + +PVValueArray::PVValueArray(StructureArrayConstPtr const & structureArray) + :base_t(structureArray) + ,structureArray(structureArray) + +{} + +PVValueArray::PVValueArray(UnionArrayConstPtr const & unionArray) + :base_t(unionArray) + ,unionArray(unionArray) +{} template -DefaultPVArray::~DefaultPVArray() -{ } -template -void DefaultPVArray::setCapacity(size_t capacity) +void PVValueArray::setCapacity(size_t capacity) { if(this->isCapacityMutable()) { this->checkLength(capacity); @@ -278,7 +158,7 @@ void DefaultPVArray::setCapacity(size_t capacity) } template -void DefaultPVArray::setLength(size_t length) +void PVValueArray::setLength(size_t length) { if(this->isImmutable()) THROW_EXCEPTION2(std::logic_error, "immutable"); @@ -295,7 +175,7 @@ void DefaultPVArray::setLength(size_t length) } template -void DefaultPVArray::replace(const const_svector& next) +void PVValueArray::replace(const const_svector& next) { this->checkLength(next.size()); @@ -304,7 +184,7 @@ void DefaultPVArray::replace(const const_svector& next) } template -void DefaultPVArray::swap(const_svector &other) +void PVValueArray::swap(const_svector &other) { if (this->isImmutable()) THROW_EXCEPTION2(std::logic_error, "immutable"); @@ -316,13 +196,13 @@ void DefaultPVArray::swap(const_svector &other) template -void DefaultPVArray::serialize(ByteBuffer *pbuffer, +void PVValueArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { serialize(pbuffer, pflusher, 0, this->getLength()); } template -void DefaultPVArray::deserialize(ByteBuffer *pbuffer, +void PVValueArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = this->getArray()->getArraySizeType() == Array::fixed ? @@ -371,7 +251,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, } template -void DefaultPVArray::serialize(ByteBuffer *pbuffer, +void PVValueArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { //TODO: avoid incrementing the ref counter... @@ -415,7 +295,7 @@ void DefaultPVArray::serialize(ByteBuffer *pbuffer, // specializations for string template<> -void DefaultPVArray::deserialize(ByteBuffer *pbuffer, +void PVValueArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = this->getArray()->getArraySizeType() == Array::fixed ? @@ -442,7 +322,7 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, } template<> -void DefaultPVArray::serialize(ByteBuffer *pbuffer, +void PVValueArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { const_svector temp(value); @@ -458,19 +338,6 @@ void DefaultPVArray::serialize(ByteBuffer *pbuffer, } } -typedef DefaultPVArray DefaultPVBooleanArray; -typedef DefaultPVArray BasePVByteArray; -typedef DefaultPVArray BasePVShortArray; -typedef DefaultPVArray BasePVIntArray; -typedef DefaultPVArray BasePVLongArray; -typedef DefaultPVArray BasePVUByteArray; -typedef DefaultPVArray BasePVUShortArray; -typedef DefaultPVArray BasePVUIntArray; -typedef DefaultPVArray BasePVULongArray; -typedef DefaultPVArray BasePVFloatArray; -typedef DefaultPVArray BasePVDoubleArray; -typedef DefaultPVArray BasePVStringArray; - // Factory PVDataCreate::PVDataCreate() @@ -564,29 +431,29 @@ PVScalarPtr PVDataCreate::createPVScalar(ScalarConstPtr const & scalar) ScalarType scalarType = scalar->getScalarType(); switch(scalarType) { case pvBoolean: - return PVScalarPtr(new BasePVBoolean(scalar)); + return PVScalarPtr(new PVBoolean(scalar)); case pvByte: - return PVScalarPtr(new BasePVByte(scalar)); + return PVScalarPtr(new PVByte(scalar)); case pvShort: - return PVScalarPtr(new BasePVShort(scalar)); + return PVScalarPtr(new PVShort(scalar)); case pvInt: - return PVScalarPtr(new BasePVInt(scalar)); + return PVScalarPtr(new PVInt(scalar)); case pvLong: - return PVScalarPtr(new BasePVLong(scalar)); + return PVScalarPtr(new PVLong(scalar)); case pvUByte: - return PVScalarPtr(new BasePVUByte(scalar)); + return PVScalarPtr(new PVUByte(scalar)); case pvUShort: - return PVScalarPtr(new BasePVUShort(scalar)); + return PVScalarPtr(new PVUShort(scalar)); case pvUInt: - return PVScalarPtr(new BasePVUInt(scalar)); + return PVScalarPtr(new PVUInt(scalar)); case pvULong: - return PVScalarPtr(new BasePVULong(scalar)); + return PVScalarPtr(new PVULong(scalar)); case pvFloat: - return PVScalarPtr(new BasePVFloat(scalar)); + return PVScalarPtr(new PVFloat(scalar)); case pvDouble: - return PVScalarPtr(new BasePVDouble(scalar)); + return PVScalarPtr(new PVDouble(scalar)); case pvString: - return PVScalarPtr(new BasePVString(scalar)); + return PVScalarPtr(new PVString(scalar)); } throw std::logic_error("PVDataCreate::createPVScalar should never get here"); } @@ -611,29 +478,29 @@ PVScalarArrayPtr PVDataCreate::createPVScalarArray( { switch(scalarArray->getElementType()) { case pvBoolean: - return PVScalarArrayPtr(new DefaultPVBooleanArray(scalarArray)); + return PVScalarArrayPtr(new PVBooleanArray(scalarArray)); case pvByte: - return PVScalarArrayPtr(new BasePVByteArray(scalarArray)); + return PVScalarArrayPtr(new PVByteArray(scalarArray)); case pvShort: - return PVScalarArrayPtr(new BasePVShortArray(scalarArray)); + return PVScalarArrayPtr(new PVShortArray(scalarArray)); case pvInt: - return PVScalarArrayPtr(new BasePVIntArray(scalarArray)); + return PVScalarArrayPtr(new PVIntArray(scalarArray)); case pvLong: - return PVScalarArrayPtr(new BasePVLongArray(scalarArray)); + return PVScalarArrayPtr(new PVLongArray(scalarArray)); case pvUByte: - return PVScalarArrayPtr(new BasePVUByteArray(scalarArray)); + return PVScalarArrayPtr(new PVUByteArray(scalarArray)); case pvUShort: - return PVScalarArrayPtr(new BasePVUShortArray(scalarArray)); + return PVScalarArrayPtr(new PVUShortArray(scalarArray)); case pvUInt: - return PVScalarArrayPtr(new BasePVUIntArray(scalarArray)); + return PVScalarArrayPtr(new PVUIntArray(scalarArray)); case pvULong: - return PVScalarArrayPtr(new BasePVULongArray(scalarArray)); + return PVScalarArrayPtr(new PVULongArray(scalarArray)); case pvFloat: - return PVScalarArrayPtr(new BasePVFloatArray(scalarArray)); + return PVScalarArrayPtr(new PVFloatArray(scalarArray)); case pvDouble: - return PVScalarArrayPtr(new BasePVDoubleArray(scalarArray)); + return PVScalarArrayPtr(new PVDoubleArray(scalarArray)); case pvString: - return PVScalarArrayPtr(new BasePVStringArray(scalarArray)); + return PVScalarArrayPtr(new PVStringArray(scalarArray)); } throw std::logic_error("PVDataCreate::createPVScalarArray should never get here"); diff --git a/src/pv/pvData.h b/src/pv/pvData.h index 3d83573..1d5cde2 100644 --- a/src/pv/pvData.h +++ b/src/pv/pvData.h @@ -336,12 +336,39 @@ protected: explicit PVScalar(ScalarConstPtr const & scalar); }; +namespace detail { +template +struct ScalarStorageOps { + T value; + typedef T arg_type; + inline void store(T v) { + value = v; + } + ScalarStorageOps() :value(0) {} +}; +template<> +struct ScalarStorageOps { + std::string value; + size_t maxLength; + typedef const std::string& arg_type; + void store(const std::string& val) { + if (maxLength > 0 && val.length() > maxLength) + throw std::overflow_error("string too long"); + + value = val; + } + + ScalarStorageOps(): value(), maxLength(0) {} // initialized in PVString::PVString +}; +} // namespace detail + /** * @brief Class that holds the data for each possible scalar type. * */ template class epicsShareClass PVScalarValue : public PVScalar { + typedef detail::ScalarStorageOps storage_t; public: POINTER_DEFINITIONS(PVScalarValue); typedef T value_type; @@ -358,12 +385,15 @@ public: * Get the value. * @return The value. */ - virtual T get() const = 0; + typename storage_t::arg_type get() const { return storage.value; } /** * Put a new value into the PVScalar. * @param value The value. */ - virtual void put(T value) = 0; + void put(typename storage_t::arg_type v) { + storage.store(v); + PVField::postPut(); + } std::ostream& dumpValue(std::ostream& o) const { @@ -381,7 +411,7 @@ public: // put operator // double value = 12.8; doubleField <<= value; // NOTE: virtual is needed for MS C++ compiler to get this operator exported - virtual void operator<<=(T value) + virtual void operator<<=(typename storage_t::arg_type value) { put(value); } @@ -393,7 +423,7 @@ public: } template - inline void putFrom(T1 val) { + inline void putFrom(typename detail::ScalarStorageOps::arg_type val) { put(castUnsafe(val)); } @@ -416,9 +446,14 @@ public: put(result); } + virtual void serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher) const; + virtual void deserialize(ByteBuffer *pbuffer, + DeserializableControl *pflusher); + protected: explicit PVScalarValue(ScalarConstPtr const & scalar) - : PVScalar(scalar) {} + : PVScalar(scalar), storage() {} virtual void getAs(void * result, ScalarType rtype) const { const T src = get(); @@ -431,8 +466,8 @@ protected: put(result); } -private: friend class PVDataCreate; + storage_t storage; }; /** @@ -492,9 +527,13 @@ public: * Destructor */ virtual ~PVString() {} + + virtual void serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher, size_t offset, size_t count) const; protected: - explicit PVString(ScalarConstPtr const & scalar) - : PVScalarValue(scalar) {} + explicit PVString(ScalarConstPtr const & scalar); + + friend class PVDataCreate; }; typedef std::tr1::shared_ptr PVStringPtr; @@ -563,7 +602,7 @@ public: protected: explicit PVArray(FieldConstPtr const & field); - void checkLength(size_t length); + void checkLength(size_t length) const; private: bool capacityMutable; friend class PVDataCreate; @@ -1180,6 +1219,22 @@ public: return o << ']'; } + virtual size_t getLength() const {return value.size();} + virtual size_t getCapacity() const {return value.capacity();} + + virtual void setCapacity(size_t capacity); + virtual void setLength(size_t length); + + virtual const_svector view() const {return value;} + virtual void swap(const_svector &other); + virtual void replace(const const_svector& next); + + // from Serializable + virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const; + virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher); + virtual void serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher, size_t offset, size_t count) const; + std::ostream& dumpValue(std::ostream& o, size_t index) const { return o << print_cast(this->view().at(index)); @@ -1197,8 +1252,8 @@ protected: this->replace(shared_vector_convert(in)); } - explicit PVValueArray(ScalarArrayConstPtr const & scalar) - : base_t(scalar) {} + explicit PVValueArray(ScalarArrayConstPtr const & scalar); + const_svector value; friend class PVDataCreate; }; @@ -1291,10 +1346,7 @@ public: void copyUnchecked(const PVStructureArray& from); protected: - explicit PVValueArray(StructureArrayConstPtr const & structureArray) - :base_t(structureArray) - ,structureArray(structureArray) - {} + PVValueArray(StructureArrayConstPtr const & structureArray); private: StructureArrayConstPtr structureArray; const_svector value; @@ -1391,10 +1443,7 @@ public: void copyUnchecked(const PVUnionArray& from); protected: - explicit PVValueArray(UnionArrayConstPtr const & unionArray) - :base_t(unionArray) - ,unionArray(unionArray) - {} + explicit PVValueArray(UnionArrayConstPtr const & unionArray); private: UnionArrayConstPtr unionArray; const_svector value;