Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | #ifndef OPENVDB_METADATA_METAMAP_HAS_BEEN_INCLUDED | ||
5 | #define OPENVDB_METADATA_METAMAP_HAS_BEEN_INCLUDED | ||
6 | |||
7 | #include "Metadata.h" | ||
8 | #include "Types.h" | ||
9 | #include "Exceptions.h" | ||
10 | #include <iosfwd> | ||
11 | #include <map> | ||
12 | |||
13 | |||
14 | namespace openvdb { | ||
15 | OPENVDB_USE_VERSION_NAMESPACE | ||
16 | namespace OPENVDB_VERSION_NAME { | ||
17 | |||
18 | /// Container that maps names (strings) to values of arbitrary types | ||
19 | class OPENVDB_API MetaMap | ||
20 | { | ||
21 | public: | ||
22 | using Ptr = SharedPtr<MetaMap>; | ||
23 | using ConstPtr = SharedPtr<const MetaMap>; | ||
24 | |||
25 | using MetadataMap = std::map<Name, Metadata::Ptr>; | ||
26 | using MetaIterator = MetadataMap::iterator; | ||
27 | using ConstMetaIterator = MetadataMap::const_iterator; | ||
28 | ///< @todo this should really iterate over a map of Metadata::ConstPtrs | ||
29 | |||
30 |
26/52✓ Branch 1 taken 24036 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 179 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 19 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 13 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 2 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 2 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 2 times.
✗ Branch 26 not taken.
✓ Branch 28 taken 2 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 2 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 2 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✗ Branch 44 not taken.
✓ Branch 45 taken 1 times.
✓ Branch 47 taken 1 times.
✗ Branch 48 not taken.
✓ Branch 50 taken 1 times.
✗ Branch 51 not taken.
✓ Branch 53 taken 1 times.
✗ Branch 54 not taken.
✓ Branch 56 taken 1 times.
✗ Branch 57 not taken.
✓ Branch 59 taken 1 times.
✗ Branch 60 not taken.
✓ Branch 62 taken 2 times.
✗ Branch 63 not taken.
✓ Branch 65 taken 1 times.
✗ Branch 66 not taken.
✓ Branch 68 taken 1 times.
✗ Branch 69 not taken.
✓ Branch 71 taken 1 times.
✗ Branch 72 not taken.
✓ Branch 74 taken 194 times.
✗ Branch 75 not taken.
|
83199 | MetaMap() {} |
31 | MetaMap(const MetaMap& other); | ||
32 |
6/12✓ Branch 1 taken 59 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 15 taken 1 times.
✗ Branch 16 not taken.
✓ Branch 27 taken 1 times.
✗ Branch 28 not taken.
✓ Branch 39 taken 1 times.
✗ Branch 40 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
|
26981 | virtual ~MetaMap() {} |
33 | |||
34 | /// Return a copy of this map whose fields are shared with this map. | ||
35 | MetaMap::Ptr copyMeta() const; | ||
36 | /// Return a deep copy of this map that shares no data with this map. | ||
37 | MetaMap::Ptr deepCopyMeta() const; | ||
38 | |||
39 | /// Assign a deep copy of another map to this map. | ||
40 | MetaMap& operator=(const MetaMap&); | ||
41 | |||
42 | /// Unserialize metadata from the given stream. | ||
43 | void readMeta(std::istream&); | ||
44 | /// Serialize metadata to the given stream. | ||
45 | void writeMeta(std::ostream&) const; | ||
46 | |||
47 | /// @brief Insert a new metadata field or overwrite the value of an existing field. | ||
48 | /// @details If a field with the given name doesn't already exist, add a new field. | ||
49 | /// Otherwise, if the new value's type is the same as the existing field's value type, | ||
50 | /// overwrite the existing value with new value. | ||
51 | /// @throw TypeError if a field with the given name already exists, but its value type | ||
52 | /// is not the same as the new value's | ||
53 | /// @throw ValueError if the given field name is empty. | ||
54 | void insertMeta(const Name&, const Metadata& value); | ||
55 | /// @brief Deep copy all of the metadata fields from the given map into this map. | ||
56 | /// @throw TypeError if any field in the given map has the same name as | ||
57 | /// but a different value type than one of this map's fields. | ||
58 | void insertMeta(const MetaMap&); | ||
59 | |||
60 | /// Remove the given metadata field if it exists. | ||
61 | void removeMeta(const Name&); | ||
62 | |||
63 | //@{ | ||
64 | /// @brief Return a pointer to the metadata with the given name. | ||
65 | /// If no such field exists, return a null pointer. | ||
66 | Metadata::Ptr operator[](const Name&); | ||
67 | Metadata::ConstPtr operator[](const Name&) const; | ||
68 | //@} | ||
69 | |||
70 | //@{ | ||
71 | /// @brief Return a pointer to a TypedMetadata object of type @c T and with the given name. | ||
72 | /// If no such field exists or if there is a type mismatch, return a null pointer. | ||
73 | template<typename T> typename T::Ptr getMetadata(const Name&); | ||
74 | template<typename T> typename T::ConstPtr getMetadata(const Name&) const; | ||
75 | //@} | ||
76 | |||
77 | /// @brief Return a reference to the value of type @c T stored in the given metadata field. | ||
78 | /// @throw LookupError if no field with the given name exists. | ||
79 | /// @throw TypeError if the given field is not of type @c T. | ||
80 | template<typename T> T& metaValue(const Name&); | ||
81 | template<typename T> const T& metaValue(const Name&) const; | ||
82 | |||
83 | // Functions for iterating over the metadata | ||
84 | MetaIterator beginMeta() { return mMeta.begin(); } | ||
85 | MetaIterator endMeta() { return mMeta.end(); } | ||
86 | ConstMetaIterator beginMeta() const { return mMeta.begin(); } | ||
87 | ConstMetaIterator endMeta() const { return mMeta.end(); } | ||
88 | |||
89 | void clearMetadata() { mMeta.clear(); } | ||
90 | |||
91 | size_t metaCount() const { return mMeta.size(); } | ||
92 | |||
93 | /// Return a string describing this metadata map. Prefix each line with @a indent. | ||
94 | std::string str(const std::string& indent = "") const; | ||
95 | |||
96 | /// Return @c true if the given map is equivalent to this map. | ||
97 | bool operator==(const MetaMap& other) const; | ||
98 | /// Return @c true if the given map is different from this map. | ||
99 |
20/40✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✓ Branch 11 taken 1 times.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 1 times.
✓ Branch 21 taken 1 times.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✓ Branch 24 taken 1 times.
✓ Branch 26 taken 1 times.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 times.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✓ Branch 34 taken 1 times.
✓ Branch 36 taken 1 times.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✓ Branch 39 taken 1 times.
✓ Branch 41 taken 1 times.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✓ Branch 44 taken 1 times.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✗ Branch 48 not taken.
✓ Branch 49 taken 1 times.
|
6213 | bool operator!=(const MetaMap& other) const { return !(*this == other); } |
100 | |||
101 | private: | ||
102 | /// @brief Return a pointer to TypedMetadata with the given template parameter. | ||
103 | /// @throw LookupError if no field with the given name is found. | ||
104 | /// @throw TypeError if the given field is not of type T. | ||
105 | template<typename T> | ||
106 | typename TypedMetadata<T>::Ptr getValidTypedMetadata(const Name&) const; | ||
107 | |||
108 | MetadataMap mMeta; | ||
109 | }; | ||
110 | |||
111 | /// Write a MetaMap to an output stream | ||
112 | std::ostream& operator<<(std::ostream&, const MetaMap&); | ||
113 | |||
114 | |||
115 | //////////////////////////////////////// | ||
116 | |||
117 | |||
118 | inline Metadata::Ptr | ||
119 | 234 | MetaMap::operator[](const Name& name) | |
120 | { | ||
121 |
2/2✓ Branch 0 taken 94 times.
✓ Branch 1 taken 140 times.
|
234 | MetaIterator iter = mMeta.find(name); |
122 |
2/2✓ Branch 0 taken 94 times.
✓ Branch 1 taken 140 times.
|
234 | return (iter == mMeta.end() ? Metadata::Ptr() : iter->second); |
123 | } | ||
124 | |||
125 | inline Metadata::ConstPtr | ||
126 | 52778 | MetaMap::operator[](const Name &name) const | |
127 | { | ||
128 |
2/2✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 51266 times.
|
52778 | ConstMetaIterator iter = mMeta.find(name); |
129 |
2/2✓ Branch 0 taken 1512 times.
✓ Branch 1 taken 51266 times.
|
52778 | return (iter == mMeta.end() ? Metadata::Ptr() : iter->second); |
130 | } | ||
131 | |||
132 | |||
133 | //////////////////////////////////////// | ||
134 | |||
135 | |||
136 | template<typename T> | ||
137 | inline typename T::Ptr | ||
138 | 12826 | MetaMap::getMetadata(const Name &name) | |
139 | { | ||
140 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12819 times.
|
12826 | ConstMetaIterator iter = mMeta.find(name); |
141 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12819 times.
|
12826 | if (iter == mMeta.end()) return typename T::Ptr{}; |
142 | |||
143 | // To ensure that we get valid conversion if the metadata pointers cross dso | ||
144 | // boundaries, we have to check the qualified typename and then do a static | ||
145 | // cast. This is slower than doing a dynamic_pointer_cast, but is safer when | ||
146 | // pointers cross dso boundaries. | ||
147 |
3/4✓ Branch 1 taken 12819 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 12818 times.
✓ Branch 6 taken 1 times.
|
12822 | if (iter->second->typeName() == T::staticTypeName()) { |
148 | 12820 | return StaticPtrCast<T, Metadata>(iter->second); | |
149 | } // else | ||
150 | return typename T::Ptr{}; | ||
151 | } | ||
152 | |||
153 | template<typename T> | ||
154 | inline typename T::ConstPtr | ||
155 | 1500665 | MetaMap::getMetadata(const Name &name) const | |
156 | { | ||
157 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 1500323 times.
|
1500665 | ConstMetaIterator iter = mMeta.find(name); |
158 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 1500323 times.
|
1500665 | if (iter == mMeta.end()) return typename T::ConstPtr{}; |
159 | |||
160 | // To ensure that we get valid conversion if the metadata pointers cross dso | ||
161 | // boundaries, we have to check the qualified typename and then do a static | ||
162 | // cast. This is slower than doing a dynamic_pointer_cast, but is safer when | ||
163 | // pointers cross dso boundaries. | ||
164 |
2/4✓ Branch 1 taken 1500323 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1500323 times.
✗ Branch 6 not taken.
|
1500325 | if (iter->second->typeName() == T::staticTypeName()) { |
165 | 1500325 | return StaticPtrCast<const T, const Metadata>(iter->second); | |
166 | } // else | ||
167 | return typename T::ConstPtr{}; | ||
168 | } | ||
169 | |||
170 | |||
171 | //////////////////////////////////////// | ||
172 | |||
173 | |||
174 | template<typename T> | ||
175 | inline typename TypedMetadata<T>::Ptr | ||
176 | 230 | MetaMap::getValidTypedMetadata(const Name &name) const | |
177 | { | ||
178 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 114 times.
|
230 | ConstMetaIterator iter = mMeta.find(name); |
179 |
3/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 114 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
236 | if (iter == mMeta.end()) OPENVDB_THROW(LookupError, "Cannot find metadata " << name); |
180 | |||
181 | // To ensure that we get valid conversion if the metadata pointers cross dso | ||
182 | // boundaries, we have to check the qualified typename and then do a static | ||
183 | // cast. This is slower than doing a dynamic_pointer_cast, but is safer when | ||
184 | // pointers cross dso boundaries. | ||
185 |
1/2✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
|
228 | typename TypedMetadata<T>::Ptr m; |
186 |
4/6✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 113 times.
✓ Branch 6 taken 1 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
|
230 | if (iter->second->typeName() == TypedMetadata<T>::staticTypeName()) { |
187 | 452 | m = StaticPtrCast<TypedMetadata<T>, Metadata>(iter->second); | |
188 | } | ||
189 |
3/6✓ Branch 0 taken 1 times.
✓ Branch 1 taken 113 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
|
234 | if (!m) OPENVDB_THROW(TypeError, "Invalid type for metadata " << name); |
190 | 226 | return m; | |
191 | } | ||
192 | |||
193 | |||
194 | //////////////////////////////////////// | ||
195 | |||
196 | |||
197 | template<typename T> | ||
198 | inline T& | ||
199 | 157 | MetaMap::metaValue(const Name &name) | |
200 | { | ||
201 | 157 | typename TypedMetadata<T>::Ptr m = getValidTypedMetadata<T>(name); | |
202 | 154 | return m->value(); | |
203 | } | ||
204 | |||
205 | |||
206 | template<typename T> | ||
207 | inline const T& | ||
208 | 17 | MetaMap::metaValue(const Name &name) const | |
209 | { | ||
210 | 17 | typename TypedMetadata<T>::Ptr m = getValidTypedMetadata<T>(name); | |
211 | 17 | return m->value(); | |
212 | } | ||
213 | |||
214 | } // namespace OPENVDB_VERSION_NAME | ||
215 | } // namespace openvdb | ||
216 | |||
217 | #endif // OPENVDB_METADATA_METAMAP_HAS_BEEN_INCLUDED | ||
218 |