| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Copyright Contributors to the OpenVDB Project | ||
| 2 | // SPDX-License-Identifier: MPL-2.0 | ||
| 3 | |||
| 4 | /// @file points/AttributeArrayString.h | ||
| 5 | /// | ||
| 6 | /// @author Dan Bailey | ||
| 7 | /// | ||
| 8 | /// @brief Attribute array storage for string data using Descriptor Metadata. | ||
| 9 | |||
| 10 | #ifndef OPENVDB_POINTS_ATTRIBUTE_ARRAY_STRING_HAS_BEEN_INCLUDED | ||
| 11 | #define OPENVDB_POINTS_ATTRIBUTE_ARRAY_STRING_HAS_BEEN_INCLUDED | ||
| 12 | |||
| 13 | #include "AttributeArray.h" | ||
| 14 | #include <memory> | ||
| 15 | #include <deque> | ||
| 16 | #include <unordered_map> | ||
| 17 | |||
| 18 | |||
| 19 | namespace openvdb { | ||
| 20 | OPENVDB_USE_VERSION_NAMESPACE | ||
| 21 | namespace OPENVDB_VERSION_NAME { | ||
| 22 | namespace points { | ||
| 23 | |||
| 24 | |||
| 25 | //////////////////////////////////////// | ||
| 26 | |||
| 27 | |||
| 28 | namespace attribute_traits | ||
| 29 | { | ||
| 30 | template <bool Truncate> struct StringTypeTrait { using Type = Index; }; | ||
| 31 | template<> struct StringTypeTrait</*Truncate=*/true> { using Type = uint16_t; }; | ||
| 32 | } | ||
| 33 | |||
| 34 | |||
| 35 | template <bool Truncate> | ||
| 36 | struct StringCodec | ||
| 37 | { | ||
| 38 | using ValueType = Index; | ||
| 39 | |||
| 40 | template <typename T> | ||
| 41 | struct Storage { using Type = typename attribute_traits::StringTypeTrait<Truncate>::Type; }; | ||
| 42 | |||
| 43 | template<typename StorageType> static void decode(const StorageType&, ValueType&); | ||
| 44 | template<typename StorageType> static void encode(const ValueType&, StorageType&); | ||
| 45 | static const char* name() { return Truncate ? "str_trnc" : "str"; } | ||
| 46 | }; | ||
| 47 | |||
| 48 | |||
| 49 | using StringAttributeArray = TypedAttributeArray<Index, StringCodec<false>>; | ||
| 50 | |||
| 51 | |||
| 52 | //////////////////////////////////////// | ||
| 53 | |||
| 54 | |||
| 55 | /// Class to compute a string->index map from all string:N metadata | ||
| 56 | 845 | class OPENVDB_API StringMetaCache | |
| 57 | { | ||
| 58 | public: | ||
| 59 | using UniquePtr = std::unique_ptr<StringMetaCache>; | ||
| 60 | using ValueMap = std::unordered_map<Name, Index>; | ||
| 61 | |||
| 62 | StringMetaCache() = default; | ||
| 63 | explicit StringMetaCache(const MetaMap& metadata); | ||
| 64 | |||
| 65 | /// Return @c true if no string elements in metadata | ||
| 66 | bool empty() const { return mCache.empty(); } | ||
| 67 | /// Returns the number of string elements in metadata | ||
| 68 | size_t size() const { return mCache.size(); } | ||
| 69 | |||
| 70 | /// Clears and re-populates the cache | ||
| 71 | void reset(const MetaMap& metadata); | ||
| 72 | |||
| 73 | /// Insert a new element in the cache | ||
| 74 | void insert(const Name& key, Index index); | ||
| 75 | |||
| 76 | /// Retrieve the value map (string -> index) | ||
| 77 | const ValueMap& map() const { return mCache; } | ||
| 78 | |||
| 79 | private: | ||
| 80 | ValueMap mCache; | ||
| 81 | }; // StringMetaCache | ||
| 82 | |||
| 83 | |||
| 84 | //////////////////////////////////////// | ||
| 85 | |||
| 86 | |||
| 87 | /// Class to help with insertion of keyed string values into metadata | ||
| 88 | 4 | class OPENVDB_API StringMetaInserter | |
| 89 | { | ||
| 90 | public: | ||
| 91 | using UniquePtr = std::unique_ptr<StringMetaInserter>; | ||
| 92 | |||
| 93 | explicit StringMetaInserter(MetaMap& metadata); | ||
| 94 | |||
| 95 | /// Returns @c true if key exists | ||
| 96 | bool hasKey(const Name& key) const; | ||
| 97 | /// Returns @c true if index exists | ||
| 98 | bool hasIndex(Index index) const; | ||
| 99 | |||
| 100 | /// @brief Insert the string into the metadata using the hint if non-zero | ||
| 101 | /// @param name the string to insert | ||
| 102 | /// @param hint requested index to use if non-zero and not already in use | ||
| 103 | /// @note the hint can be used to insert non-sequentially so as to avoid an | ||
| 104 | /// expensive re-indexing of string keys | ||
| 105 | /// @return the chosen index which will match hint if the hint was used | ||
| 106 | Index insert(const Name& name, Index hint = Index(0)); | ||
| 107 | |||
| 108 | /// Reset the cache from the metadata | ||
| 109 | void resetCache(); | ||
| 110 | |||
| 111 | private: | ||
| 112 | using IndexPairArray = std::deque<std::pair<Index, Index>>; | ||
| 113 | |||
| 114 | MetaMap& mMetadata; | ||
| 115 | IndexPairArray mIdBlocks; | ||
| 116 | StringMetaCache mCache; | ||
| 117 | }; // StringMetaInserter | ||
| 118 | |||
| 119 | |||
| 120 | //////////////////////////////////////// | ||
| 121 | |||
| 122 | |||
| 123 | template <bool Truncate> | ||
| 124 | template<typename StorageType> | ||
| 125 | inline void | ||
| 126 | StringCodec<Truncate>::decode(const StorageType& data, ValueType& val) | ||
| 127 | { | ||
| 128 | 1507578 | val = static_cast<ValueType>(data); | |
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | template <bool Truncate> | ||
| 133 | template<typename StorageType> | ||
| 134 | inline void | ||
| 135 | StringCodec<Truncate>::encode(const ValueType& val, StorageType& data) | ||
| 136 | { | ||
| 137 | 6947 | data = static_cast<ValueType>(val); | |
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | //////////////////////////////////////// | ||
| 142 | |||
| 143 | |||
| 144 | inline bool isString(const AttributeArray& array) | ||
| 145 | { | ||
| 146 |
8/16✓ Branch 1 taken 9234 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
|
9241 | return array.isType<StringAttributeArray>(); |
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | //////////////////////////////////////// | ||
| 151 | |||
| 152 | |||
| 153 | 5822 | class OPENVDB_API StringAttributeHandle | |
| 154 | { | ||
| 155 | public: | ||
| 156 | using Ptr = std::shared_ptr<StringAttributeHandle>;//SharedPtr<StringAttributeHandle>; | ||
| 157 | using UniquePtr = std::unique_ptr<StringAttributeHandle>; | ||
| 158 | |||
| 159 | static Ptr create(const AttributeArray& array, const MetaMap& metadata, const bool preserveCompression = true); | ||
| 160 | |||
| 161 | StringAttributeHandle( const AttributeArray& array, | ||
| 162 | const MetaMap& metadata, | ||
| 163 | const bool preserveCompression = true); | ||
| 164 | |||
| 165 | Index stride() const { return mHandle.stride(); } | ||
| 166 | Index size() const { return mHandle.size(); } | ||
| 167 | |||
| 168 |
9/18✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 1 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 1 times.
✗ Branch 17 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 22 taken 1 times.
✗ Branch 23 not taken.
✓ Branch 25 taken 1 times.
✗ Branch 26 not taken.
|
5816 | bool isUniform() const { return mHandle.isUniform(); } |
| 169 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
3 | bool hasConstantStride() const { return mHandle.hasConstantStride(); } |
| 170 | |||
| 171 | Name get(Index n, Index m = 0) const; | ||
| 172 | void get(Name& name, Index n, Index m = 0) const; | ||
| 173 | |||
| 174 | /// @brief Returns a reference to the array held in the Handle. | ||
| 175 | const AttributeArray& array() const; | ||
| 176 | |||
| 177 | protected: | ||
| 178 | AttributeHandle<Index, StringCodec<false>> mHandle; | ||
| 179 | const MetaMap& mMetadata; | ||
| 180 | }; // class StringAttributeHandle | ||
| 181 | |||
| 182 | |||
| 183 | //////////////////////////////////////// | ||
| 184 | |||
| 185 | |||
| 186 | class OPENVDB_API StringAttributeWriteHandle : public StringAttributeHandle | ||
| 187 | { | ||
| 188 | public: | ||
| 189 | using Ptr = std::shared_ptr<StringAttributeWriteHandle>;//SharedPtr<StringAttributeWriteHandle>; | ||
| 190 | using UniquePtr = std::unique_ptr<StringAttributeWriteHandle>; | ||
| 191 | |||
| 192 | static Ptr create(AttributeArray& array, const MetaMap& metadata, const bool expand = true); | ||
| 193 | |||
| 194 | StringAttributeWriteHandle( AttributeArray& array, | ||
| 195 | const MetaMap& metadata, | ||
| 196 | const bool expand = true); | ||
| 197 | |||
| 198 | /// @brief If this array is uniform, replace it with an array of length size(). | ||
| 199 | /// @param fill if true, assign the uniform value to each element of the array. | ||
| 200 | void expand(bool fill = true); | ||
| 201 | |||
| 202 | /// @brief Set membership for the whole array and attempt to collapse | ||
| 203 | void collapse(); | ||
| 204 | /// @brief Set membership for the whole array and attempt to collapse | ||
| 205 | /// @param name Name of the String | ||
| 206 | void collapse(const Name& name); | ||
| 207 | |||
| 208 | /// Compact the existing array to become uniform if all values are identical | ||
| 209 | bool compact(); | ||
| 210 | |||
| 211 | /// @brief Fill the existing array with the given value. | ||
| 212 | /// @note Identical to collapse() except a non-uniform array will not become uniform. | ||
| 213 | void fill(const Name& name); | ||
| 214 | |||
| 215 | /// Set the value of the index to @a name | ||
| 216 | void set(Index n, const Name& name); | ||
| 217 | void set(Index n, Index m, const Name& name); | ||
| 218 | |||
| 219 | /// Reset the value cache from the metadata | ||
| 220 | void resetCache(); | ||
| 221 | |||
| 222 | /// @brief Returns a reference to the array held in the Write Handle. | ||
| 223 | AttributeArray& array(); | ||
| 224 | |||
| 225 | /// @brief Returns whether or not the metadata cache contains a given value. | ||
| 226 | /// @param name Name of the String. | ||
| 227 | bool contains(const Name& name) const; | ||
| 228 | |||
| 229 | private: | ||
| 230 | /// Retrieve the index of this string value from the cache | ||
| 231 | /// @note throws if name does not exist in cache | ||
| 232 | Index getIndex(const Name& name) const; | ||
| 233 | |||
| 234 | StringMetaCache mCache; | ||
| 235 | AttributeWriteHandle<Index, StringCodec<false>> mWriteHandle; | ||
| 236 | }; // class StringAttributeWriteHandle | ||
| 237 | |||
| 238 | |||
| 239 | //////////////////////////////////////// | ||
| 240 | |||
| 241 | |||
| 242 | } // namespace points | ||
| 243 | } // namespace OPENVDB_VERSION_NAME | ||
| 244 | } // namespace openvdb | ||
| 245 | |||
| 246 | #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_STRING_HAS_BEEN_INCLUDED | ||
| 247 | |||
| 248 |