Skip to content

Commit

Permalink
DPL: refactor ConfigParamRegistry to use C++20
Browse files Browse the repository at this point in the history
  • Loading branch information
ktf committed Jan 10, 2025
1 parent 651d9e5 commit 48757bd
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 88 deletions.
1 change: 1 addition & 0 deletions Framework/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ o2_add_library(Framework
src/ConfigParamDiscovery.cxx
src/ConfigParamStore.cxx
src/ConfigParamsHelper.cxx
src/ConfigParamRegistry.cxx
src/ChannelParamSpec.cxx
src/DDSConfigHelpers.cxx
src/DataAllocator.cxx
Expand Down
135 changes: 47 additions & 88 deletions Framework/Core/include/Framework/ConfigParamRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,38 @@
#ifndef O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
#define O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_

#include "Framework/ParamRetriever.h"
#include "Array2D.h"
#include "Framework/ConfigParamStore.h"
#include <boost/property_tree/ptree.hpp>
#include "Framework/Traits.h"
#include "Framework/VariantPropertyTreeHelpers.h"

#include <boost/property_tree/ptree_fwd.hpp>
#include <concepts>
#include <memory>
#include <string>
#include <cassert>

namespace
{
template <typename T>
constexpr auto isSimpleType()
{
return std::is_same_v<T, int> ||
std::is_same_v<T, int8_t> ||
std::is_same_v<T, int16_t> ||
std::is_same_v<T, uint8_t> ||
std::is_same_v<T, uint16_t> ||
std::is_same_v<T, uint32_t> ||
std::is_same_v<T, uint64_t> ||
std::is_same_v<T, int64_t> ||
std::is_same_v<T, long> ||
std::is_same_v<T, float> ||
std::is_same_v<T, double> ||
std::is_same_v<T, bool>;
}
} // namespace
concept SimpleConfigValueType = std::same_as<T, int> ||
std::same_as<T, int8_t> ||
std::same_as<T, int16_t> ||
std::same_as<T, uint8_t> ||
std::same_as<T, uint16_t> ||
std::same_as<T, uint32_t> ||
std::same_as<T, uint64_t> ||
std::same_as<T, int64_t> ||
std::same_as<T, long> ||
std::same_as<T, float> ||
std::same_as<T, double> ||
std::same_as<T, bool>;

template <typename T>
concept StringConfigValueType = std::same_as<T, std::string>;

template <typename T>
concept PtreeConfigValueType = std::same_as<T, boost::property_tree::ptree> || std::constructible_from<T, boost::property_tree::ptree>;

template <typename T>
concept ConfigValueType = SimpleConfigValueType<T> || StringConfigValueType<T> || o2::framework::base_of_template<std::vector, T> || o2::framework::base_of_template<o2::framework::Array2D, T> || o2::framework::base_of_template<o2::framework::LabeledArray, T>;

namespace o2::framework
{
Expand All @@ -54,87 +57,43 @@ class ConfigParamStore;
class ConfigParamRegistry
{
public:
ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store)
: mStore{std::move(store)}
{
}
ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store);

bool isSet(const char* key) const
{
return mStore->store().count(key);
}
bool isSet(const char* key) const;

bool hasOption(const char* key) const
{
return mStore->store().get_child_optional(key).is_initialized();
}
bool hasOption(const char* key) const;

bool isDefault(const char* key) const
{
return mStore->store().count(key) > 0 && mStore->provenance(key) != "default";
}
bool isDefault(const char* key) const;

[[nodiscard]] std::vector<ConfigParamSpec> const& specs() const
{
return mStore->specs();
}
[[nodiscard]] std::vector<ConfigParamSpec> const& specs() const;

template <typename T>
T get(const char* key) const
{
assert(mStore.get());
try {
if constexpr (isSimpleType<T>()) {
return mStore->store().get<T>(key);
} else if constexpr (std::is_same_v<T, std::string>) {
return mStore->store().get<std::string>(key);
} else if constexpr (std::is_same_v<T, std::string_view>) {
return std::string_view{mStore->store().get<std::string>(key)};
} else if constexpr (base_of_template<std::vector, T>) {
return vectorFromBranch<typename T::value_type>(mStore->store().get_child(key));
} else if constexpr (base_of_template<o2::framework::Array2D, T>) {
return array2DFromBranch<typename T::element_t>(mStore->store().get_child(key));
} else if constexpr (base_of_template<o2::framework::LabeledArray, T>) {
return labeledArrayFromBranch<typename T::element_t>(mStore->store().get_child(key));
} else if constexpr (std::is_same_v<T, boost::property_tree::ptree>) {
return mStore->store().get_child(key);
} else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree>) {
return T{mStore->store().get_child(key)};
} else if constexpr (std::is_constructible_v<T, boost::property_tree::ptree> == false) {
static_assert(std::is_constructible_v<T, boost::property_tree::ptree> == false,
"Not a basic type and no constructor from ptree provided");
}
} catch (std::exception& e) {
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
} catch (...) {
throw std::invalid_argument(std::string("error parsing option: ") + key);
}
throw std::invalid_argument(std::string("bad type for option: ") + key);
}
template <ConfigValueType T>
T get(const char* key) const;

template <typename T>
void override(const char* key, const T& val) const
{
assert(mStore.get());
try {
mStore->store().put(key, val);
} catch (std::exception& e) {
throw std::invalid_argument(std::string("failed to store an option: ") + key + " (" + e.what() + ")");
} catch (...) {
throw std::invalid_argument(std::string("failed to store an option: ") + key);
}
}
T get(const char* key) const;

void override(const char* key, ConfigValueType auto const& val) const;

