IDS peak AFL v2.0.2
Loading...
Searching...
No Matches
peak_common_metadata.hpp
Go to the documentation of this file.
1
10
11#pragma once
12
18
19#include <unordered_map>
20#include <algorithm>
21#include <sstream>
22#include <vector>
23
24namespace peak
25{
26namespace common
27{
28namespace detail
29{
30struct MetadataAccessor;
31}
32
49{
50public:
51 using allowedTypes = std::tuple<int64_t, std::vector<int64_t>, double, std::vector<double>, std::string, std::vector<std::string>, bool,
52 std::vector<bool>>;
53
63 template <typename T>
64 void SetValueByName(const std::string& name, T&& value)
65 {
66 Dispatch(name, std::forward<T>(value), std::is_lvalue_reference<T>{});
67 }
68
78 void RemoveEntryByName(const std::string& name)
79 {
80 m_data.erase(name);
81 }
82
96 template <MetadataKey metadataKey, typename T>
97 void SetValueByKey(T value)
98 {
99 static_assert(
100 std::is_convertible<T, typename detail::MetadataKeyTraits<metadataKey>::type>::value, "Incorrect value type for metadata key");
101 constexpr auto key = detail::MetadataKeyTraits<metadataKey>::Name();
102 m_data[key] = Any(static_cast<typename detail::MetadataKeyTraits<metadataKey>::type>(std::forward<T>(value)));
103 }
104
113 PEAK_COMMON_NO_DISCARD bool HasEntryByName(const std::string& name) const
114 {
115 return m_data.find(name) != m_data.end(); // NOLINT
116 }
117
128 template <MetadataKey metadataKey>
129 PEAK_COMMON_NO_DISCARD bool HasEntryByKey() const
130 {
131 using trait = detail::MetadataKeyTraits<metadataKey>;
132 const auto hasKey = HasEntryByName(trait::Name());
133
134 if (hasKey)
135 {
136 const auto hasCorrectType = TryGetValueByName(trait::Name()).GetType() == typeid(typename trait::type);
137 return hasCorrectType;
138 }
139
140 return false;
141 }
142
151 PEAK_COMMON_NO_DISCARD Any TryGetValueByName(const std::string& name) const
152 {
153 if (!HasEntryByName(name))
154 {
155 return {};
156 }
157
158 return m_data.at(name);
159 }
160
174 template <typename T>
175 PEAK_COMMON_NO_DISCARD T GetValueByName(const std::string& name) const
176 {
177 static_assert(detail::is_in_tuple<std::decay_t<T>, allowedTypes>::value, "T must be one of the allowedTypes!");
178
179 if (!HasEntryByName(name))
180 {
181 throw OutOfRangeException("There is no value named " + name);
182 }
183
184 return TryGetValueByName(name).AnyCast<T>();
185 }
186
202 template <MetadataKey metadataKey>
203 PEAK_COMMON_NO_DISCARD typename detail::MetadataKeyTraits<metadataKey>::type GetValueByKey() const
204 {
205 using trait = detail::MetadataKeyTraits<metadataKey>;
206 if (!HasEntryByName(trait::Name()))
207 {
208 const std::string keyName = trait::Name();
209 throw OutOfRangeException("There is no value named " + keyName);
210 }
211
212 return TryGetValueByName(trait::Name()).template AnyCast<typename trait::type>();
213 }
214
226 friend std::ostream& operator<<(std::ostream& os, const Metadata& metadata)
227 {
228 bool first = true;
229 os << "{";
230 for (const auto& pair : metadata.m_data)
231 {
232 if (!first)
233 {
234 os << ',';
235 }
236
237 // NOTE: Cannot output value, as we don't know the type...
238 os << " \"" << pair.first << "\"";
239
240 first = false;
241 }
242 os << " }";
243
244 return os;
245 }
246
256 PEAK_COMMON_NO_DISCARD std::string ToString() const
257 {
258 std::ostringstream ss;
259 ss << *this;
260 return ss.str();
261 }
262
270 PEAK_COMMON_NO_DISCARD std::vector<std::string> GetKeyNames() const
271 {
272 std::vector<std::string> names;
273 names.reserve(m_data.size());
274 std::transform(m_data.cbegin(), m_data.cend(), std::back_inserter(names), [](const auto& pair) {
275 return pair.first;
276 });
277
278 return names;
279 }
280
281private:
282 template <typename T>
283 void Dispatch(const std::string& key, T&& value, std::true_type)
284 {
285 using Decayed = typename std::decay<T>::type;
286
287 static_assert(detail::is_in_tuple<Decayed, allowedTypes>::value, "Lvalue type must be exactly one of the 'allowedTypes'!");
288
289 m_data[key] = Any(value);
290 }
291
292 template <typename T>
293 void Dispatch(const std::string& key, T&& value, std::false_type)
294 {
295 using Normalized = detail::normalize_t<T>;
296
297 static_assert(detail::is_in_tuple<Normalized, allowedTypes>::value,
298 "Rvalue type must be one of the 'allowedTypes' or be able to be widened into one of the 'allowedTypes'!");
299
300 m_data[key] = Any(Cast(std::forward<T>(value)));
301 }
302
303 template <typename T>
304 void SetValueByNameInternal(const std::string& name, T&& value)
305 {
306 m_data[name] = Any(std::forward<T>(value));
307 }
308
309 template <typename T>
310 static detail::normalize_t<T> Cast(T&& v)
311 {
312 return static_cast<detail::normalize_t<T>>(v);
313 }
314
315 template <typename T>
316 static std::vector<T> Cast(std::vector<T>&& v)
317 {
318 return std::move(v);
319 }
320
321 std::unordered_map<std::string, Any> m_data;
322
323 friend struct detail::MetadataAccessor;
324};
325
326namespace detail
327{
328struct MetadataAccessor
329{
330 template <typename T>
331 static void SetValueByName(Metadata& metadata, const std::string& key, T&& value)
332 {
333 metadata.SetValueByNameInternal(key, std::forward<T>(value));
334 }
335};
336} // namespace detail
337
338} // namespace common
339} // namespace peak
A type-erased container for any copyable value.
Definition peak_common_any.hpp:36
const std::type_info & GetType() const
Gets the type of the stored value.
Definition peak_common_any.hpp:164
T & AnyCast()
Casts the stored value to the specified type.
Definition peak_common_any.hpp:179
Type-safe container for image acquisition metadata.
Definition peak_common_metadata.hpp:49
Any TryGetValueByName(const std::string &name) const
Retrieves a value by string name as a type-erased object.
Definition peak_common_metadata.hpp:151
friend std::ostream & operator<<(std::ostream &os, const Metadata &metadata)
Outputs the metadata keys in human-readable form.
Definition peak_common_metadata.hpp:226
std::string ToString() const
Returns a string representation of the metadata.
Definition peak_common_metadata.hpp:256
void SetValueByName(const std::string &name, T &&value)
Stores a value using a string-based name.
Definition peak_common_metadata.hpp:64
std::vector< std::string > GetKeyNames() const
Returns a vector of key names.
Definition peak_common_metadata.hpp:270
bool HasEntryByName(const std::string &name) const
Checks if a given string key is stored in the metadata.
Definition peak_common_metadata.hpp:113
void SetValueByKey(T value)
Stores a value using a strongly typed metadata key.
Definition peak_common_metadata.hpp:97
T GetValueByName(const std::string &name) const
Retrieves and casts the value associated with a string name.
Definition peak_common_metadata.hpp:175
void RemoveEntryByName(const std::string &name)
Removes the entry using a string-based name.
Definition peak_common_metadata.hpp:78
bool HasEntryByKey() const
Checks if a known key is stored in the metadata.
Definition peak_common_metadata.hpp:129
detail::MetadataKeyTraits< metadataKey >::type GetValueByKey() const
Retrieves the value of a strongly typed metadata key.
Definition peak_common_metadata.hpp:203
Thrown when a parameter is outside the valid range.
Definition peak_common_exceptions.hpp:119
Namespace for internal implementation details and low-level types.
Definition peak_common_math.hpp:24
Root namespace for common types and interfaces shared across multiple libraries.
Definition peak_common_math.hpp:22