/*PVDataCreateFactory.cpp*/ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvDataCPP is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ #include #include #include #include #include "lock.h" #include "pvIntrospect.h" #include "pvData.h" #include "convert.h" #include "factory.h" #include "PVField.cpp" #include "PVScalar.cpp" #include "PVArray.cpp" #include "PVScalarArray.cpp" #include "PVStructure.cpp" #include "DefaultPVStructureArray.cpp" namespace epics { namespace pvData { static Convert* convert = 0; static FieldCreate * fieldCreate = 0; static PVDataCreate* pvDataCreate = 0; /** Default storage for scalar values */ template class BasePVScalar : public PVScalarValue { public: typedef T value_type; typedef T* pointer; typedef const T* const_pointer; BasePVScalar(PVStructure *parent,ScalarConstPtr scalar); virtual ~BasePVScalar(); virtual T get(); virtual void put(T val); virtual void serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher); virtual bool operator==(PVField& pv) ; virtual bool operator!=(PVField& pv) ; private: T value; }; template BasePVScalar::BasePVScalar(PVStructure *parent,ScalarConstPtr scalar) : PVScalarValue(parent,scalar),value(0) {} //Note: '0' is a suitable default for all POD types (not String) template BasePVScalar::~BasePVScalar() {} template T BasePVScalar::get() { return value;} template void BasePVScalar::put(T val){value = val;} template void BasePVScalar::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { pflusher->ensureBuffer(1); pbuffer->put(value); } template void BasePVScalar::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { pflusher->ensureData(1); value = pbuffer->get(); } template bool BasePVScalar::operator==(PVField& pvField) { return getConvert()->equals(this, &pvField); } template bool BasePVScalar::operator!=(PVField& pvField) { return !(getConvert()->equals(this, &pvField)); } // Specializations for scalar String template<> BasePVScalar::BasePVScalar(PVStructure *parent,ScalarConstPtr scalar) : PVScalarValue(parent,scalar),value() {} template<> void BasePVScalar::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { SerializeHelper::serializeString(value, pbuffer, pflusher); } template<> void BasePVScalar::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { value = SerializeHelper::deserializeString(pbuffer, pflusher); } typedef BasePVScalar BasePVBoolean; typedef BasePVScalar BasePVByte; typedef BasePVScalar BasePVShort; typedef BasePVScalar BasePVInt; typedef BasePVScalar BasePVLong; typedef BasePVScalar BasePVFloat; typedef BasePVScalar BasePVDouble; typedef BasePVScalar BasePVString; /** Default storage for arrays */ template class DefaultPVArray : public PVValueArray { public: typedef T value_type; typedef T* pointer; typedef const T* const_pointer; DefaultPVArray(PVStructure *parent,ScalarArrayConstPtr scalarArray); virtual ~DefaultPVArray(); virtual void setCapacity(int capacity); virtual int get(int offset, int length, PVArrayData *data) ; virtual int put(int offset,int length, pointer from, int fromOffset); virtual void shareData(pointer value,int capacity,int length); // from Serializable virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher); virtual void serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, int offset, int count) const; virtual bool operator==(PVField& pv) ; virtual bool operator!=(PVField& pv) ; private: pointer value; }; template DefaultPVArray::DefaultPVArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) : PVValueArray(parent,scalarArray),value(new T[0]) { } template DefaultPVArray::~DefaultPVArray() { delete[] value; } template void DefaultPVArray::setCapacity(int capacity) { if(PVArray::getCapacity()==capacity) return; if(!PVArray::isCapacityMutable()) { std::string message("not capacityMutable"); PVField::message(message, errorMessage); return; } int length = PVArray::getLength(); if(length>capacity) length = capacity; T *newValue = new T[capacity]; for(int i=0; i int DefaultPVArray::get(int offset, int len, PVArrayData *data) { int n = len; int length = this->getLength(); if(offset+len > length) { n = length-offset; if(n<0) n = 0; } data->data = value; data->offset = offset; return n; } template int DefaultPVArray::put(int offset,int len, pointer from,int fromOffset) { if(PVField::isImmutable()) { PVField::message("field is immutable",errorMessage); return 0; } if(from==value) return len; if(len<1) return 0; int length = this->getLength(); int capacity = this->getCapacity(); if(offset+len > length) { int newlength = offset + len; if(newlength>capacity) { setCapacity(newlength); newlength = this->getCapacity(); len = newlength - offset; if(len<=0) return 0; } length = newlength; } for(int i=0;isetLength(length); this->postPut(); return len; } template void DefaultPVArray::shareData(pointer shareValue,int capacity,int length) { delete[] value; value = shareValue; PVArray::setCapacityLength(capacity,length); } template void DefaultPVArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { serialize(pbuffer, pflusher, 0, this->getLength()); } template void DefaultPVArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { int size = SerializeHelper::readSize(pbuffer, pcontrol); if(size>=0) { // prepare array, if necessary if(size>this->getCapacity()) this->setCapacity(size); // retrieve value from the buffer int i = 0; while(true) { int maxIndex = std::min(size-i, pbuffer->getRemaining())+i; for(; iget(); if(iensureData(1); // // TODO is there a better way to ensureData? else break; } // set new length this->setLength(size); PVField::postPut(); } // TODO null arrays (size == -1) not supported } template void DefaultPVArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, int offset, int count) const { // cache int length = this->getLength(); // check bounds if(offset<0) offset = 0; else if(offset>length) offset = length; if(count<0) count = length; int maxCount = length-offset; if(count>maxCount) count = maxCount; // write SerializeHelper::writeSize(count, pbuffer, pflusher); int end = offset+count; int i = offset; while(true) { int maxIndex = std::min(end-i, pbuffer->getRemaining())+i; for(; iput(value[i]); if(iflushSerializeBuffer(); else break; } } template bool DefaultPVArray::operator==(PVField& pv) { return getConvert()->equals(this, &pv); } template bool DefaultPVArray::operator!=(PVField& pv) { return !(getConvert()->equals(this, &pv)); } // specializations for String template<> void DefaultPVArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { int size = SerializeHelper::readSize(pbuffer, pcontrol); if(size>=0) { // prepare array, if necessary if(size>getCapacity()) setCapacity(size); // retrieve value from the buffer for(int i = 0; i void DefaultPVArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, int offset, int count) const { int length = getLength(); // check bounds if(offset<0) offset = 0; else if(offset>length) offset = length; if(count<0) count = length; int maxCount = length-offset; if(count>maxCount) count = maxCount; // write SerializeHelper::writeSize(count, pbuffer, pflusher); int end = offset+count; for(int i = offset; i DefaultPVBooleanArray; typedef DefaultPVArray BasePVByteArray; typedef DefaultPVArray BasePVShortArray; typedef DefaultPVArray BasePVIntArray; typedef DefaultPVArray BasePVLongArray; typedef DefaultPVArray BasePVFloatArray; typedef DefaultPVArray BasePVDoubleArray; typedef DefaultPVArray BasePVStringArray; // Factory PVDataCreate::PVDataCreate(){ } PVField *PVDataCreate::createPVField(PVStructure *parent, FieldConstPtr field) { switch(field->getType()) { case scalar: return createPVScalar(parent,(ScalarConstPtr)field); case scalarArray: return (PVField *)createPVScalarArray(parent, (ScalarArrayConstPtr)field); case structure: return (PVField *)createPVStructure(parent, (StructureConstPtr)field); case structureArray: return createPVStructureArray(parent, (StructureArrayConstPtr)field); } String message("PVDataCreate::createPVField should never get here"); throw std::logic_error(message); } PVField *PVDataCreate::createPVField(PVStructure *parent, String fieldName,PVField * fieldToClone) { switch(fieldToClone->getField()->getType()) { case scalar: return createPVScalar(parent,fieldName,(PVScalar*)fieldToClone); case scalarArray: return (PVField *)createPVScalarArray(parent,fieldName, (PVScalarArray *)fieldToClone); case structure: return (PVField *)createPVStructure(parent,fieldName, (PVStructure *)fieldToClone); case structureArray: String message( "PVDataCreate::createPVField structureArray not valid fieldToClone"); throw std::invalid_argument(message); } String message("PVDataCreate::createPVField should never get here"); throw std::logic_error(message); } PVScalar *PVDataCreate::createPVScalar(PVStructure *parent,ScalarConstPtr scalar) { ScalarType scalarType = scalar->getScalarType(); switch(scalarType) { case pvBoolean: return new BasePVBoolean(parent,scalar); case pvByte: return new BasePVByte(parent,scalar); case pvShort: return new BasePVShort(parent,scalar); case pvInt: return new BasePVInt(parent,scalar); case pvLong: return new BasePVLong(parent,scalar); case pvFloat: return new BasePVFloat(parent,scalar); case pvDouble: return new BasePVDouble(parent,scalar); case pvString: return new BasePVString(parent,scalar); } String message("PVDataCreate::createPVScalar should never get here"); throw std::logic_error(message); } PVScalar *PVDataCreate::createPVScalar(PVStructure *parent, String fieldName,ScalarType scalarType) { ScalarConstPtr scalar = fieldCreate->createScalar(fieldName,scalarType); return createPVScalar(parent,scalar); } PVScalar *PVDataCreate::createPVScalar(PVStructure *parent, String fieldName,PVScalar * scalarToClone) { scalarToClone->getField()->incReferenceCount(); PVScalar *pvScalar = createPVScalar(parent,fieldName, scalarToClone->getScalar()->getScalarType()); convert->copyScalar(scalarToClone, pvScalar); PVAuxInfo *from = scalarToClone->getPVAuxInfo(); PVAuxInfo *to = pvScalar->getPVAuxInfo(); int numberInfo = from->getNumberInfo(); for(int i=0; igetInfo(i); ScalarConstPtr scalar = pvFrom->getScalar(); PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType()); convert->copyScalar(pvFrom,pvTo); } return pvScalar; } PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent, ScalarArrayConstPtr scalarArray) { switch(scalarArray->getElementType()) { case pvBoolean: return new DefaultPVBooleanArray(parent,scalarArray); case pvByte: return new BasePVByteArray(parent,scalarArray); case pvShort: return new BasePVShortArray(parent,scalarArray); case pvInt: return new BasePVIntArray(parent,scalarArray); case pvLong: return new BasePVLongArray(parent,scalarArray); case pvFloat: return new BasePVFloatArray(parent,scalarArray); case pvDouble: return new BasePVDoubleArray(parent,scalarArray); case pvString: return new BasePVStringArray(parent,scalarArray); } String message("PVDataCreate::createPVScalarArray should never get here"); throw std::logic_error(message); } PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent, String fieldName,ScalarType elementType) { return createPVScalarArray(parent, fieldCreate->createScalarArray(fieldName, elementType)); } PVScalarArray *PVDataCreate::createPVScalarArray(PVStructure *parent, String fieldName,PVScalarArray * arrayToClone) { arrayToClone->getField()->incReferenceCount(); PVScalarArray *pvArray = createPVScalarArray(parent,fieldName, arrayToClone->getScalarArray()->getElementType()); convert->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength()); PVAuxInfo *from = arrayToClone->getPVAuxInfo(); PVAuxInfo *to = pvArray->getPVAuxInfo(); int numberInfo = from->getNumberInfo(); for(int i=0; igetInfo(i); ScalarConstPtr scalar = pvFrom->getScalar(); PVScalar *pvTo = to->createInfo(scalar->getFieldName(),scalar->getScalarType()); convert->copyScalar(pvFrom,pvTo); } return pvArray; } PVStructureArray *PVDataCreate::createPVStructureArray(PVStructure *parent, StructureArrayConstPtr structureArray) { return new BasePVStructureArray(parent,structureArray); } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, StructureConstPtr structure) { PVStructure *pvStructure = new BasePVStructure(parent,structure); return pvStructure; } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, String fieldName,int numberFields,FieldConstPtrArray fields) { StructureConstPtr structure = fieldCreate->createStructure( fieldName,numberFields, fields); return new BasePVStructure(parent,structure); } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, String fieldName,PVStructure *structToClone) { FieldConstPtrArray fields = 0; int numberFields = 0; PVStructure *pvStructure = 0;; if(structToClone==0) { fields = new FieldConstPtr[0]; StructureConstPtr structure = fieldCreate->createStructure( fieldName,numberFields,fields); pvStructure = new BasePVStructure(parent,structure); } else { StructureConstPtr structure = structToClone->getStructure(); structure->incReferenceCount(); pvStructure = new BasePVStructure(parent,structure); convert->copyStructure(structToClone,pvStructure); } return pvStructure; } PVDataCreate * getPVDataCreate() { static Mutex mutex; Lock xx(&mutex); if(pvDataCreate==0){ pvDataCreate = new PVDataCreate(); convert = getConvert(); fieldCreate = getFieldCreate(); } return pvDataCreate; } }}