File indexing completed on 2026-08-06 09:30:08
0001 #ifndef PODIO_GENERICPARAMETERS_H
0002 #define PODIO_GENERICPARAMETERS_H
0003
0004 #include "podio/utilities/TypeHelpers.h"
0005
0006 #include <algorithm>
0007 #include <iostream>
0008 #include <iterator>
0009 #include <map>
0010 #include <memory>
0011 #include <mutex>
0012 #include <optional>
0013 #include <string>
0014 #include <vector>
0015
0016 #if PODIO_ENABLE_SIO
0017 namespace sio {
0018 class read_device;
0019 class write_device;
0020 using version_type = uint32_t;
0021 }
0022 #endif
0023
0024 namespace podio {
0025
0026
0027 using SupportedGenericDataTypes = std::tuple<int, float, std::string, double>;
0028
0029
0030 template <typename T>
0031 inline constexpr bool isSupportedGenericDataType = detail::isAnyOrVectorOf<T, SupportedGenericDataTypes>;
0032
0033
0034 template <typename T>
0035 concept ValidGenericDataType = isSupportedGenericDataType<T>;
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045 class GenericParameters {
0046 public:
0047 template <typename T>
0048 using MapType = std::map<std::string, std::vector<T>>;
0049
0050 private:
0051
0052 using MutexPtr = std::unique_ptr<std::mutex>;
0053
0054 public:
0055 GenericParameters() = default;
0056
0057
0058
0059
0060 GenericParameters(const GenericParameters&);
0061 GenericParameters& operator=(const GenericParameters&) = delete;
0062
0063
0064 GenericParameters(GenericParameters&&) = default;
0065 GenericParameters& operator=(GenericParameters&&) = default;
0066
0067 ~GenericParameters() = default;
0068
0069 template <ValidGenericDataType T>
0070 std::optional<T> get(const std::string& key) const;
0071
0072
0073 template <ValidGenericDataType T>
0074 void set(const std::string& key, T value);
0075
0076
0077 void set(const std::string& key, const char* value) {
0078 set<std::string>(key, std::string(value));
0079 }
0080
0081
0082 void set(const std::string& key, std::vector<std::string> values) {
0083 set<std::vector<std::string>>(key, std::move(values));
0084 }
0085
0086
0087 template <ValidGenericDataType T>
0088 void set(const std::string& key, std::initializer_list<T>&& values) {
0089 set<std::vector<T>>(key, std::move(values));
0090 }
0091
0092
0093 template <typename T, template <typename...> typename VecLike>
0094 void loadFrom(VecLike<std::string> keys, VecLike<std::vector<T>> values);
0095
0096
0097 template <ValidGenericDataType T>
0098 size_t getN(const std::string& key) const;
0099
0100
0101 template <ValidGenericDataType T>
0102 std::vector<std::string> getKeys() const;
0103
0104
0105 template <ValidGenericDataType T>
0106 std::tuple<std::vector<std::string>, std::vector<std::vector<T>>> getKeysAndValues() const;
0107
0108
0109 void clear() {
0110 _intMap.clear();
0111 _floatMap.clear();
0112 _doubleMap.clear();
0113 _stringMap.clear();
0114 }
0115
0116 void print(std::ostream& os = std::cout, bool flush = true) const;
0117
0118
0119 bool empty() const {
0120 return _intMap.empty() && _floatMap.empty() && _doubleMap.empty() && _stringMap.empty();
0121 }
0122
0123 #if PODIO_ENABLE_SIO
0124 friend void writeGenericParameters(sio::write_device& device, const GenericParameters& parameters);
0125 friend void readGenericParameters(sio::read_device& device, GenericParameters& parameters, sio::version_type version);
0126 #endif
0127
0128
0129 template <typename T>
0130 const MapType<detail::GetVectorType<T>>& getMap() const {
0131 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0132 return _intMap;
0133 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0134 return _floatMap;
0135 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0136 return _doubleMap;
0137 } else {
0138 return _stringMap;
0139 }
0140 }
0141
0142 private:
0143
0144 template <typename T>
0145 MapType<detail::GetVectorType<T>>& getMap() {
0146 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0147 return _intMap;
0148 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0149 return _floatMap;
0150 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0151 return _doubleMap;
0152 } else {
0153 return _stringMap;
0154 }
0155 }
0156
0157
0158 template <typename T>
0159 std::mutex& getMutex() const {
0160 if constexpr (std::is_same_v<detail::GetVectorType<T>, int>) {
0161 return *(m_intMtx.get());
0162 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, float>) {
0163 return *(m_floatMtx.get());
0164 } else if constexpr (std::is_same_v<detail::GetVectorType<T>, double>) {
0165 return *(m_doubleMtx.get());
0166 } else {
0167 return *(m_stringMtx.get());
0168 }
0169 }
0170
0171 private:
0172 MapType<int> _intMap{};
0173 mutable MutexPtr m_intMtx{std::make_unique<std::mutex>()};
0174 MapType<float> _floatMap{};
0175 mutable MutexPtr m_floatMtx{std::make_unique<std::mutex>()};
0176 MapType<std::string> _stringMap{};
0177 mutable MutexPtr m_stringMtx{std::make_unique<std::mutex>()};
0178 MapType<double> _doubleMap{};
0179 mutable MutexPtr m_doubleMtx{std::make_unique<std::mutex>()};
0180 };
0181
0182 template <ValidGenericDataType T>
0183 std::optional<T> GenericParameters::get(const std::string& key) const {
0184 const auto& map = getMap<T>();
0185 auto& mtx = getMutex<T>();
0186 std::lock_guard lock{mtx};
0187 const auto it = map.find(key);
0188 if (it == map.end()) {
0189 return std::nullopt;
0190 }
0191
0192
0193 if constexpr (detail::isVector<T>) {
0194 return it->second;
0195 } else {
0196 const auto& iv = it->second;
0197 if (iv.empty()) {
0198 return std::nullopt;
0199 }
0200 return iv[0];
0201 }
0202 }
0203
0204 template <ValidGenericDataType T>
0205 void GenericParameters::set(const std::string& key, T value) {
0206 auto& map = getMap<T>();
0207 auto& mtx = getMutex<T>();
0208
0209 if constexpr (detail::isVector<T>) {
0210 std::lock_guard lock{mtx};
0211 map.insert_or_assign(key, std::move(value));
0212 } else {
0213
0214 std::vector<T> v = {std::move(value)};
0215 std::lock_guard lock{mtx};
0216 map.insert_or_assign(key, std::move(v));
0217 }
0218 }
0219
0220 template <ValidGenericDataType T>
0221 size_t GenericParameters::getN(const std::string& key) const {
0222 const auto& map = getMap<T>();
0223 auto& mtx = getMutex<T>();
0224 std::lock_guard lock{mtx};
0225 if (const auto it = map.find(key); it != map.end()) {
0226 return it->second.size();
0227 }
0228 return 0;
0229 }
0230
0231 template <ValidGenericDataType T>
0232 std::vector<std::string> GenericParameters::getKeys() const {
0233 std::vector<std::string> keys;
0234 const auto& map = getMap<T>();
0235 keys.reserve(map.size());
0236 {
0237 auto& mtx = getMutex<T>();
0238 std::lock_guard lock{mtx};
0239 std::transform(map.begin(), map.end(), std::back_inserter(keys), [](const auto& pair) { return pair.first; });
0240 }
0241
0242 return keys;
0243 }
0244
0245 template <ValidGenericDataType T>
0246 std::tuple<std::vector<std::string>, std::vector<std::vector<T>>> GenericParameters::getKeysAndValues() const {
0247 std::vector<std::vector<T>> values;
0248 std::vector<std::string> keys;
0249 auto& mtx = getMutex<T>();
0250 const auto& map = getMap<T>();
0251 {
0252
0253
0254 std::lock_guard lock{mtx};
0255 values.reserve(map.size());
0256 keys.reserve(map.size());
0257
0258 for (const auto& [k, v] : map) {
0259 keys.emplace_back(k);
0260 values.emplace_back(v);
0261 }
0262 }
0263 return {keys, values};
0264 }
0265
0266 template <typename T, template <typename...> typename VecLike>
0267 void GenericParameters::loadFrom(VecLike<std::string> keys, VecLike<std::vector<T>> values) {
0268 auto& map = getMap<T>();
0269 auto& mtx = getMutex<T>();
0270
0271 std::lock_guard lock{mtx};
0272 for (size_t i = 0; i < keys.size(); ++i) {
0273 map.emplace(std::move(keys[i]), std::move(values[i]));
0274 }
0275 }
0276
0277 }
0278 #endif