GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/MetaMap.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 33 33 100.0%
Functions: 18 19 94.7%
Branches: 86 150 57.3%

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