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