Files
pvData/src/factory/PVUnionArray.cpp
2014-03-28 10:20:24 -05:00

218 lines
5.0 KiB
C++

/*PVUnionArray.cpp*/
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#define epicsExportSharedSymbols
#include <pv/pvData.h>
#include <pv/convert.h>
#include <pv/factory.h>
#include <pv/serializeHelper.h>
using std::tr1::static_pointer_cast;
using std::size_t;
namespace epics { namespace pvData {
size_t PVUnionArray::append(size_t number)
{
svector data(reuse());
data.resize(data.size()+number);
UnionConstPtr punion = unionArray->getUnion();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(svector::reverse_iterator it = data.rbegin(); number; ++it, --number)
*it = pvDataCreate->createPVUnion(punion);
size_t newLength = data.size();
const_svector cdata(freeze(data));
swap(cdata);
return newLength;
}
bool PVUnionArray::remove(size_t offset,size_t number)
{
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].swap(vec[i + number]);
}
vec.resize(length - number);
const_svector cdata(freeze(vec));
swap(cdata);
return true;
}
void PVUnionArray::compress() {
svector vec(reuse()); // TODO: check for first NULL before realloc
size_t length = vec.size();
size_t newLength = 0;
for(size_t i=0; i<length; i++) {
if(vec[i].get()!=NULL) {
newLength++;
continue;
}
// find first non 0
size_t notNull = 0;
for(size_t j=i+1;j<length;j++) {
if(vec[j].get()!=NULL) {
notNull = j;
break;
}
}
if(notNull!=0) {
vec[i] = vec[notNull];
vec[notNull].reset();
newLength++;
continue;
}
break;
}
vec.resize(newLength);
const_svector cdata(freeze(vec));
swap(cdata);
}
void PVUnionArray::setCapacity(size_t capacity)
{
if(this->isCapacityMutable()) {
const_svector value;
swap(value);
if(value.capacity()<capacity) {
svector mvalue(thaw(value));
mvalue.reserve(capacity);
value = freeze(mvalue);
}
swap(value);
}
}
void PVUnionArray::setLength(size_t length)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
const_svector value;
swap(value);
if(length == value.size()) {
// nothing
} else if(length < value.size()) {
value.slice(0, length);
} else {
svector mvalue(thaw(value));
mvalue.resize(length);
value = freeze(mvalue);
}
swap(value);
}
void PVUnionArray::swap(const_svector &other)
{
if(this->isImmutable())
THROW_EXCEPTION2(std::logic_error,"Immutable");
value.swap(other);
}
void PVUnionArray::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher) const {
serialize(pbuffer, pflusher, 0, getLength());
}
void PVUnionArray::deserialize(ByteBuffer *pbuffer,
DeserializableControl *pcontrol) {
svector data(reuse());
size_t size = SerializeHelper::readSize(pbuffer, pcontrol);
data.resize(size);
UnionConstPtr punion = unionArray->getUnion();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i = 0; i<size; i++) {
pcontrol->ensureData(1);
size_t temp = pbuffer->getByte();
if(temp==0) {
data[i].reset();
}
else {
if(data[i].get()==NULL) {
data[i] = pvDataCreate->createPVUnion(punion);
}
data[i]->deserialize(pbuffer, pcontrol);
}
}
replace(freeze(data)); // calls postPut()
}
void PVUnionArray::serialize(ByteBuffer *pbuffer,
SerializableControl *pflusher, size_t offset, size_t count) const {
const_svector temp(view());
temp.slice(offset, count);
SerializeHelper::writeSize(temp.size(), pbuffer, pflusher);
for(size_t i = 0; i<count; i++) {
if(pbuffer->getRemaining()<1)
pflusher->flushSerializeBuffer();
if(temp[i].get()==NULL) {
pbuffer->putByte(0);
}
else {
pbuffer->putByte(1);
temp[i]->serialize(pbuffer, pflusher);
}
}
}
std::ostream& PVUnionArray::dumpValue(std::ostream& o) const
{
o << format::indent() << getUnionArray()->getID() << ' ' << getFieldName() << std::endl;
size_t length = getLength();
if (length > 0)
{
format::indent_scope s(o);
for (size_t i = 0; i < length; i++)
dumpValue(o, i);
}
return o;
}
std::ostream& PVUnionArray::dumpValue(std::ostream& o, std::size_t index) const
{
const_svector temp(view());
if(index<temp.size())
o << *temp[index];
return o;
}
}}