/*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. */ #ifdef _WIN32 #define NOMINMAX #endif #include #include #include #include #include #include #include #include #include #include #include "DefaultPVStructureArray.h" using std::tr1::static_pointer_cast; using std::tr1::const_pointer_cast; 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); 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(sizeof(T)); pbuffer->put(value); } template void BasePVScalar::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { pflusher->ensureData(sizeof(T)); value = pbuffer->get(); } typedef BasePVScalar BasePVBoolean; typedef BasePVScalar BasePVByte; typedef BasePVScalar BasePVShort; typedef BasePVScalar BasePVInt; typedef BasePVScalar BasePVLong; typedef BasePVScalar BasePVFloat; typedef BasePVScalar BasePVDouble; // BasePVString is special case, since it implements SerializableArray class BasePVString : public PVString { public: typedef String value_type; typedef String* pointer; typedef const String* const_pointer; BasePVString(PVStructure *parent,ScalarConstPtr scalar); virtual ~BasePVString(); virtual String get(); virtual void put(String val); 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; private: String value; }; BasePVString::BasePVString(PVStructure *parent,ScalarConstPtr scalar) : PVString(parent,scalar),value() {} BasePVString::~BasePVString() {} String BasePVString::get() { return value;} void BasePVString::put(String val){value = val;} void BasePVString::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { SerializeHelper::serializeString(value, pbuffer, pflusher); } void BasePVString::deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) { value = SerializeHelper::deserializeString(pbuffer, pflusher); } void BasePVString::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, int offset, int count) const { // check bounds const int length = /*(value == null) ? 0 :*/ value.length(); if (offset < 0) offset = 0; else if (offset > length) offset = length; if (count < 0) count = length; const int maxCount = length - offset; if (count > maxCount) count = maxCount; // write SerializeHelper::serializeSubstring(value, offset, count, pbuffer, pflusher); } /** 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; 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) { pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); } 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, (int)(pbuffer->getRemaining()/sizeof(T)))+i; for(; iget(); */ int maxCount = std::min(size-i, (int)(pbuffer->getRemaining()/sizeof(T))); pbuffer->getArray(&value[i], maxCount); i += maxCount; if(iensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T)); 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); //if (count == 0) return; pcontrol->ensureData(sizeof(T)-1); pbuffer->align(sizeof(T)); int end = offset+count; int i = offset; while(true) { /* int maxIndex = std::min(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i; for(; iput(value[i]); */ int maxCount = std::min(end-i, (int)(pbuffer->getRemaining()/sizeof(T))); pbuffer->putArray(&value[i], maxCount); i += maxCount; if(iflushSerializeBuffer(); else break; } } // 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: { ScalarConstPtr xx = static_pointer_cast(field); return createPVScalar(parent,xx); } case scalarArray: { ScalarArrayConstPtr xx = static_pointer_cast(field); return (PVField *)createPVScalarArray(parent,xx); } case structure: { StructureConstPtr xx = static_pointer_cast(field); return (PVField *)createPVStructure(parent,xx); } case structureArray: { StructureArrayConstPtr xx = static_pointer_cast(field); return createPVStructureArray(parent,xx); } } 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) { 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) { 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 PVStructure(parent,structure); return pvStructure; } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, String fieldName,int numberFields,FieldConstPtrArray fields) { StructureConstPtr structure = fieldCreate->createStructure( fieldName,numberFields, fields); return new PVStructure(parent,structure); } PVStructure *PVDataCreate::createPVStructure(PVStructure *parent, String fieldName,int numberFields,PVFieldPtrArray pvFields) { FieldConstPtrArray fields = new FieldConstPtr[numberFields]; for(int i=0; igetField(); } StructureConstPtr structure = fieldCreate->createStructure( fieldName,numberFields,fields); PVStructure *pvStructure = new PVStructure(parent,structure,pvFields); return pvStructure; } 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 PVStructure(parent,structure); } else { StructureConstPtr structure = structToClone->getStructure(); pvStructure = new PVStructure(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; } }}