| 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 |