/*PVStructure.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 #include #include #include #include #include using std::tr1::static_pointer_cast; using std::tr1::const_pointer_cast; using std::size_t; namespace epics { namespace pvData { static PVFieldPtr nullPVField; static PVBooleanPtr nullPVBoolean; static PVBytePtr nullPVByte; static PVShortPtr nullPVShort; static PVIntPtr nullPVInt; static PVLongPtr nullPVLong; static PVUBytePtr nullPVUByte; static PVUShortPtr nullPVUShort; static PVUIntPtr nullPVUInt; static PVULongPtr nullPVULong; static PVFloatPtr nullPVFloat; static PVDoublePtr nullPVDouble; static PVStringPtr nullPVString; static PVStructurePtr nullPVStructure; static PVStructureArrayPtr nullPVStructureArray; static PVScalarArrayPtr nullPVScalarArray; static PVFieldPtr findSubField(String fieldName,PVStructure *pvStructure); PVStructure::PVStructure(StructureConstPtr& structurePtr) : PVField(structurePtr), structurePtr(structurePtr), extendsStructureName("") { size_t numberFields = structurePtr->getNumberFields(); FieldConstPtrArray fields = structurePtr->getFields(); StringArray fieldNames = structurePtr->getFieldNames(); pvFields.reserve(numberFields); PVDataCreatePtr pvDataCreate = getPVDataCreate(); for(size_t i=0; icreatePVField(fields[i])); } for(size_t i=0; isetParentAndName(this,fieldNames[i]); } } PVStructure::PVStructure(StructureConstPtr structurePtr, PVFieldPtrArray & pvs ) : PVField(structurePtr), structurePtr(structurePtr), extendsStructureName("") { size_t numberFields = structurePtr->getNumberFields(); StringArray fieldNames = structurePtr->getFieldNames(); pvFields = pvs; for(size_t i=0; isetParentAndName(this,fieldNames[i]); } } PVStructure::~PVStructure() { } StructureConstPtr &PVStructure::getStructure() { return structurePtr; } PVFieldPtrArray & PVStructure::getPVFields() { return pvFields; } PVFieldPtr PVStructure::getSubField(String fieldName) { return findSubField(fieldName,this); } PVFieldPtr PVStructure::getSubField(size_t fieldOffset) { if(fieldOffset<=getFieldOffset()) { return nullPVField; } if(fieldOffset>getNextFieldOffset()) return nullPVField; size_t numFields = pvFields.size(); for(size_t i=0; igetFieldOffset()==fieldOffset) return pvFields[i]; if(pvField->getNextFieldOffset()<=fieldOffset) continue; if(pvField->getField()->getType()==structure) { PVStructure *pvStructure = static_cast(pvField.get()); return pvStructure->getSubField(fieldOffset); } } throw std::logic_error("PVStructure.getSubField: Logic error"); } void PVStructure::appendPVField(String fieldName,PVFieldPtr & pvField ) { size_t origLength = pvFields.size(); size_t newLength = origLength+1; PVFieldPtrArray newPVFields; newPVFields.reserve(newLength); for(size_t i=0; iappendField(structurePtr,fieldName,pvField->getField()); replaceField(field); structurePtr = static_pointer_cast(field); StringArray fieldNames = structurePtr->getFieldNames(); for(size_t i=0; isetParentAndName(this,fieldNames[i]); } } void PVStructure::appendPVFields(StringArray &fieldNames,PVFieldPtrArray &pvFields) { size_t origLength = this->pvFields.size(); size_t extra = fieldNames.size(); if(extra==0) return; size_t newLength = origLength + extra; PVFieldPtrArray newPVFields; newPVFields.reserve(newLength); for(size_t i=0; ipvFields[i]); } for(size_t i=0; ipvFields.swap(newPVFields); FieldConstPtrArray fields; fields.reserve(extra); for(size_t i=0; igetField()); FieldConstPtr field = getFieldCreate()->appendFields(structurePtr,fieldNames,fields); replaceField(field); structurePtr = static_pointer_cast(field); StringArray names = structurePtr->getFieldNames(); for(size_t i=0; isetParentAndName(this,names[i]); } } void PVStructure::removePVField(String fieldName) { PVFieldPtr pvField = getSubField(fieldName); if(pvField.get()==NULL) { String message("removePVField "); message += fieldName + " does not exist"; this->message(message, errorMessage); return; } size_t origLength = pvFields.size(); size_t newLength = origLength - 1; PVFieldPtrArray const & origPVFields = pvFields; FieldConstPtrArray origFields = structurePtr->getFields(); PVFieldPtrArray newPVFields; newPVFields.reserve(newLength); StringArray newFieldNames; newFieldNames.reserve(newLength); FieldConstPtrArray fields; fields.reserve(newLength); for(size_t i=0; igetFieldName()); newPVFields.push_back(origPVFields[i]); fields.push_back(origFields[i]); } } pvFields.swap(newPVFields); FieldConstPtr field = getFieldCreate()->createStructure(newFieldNames,fields); replaceField(field); structurePtr = static_pointer_cast(field); StringArray fieldNames = structurePtr->getFieldNames(); for(size_t i=0; isetParentAndName(this,fieldNames[i]); } } PVBooleanPtr PVStructure::getBooleanField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVBoolean; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvBoolean) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type boolean "; this->message(message, errorMessage); return nullPVBoolean; } PVBytePtr PVStructure::getByteField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVByte; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvByte) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type byte "; this->message(message, errorMessage); return nullPVByte; } PVShortPtr PVStructure::getShortField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVShort; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvShort) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type short "; this->message(message, errorMessage); return nullPVShort; } PVIntPtr PVStructure::getIntField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVInt; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvInt) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type int "; this->message(message, errorMessage); return nullPVInt; } PVLongPtr PVStructure::getLongField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVLong; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvLong) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type long "; this->message(message, errorMessage); return nullPVLong; } PVUBytePtr PVStructure::getUByteField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVUByte; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvUByte) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type byte "; this->message(message, errorMessage); return nullPVUByte; } PVUShortPtr PVStructure::getUShortField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVUShort; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvUShort) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type short "; this->message(message, errorMessage); return nullPVUShort; } PVUIntPtr PVStructure::getUIntField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVUInt; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvUInt) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type int "; this->message(message, errorMessage); return nullPVUInt; } PVULongPtr PVStructure::getULongField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVULong; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvULong) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type long "; this->message(message, errorMessage); return nullPVULong; } PVFloatPtr PVStructure::getFloatField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVFloat; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvFloat) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type float "; this->message(message, errorMessage); return nullPVFloat; } PVDoublePtr PVStructure::getDoubleField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVDouble; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvDouble) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type double "; this->message(message, errorMessage); return nullPVDouble; } PVStringPtr PVStructure::getStringField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVString; } if(pvField->getField()->getType()==scalar) { ScalarConstPtr pscalar = static_pointer_cast( pvField->getField()); if(pscalar->getScalarType()==pvString) { return std::tr1::static_pointer_cast(pvField); } } String message("fieldName "); message += fieldName + " does not have type string "; this->message(message, errorMessage); return nullPVString; } PVStructurePtr PVStructure::getStructureField(String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVStructure; } if(pvField->getField()->getType()==structure) { return std::tr1::static_pointer_cast(pvField); } String message("fieldName "); message += fieldName + " does not have type structure "; this->message(message, errorMessage); return nullPVStructure; } PVScalarArrayPtr PVStructure::getScalarArrayField( String fieldName,ScalarType elementType) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVScalarArray; } FieldConstPtr field = pvField->getField(); Type type = field->getType(); if(type!=scalarArray) { String message("fieldName "); message += fieldName + " does not have type array "; this->message(message, errorMessage); return nullPVScalarArray; } ScalarArrayConstPtr pscalarArray = static_pointer_cast(pvField->getField()); if(pscalarArray->getElementType()!=elementType) { String message("fieldName "); message += fieldName + " is array but does not have elementType "; ScalarTypeFunc::toString(&message,elementType); this->message(message, errorMessage); return nullPVScalarArray; } return std::tr1::static_pointer_cast(pvField); } PVStructureArrayPtr PVStructure::getStructureArrayField( String fieldName) { PVFieldPtr pvField = findSubField(fieldName,this); if(pvField.get()==NULL) { String message("fieldName "); message += fieldName + " does not exist"; this->message(message, errorMessage); return nullPVStructureArray; } if(pvField->getField()->getType()==structureArray) { return std::tr1::static_pointer_cast(pvField); } String message("fieldName "); message += fieldName + " does not have type structureArray "; this->message(message, errorMessage); return nullPVStructureArray; } String PVStructure::getExtendsStructureName() { return extendsStructureName; } bool PVStructure::putExtendsStructureName( String extendsStructureName) { if(extendsStructureName.length()!=0) return false; extendsStructureName = extendsStructureName; return true; } void PVStructure::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher) const { for(size_t i = 0; iserialize(pbuffer, pflusher); } void PVStructure::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol) { for(size_t i = 0; ideserialize(pbuffer, pcontrol); } void PVStructure::serialize(ByteBuffer *pbuffer, SerializableControl *pflusher, BitSet *pbitSet) const { size_t offset = const_cast(this)->getFieldOffset(); size_t numberFields = const_cast(this)->getNumberFields(); size_t next = pbitSet->nextSetBit(offset); // no more changes or no changes in this structure if(next<0||next>=offset+numberFields) return; // entire structure if(offset==next) { serialize(pbuffer, pflusher); return; } for(size_t i = 0; igetFieldOffset(); numberFields = pvField->getNumberFields(); next = pbitSet->nextSetBit(offset); // no more changes if(next<0) return; // no change in this pvField if(next>=offset+numberFields) continue; // serialize field or fields if(numberFields==1) { pvField->serialize(pbuffer, pflusher); } else { PVStructurePtr pvStructure = std::tr1::static_pointer_cast(pvField); pvStructure->serialize(pbuffer, pflusher, pbitSet); } } } void PVStructure::deserialize(ByteBuffer *pbuffer, DeserializableControl *pcontrol, BitSet *pbitSet) { size_t offset = getFieldOffset(); size_t numberFields = getNumberFields(); size_t next = pbitSet->nextSetBit(offset); // no more changes or no changes in this structure if(next<0||next>=offset+numberFields) return; // entire structure if(offset==next) { deserialize(pbuffer, pcontrol); return; } for(size_t i = 0; igetFieldOffset(); numberFields = pvField->getNumberFields(); next = pbitSet->nextSetBit(offset); // no more changes if(next<0) return; // no change in this pvField if(next>=offset+numberFields) continue; // deserialize field or fields if(numberFields==1) { pvField->deserialize(pbuffer, pcontrol); } else { PVStructurePtr pvStructure = std::tr1::static_pointer_cast(pvField); pvStructure->deserialize(pbuffer, pcontrol, pbitSet); } } } static PVFieldPtr findSubField(String fieldName,PVStructure *pvStructure) { if( fieldName.length()<1) return nullPVField; String::size_type index = fieldName.find('.'); String name = fieldName; String restOfName = String(); if(index>0) { name = fieldName.substr(0, index); if(fieldName.length()>index) { restOfName = fieldName.substr(index+1); } } PVFieldPtrArray pvFields = pvStructure->getPVFields(); PVFieldPtr pvField; size_t numFields = pvStructure->getStructure()->getNumberFields(); for(size_t i=0; igetFieldName().compare(name); if(result==0) { if(restOfName.length()==0) return pvFields[i]; if(pvField->getField()->getType()!=structure) return nullPVField; PVStructurePtr pvStructure = std::tr1::static_pointer_cast(pvField); return findSubField(restOfName,pvStructure.get()); } } return nullPVField; } }}