Implement PVStructureArray with shared_vector

Combine as much as possible with scalar array handling.

PVStructureArray becomes PVValueArray<shared_ptr<PVStructure> >

Bulk of shared implementation moved the PVVectorStorage
which has a parametrized base to avoid using multiple inheritance.
This commit is contained in:
Michael Davidsaver
2013-06-10 18:47:55 -04:00
parent 4e749cc8be
commit 7f9745c8d1
5 changed files with 374 additions and 480 deletions

View File

@@ -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)

View File

@@ -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)
{

View File

@@ -231,9 +231,8 @@ DefaultPVArray<T>::~DefaultPVArray()
template<typename T>
void DefaultPVArray<T>::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<T>::setLength(size_t length)
value.slice(0, length);
else
value.resize(length);
PVArray::setCapacityLength(value.capacity(), value.size());
}
@@ -265,7 +263,6 @@ void DefaultPVArray<T>::swap(svector &other)
THROW_EXCEPTION2(std::logic_error,"Immutable");
value.swap(other);
PVArray::setCapacityLength(value.capacity(), value.size());
}
@@ -282,7 +279,6 @@ void DefaultPVArray<T>::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<String>::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<size; i++) {

View File

@@ -21,44 +21,51 @@ using std::size_t;
namespace epics { namespace pvData {
PVStructureArray::PVStructureArray(StructureArrayConstPtr const & structureArray)
: PVArray(structureArray),
structureArray(structureArray),
value(std::tr1::shared_ptr<PVStructurePtrArray>(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; i<newLength; i++) {
(*to)[i] =getPVDataCreate()->createPVStructure(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; i<length; i++) {
if(vec[i].get()!=NULL) {
newLength++;
@@ -80,113 +87,43 @@ void PVStructureArray::compress() {
}
break;
}
setCapacityLength(newLength,newLength);
vec.resize(newLength);
swap(vec);
}
void PVStructureArray::setCapacity(size_t capacity) {
if(getCapacity()==capacity) return;
if(!isCapacityMutable()) {
std::string message("not capacityMutable");
PVField::message(message, errorMessage);
return;
void PVStructureArray::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
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; i<length; i++) array[i] = from[i];
value->swap(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; i<len; i++) {
PVStructurePtr frompv = from[i+fromOffset];
if(frompv.get()!=NULL) {
if(frompv->getStructure()!=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<std::vector<PVStructurePtr> > 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; i<size; i++) {
pcontrol->ensureData(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; i<size; i++) {
pcontrol->ensureData(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; i<count; i++) {
if(pbuffer->getRemaining()<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<temp.size())
o << temp[index].get();
return o;
}

View File

@@ -102,7 +102,9 @@ class PVScalar;
class PVScalarArray;
class PVStructure;
class PVStructureArray;
template<typename T> class PVValueArray;
/**
* typedef for a pointer to a PVAuxInfo.
@@ -149,6 +151,8 @@ typedef std::vector<PVStructurePtr>::const_iterator PVStructurePtrArray_const__i
/**
* typedef for a pointer to a PVStructureArray.
*/
typedef PVValueArray<PVStructurePtr> PVStructureArray;
typedef std::tr1::shared_ptr<PVStructureArray> PVStructureArrayPtr;
typedef std::vector<PVStructureArrayPtr> PVStructureArrayPtrArray;
typedef std::tr1::shared_ptr<PVStructureArrayPtrArray> 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<PVStructurePtr> 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<PVStructurePtr> ArrayDataType;
typedef std::vector<PVStructurePtr> vector;
typedef const std::vector<PVStructurePtr> const_vector;
typedef std::tr1::shared_ptr<vector> 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<typename T, class Base>
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<T> svector;
typedef ::epics::pvData::shared_vector<const T> const_svector;
// begin deprecated
typedef PVArrayData<T> ArrayDataType;
typedef std::vector<T> vector;
typedef const std::vector<T> const_vector;
typedef std::tr1::shared_ptr<vector> shared_vector;
// end deprecated
protected:
PVVectorStorage() : Base() {}
template<typename A>
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<T>(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<typename T>
class PVValueArray : public PVScalarArray {
class PVValueArray : public detail::PVVectorStorage<T,PVScalarArray> {
typedef detail::PVVectorStorage<T,PVScalarArray> 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<T>(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<void>& out) const
{
const svector& data(viewUnsafe());
const svector& data(this->viewUnsafe());
::epics::pvData::shared_vector<void> temp(static_shared_vector_cast<void>(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<PVStructurePtr> StructureArrayData;
/**
* Data class for a structureArray
*/
template<>
class PVValueArray<PVStructurePtr> : public detail::PVVectorStorage<PVStructurePtr,PVArray>
{
typedef detail::PVVectorStorage<PVStructurePtr,PVArray> base_t;
public:
POINTER_DEFINITIONS(PVStructureArray);
typedef PVStructurePtr value_type;
typedef PVStructurePtr* pointer;
typedef const PVStructurePtr* const_pointer;
typedef PVArrayData<PVStructurePtr> ArrayDataType;
typedef std::vector<PVStructurePtr> vector;
typedef const std::vector<PVStructurePtr> const_vector;
typedef std::tr1::shared_ptr<vector> 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<PVStructurePtr> svector;
typedef ::epics::pvData::shared_vector<const PVStructurePtr> 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.