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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user