Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DPL: refactor ConfigParamRegistry to use C++20 #13850

Merged
merged 1 commit into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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, long> ||
std::same_as<T, long 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
Loading