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