// Load extra parameters discovered while we process data
void loadExtra(std::vector<ConfigParamSpec>& extras)
{
mStore->load(extras);
}
void loadExtra(std::vector<ConfigParamSpec>& extras);

private:
std::unique_ptr<ConfigParamStore> mStore;
};

template <typename T>
T ConfigParamRegistry::get(const char* key) const
{
try {
return T{mStore->store().get_child(key)};
} catch (std::exception& e) {
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
} catch (...) {
throw std::invalid_argument(std::string("error parsing option: ") + key);
}
}

} // namespace o2::framework

#endif // O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
131 changes: 131 additions & 0 deletions Framework/Core/src/ConfigParamRegistry.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
#include "Framework/ConfigParamRegistry.h"
#include "Framework/VariantPropertyTreeHelpers.h"

namespace o2::framework
{

ConfigParamRegistry::ConfigParamRegistry(std::unique_ptr<ConfigParamStore> store)
: mStore{std::move(store)}
{
}

bool ConfigParamRegistry::isSet(const char* key) const
{
return mStore->store().count(key);
}

bool ConfigParamRegistry::hasOption(const char* key) const
{
return mStore->store().get_child_optional(key).is_initialized();
}

bool ConfigParamRegistry::isDefault(const char* key) const
{
return mStore->store().count(key) > 0 && mStore->provenance(key) != "default";
}

namespace
{
template <SimpleConfigValueType T>
T getImpl(boost::property_tree::ptree const& tree, const char* key)
{
return tree.get<T>(key);
}

template <StringConfigValueType T>
T getImpl(boost::property_tree::ptree const& tree, const char* key)
{
return tree.get<std::string>(key);
}

template <typename T>
requires base_of_template<std::vector, T>
auto getImpl(boost::property_tree::ptree const& tree, const char* key)
{
return o2::framework::vectorFromBranch<typename T::value_type>(tree.get_child(key));
}

template <typename T>
requires base_of_template<o2::framework::Array2D, T>
auto getImpl(boost::property_tree::ptree& tree, const char* key)
{
return array2DFromBranch<typename T::element_t>(tree.get_child(key));
}

template <typename T>
requires base_of_template<o2::framework::LabeledArray, T>
auto getImpl(boost::property_tree::ptree& tree, const char* key)
{
return labeledArrayFromBranch<typename T::element_t>(tree.get_child(key));
}
} // namespace

template <ConfigValueType T>
T ConfigParamRegistry::get(const char* key) const
{
try {
return getImpl<T>(this->mStore->store(), key);
} catch (std::exception& e) {
throw std::invalid_argument(std::string("missing option: ") + key + " (" + e.what() + ")");
} catch (...) {
throw std::invalid_argument(std::string("error parsing option: ") + key);
}
}

void ConfigParamRegistry::override(const char* key, ConfigValueType auto const& val) const
{
try {
mStore->store().put(key, val);
} catch (std::exception& e) {
throw std::invalid_argument(std::string("failed to store an option: ") + key + " (" + e.what() + ")");
} catch (...) {
throw std::invalid_argument(std::string("failed to store an option: ") + key);
}
}

// Load extra parameters discovered while we process data
void ConfigParamRegistry::loadExtra(std::vector<ConfigParamSpec>& extras)
{
mStore->load(extras);
}

[[nodiscard]] std::vector<ConfigParamSpec> const& ConfigParamRegistry::specs() const
{
return mStore->specs();
}

template int8_t ConfigParamRegistry::get<int8_t>(const char* key) const;
template int16_t ConfigParamRegistry::get<int16_t>(const char* key) const;
template int32_t ConfigParamRegistry::get<int32_t>(const char* key) const;
template int64_t ConfigParamRegistry::get<int64_t>(const char* key) const;
template uint8_t ConfigParamRegistry::get<uint8_t>(const char* key) const;
template uint32_t ConfigParamRegistry::get<uint32_t>(const char* key) const;
template uint16_t ConfigParamRegistry::get<uint16_t>(const char* key) const;
template uint64_t ConfigParamRegistry::get<uint64_t>(const char* key) const;
template LabeledArray<std::string> ConfigParamRegistry::get<LabeledArray<std::string>>(const char* key) const;
template LabeledArray<double> ConfigParamRegistry::get<LabeledArray<double>>(const char* key) const;
template LabeledArray<float> ConfigParamRegistry::get<LabeledArray<float>>(const char* key) const;
template LabeledArray<int> ConfigParamRegistry::get<LabeledArray<int>>(const char* key) const;
template Array2D<std::string> ConfigParamRegistry::get<Array2D<std::string>>(const char* key) const;
template Array2D<double> ConfigParamRegistry::get<Array2D<double>>(const char* key) const;
template Array2D<float> ConfigParamRegistry::get<Array2D<float>>(const char* key) const;
template Array2D<int> ConfigParamRegistry::get<Array2D<int>>(const char* key) const;
template std::vector<std::string> ConfigParamRegistry::get<std::vector<std::string>>(const char* key) const;
template std::vector<double> ConfigParamRegistry::get<std::vector<double>>(const char* key) const;
template std::vector<float> ConfigParamRegistry::get<std::vector<float>>(const char* key) const;
template std::vector<int> ConfigParamRegistry::get<std::vector<int>>(const char* key) const;
template float ConfigParamRegistry::get<float>(const char* key) const;
template double ConfigParamRegistry::get<double>(const char* key) const;
template std::string ConfigParamRegistry::get<std::string>(const char* key) const;
template bool ConfigParamRegistry::get<bool>(const char* key) const;
} // namespace o2::framework

0 comments on commit 48757bd

Please sign in to comment.