/*PVField.cpp*/ /* * Copyright information and license terms for this software can be * found in the file LICENSE that is included with the distribution */ /** * @author mrk */ #include #include #include #include #include #define epicsExportSharedSymbols #include #include #include #include using std::tr1::const_pointer_cast; using std::size_t; using std::string; namespace epics { namespace pvData { size_t PVField::num_instances; PVField::PVField(FieldConstPtr field) : parent(NULL),field(field), fieldOffset(0), nextFieldOffset(0), immutable(false) { REFTRACE_INCREMENT(num_instances); } PVField::~PVField() { REFTRACE_DECREMENT(num_instances); } size_t PVField::getFieldOffset() const { if(nextFieldOffset==0) computeOffset(this); return fieldOffset; } size_t PVField::getNextFieldOffset() const { if(nextFieldOffset==0) computeOffset(this); return nextFieldOffset; } size_t PVField::getNumberFields() const { if(nextFieldOffset==0) computeOffset(this); return (nextFieldOffset - fieldOffset); } void PVField::setImmutable() {immutable = true;} void PVField::postPut() { if(postHandler) postHandler->postPut(); } void PVField::setPostHandler(PostHandlerPtr const &handler) { if(postHandler) { if(postHandler.get()==handler.get()) return; throw std::logic_error( "PVField::setPostHandler a postHandler is already registered"); } postHandler = handler; } void PVField::setParentAndName(PVStructure * xxx,string const & name) { parent = xxx; fieldName = name; } bool PVField::equals(PVField &pv) { return pv==*this; } std::ostream& operator<<(std::ostream& o, const PVField& f) { return f.dumpValue(o); }; string PVField::getFullName() const { string ret(fieldName); for(const PVField *fld=getParent(); fld; fld=fld->getParent()) { if(fld->getFieldName().size()==0) break; ret = fld->getFieldName() + '.' + ret; } return ret; } void PVField::computeOffset(const PVField * pvField) { const PVStructure * pvTop = pvField->getParent(); if(pvTop==NULL) { if(pvField->getField()->getType()!=structure) { PVField *xxx = const_cast(pvField); xxx->fieldOffset = 0; xxx->nextFieldOffset = 1; return; } pvTop = static_cast(pvField); } else { while(pvTop->getParent()!=NULL) pvTop = pvTop->getParent(); } size_t offset = 0; size_t nextOffset = 1; const PVFieldPtrArray & pvFields = pvTop->getPVFields(); for(size_t i=0; i < pvTop->getStructure()->getNumberFields(); i++) { offset = nextOffset; PVField *pvField = pvFields[i].get(); FieldConstPtr field = pvField->getField(); switch(field->getType()) { case scalar: case scalarArray: case structureArray: case union_: case unionArray: { nextOffset++; pvField->fieldOffset = offset; pvField->nextFieldOffset = nextOffset; break; } case structure: { pvField->computeOffset(pvField,offset); nextOffset = pvField->getNextFieldOffset(); } } } PVField *top = (PVField *)pvTop; PVField *xxx = const_cast(top); xxx->fieldOffset = 0; xxx->nextFieldOffset = nextOffset; } void PVField::computeOffset(const PVField * pvField,size_t offset) { size_t beginOffset = offset; size_t nextOffset = offset + 1; const PVStructure *pvStructure = static_cast(pvField); const PVFieldPtrArray & pvFields = pvStructure->getPVFields(); for(size_t i=0; i < pvStructure->getStructure()->getNumberFields(); i++) { offset = nextOffset; PVField *pvSubField = pvFields[i].get(); FieldConstPtr field = pvSubField->getField(); switch(field->getType()) { case scalar: case scalarArray: case structureArray: case union_: case unionArray: { nextOffset++; pvSubField->fieldOffset = offset; pvSubField->nextFieldOffset = nextOffset; break; } case structure: { pvSubField->computeOffset(pvSubField,offset); nextOffset = pvSubField->getNextFieldOffset(); } } } PVField *xxx = const_cast(pvField); xxx->fieldOffset = beginOffset; xxx->nextFieldOffset = nextOffset; } void PVField::copy(const PVField& from) { if(isImmutable()) throw std::invalid_argument("destination is immutable"); if (getField() != from.getField()) throw std::invalid_argument("field types do not match"); copyUnchecked(from); } void PVField::copyUnchecked(const PVField& from) { assert(getField()==from.getField()); switch(getField()->getType()) { case scalar: { const PVScalar* fromS = static_cast(&from); PVScalar* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } case scalarArray: { const PVScalarArray* fromS = static_cast(&from); PVScalarArray* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } case structure: { const PVStructure* fromS = static_cast(&from); PVStructure* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } case structureArray: { const PVStructureArray* fromS = static_cast(&from); PVStructureArray* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } case union_: { const PVUnion* fromS = static_cast(&from); PVUnion* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } case unionArray: { const PVUnionArray* fromS = static_cast(&from); PVUnionArray* toS = static_cast(this); toS->copyUnchecked(*fromS); break; } default: { throw std::logic_error("PVField::copy unknown type"); } } } }}