/*PVDataCreateFactory.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 */ #ifdef _WIN32 #define NOMINMAX #endif #include #include #include #include #include #include #include #include #include #include using std::tr1::static_pointer_cast; using std::size_t; using std::min; namespace epics { namespace pvData { static Convert* convert = 0; static FieldCreate * fieldCreate = 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(ScalarConstPtr const & scalar); virtual ~BasePVScalar(); virtual T get() const ; 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(ScalarConstPtr const & scalar) : PVScalarValue(scalar),value(0) {} //Note: '0' is a suitable default for all POD types (not String) template BasePVScalar::~BasePVScalar() {} template T BasePVScalar::get() const { 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(T); } typedef BasePVScalar BasePVBoolean; typedef BasePVScalar BasePVByte; typedef BasePVScalar BasePVShort; typedef BasePVScalar BasePVInt; typedef BasePVScalar BasePVLong; typedef BasePVScalar BasePVUByte; typedef BasePVScalar BasePVUShort; typedef BasePVScalar BasePVUInt; typedef BasePVScalar BasePVULong; 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(ScalarConstPtr const & scalar); virtual ~BasePVString(); virtual String get() const ; 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, size_t offset, size_t count) const; private: String value; }; BasePVString::BasePVString(ScalarConstPtr const & scalar) : PVString(scalar),value() {} BasePVString::~BasePVString() {} String BasePVString::get() const { 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, size_t offset, size_t count) const { // check bounds const size_t length = /*(value == null) ? 0 :*/ value.length(); if (offset < 0) offset = 0; else if (offset > length) offset = length; if (count < 0) count = length; const size_t 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* pointer; typedef const T* const_pointer; typedef std::vector vector; typedef const std::vector const_vector; typedef std::tr1::shared_ptr shared_vector; DefaultPVArray(ScalarArrayConstPtr const & scalarArray); virtual ~DefaultPVArray(); virtual void setCapacity(size_t capacity); virtual void setLength(size_t length); virtual size_t get(size_t offset, size_t length, PVArrayData &data) ; virtual size_t put(size_t offset,size_t length, const_pointer from, size_t fromOffset); virtual void shareData( std::tr1::shared_ptr > const & value, std::size_t capacity, std::size_t length); virtual pointer get() ; virtual pointer get() const ; virtual vector const & getVector() { return *value.get(); } virtual shared_vector const & getSharedVector(){return value;}; // from Serializable virtual void serialize(ByteBuffer *pbuffer,SerializableControl *pflusher) const; virtual void deserialize(ByteBuffer *pbuffer,DeserializableControl *pflusher); virtual void serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const; private: shared_vector value; }; template T *DefaultPVArray::get() { std::vector *vec = value.get(); T *praw = &((*vec)[0]); return praw; } template T *DefaultPVArray::get() const { std::vector *vec = value.get(); T *praw = &((*vec)[0]); return praw; } template DefaultPVArray::DefaultPVArray(ScalarArrayConstPtr const & scalarArray) : PVValueArray(scalarArray), value(std::tr1::shared_ptr >(new std::vector())) { } template DefaultPVArray::~DefaultPVArray() { } template void DefaultPVArray::setCapacity(size_t capacity) { if(PVArray::getCapacity()==capacity) return; if(!PVArray::isCapacityMutable()) { std::string message("not capacityMutable"); PVField::message(message, errorMessage); return; } size_t length = PVArray::getLength(); if(length>capacity) length = capacity; size_t oldCapacity = PVArray::getCapacity(); if(oldCapacity>capacity) { std::vector array; array.reserve(capacity); array.resize(length); T * from = get(); for (size_t i=0; iswap(array); } else { value->reserve(capacity); } PVArray::setCapacityLength(capacity,length); } template void DefaultPVArray::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); } template size_t DefaultPVArray::get(size_t offset, size_t len, PVArrayData &data) { size_t n = len; size_t length = this->getLength(); if(offset+len > length) { n = length-offset; if(n<0) n = 0; } data.data = *value.get(); data.offset = offset; return n; } template size_t DefaultPVArray::put(size_t offset,size_t len, const_pointer from,size_t fromOffset) { if(PVField::isImmutable()) { PVField::message("field is immutable",errorMessage); return 0; } T * pvalue = get(); if(from==pvalue) return len; if(len<1) return 0; size_t length = this->getLength(); size_t capacity = this->getCapacity(); if(offset+len > length) { size_t newlength = offset + len; if(newlength>capacity) { setCapacity(newlength); newlength = this->getCapacity(); len = newlength - offset; if(len<=0) return 0; } length = newlength; setLength(length); } pvalue = get(); for(size_t i=0;isetLength(length); this->postPut(); return len; } template void DefaultPVArray::shareData( std::tr1::shared_ptr > const & sharedValue, std::size_t capacity, std::size_t length) { value = sharedValue; 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) { size_t 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); // set new length this->setLength(size); // retrieve value from the buffer size_t i = 0; while(true) { /* size_t maxIndex = min(size-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i; for(; iget(); */ size_t maxCount = min(size-i, (pbuffer->getRemaining()/sizeof(T))); pbuffer->getArray(get()+i, maxCount); i += maxCount; if(iensureData(sizeof(T)); // this is not OK since can exceen max local buffer (size-i)*sizeof(T)); else break; } // inform about the change? PVField::postPut(); } // TODO null arrays (size == -1) not supported } template void DefaultPVArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { // cache size_t length = this->getLength(); // check bounds if(offset<0) offset = 0; else if(offset>length) offset = length; if(count<0) count = length; size_t 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)); size_t end = offset+count; size_t i = offset; while(true) { /* size_t maxIndex = min(end-i, (int)(pbuffer->getRemaining()/sizeof(T)))+i; for(; iput(value[i]); */ size_t maxCount = min(end-i, (int)(pbuffer->getRemaining()/sizeof(T))); T * pvalue = const_cast(get()); pbuffer->putArray(pvalue+i, maxCount); i += maxCount; if(iflushSerializeBuffer(); else break; } } // specializations for String template<> void DefaultPVArray::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { size_t size = SerializeHelper::readSize(pbuffer, pcontrol); if(size>=0) { // prepare array, if necessary if(size>getCapacity()) setCapacity(size); // set new length setLength(size); // retrieve value from the buffer String * pvalue = get(); for(size_t i = 0; i void DefaultPVArray::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, size_t offset, size_t count) const { size_t length = getLength(); // check bounds if(offset<0) offset = 0; else if(offset>length) offset = length; if(count<0) count = length; size_t maxCount = length-offset; if(count>maxCount) count = maxCount; // write SerializeHelper::writeSize(count, pbuffer, pflusher); size_t end = offset+count; String * pvalue = get(); for(size_t i = offset; i DefaultPVBooleanArray; typedef DefaultPVArray BasePVByteArray; typedef DefaultPVArray BasePVShortArray; typedef DefaultPVArray BasePVIntArray; typedef DefaultPVArray BasePVLongArray; typedef DefaultPVArray BasePVUByteArray; typedef DefaultPVArray BasePVUShortArray; typedef DefaultPVArray BasePVUIntArray; typedef DefaultPVArray BasePVULongArray; typedef DefaultPVArray BasePVFloatArray; typedef DefaultPVArray BasePVDoubleArray; typedef DefaultPVArray BasePVStringArray; // Factory PVDataCreate::PVDataCreate(){ } PVFieldPtr PVDataCreate::createPVField(FieldConstPtr const & field) { switch(field->getType()) { case scalar: { ScalarConstPtr xx = static_pointer_cast(field); return createPVScalar(xx); } case scalarArray: { ScalarArrayConstPtr xx = static_pointer_cast(field); return createPVScalarArray(xx); } case structure: { StructureConstPtr xx = static_pointer_cast(field); return createPVStructure(xx); } case structureArray: { StructureArrayConstPtr xx = static_pointer_cast(field); return createPVStructureArray(xx); } } throw std::logic_error("PVDataCreate::createPVField should never get here"); } PVFieldPtr PVDataCreate::createPVField(PVFieldPtr const & fieldToClone) { switch(fieldToClone->getField()->getType()) { case scalar: { PVScalarPtr pvScalar = static_pointer_cast(fieldToClone); return createPVScalar(pvScalar); } case scalarArray: { PVScalarArrayPtr pvScalarArray = static_pointer_cast(fieldToClone); return createPVScalarArray(pvScalarArray); } case structure: { PVStructurePtr pvStructure = static_pointer_cast(fieldToClone); StringArray fieldNames = pvStructure->getStructure()->getFieldNames(); PVFieldPtrArray pvFieldPtrArray = pvStructure->getPVFields(); return createPVStructure(fieldNames,pvFieldPtrArray); } case structureArray: { PVStructureArrayPtr from = static_pointer_cast(fieldToClone); StructureArrayConstPtr structureArray = from->getStructureArray(); PVStructureArrayPtr to = createPVStructureArray( structureArray); convert->copyStructureArray(from, to); return to; } } throw std::logic_error("PVDataCreate::createPVField should never get here"); } PVScalarPtr PVDataCreate::createPVScalar(ScalarConstPtr const & scalar) { ScalarType scalarType = scalar->getScalarType(); switch(scalarType) { case pvBoolean: return PVScalarPtr(new BasePVBoolean(scalar)); case pvByte: return PVScalarPtr(new BasePVByte(scalar)); case pvShort: return PVScalarPtr(new BasePVShort(scalar)); case pvInt: return PVScalarPtr(new BasePVInt(scalar)); case pvLong: return PVScalarPtr(new BasePVLong(scalar)); case pvUByte: return PVScalarPtr(new BasePVUByte(scalar)); case pvUShort: return PVScalarPtr(new BasePVUShort(scalar)); case pvUInt: return PVScalarPtr(new BasePVUInt(scalar)); case pvULong: return PVScalarPtr(new BasePVULong(scalar)); case pvFloat: return PVScalarPtr(new BasePVFloat(scalar)); case pvDouble: return PVScalarPtr(new BasePVDouble(scalar)); case pvString: return PVScalarPtr(new BasePVString(scalar)); } throw std::logic_error("PVDataCreate::createPVScalar should never get here"); } PVScalarPtr PVDataCreate::createPVScalar(ScalarType scalarType) { ScalarConstPtr scalar = fieldCreate->createScalar(scalarType); return createPVScalar(scalar); } PVScalarPtr PVDataCreate::createPVScalar(PVScalarPtr const & scalarToClone) { ScalarType scalarType = scalarToClone->getScalar()->getScalarType(); PVScalarPtr pvScalar = createPVScalar(scalarType); convert->copyScalar(scalarToClone, pvScalar); PVAuxInfoPtr from = scalarToClone->getPVAuxInfo(); PVAuxInfoPtr to = pvScalar->getPVAuxInfo(); PVAuxInfo::PVInfoMap & map = from->getInfoMap(); for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) { String key = iter->first; PVScalarPtr pvFrom = iter->second; ScalarConstPtr scalar = pvFrom->getScalar(); PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType()); convert->copyScalar(pvFrom,pvTo); } return pvScalar; } PVScalarArrayPtr PVDataCreate::createPVScalarArray( ScalarArrayConstPtr const & scalarArray) { switch(scalarArray->getElementType()) { case pvBoolean: return PVScalarArrayPtr(new DefaultPVBooleanArray(scalarArray)); case pvByte: return PVScalarArrayPtr(new BasePVByteArray(scalarArray)); case pvShort: return PVScalarArrayPtr(new BasePVShortArray(scalarArray)); case pvInt: return PVScalarArrayPtr(new BasePVIntArray(scalarArray)); case pvLong: return PVScalarArrayPtr(new BasePVLongArray(scalarArray)); case pvUByte: return PVScalarArrayPtr(new BasePVUByteArray(scalarArray)); case pvUShort: return PVScalarArrayPtr(new BasePVUShortArray(scalarArray)); case pvUInt: return PVScalarArrayPtr(new BasePVUIntArray(scalarArray)); case pvULong: return PVScalarArrayPtr(new BasePVULongArray(scalarArray)); case pvFloat: return PVScalarArrayPtr(new BasePVFloatArray(scalarArray)); case pvDouble: return PVScalarArrayPtr(new BasePVDoubleArray(scalarArray)); case pvString: return PVScalarArrayPtr(new BasePVStringArray(scalarArray)); } throw std::logic_error("PVDataCreate::createPVScalarArray should never get here"); } PVScalarArrayPtr PVDataCreate::createPVScalarArray( ScalarType elementType) { ScalarArrayConstPtr scalarArray = fieldCreate->createScalarArray(elementType); return createPVScalarArray(scalarArray); } PVScalarArrayPtr PVDataCreate::createPVScalarArray( PVScalarArrayPtr const & arrayToClone) { PVScalarArrayPtr pvArray = createPVScalarArray( arrayToClone->getScalarArray()->getElementType()); convert->copyScalarArray(arrayToClone,0, pvArray,0,arrayToClone->getLength()); PVAuxInfoPtr from = arrayToClone->getPVAuxInfo(); PVAuxInfoPtr to = pvArray->getPVAuxInfo(); PVAuxInfo::PVInfoMap & map = from->getInfoMap(); for(PVAuxInfo::PVInfoIter iter = map.begin(); iter!= map.end(); ++iter) { String key = iter->first; PVScalarPtr pvFrom = iter->second; ScalarConstPtr scalar = pvFrom->getScalar(); PVScalarPtr pvTo = to->createInfo(key,scalar->getScalarType()); convert->copyScalar(pvFrom,pvTo); } return pvArray; } PVStructureArrayPtr PVDataCreate::createPVStructureArray( StructureArrayConstPtr const & structureArray) { return PVStructureArrayPtr(new PVStructureArray(structureArray)); } PVStructurePtr PVDataCreate::createPVStructure( StructureConstPtr const & structure) { return PVStructurePtr(new PVStructure(structure)); } PVStructurePtr PVDataCreate::createPVStructure( StringArray const & fieldNames,PVFieldPtrArray const & pvFields) { size_t num = fieldNames.size(); FieldConstPtrArray fields(num); for (size_t i=0;igetField(); StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields); PVStructurePtr pvStructure(new PVStructure(structure,pvFields)); return pvStructure; } PVStructurePtr PVDataCreate::createPVStructure(PVStructurePtr const & structToClone) { FieldConstPtrArray field; if(structToClone==0) { FieldConstPtrArray fields(0); StringArray fieldNames(0); StructureConstPtr structure = fieldCreate->createStructure(fieldNames,fields); return PVStructurePtr(new PVStructure(structure)); } StructureConstPtr structure = structToClone->getStructure(); PVStructurePtr pvStructure(new PVStructure(structure)); convert->copyStructure(structToClone,pvStructure); return pvStructure; } PVDataCreatePtr PVDataCreate::getPVDataCreate() { static PVDataCreatePtr pvDataCreate; static Mutex mutex; Lock xx(mutex); if(pvDataCreate.get()==0) pvDataCreate = PVDataCreatePtr(new PVDataCreate()); return pvDataCreate; } PVDataCreatePtr getPVDataCreate() { return PVDataCreate::getPVDataCreate(); } }}