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 c4a029d
Show file tree
Hide file tree
Showing 4 changed files with 214 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
2 changes: 2 additions & 0 deletions Framework/Core/include/Framework/Array2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace o2::framework
// has no range checks
template <typename T>
struct Array2D {
void is_array_2d();
using element_t = T;

Array2D()
Expand Down Expand Up @@ -161,6 +162,7 @@ template <typename T>
class LabeledArray : public LabelMap
{
public:
void is_labeled_array();
using element_t = T;

LabeledArray()
Expand Down
142 changes: 54 additions & 88 deletions Framework/Core/include/Framework/ConfigParamRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,45 @@
#ifndef O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_
#define O2_FRAMEWORK_CONFIGPARAMREGISTRY_H_

#include "Framework/ParamRetriever.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 <cstdint>
#include <memory>
#include <string>
#include <cassert>
#include <type_traits>

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 Array2DLike = requires(T& t) { t.is_array_2d(); };

template <typename T>
concept LabeledArrayLike = requires(T& t) { t.is_labeled_array(); };

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

namespace o2::framework
{
Expand All @@ -54,87 +64,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_
157 changes: 157 additions & 0 deletions Framework/Core/src/ConfigParamRegistry.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// 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"
#include "Framework/Array2D.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 <Array2DLike T>
auto getImpl(boost::property_tree::ptree& tree, const char* key)
{
return array2DFromBranch<typename T::element_t>(tree.get_child(key));
}

template <LabeledArrayLike 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 short ConfigParamRegistry::get<short>(const char* key) const;
template int ConfigParamRegistry::get<int>(const char* key) const;
template long ConfigParamRegistry::get<long>(const char* key) const;
template long long ConfigParamRegistry::get<long long>(const char* key) const;
template uint8_t ConfigParamRegistry::get<uint8_t>(const char* key) const;
template uint16_t ConfigParamRegistry::get<uint16_t>(const char* key) const;
template uint32_t ConfigParamRegistry::get<uint32_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;

template void ConfigParamRegistry::override(const char* key, int8_t const&) const;
template void ConfigParamRegistry::override(const char* key, int16_t const&) const;
template void ConfigParamRegistry::override(const char* key, int32_t const&) const;
template void ConfigParamRegistry::override(const char* key, int64_t const&) const;
template void ConfigParamRegistry::override(const char* key, uint8_t const&) const;
template void ConfigParamRegistry::override(const char* key, uint16_t const&) const;
template void ConfigParamRegistry::override(const char* key, uint32_t const&) const;
template void ConfigParamRegistry::override(const char* key, uint64_t const&) const;
template void ConfigParamRegistry::override(const char* key, float const&) const;
template void ConfigParamRegistry::override(const char* key, double const&) const;
template void ConfigParamRegistry::override(const char* key, std::string const&) const;
template void ConfigParamRegistry::override(const char* key, bool const&) const;

//template void ConfigParamRegistry::override(char const* key, LabeledArray<std::string> const&) const;
//template void ConfigParamRegistry::override(char const* key, LabeledArray<double> const&) const;
//template void ConfigParamRegistry::override(char const* key, LabeledArray<float> const&) const;
//template void ConfigParamRegistry::override(char const* key, LabeledArray<int> const&) const;
//template void ConfigParamRegistry::override(char const* key, Array2D<std::string> const&) const;
//template void ConfigParamRegistry::override(char const* key, Array2D<double> const&) const;
//template void ConfigParamRegistry::override(char const* key, Array2D<float> const&) const;
//template void ConfigParamRegistry::override(char const* key, Array2D<int> const&) const;
//template void ConfigParamRegistry::override(char const* key, std::vector<std::string> const&) const;
//template void ConfigParamRegistry::override(char const* key, std::vector<double> const&) const;
//template void ConfigParamRegistry::override(char const* key, std::vector<float> const&) const;
//template void ConfigParamRegistry::override(char const* key, std::vector<int> const&) const;
} // namespace o2::framework

0 comments on commit c4a029d

Please sign in to comment.