IDS peak genericC++ v1.17.0
Loading...
Searching...
No Matches
peak_common_metadata.hpp
Go to the documentation of this file.
1
5
6#pragma once
7
13
14#include <unordered_map>
15#include <algorithm>
16#include <sstream>
17#include <vector>
18
19namespace peak
20{
21namespace common
22{
23namespace detail
24{
25struct MetadataAccessor;
26}
27
44{
45public:
46 using allowedTypes = std::tuple<int64_t, std::vector<int64_t>, double, std::vector<double>, std::string, std::vector<std::string>, bool,
47 std::vector<bool>>;
48
58 template <typename T>
59 void SetValueByName(const std::string& name, T&& value)
60 {
61 Dispatch(name, std::forward<T>(value), std::is_lvalue_reference<T>{});
62 }
63
73 void RemoveEntryByName(const std::string& name)
74 {
75 m_data.erase(name);
76 }
77
91 template <MetadataKey metadataKey, typename T>
92 void SetValueByKey(T value)
93 {
94 static_assert(
95 std::is_convertible<T, typename detail::MetadataKeyTraits<metadataKey>::type>::value, "Incorrect value type for metadata key");
96 constexpr auto key = detail::MetadataKeyTraits<metadataKey>::Name();
97 m_data[key] = Any(static_cast<typename detail::MetadataKeyTraits<metadataKey>::type>(std::forward<T>(value)));
98 }
99
108 PEAK_COMMON_NO_DISCARD bool HasEntryByName(const std::string& name) const
109 {
110 return m_data.find(name) != m_data.end(); // NOLINT
111 }
112
123 template <MetadataKey metadataKey>
125 {
126 using trait = detail::MetadataKeyTraits<metadataKey>;
127 const auto hasKey = HasEntryByName(trait::Name());
128
129 if (hasKey)
130 {
131 const auto hasCorrectType = TryGetValueByName(trait::Name()).GetType() == typeid(typename trait::type);
132 return hasCorrectType;
133 }
134
135 return false;
136 }
137
146 PEAK_COMMON_NO_DISCARD Any TryGetValueByName(const std::string& name) const
147 {
148 if (!HasEntryByName(name))
149 {
150 return {};
151 }
152
153 return m_data.at(name);
154 }
155
169 template <typename T>
170 PEAK_COMMON_NO_DISCARD T GetValueByName(const std::string& name) const
171 {
172 static_assert(detail::is_in_tuple<std::decay_t<T>, allowedTypes>::value, "T must be one of the allowedTypes!");
173
174 if (!HasEntryByName(name))
175 {
176 throw OutOfRangeException("There is no value named " + name);
177 }
178
179 return TryGetValueByName(name).AnyCast<T>();
180 }
181
197 template <MetadataKey metadataKey>
198 PEAK_COMMON_NO_DISCARD typename detail::MetadataKeyTraits<metadataKey>::type GetValueByKey() const
199 {
200 using trait = detail::MetadataKeyTraits<metadataKey>;
201 if (!HasEntryByName(trait::Name()))
202 {
203 const std::string keyName = trait::Name();
204 throw OutOfRangeException("There is no value named " + keyName);
205 }
206
207 return TryGetValueByName(trait::Name()).template AnyCast<typename trait::type>();
208 }
209
221 friend std::ostream& operator<<(std::ostream& os, const Metadata& metadata)
222 {
223 bool first = true;
224 os << "{";
225 for (const auto& pair : metadata.m_data)
226 {
227 if (!first)
228 {
229 os << ',';
230 }
231
232 // NOTE: Cannot output value, as we don't know the type...
233 os << " \"" << pair.first << "\"";
234
235 first = false;
236 }
237 os << " }";
238
239 return os;
240 }
241
252 {
253 std::ostringstream ss;
254 ss << *this;
255 return ss.str();
256 }
257
265 PEAK_COMMON_NO_DISCARD std::vector<std::string> GetKeyNames() const
266 {
267 std::vector<std::string> names;
268 names.reserve(m_data.size());
269 std::transform(m_data.cbegin(), m_data.cend(), std::back_inserter(names), [](const auto& pair) {
270 return pair.first;
271 });
272
273 return names;
274 }
275
276private:
277 template <typename T>
278 void Dispatch(const std::string& key, T&& value, std::true_type)
279 {
280 using Decayed = typename std::decay<T>::type;
281
282 static_assert(detail::is_in_tuple<Decayed, allowedTypes>::value, "Lvalue type must be exactly one of the 'allowedTypes'!");
283
284 m_data[key] = Any(value);
285 }
286
287 template <typename T>
288 void Dispatch(const std::string& key, T&& value, std::false_type)
289 {
290 using Normalized = detail::normalize_t<T>;
291
292 static_assert(detail::is_in_tuple<Normalized, allowedTypes>::value,
293 "Rvalue type must be one of the 'allowedTypes' or be able to be widened into one of the 'allowedTypes'!");
294
295 m_data[key] = Any(Cast(std::forward<T>(value)));
296 }
297
298 template <typename T>
299 void SetValueByNameInternal(const std::string& name, T&& value)
300 {
301 m_data[name] = Any(std::forward<T>(value));
302 }
303
304 template <typename T>
305 static detail::normalize_t<T> Cast(T&& v)
306 {
307 return static_cast<detail::normalize_t<T>>(v);
308 }
309
310 template <typename T>
311 static std::vector<T> Cast(std::vector<T>&& v)
312 {
313 return std::move(v);
314 }
315
316 std::unordered_map<std::string, Any> m_data;
317
319};
320
321namespace detail
322{
324{
325 template <typename T>
326 static void SetValueByName(Metadata& metadata, const std::string& key, T&& value)
327 {
328 metadata.SetValueByNameInternal(key, std::forward<T>(value));
329 }
330};
331} // namespace detail
332
333} // namespace common
334} // namespace peak
A type-erased container for any copyable value.
Definition peak_common_any.hpp:31
T & AnyCast()
Casts the stored value to the specified type.
Definition peak_common_any.hpp:174
PEAK_COMMON_NO_DISCARD const std::type_info & GetType() const
Gets the type of the stored value.
Definition peak_common_any.hpp:159
Type-safe container for image acquisition metadata.
Definition peak_common_metadata.hpp:44
PEAK_COMMON_NO_DISCARD Any TryGetValueByName(const std::string &name) const
Retrieves a value by string name as a type-erased object.
Definition peak_common_metadata.hpp:146
friend std::ostream & operator<<(std::ostream &os, const Metadata &metadata)
Outputs the metadata keys in human-readable form.
Definition peak_common_metadata.hpp:221
PEAK_COMMON_NO_DISCARD bool HasEntryByKey() const
Checks if a known key is stored in the metadata.
Definition peak_common_metadata.hpp:124
PEAK_COMMON_NO_DISCARD bool HasEntryByName(const std::string &name) const
Checks if a given string key is stored in the metadata.
Definition peak_common_metadata.hpp:108
void SetValueByName(const std::string &name, T &&value)
Stores a value using a string-based name.
Definition peak_common_metadata.hpp:59
void SetValueByKey(T value)
Stores a value using a strongly typed metadata key.
Definition peak_common_metadata.hpp:92
PEAK_COMMON_NO_DISCARD detail::MetadataKeyTraits< metadataKey >::type GetValueByKey() const
Retrieves the value of a strongly typed metadata key.
Definition peak_common_metadata.hpp:198
PEAK_COMMON_NO_DISCARD std::vector< std::string > GetKeyNames() const
Returns a vector of key names.
Definition peak_common_metadata.hpp:265
PEAK_COMMON_NO_DISCARD T GetValueByName(const std::string &name) const
Retrieves and casts the value associated with a string name.
Definition peak_common_metadata.hpp:170
void RemoveEntryByName(const std::string &name)
Removes the entry using a string-based name.
Definition peak_common_metadata.hpp:73
std::tuple< int64_t, std::vector< int64_t >, double, std::vector< double >, std::string, std::vector< std::string >, bool, std::vector< bool > > allowedTypes
Definition peak_common_metadata.hpp:46
PEAK_COMMON_NO_DISCARD std::string ToString() const
Returns a string representation of the metadata.
Definition peak_common_metadata.hpp:251
Thrown when a parameter is outside the valid range.
Definition peak_common_exceptions.hpp:114
Namespace for internal implementation details and low-level types.
Definition peak_common_math.hpp:19
Root namespace for common types and interfaces shared across multiple libraries.
Definition peak_common_math.hpp:17
The "peak" namespace directly contains convenience functionality like the DeviceManager as well as th...
Definition peak_buffer.hpp:29
#define PEAK_COMMON_NO_DISCARD
Definition peak_common_defines.h:89
Definition peak_common_metadata.hpp:324
static void SetValueByName(Metadata &metadata, const std::string &key, T &&value)
Definition peak_common_metadata.hpp:326