Skip to content
Snippets Groups Projects
Commit f68766a0 authored by Martin Christoph Hierholzer's avatar Martin Christoph Hierholzer
Browse files

replace castingMap with callForType()

parent 5427af6d
No related branches found
No related tags found
No related merge requests found
......@@ -54,7 +54,7 @@ namespace ChimeraTK {
boost::shared_ptr<D_fct> autoCreate(std::shared_ptr<PropertyDescription> const& propertyDescription);
template<class DOOCS_SCALAR_T, class DOOCS_PRIMARY_T, class DOOCS_ARRAY_T, class DOOCS_ARRAY_PRIMITIVE_T>
boost::shared_ptr<D_fct> typedCreateScalarOrArray(std::type_index valueType, ProcessVariable& processVariable,
boost::shared_ptr<D_fct> typedCreateScalarOrArray(const std::type_info& valueType, ProcessVariable& processVariable,
AutoPropertyDescription const& propertyDescription, DecoratorType decoratorType);
};
......
......@@ -307,96 +307,47 @@ namespace ChimeraTK {
boost::dynamic_pointer_cast<DoocsIfff>(doocsPV)->publishZeroMQ();
}
if(not ifffDescription.isWriteable){
if(not ifffDescription.isWriteable) {
doocsPV->set_ro_access();
}
return doocsPV;
}
static std::map<std::type_index, std::function<unsigned int(ProcessVariable&)>> castingMap{
{typeid(uint8_t),
[](auto& pv) { return dynamic_cast<ChimeraTK::NDRegisterAccessor<uint8_t>&>(pv).getNumberOfSamples(); }},
{typeid(int8_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<int8_t>&>(pv).getNumberOfSamples();
} // namespace ChimeraTK
}
,
{typeid(uint16_t),
[](auto& pv) { return dynamic_cast<ChimeraTK::NDRegisterAccessor<uint16_t>&>(pv).getNumberOfSamples(); }},
{typeid(int16_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<int16_t>&>(pv).getNumberOfSamples();
}
}
,
{typeid(uint32_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<uint32_t>&>(pv).getNumberOfSamples();
}
}
,
{typeid(int32_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<int32_t>&>(pv).getNumberOfSamples();
}
}
,
{typeid(uint64_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<uint64_t>&>(pv).getNumberOfSamples();
}
}
,
{typeid(int64_t),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<int64_t>&>(pv).getNumberOfSamples();
}
}
,
{typeid(float),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<float>&>(pv).getNumberOfSamples();
}
}
,
{typeid(double),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<double>&>(pv).getNumberOfSamples();
}
}
,
{typeid(std::string),
[](auto& pv) -> auto {return dynamic_cast<ChimeraTK::NDRegisterAccessor<std::string>&>(pv).getNumberOfSamples();
}
}
,
}
;
// fixme: some of the variables needed here are redundant and can be sovled with
// mpl and/or fusion maps
template<class DOOCS_SCALAR_T, class DOOCS_PRIMITIVE_T, class DOOCS_ARRAY_T, class DOOCS_ARRAY_PRIMITIVE_T>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateScalarOrArray(std::type_index valueType,
ProcessVariable& processVariable, AutoPropertyDescription const& autoPropertyDescription,
DecoratorType decoratorType) {
// We have to convert to the original NDRegisterAccessor to determine the
// number of samples. We cannot use a decorator because scalar and array
// DOOCS_PRIMITIVE_T can be different, and once a decorator is created you
// cannot get the other type any more.
auto nSamples = castingMap[valueType](processVariable);
if(nSamples == 1) {
return createDoocsScalar<DOOCS_PRIMITIVE_T, DOOCS_SCALAR_T>(autoPropertyDescription, decoratorType);
}
else {
return typedCreateDoocsArray<DOOCS_ARRAY_PRIMITIVE_T, DOOCS_ARRAY_T>(
AutoPropertyDescription(autoPropertyDescription));
// fixme: some of the variables needed here are redundant and can be sovled with
// mpl and/or fusion maps
template<class DOOCS_SCALAR_T, class DOOCS_PRIMITIVE_T, class DOOCS_ARRAY_T, class DOOCS_ARRAY_PRIMITIVE_T>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateScalarOrArray(const std::type_info& valueType,
ProcessVariable& processVariable, AutoPropertyDescription const& autoPropertyDescription,
DecoratorType decoratorType) {
// We have to convert to the original NDRegisterAccessor to determine the
// number of samples. We cannot use a decorator because scalar and array
// DOOCS_PRIMITIVE_T can be different, and once a decorator is created you
// cannot get the other type any more.
size_t nSamples;
callForType(valueType, [&](auto t) {
using T = decltype(t);
nSamples = dynamic_cast<ChimeraTK::NDRegisterAccessor<T>&>(processVariable).getNumberOfSamples();
});
if(nSamples == 1) {
return createDoocsScalar<DOOCS_PRIMITIVE_T, DOOCS_SCALAR_T>(autoPropertyDescription, decoratorType);
}
else {
return typedCreateDoocsArray<DOOCS_ARRAY_PRIMITIVE_T, DOOCS_ARRAY_T>(
AutoPropertyDescription(autoPropertyDescription));
}
}
}
boost::shared_ptr<D_fct> DoocsPVFactory::autoCreate(std::shared_ptr<PropertyDescription> const& propertyDescription) {
// do auto creation
auto autoPropertyDescription = std::static_pointer_cast<AutoPropertyDescription>(propertyDescription);
boost::shared_ptr<D_fct> DoocsPVFactory::autoCreate(std::shared_ptr<PropertyDescription> const& propertyDescription) {
// do auto creation
auto autoPropertyDescription = std::static_pointer_cast<AutoPropertyDescription>(propertyDescription);
auto pvName = autoPropertyDescription->source;
auto processVariable = _controlSystemPVManager->getProcessVariable(pvName);
auto pvName = autoPropertyDescription->source;
auto processVariable = _controlSystemPVManager->getProcessVariable(pvName);
std::type_info const& valueType = processVariable->getValueType();
/* TODO:
std::type_info const& valueType = processVariable->getValueType();
/* TODO:
- create functions "createDoocsArray" and "createDoocsSpectrum"
- first use spectrum here for 1D, then switch to array (tests need to be
adapted)
......@@ -404,154 +355,154 @@ boost::shared_ptr<D_fct> DoocsPVFactory::autoCreate(std::shared_ptr<PropertyDesc
(scalar for D_array and 1D)
*/
if(autoPropertyDescription->dataType == AutoPropertyDescription::DataType::Auto) {
autoPropertyDescription->deriveType(valueType);
}
if(autoPropertyDescription->dataType == AutoPropertyDescription::DataType::Auto) {
autoPropertyDescription->deriveType(valueType);
}
switch(autoPropertyDescription->dataType) {
case AutoPropertyDescription::DataType::Byte:
return typedCreateScalarOrArray<D_int, int32_t, D_bytearray, uint8_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Short:
return typedCreateScalarOrArray<D_int, int32_t, D_shortarray, int16_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Int:
return typedCreateScalarOrArray<D_int, int32_t, D_intarray, int32_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Long:
return typedCreateDoocsArray<int64_t, D_longarray>(AutoPropertyDescription(*autoPropertyDescription));
case AutoPropertyDescription::DataType::Float:
return typedCreateScalarOrArray<D_float, float, D_floatarray, float>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Double:
return typedCreateScalarOrArray<D_double, double, D_doublearray, double>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Auto:
if(valueType == typeid(std::string)) {
return typedCreateScalarOrArray<D_textUnifier, std::string, std::nullptr_t, std::nullptr_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::limiting);
}
throw std::logic_error("DoocsPVFactory does not implement a data type it should!");
switch(autoPropertyDescription->dataType) {
case AutoPropertyDescription::DataType::Byte:
return typedCreateScalarOrArray<D_int, int32_t, D_bytearray, uint8_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Short:
return typedCreateScalarOrArray<D_int, int32_t, D_shortarray, int16_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Int:
return typedCreateScalarOrArray<D_int, int32_t, D_intarray, int32_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Long:
return typedCreateDoocsArray<int64_t, D_longarray>(AutoPropertyDescription(*autoPropertyDescription));
case AutoPropertyDescription::DataType::Float:
return typedCreateScalarOrArray<D_float, float, D_floatarray, float>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Double:
return typedCreateScalarOrArray<D_double, double, D_doublearray, double>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::C_style_conversion);
case AutoPropertyDescription::DataType::Auto:
if(valueType == typeid(std::string)) {
return typedCreateScalarOrArray<D_textUnifier, std::string, std::nullptr_t, std::nullptr_t>(
valueType, *processVariable, *autoPropertyDescription, DecoratorType::limiting);
}
throw std::logic_error("DoocsPVFactory does not implement a data type it should!");
}
// Make compiler happy
throw std::logic_error("Should not be reached");
}
// Make compiler happy
throw std::logic_error("Should not be reached");
}
template<class DOOCS_PRIMITIVE_T, class DOOCS_T>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateDoocsArray(AutoPropertyDescription const& propertyDescription) {
auto processVariable = _controlSystemPVManager->getProcessVariable(propertyDescription.source);
template<class DOOCS_PRIMITIVE_T, class DOOCS_T>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateDoocsArray(AutoPropertyDescription const& propertyDescription) {
auto processVariable = _controlSystemPVManager->getProcessVariable(propertyDescription.source);
// the DoocsProcessScalar needs the real ProcessScalar type, not just
// ProcessVariable
boost::shared_ptr<NDRegisterAccessor<DOOCS_PRIMITIVE_T>> processArray;
if(typeid(DOOCS_PRIMITIVE_T) == processVariable->getValueType()) {
processArray = boost::dynamic_pointer_cast<ChimeraTK::NDRegisterAccessor<DOOCS_PRIMITIVE_T>>(processVariable);
}
else {
processArray = getDecorator<DOOCS_PRIMITIVE_T>(processVariable, DecoratorType::C_style_conversion);
}
// the DoocsProcessScalar needs the real ProcessScalar type, not just
// ProcessVariable
boost::shared_ptr<NDRegisterAccessor<DOOCS_PRIMITIVE_T>> processArray;
if(typeid(DOOCS_PRIMITIVE_T) == processVariable->getValueType()) {
processArray = boost::dynamic_pointer_cast<ChimeraTK::NDRegisterAccessor<DOOCS_PRIMITIVE_T>>(processVariable);
}
else {
processArray = getDecorator<DOOCS_PRIMITIVE_T>(processVariable, DecoratorType::C_style_conversion);
}
///@todo FIXME Add the decorator type as option to the array description, and
/// only use C_style_conversion as default
boost::shared_ptr<D_fct> doocsPV(
new DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>(_eqFct, propertyDescription.name, processArray, _updater));
///@todo FIXME Add the decorator type as option to the array description, and
/// only use C_style_conversion as default
boost::shared_ptr<D_fct> doocsPV(
new DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>(_eqFct, propertyDescription.name, processArray, _updater));
// set read only mode if configures in the xml file or for output variables
if(!processVariable->isWriteable() || !propertyDescription.isWriteable) {
doocsPV->set_ro_access();
}
// set read only mode if configures in the xml file or for output variables
if(!processVariable->isWriteable() || !propertyDescription.isWriteable) {
doocsPV->set_ro_access();
}
// publish via ZeroMQ if configured in the xml file
if(propertyDescription.publishZMQ) {
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)->publishZeroMQ();
}
// publish via ZeroMQ if configured in the xml file
if(propertyDescription.publishZMQ) {
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)->publishZeroMQ();
}
// set data matching mode (need to call before setMacroPulseNumberSource, as the mode is checked there)
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)
->_consistencyGroup.setMatchingMode(propertyDescription.dataMatching);
// set data matching mode (need to call before setMacroPulseNumberSource, as the mode is checked there)
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)
->_consistencyGroup.setMatchingMode(propertyDescription.dataMatching);
// set macro pulse number source, if configured
if(propertyDescription.macroPulseNumberSource.size() > 0) {
auto mpnSource = _controlSystemPVManager->getProcessVariable(propertyDescription.macroPulseNumberSource);
auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion);
if(mpnDecorated->getNumberOfSamples() != 1) {
throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
"' is used as a macro pulse number source, but it has an array "
"length of " +
std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1");
}
if(!mpnDecorated->isReadable()) {
throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
"' is used as a macro pulse number source, but it is not readable.");
}
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)->setMacroPulseNumberSource(
mpnDecorated);
}
// set macro pulse number source, if configured
if(propertyDescription.macroPulseNumberSource.size() > 0) {
auto mpnSource = _controlSystemPVManager->getProcessVariable(propertyDescription.macroPulseNumberSource);
auto mpnDecorated = getDecorator<int64_t>(mpnSource, DecoratorType::C_style_conversion);
if(mpnDecorated->getNumberOfSamples() != 1) {
throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
"' is used as a macro pulse number source, but it has an array "
"length of " +
std::to_string(mpnDecorated->getNumberOfSamples()) + ". Length must be exactly 1");
}
if(!mpnDecorated->isReadable()) {
throw ChimeraTK::logic_error("The property '" + mpnDecorated->getName() +
"' is used as a macro pulse number source, but it is not readable.");
}
boost::dynamic_pointer_cast<DoocsProcessArray<DOOCS_T, DOOCS_PRIMITIVE_T>>(doocsPV)->setMacroPulseNumberSource(
mpnDecorated);
}
return doocsPV;
}
// template specialisation for cases with no matching DOOCS array type (e.g.
// string)
template<>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateDoocsArray<std::nullptr_t, std::nullptr_t>(
AutoPropertyDescription const&) {
throw std::invalid_argument("Type not supported as an array");
}
boost::shared_ptr<D_fct> DoocsPVFactory::createDoocsArray(
std::shared_ptr<AutoPropertyDescription> const& propertyDescription) {
if(propertyDescription->dataType == AutoPropertyDescription::DataType::Auto) {
// leave the desision which array to produce to the auto creation algorithm.
// We need it there anyway
// FIXME: This does not produce arrays of length 1 because it will produce a
// scalar
return autoCreate(propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Byte) {
return typedCreateDoocsArray<uint8_t, D_bytearray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Short) {
return typedCreateDoocsArray<int16_t, D_shortarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Int) {
return typedCreateDoocsArray<int32_t, D_intarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Long) {
return typedCreateDoocsArray<int64_t, D_longarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Float) {
return typedCreateDoocsArray<float, D_floatarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Double) {
return typedCreateDoocsArray<double, D_doublearray>(*propertyDescription);
}
else {
throw std::logic_error("DoocsPVFactory does not implement a data type it should!");
return doocsPV;
}
}
boost::shared_ptr<D_fct> DoocsPVFactory::create(std::shared_ptr<PropertyDescription> const& propertyDescription) {
auto& requestedType = propertyDescription->type();
if(requestedType == typeid(AutoPropertyDescription)) {
return autoCreate(propertyDescription);
}
else if(requestedType == typeid(SpectrumDescription)) {
return createDoocsSpectrum(*std::static_pointer_cast<SpectrumDescription>(propertyDescription));
}
else if(requestedType == typeid(XyDescription)) {
return createXy(*std::static_pointer_cast<XyDescription>(propertyDescription));
}
else if(requestedType == typeid(IfffDescription)) {
return createIfff(*std::static_pointer_cast<IfffDescription>(propertyDescription));
// template specialisation for cases with no matching DOOCS array type (e.g.
// string)
template<>
boost::shared_ptr<D_fct> DoocsPVFactory::typedCreateDoocsArray<std::nullptr_t, std::nullptr_t>(
AutoPropertyDescription const&) {
throw std::invalid_argument("Type not supported as an array");
}
else if(requestedType == typeid(AutoPropertyDescription)) {
return createDoocsArray(std::static_pointer_cast<AutoPropertyDescription>(propertyDescription));
boost::shared_ptr<D_fct> DoocsPVFactory::createDoocsArray(
std::shared_ptr<AutoPropertyDescription> const& propertyDescription) {
if(propertyDescription->dataType == AutoPropertyDescription::DataType::Auto) {
// leave the desision which array to produce to the auto creation algorithm.
// We need it there anyway
// FIXME: This does not produce arrays of length 1 because it will produce a
// scalar
return autoCreate(propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Byte) {
return typedCreateDoocsArray<uint8_t, D_bytearray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Short) {
return typedCreateDoocsArray<int16_t, D_shortarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Int) {
return typedCreateDoocsArray<int32_t, D_intarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Long) {
return typedCreateDoocsArray<int64_t, D_longarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Float) {
return typedCreateDoocsArray<float, D_floatarray>(*propertyDescription);
}
else if(propertyDescription->dataType == AutoPropertyDescription::DataType::Double) {
return typedCreateDoocsArray<double, D_doublearray>(*propertyDescription);
}
else {
throw std::logic_error("DoocsPVFactory does not implement a data type it should!");
}
}
else {
throw std::invalid_argument("Sorry, your type is not supported yet.");
boost::shared_ptr<D_fct> DoocsPVFactory::create(std::shared_ptr<PropertyDescription> const& propertyDescription) {
auto& requestedType = propertyDescription->type();
if(requestedType == typeid(AutoPropertyDescription)) {
return autoCreate(propertyDescription);
}
else if(requestedType == typeid(SpectrumDescription)) {
return createDoocsSpectrum(*std::static_pointer_cast<SpectrumDescription>(propertyDescription));
}
else if(requestedType == typeid(XyDescription)) {
return createXy(*std::static_pointer_cast<XyDescription>(propertyDescription));
}
else if(requestedType == typeid(IfffDescription)) {
return createIfff(*std::static_pointer_cast<IfffDescription>(propertyDescription));
}
else if(requestedType == typeid(AutoPropertyDescription)) {
return createDoocsArray(std::static_pointer_cast<AutoPropertyDescription>(propertyDescription));
}
else {
throw std::invalid_argument("Sorry, your type is not supported yet.");
}
}
}
} // namespace ChimeraTK
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment