diff --git a/pvDataApp/factory/Convert.cpp b/pvDataApp/factory/Convert.cpp index 35763ac..dc29861 100644 --- a/pvDataApp/factory/Convert.cpp +++ b/pvDataApp/factory/Convert.cpp @@ -382,12 +382,15 @@ bool Convert::isCopyStructureArrayCompatible( void Convert::copyStructureArray( PVStructureArrayPtr const & from, PVStructureArrayPtr const & to) { - if(to->isImmutable()) { - if(from==to) return; - String message("Convert.copyStructureArray destination is immutable"); - throw std::invalid_argument(message); + if(from==to) { + return; + } else if(to->isImmutable()) { + throw std::invalid_argument("Convert.copyStructureArray destination is immutable"); } - to->put(0,from->getLength(),from->getVector(),0); + PVStructureArray::svector data; + from->swap(data); + to->replace(data); + from->swap(data); } void Convert::newLine(StringBuilder buffer, int indentLevel) diff --git a/pvDataApp/factory/PVArray.cpp b/pvDataApp/factory/PVArray.cpp index 89dd863..19e3b88 100644 --- a/pvDataApp/factory/PVArray.cpp +++ b/pvDataApp/factory/PVArray.cpp @@ -19,83 +19,32 @@ using std::size_t; namespace epics { namespace pvData { -class PVArrayPvt { -public: - PVArrayPvt() : length(0),capacity(0),capacityMutable(true) - {} - size_t length; - size_t capacity; - bool capacityMutable; -}; - PVArray::PVArray(FieldConstPtr const & field) -: PVField(field),pImpl(new PVArrayPvt()) +: PVField(field),capacityMutable(true) { } -PVArray::~PVArray() -{ - delete pImpl; -} - void PVArray::setImmutable() { - pImpl->capacityMutable = false; + capacityMutable = false; PVField::setImmutable(); } - size_t PVArray::getLength() const {return pImpl->length;} - - size_t PVArray::getCapacity() const {return pImpl->capacity;} - - static String fieldImmutable("field is immutable"); - - void PVArray::setLength(size_t length) { - if(length==pImpl->length) return; - if(PVField::isImmutable()) { - PVField::message(fieldImmutable,errorMessage); - return; - } - if(length>pImpl->capacity) this->setCapacity(length); - if(length>pImpl->capacity) length = pImpl->capacity; - pImpl->length = length; - } - - void PVArray::setCapacityLength(size_t capacity,size_t length) { - pImpl->capacity = capacity; - pImpl->length = length; - } - - bool PVArray::isCapacityMutable() const { if(PVField::isImmutable()) { return false; } - return pImpl->capacityMutable; + return capacityMutable; } void PVArray::setCapacityMutable(bool isMutable) { if(isMutable && PVField::isImmutable()) { - PVField::message(fieldImmutable,errorMessage); - return; + throw std::runtime_error("field is immutable"); } - pImpl->capacityMutable = isMutable; + capacityMutable = isMutable; } - static String capacityImmutable("capacity is immutable"); - - void PVArray::setCapacity(size_t capacity) { - if(PVField::isImmutable()) { - PVField::message(fieldImmutable,errorMessage); - return; - } - if(pImpl->capacityMutable==false) { - PVField::message(capacityImmutable,errorMessage); - return; - } - pImpl->capacity = capacity; - } std::ostream& operator<<(format::array_at_internal const& manip, const PVArray& array) { diff --git a/pvDataApp/factory/PVDataCreateFactory.cpp b/pvDataApp/factory/PVDataCreateFactory.cpp index e169596..7c20509 100644 --- a/pvDataApp/factory/PVDataCreateFactory.cpp +++ b/pvDataApp/factory/PVDataCreateFactory.cpp @@ -231,9 +231,8 @@ DefaultPVArray::~DefaultPVArray() template void DefaultPVArray::setCapacity(size_t capacity) { - if(this->isCapacityMutable() && capacity>value.capacity()) { + if(this->isCapacityMutable()) { value.reserve(capacity); - PVArray::setCapacityLength(value.capacity(), value.size()); } } @@ -248,7 +247,6 @@ void DefaultPVArray::setLength(size_t length) value.slice(0, length); else value.resize(length); - PVArray::setCapacityLength(value.capacity(), value.size()); } @@ -265,7 +263,6 @@ void DefaultPVArray::swap(svector &other) THROW_EXCEPTION2(std::logic_error,"Immutable"); value.swap(other); - PVArray::setCapacityLength(value.capacity(), value.size()); } @@ -282,7 +279,6 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, value.resize(size); // TODO: avoid copy of stuff we will then overwrite - PVArray::setCapacityLength(value.capacity(), value.size()); T* cur = value.data(); // try to avoid deserializing from the buffer @@ -379,8 +375,6 @@ void DefaultPVArray::deserialize(ByteBuffer *pbuffer, else if(size < value.size()) value.slice(0, size); - setCapacityLength(size, size); - String * pvalue = value.data(); for(size_t i = 0; i(new PVStructurePtrArray())) -{ -} - size_t PVStructureArray::append(size_t number) { - size_t currentLength = getLength(); - size_t newLength = currentLength + number; - setCapacity(newLength); - setLength(newLength); + svector data; + swap(data); + data.resize(data.size()+number); + StructureConstPtr structure = structureArray->getStructure(); - PVStructurePtrArray *to = value.get(); - for(size_t i=currentLength; icreatePVStructure(structure); - } + + for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number) + *it = getPVDataCreate()->createPVStructure(structure); + + size_t newLength = data.size(); + + swap(data); + return newLength; } bool PVStructureArray::remove(size_t offset,size_t number) { - size_t length = getLength(); - if(offset+number>length) return false; - PVStructurePtrArray vec = *value.get(); + if(number==0) + return true; + else if(offset+number>getLength()) + return false; + + svector vec(reuse()); + + size_t length = vec.size(); + for(size_t i = offset; i+number < length; i++) { - vec[i] = vec[i + number]; + vec[i].swap(vec[i + number]); } - size_t newLength = length - number; - setCapacityLength(newLength,newLength); + + vec.resize(length - number); + swap(vec); + return true; } void PVStructureArray::compress() { - size_t length = getCapacity(); + svector vec(reuse()); // TODO: check for first NULL before realloc + + size_t length = vec.size(); size_t newLength = 0; - PVStructurePtrArray vec = *value.get(); + for(size_t i=0; iisCapacityMutable()) { + svector value; + swap(value); + value.reserve(capacity); + swap(value); } - size_t length = getLength(); - if(length>capacity) length = capacity; - size_t oldCapacity = getCapacity(); - if(oldCapacity>capacity) { - PVStructurePtrArray array; - array.reserve(capacity); - array.resize(length); - PVStructurePtr * from = get(); - for (size_t i=0; iswap(array); +} + +void PVStructureArray::setLength(size_t length) +{ + if(this->isImmutable()) + THROW_EXCEPTION2(std::logic_error,"Immutable"); + svector value; + swap(value); + if(length == value.size()) { + // nothing + } else if(length < value.size()) { + value.slice(0, length); } else { - value->reserve(capacity); + value.resize(length); } - setCapacityLength(capacity,length); + swap(value); } -void PVStructureArray::setLength(size_t length) { - if(PVArray::getLength()==length) return; - size_t capacity = PVArray::getCapacity(); - if(length>capacity) { - if(!PVArray::isCapacityMutable()) { - std::string message("not capacityMutable"); - PVField::message(message, errorMessage); - return; - } - setCapacity(length); - } - value->resize(length); - PVArray::setCapacityLength(capacity,length); -} - -StructureArrayConstPtr PVStructureArray::getStructureArray() const +void PVStructureArray::swap(svector &other) { - return structureArray; -} + if(this->isImmutable()) + THROW_EXCEPTION2(std::logic_error,"Immutable"); -size_t PVStructureArray::get( - size_t offset, size_t len, StructureArrayData &data) -{ - size_t n = len; - size_t length = getLength(); - if(offset+len > length) { - n = length - offset; - //if(n<0) n = 0; - } - data.data = *value.get(); - data.offset = offset; - return n; -} - -size_t PVStructureArray::put(size_t offset,size_t len, - const_vector const & from, size_t fromOffset) -{ - if(isImmutable()) { - message(String("field is immutable"), errorMessage); - return 0; - } - if(&from==value.get()) return 0; - if(len<1) return 0; - size_t length = getLength(); - size_t capacity = getCapacity(); - if(offset+len > length) { - size_t newlength = offset + len; - if(newlength>capacity) { - setCapacity(newlength); - capacity = getCapacity(); - newlength = capacity; - len = newlength - offset; - if(len<=0) return 0; - } - length = newlength; - setLength(length); - } - PVStructurePtrArray *to = value.get(); - StructureConstPtr structure = structureArray->getStructure(); - for(size_t i=0; igetStructure()!=structure) { - throw std::invalid_argument(String( - "Element is not a compatible structure")); - } - } - (*to)[i+offset] = frompv; - } - setLength(length); - postPut(); - return len; -} - -void PVStructureArray::shareData( - std::tr1::shared_ptr > const & sharedValue, - std::size_t capacity, - std::size_t length) -{ - value = sharedValue; - setCapacityLength(capacity,length); + value.swap(other); } void PVStructureArray::serialize(ByteBuffer *pbuffer, @@ -196,56 +133,48 @@ void PVStructureArray::serialize(ByteBuffer *pbuffer, void PVStructureArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { + svector data; + swap(data); + size_t size = SerializeHelper::readSize(pbuffer, pcontrol); - //if(size>=0) { - // prepare array, if necessary - if(size>getCapacity()) setCapacity(size); - setLength(size); - PVStructurePtrArray *pvArray = value.get(); - for(size_t i = 0; iensureData(1); - size_t temp = pbuffer->getByte(); - if(temp==0) { - (*pvArray)[i].reset(); - } - else { - if((*pvArray)[i].get()==NULL) { - StructureConstPtr structure = structureArray->getStructure(); - (*pvArray)[i] = getPVDataCreate()->createPVStructure(structure); - } - (*pvArray)[i]->deserialize(pbuffer, pcontrol); - } + data.resize(size); + + StructureConstPtr structure = structureArray->getStructure(); + + for(size_t i = 0; iensureData(1); + size_t temp = pbuffer->getByte(); + if(temp==0) { + data[i].reset(); } - postPut(); - //} + else { + if(data[i].get()==NULL) { + data[i] = getPVDataCreate()->createPVStructure(structure); + } + data[i]->deserialize(pbuffer, pcontrol); + } + } + replace(data); // calls postPut() } void PVStructureArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { - // cache - size_t length = getLength(); - // check bounds - /*if(offset<0) - offset = 0; - else*/ if(offset>length) offset = length; - //if(count<0) count = length; + const_svector temp(view()); + temp.slice(offset, count); - size_t maxCount = length-offset; - if(count>maxCount) count = maxCount; + SerializeHelper::writeSize(temp.size(), pbuffer, pflusher); - PVStructurePtrArray pvArray = *value.get(); - // write - SerializeHelper::writeSize(count, pbuffer, pflusher); for(size_t i = 0; igetRemaining()<1) pflusher->flushSerializeBuffer(); - PVStructurePtr pvStructure = pvArray[i+offset]; - if(pvStructure.get()==NULL) { + if(pbuffer->getRemaining()<1) + pflusher->flushSerializeBuffer(); + + if(temp[i].get()==NULL) { pbuffer->putByte(0); } else { pbuffer->putByte(1); - pvStructure->serialize(pbuffer, pflusher); + temp[i]->serialize(pbuffer, pflusher); } } } @@ -267,9 +196,9 @@ std::ostream& PVStructureArray::dumpValue(std::ostream& o) const std::ostream& PVStructureArray::dumpValue(std::ostream& o, std::size_t index) const { - PVStructurePtrArray pvArray = *value.get(); - PVStructurePtr pvStructure = pvArray[index]; - return o << *(pvStructure.get()); + const_svector temp(view()); + if(index class PVValueArray; + /** * typedef for a pointer to a PVAuxInfo. @@ -149,6 +151,8 @@ typedef std::vector::const_iterator PVStructurePtrArray_const__i /** * typedef for a pointer to a PVStructureArray. */ + +typedef PVValueArray PVStructureArray; typedef std::tr1::shared_ptr PVStructureArrayPtr; typedef std::vector PVStructureArrayPtrArray; typedef std::tr1::shared_ptr PVStructureArrayPtrArrayPtr; @@ -574,7 +578,7 @@ public: /** * Destructor */ - virtual ~PVArray(); + virtual ~PVArray(){}; /** * Set the field to be immutable, i. e. it can no longer be modified. * This is permanent, i.e. once done the field can onot be made mutable. @@ -584,17 +588,17 @@ public: * Get the array length. * @return The length. */ - std::size_t getLength() const; + virtual std::size_t getLength() const = 0; /** * Set the array length. * @param The length. */ - virtual void setLength(std::size_t length); + virtual void setLength(std::size_t length) = 0; /** * Get the array capacity. * @return The capacity. */ - std::size_t getCapacity() const; + virtual std::size_t getCapacity() const = 0; /** * Can the capacity be changed. * @return (false,true) if (can not, can) be changed. @@ -615,9 +619,8 @@ public: protected: PVArray(FieldConstPtr const & field); - void setCapacityLength(std::size_t capacity,std::size_t length); private: - class PVArrayPvt * pImpl; + bool capacityMutable; friend class PVDataCreate; }; @@ -748,113 +751,6 @@ private: friend class PVDataCreate; }; -/** - * This is provided by code that calls get. - */ -typedef PVArrayData StructureArrayData; - -/** - * Data class for a structureArray - */ -class PVStructureArray : public PVArray -{ -public: - POINTER_DEFINITIONS(PVStructureArray); - typedef PVStructurePtr value_type; - typedef PVStructurePtr* pointer; - typedef const PVStructurePtr* const_pointer; - typedef PVArrayData ArrayDataType; - typedef std::vector vector; - typedef const std::vector const_vector; - typedef std::tr1::shared_ptr shared_vector; - typedef PVStructureArray &reference; - typedef const PVStructureArray& const_reference; - /** - * Destructor - */ - virtual ~PVStructureArray() {} - /** - * Set the array capacity. - * @param capacity The length. - */ - virtual void setCapacity(size_t capacity); - /** - * Set the array length. - * @param length The length. - */ - virtual void setLength(std::size_t length); - /** - * Get the introspection interface - * @return The interface. - */ - virtual StructureArrayConstPtr getStructureArray() const ; - /** - * Append new elements to the end of the array. - * @param number The number of elements to add. - * @return the new length of the array. - */ - virtual std::size_t append(std::size_t number); - /** - * Remove elements from the array. - * @param offset The offset of the first element to remove. - * @param number The number of elements to remove. - * @return (false,true) if the elements were removed. - */ - virtual bool remove(std::size_t offset,std::size_t number); - /** - * Compress. This removes all null elements from the array. - */ - virtual void compress(); - /** - * Get array elements - * @param offset The offset of the first element, - * @param length The number of elements to get. - * @param data The place where the data is placed. - */ - virtual std::size_t get(std::size_t offset, std::size_t length, - StructureArrayData &data); - /** - * Put data into the array. - * @param offset The offset of the first element, - * @param length The number of elements to get. - * @param from The new values to put into the array. - * @param fromOffset The offset in from. - * @return The number of elements put into the array. - */ - virtual std::size_t put(std::size_t offset,std::size_t length, - const_vector const & from, std::size_t fromOffset); - /** - * Share data from another source. - * @param value The data to share. - * @param capacity The capacity of the array. - * @param length The length of the array. - */ - virtual void shareData( - shared_vector const & value, - std::size_t capacity, - std::size_t length); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher) const; - virtual void deserialize(ByteBuffer *buffer, - DeserializableControl *pflusher); - virtual void serialize(ByteBuffer *pbuffer, - SerializableControl *pflusher, std::size_t offset, std::size_t count) const ; - virtual pointer get() { return &((*value.get())[0]); } - virtual pointer get() const { return &((*value.get())[0]); } - virtual vector const & getVector() {return *value;} - virtual shared_vector const & getSharedVector() {return value;} - - virtual std::ostream& dumpValue(std::ostream& o) const; - virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; - -protected: - PVStructureArray(StructureArrayConstPtr const & structureArray); -private: - StructureArrayConstPtr structureArray; - shared_vector value; - friend class PVDataCreate; -}; - class PVStructure : public PVField, public BitSetSerializable { @@ -1094,10 +990,176 @@ namespace detail { :vec(v) {} void operator()(T*){vec.reset();} }; -} + + template + class PVVectorStorage : public Base + { + public: + typedef T value_type; + typedef T* pointer; + typedef const T* const_pointer; + + //TODO: full namespace can be removed along with local typedef 'shared_vector' + typedef ::epics::pvData::shared_vector svector; + typedef ::epics::pvData::shared_vector const_svector; + + // begin deprecated + typedef PVArrayData ArrayDataType; + typedef std::vector vector; + typedef const std::vector const_vector; + typedef std::tr1::shared_ptr shared_vector; + // end deprecated + + protected: + PVVectorStorage() : Base() {} + + template + PVVectorStorage(A a) : Base(a) {} + public: + virtual ~PVVectorStorage(){}; + + // Primative array manipulations + protected: + //! unchecked reference to writable data + //! Please consider the view() method instead of viewUnsafe(). + virtual const svector& viewUnsafe() const = 0; + public: + + /** Exchange our contents for the provided. + * + @throws std::logic_error for Immutable arrays. + * + * Callers must ensure that postPut() is called + * after the last swap() operation. + * + * Before you call this directly, consider using + * the take(), reuse(), or replace() methods. + */ + virtual void swap(svector& other) = 0; + + //! Discard current contents and replaced with the provided. + //! Fails for Immutable arrays + //! calls postPut() + virtual void replace(const svector& next) + { + svector temp(next); + this->swap(temp); + this->postPut(); + } + + // methods from PVArray + + virtual size_t getLength() const {return viewUnsafe().size();} + virtual size_t getCapacity() const {return viewUnsafe().capacity();} + + // Derived operations + + //! Fetch a read-only view of the current array data + inline const_svector view() const + { + const_svector newref(this->viewUnsafe()); + return newref; + } + + //! Remove and return the current array data + //! Does @b not (and should not) call postPut() + inline svector take() + { + svector result; + this->swap(result); + return result; + } + + //! take() with an implied make_unique() + //! Does @b not (and should not) call postPut() + inline svector reuse() + { + svector result; + this->swap(result); + result.make_unique(); + return result; + } + + /** + * Get array elements + * @param offset The offset of the first element, + * @param length The number of elements to get. + * @param data The place where the data is placed. + */ + std::size_t get( + std::size_t offset, std::size_t length, ArrayDataType &data) USAGE_DEPRECATED + { + const_svector ref = this->view(); + ref.slice(offset, length); + data.data.resize(ref.size()); + data.offset = 0; + std::copy(ref.begin(), ref.end(), data.data.begin()); + return ref.size(); + } + + /** + * Copy data into the array growing the length as needed. + * @param offset The offset of the first element, + * @param length The number of elements to get. + * @param from The new values to put into the array. + * @param fromOffset The offset in from. + * @return The number of elements put into the array. + * calls postPut() + */ + std::size_t put(std::size_t offset, + std::size_t length, const_pointer from, std::size_t fromOffset) USAGE_DEPRECATED + { + from += fromOffset; + + svector temp; + this->swap(temp); + if(temp.size() < length+offset) + temp.resize(length+offset); + else + temp.make_unique(); + + std::copy(from, from + length, temp.begin() + offset); + this->swap(temp); + this->postPut(); + return length; + } + + std::size_t put(std::size_t offset, + std::size_t length, const_vector &from, std::size_t fromOffset) USAGE_DEPRECATED + { return this->put(offset,length, &from[0], fromOffset); } + + /** + * Share data from another source. + * @param value The data to share. + * @param capacity The capacity of the array. + * @param length The length of the array. + * Does @b not call postPut() + */ + void shareData( + shared_vector const & value, + std::size_t capacity, + std::size_t length) USAGE_DEPRECATED + { + vector& vref = *value.get(); + typename svector::shared_pointer_type p(&vref[0], + detail::shared_ptr_vector_deletor(value)); + svector temp(p, 0, std::min(length, vref.size())); + this->swap(temp); + } + + pointer get() const { + return this->viewUnsafe().data(); + } + + vector const & getVector() USAGE_ERROR("No longer implemented. Replace with view()"); + shared_vector const & getSharedVector() USAGE_ERROR("No longer implemented. Replace with view()"); + + }; +} // namespace detail template -class PVValueArray : public PVScalarArray { +class PVValueArray : public detail::PVVectorStorage { + typedef detail::PVVectorStorage base_t; public: POINTER_DEFINITIONS(PVValueArray); typedef T value_type; @@ -1124,141 +1186,10 @@ public: */ virtual ~PVValueArray() {} - // Primative array manipulations -protected: - //! unchecked reference to writable data - //! Please consider the view() method instead of viewUnsafe(). - virtual const svector& viewUnsafe() const = 0; -public: - - /** Exchange our contents for the provided. - * - @throws std::logic_error for Immutable arrays. - * - * Callers must ensure that postPut() is called - * after the last swap() operation. - * - * Before you call this directly, consider using - * the take(), reuse(), or replace() methods. - */ - virtual void swap(svector& other) = 0; - - //! Discard current contents and replaced with the provided. - //! Fails for Immutable arrays - //! calls postPut() - virtual void replace(const svector& next) - { - svector temp(next); - this->swap(temp); - this->postPut(); - } - - // Derived operations - - //! Fetch a read-only view of the current array data - inline const_svector view() const - { - const_svector newref(this->viewUnsafe()); - return newref; - } - - //! Remove and return the current array data - //! Does @b not (and should not) call postPut() - inline svector take() - { - svector result; - this->swap(result); - return result; - } - - //! take() with an implied make_unique() - //! Does @b not (and should not) call postPut() - inline svector reuse() - { - svector result; - this->swap(result); - result.make_unique(); - return result; - } - - /** - * Get array elements - * @param offset The offset of the first element, - * @param length The number of elements to get. - * @param data The place where the data is placed. - */ - std::size_t get( - std::size_t offset, std::size_t length, ArrayDataType &data) USAGE_DEPRECATED - { - const_svector ref = this->view(); - ref.slice(offset, length); - data.data.resize(ref.size()); - data.offset = 0; - std::copy(ref.begin(), ref.end(), data.data.begin()); - return ref.size(); - } - - /** - * Copy data into the array growing the length as needed. - * @param offset The offset of the first element, - * @param length The number of elements to get. - * @param from The new values to put into the array. - * @param fromOffset The offset in from. - * @return The number of elements put into the array. - * calls postPut() - */ - std::size_t put(std::size_t offset, - std::size_t length, const_pointer from, std::size_t fromOffset) USAGE_DEPRECATED - { - from += fromOffset; - - svector temp; - this->swap(temp); - if(temp.size() < length+offset) - temp.resize(length+offset); - else - temp.make_unique(); - - std::copy(from, from + length, temp.begin() + offset); - this->swap(temp); - this->postPut(); - return length; - } - - std::size_t put(std::size_t offset, - std::size_t length, const_vector &from, std::size_t fromOffset) USAGE_DEPRECATED - { return this->put(offset,length, &from[0], fromOffset); } - - /** - * Share data from another source. - * @param value The data to share. - * @param capacity The capacity of the array. - * @param length The length of the array. - * Does @b not call postPut() - */ - void shareData( - shared_vector const & value, - std::size_t capacity, - std::size_t length) USAGE_DEPRECATED - { - vector& vref = *value.get(); - typename svector::shared_pointer_type p(&vref[0], - detail::shared_ptr_vector_deletor(value)); - svector temp(p, 0, std::min(length, vref.size())); - this->swap(temp); - } - - pointer get() const { - return this->viewUnsafe().data(); - } - - vector const & getVector() USAGE_ERROR("No longer implemented. Replace with view()"); - shared_vector const & getSharedVector() USAGE_ERROR("No longer implemented. Replace with view()"); - std::ostream& dumpValue(std::ostream& o) const { o << '['; - std::size_t len = getLength(); + std::size_t len = this->getLength(); bool first = true; for (std::size_t i = 0; i < len; i++) { @@ -1273,13 +1204,13 @@ public: std::ostream& dumpValue(std::ostream& o, size_t index) const { - return o << *(get() + index); + return o << *(this->get() + index); } virtual void getAs(ScalarType id, ::epics::pvData::shared_vector& out) const { - const svector& data(viewUnsafe()); + const svector& data(this->viewUnsafe()); ::epics::pvData::shared_vector temp(static_shared_vector_cast(data)); if(id==typeCode) { out = temp; // no convert = no copy @@ -1295,7 +1226,7 @@ public: virtual size_t copyOut(ScalarType id, void* ptr, size_t olen) const { - const svector& data(viewUnsafe()); + const svector& data(this->viewUnsafe()); size_t len = std::min(olen, data.size()); castUnsafeV(len, id, ptr, typeCode, (const void*)data.data()); @@ -1348,10 +1279,98 @@ public: protected: PVValueArray(ScalarArrayConstPtr const & scalar) - : PVScalarArray(scalar) {} + : base_t(scalar) {} friend class PVDataCreate; }; +/** + * This is provided by code that calls get. + */ +typedef PVArrayData StructureArrayData; + +/** + * Data class for a structureArray + */ +template<> +class PVValueArray : public detail::PVVectorStorage +{ + typedef detail::PVVectorStorage base_t; +public: + POINTER_DEFINITIONS(PVStructureArray); + typedef PVStructurePtr value_type; + typedef PVStructurePtr* pointer; + typedef const PVStructurePtr* const_pointer; + typedef PVArrayData ArrayDataType; + typedef std::vector vector; + typedef const std::vector const_vector; + typedef std::tr1::shared_ptr shared_vector; + typedef PVStructureArray &reference; + typedef const PVStructureArray& const_reference; + + //TODO: full namespace can be removed along with local typedef 'shared_vector' + typedef ::epics::pvData::shared_vector svector; + typedef ::epics::pvData::shared_vector const_svector; + /** + * Destructor + */ + virtual ~PVValueArray() {} + /** + * Set the array capacity. + * @param capacity The length. + */ + virtual void setCapacity(size_t capacity); + /** + * Set the array length. + * @param length The length. + */ + virtual void setLength(std::size_t length); + + /** + * Get the introspection interface + * @return The interface. + */ + StructureArrayConstPtr getStructureArray() const {return structureArray;} + /** + * Append new elements to the end of the array. + * @param number The number of elements to add. + * @return the new length of the array. + */ + virtual std::size_t append(std::size_t number); + /** + * Remove elements from the array. + * @param offset The offset of the first element to remove. + * @param number The number of elements to remove. + * @return (false,true) if the elements were removed. + */ + virtual bool remove(std::size_t offset,std::size_t number); + /** + * Compress. This removes all null elements from the array. + */ + virtual void compress(); + + virtual const svector& viewUnsafe() const { return value; } + virtual void swap(svector &other); + + virtual void serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher) const; + virtual void deserialize(ByteBuffer *buffer, + DeserializableControl *pflusher); + virtual void serialize(ByteBuffer *pbuffer, + SerializableControl *pflusher, std::size_t offset, std::size_t count) const ; + + virtual std::ostream& dumpValue(std::ostream& o) const; + virtual std::ostream& dumpValue(std::ostream& o, std::size_t index) const; + +protected: + PVValueArray(StructureArrayConstPtr const & structureArray) + :base_t(structureArray) + ,structureArray(structureArray) + {} +private: + StructureArrayConstPtr structureArray; + svector value; + friend class PVDataCreate; +}; /** * Definitions for the various scalarArray types.