Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright Contributors to the OpenVDB Project | ||
2 | // SPDX-License-Identifier: MPL-2.0 | ||
3 | |||
4 | /// @file points/AttributeSet.h | ||
5 | /// | ||
6 | /// @authors Dan Bailey, Mihai Alden | ||
7 | /// | ||
8 | /// @brief Set of Attribute Arrays which tracks metadata about each array. | ||
9 | |||
10 | #ifndef OPENVDB_POINTS_ATTRIBUTE_SET_HAS_BEEN_INCLUDED | ||
11 | #define OPENVDB_POINTS_ATTRIBUTE_SET_HAS_BEEN_INCLUDED | ||
12 | |||
13 | #include "AttributeArray.h" | ||
14 | #include <openvdb/version.h> | ||
15 | #include <openvdb/MetaMap.h> | ||
16 | |||
17 | #include <limits> | ||
18 | #include <memory> | ||
19 | #include <vector> | ||
20 | |||
21 | |||
22 | class TestAttributeSet; | ||
23 | |||
24 | |||
25 | namespace openvdb { | ||
26 | OPENVDB_USE_VERSION_NAMESPACE | ||
27 | namespace OPENVDB_VERSION_NAME { | ||
28 | namespace points { | ||
29 | |||
30 | |||
31 | using GroupType = uint8_t; | ||
32 | |||
33 | |||
34 | //////////////////////////////////////// | ||
35 | |||
36 | |||
37 | /// Ordered collection of uniquely-named attribute arrays | ||
38 | class OPENVDB_API AttributeSet | ||
39 | { | ||
40 | public: | ||
41 | enum { INVALID_POS = std::numeric_limits<size_t>::max() }; | ||
42 | |||
43 | using Ptr = std::shared_ptr<AttributeSet>; | ||
44 | using ConstPtr = std::shared_ptr<const AttributeSet>; | ||
45 | using UniquePtr = std::unique_ptr<AttributeSet>; | ||
46 | |||
47 | class Descriptor; | ||
48 | |||
49 | using DescriptorPtr = std::shared_ptr<Descriptor>; | ||
50 | using DescriptorConstPtr = std::shared_ptr<const Descriptor>; | ||
51 | |||
52 | ////////// | ||
53 | |||
54 | struct Util | ||
55 | { | ||
56 | /// Attribute and type name pair. | ||
57 | 67248 | struct NameAndType { | |
58 | 54992 | NameAndType(const std::string& n, const NamePair& t, const Index s = 1) | |
59 |
1/2✓ Branch 2 taken 54992 times.
✗ Branch 3 not taken.
|
54992 | : name(n), type(t), stride(s) {} |
60 | Name name; | ||
61 | NamePair type; | ||
62 | Index stride; | ||
63 | }; | ||
64 | |||
65 | using NameAndTypeVec = std::vector<NameAndType>; | ||
66 | using NameToPosMap = std::map<std::string, size_t>; | ||
67 | using GroupIndex = std::pair<size_t, uint8_t>; | ||
68 | }; | ||
69 | |||
70 | ////////// | ||
71 | |||
72 | AttributeSet(); | ||
73 | |||
74 | /// Construct a new AttributeSet from the given AttributeSet. | ||
75 | /// @param attributeSet the old attribute set | ||
76 | /// @param arrayLength the desired length of the arrays in the new AttributeSet | ||
77 | /// @param lock an optional scoped registry lock to avoid contention | ||
78 | /// @note This constructor is typically used to resize an existing AttributeSet as | ||
79 | /// it transfers attribute metadata such as hidden and transient flags | ||
80 | AttributeSet(const AttributeSet& attributeSet, Index arrayLength, | ||
81 | const AttributeArray::ScopedRegistryLock* lock = nullptr); | ||
82 | |||
83 | /// Construct a new AttributeSet from the given Descriptor. | ||
84 | /// @param descriptor stored in the new AttributeSet and used in construction | ||
85 | /// @param arrayLength the desired length of the arrays in the new AttributeSet | ||
86 | /// @param lock an optional scoped registry lock to avoid contention | ||
87 | /// @note Descriptors do not store attribute metadata such as hidden and transient flags | ||
88 | /// which live on the AttributeArrays, so for constructing from an existing AttributeSet | ||
89 | /// use the AttributeSet(const AttributeSet&, Index) constructor instead | ||
90 | AttributeSet(const DescriptorPtr& descriptor, Index arrayLength = 1, | ||
91 | const AttributeArray::ScopedRegistryLock* lock = nullptr); | ||
92 | |||
93 | /// Shallow copy constructor, the descriptor and attribute arrays will be shared. | ||
94 | AttributeSet(const AttributeSet&); | ||
95 | |||
96 | /// Disallow copy assignment, since it wouldn't be obvious whether the copy is deep or shallow. | ||
97 | AttributeSet& operator=(const AttributeSet&) = delete; | ||
98 | |||
99 | //@{ | ||
100 | /// @brief Return a reference to this attribute set's descriptor, which might | ||
101 | /// be shared with other sets. | ||
102 | Descriptor& descriptor() { return *mDescr; } | ||
103 | const Descriptor& descriptor() const { return *mDescr; } | ||
104 | //@} | ||
105 | |||
106 | /// @brief Return a pointer to this attribute set's descriptor, which might be | ||
107 | /// shared with other sets | ||
108 | DescriptorPtr descriptorPtr() const { return mDescr; } | ||
109 | |||
110 | /// Return the number of attributes in this set. | ||
111 | size_t size() const { return mAttrs.size(); } | ||
112 | |||
113 | /// Return the number of bytes of memory used by this attribute set. | ||
114 | size_t memUsage() const; | ||
115 | |||
116 | #if OPENVDB_ABI_VERSION_NUMBER >= 10 | ||
117 | /// Return the number of bytes of memory used by this attribute set once it | ||
118 | /// has been deserialized (this may be different to memUsage() if delay-loading | ||
119 | /// is in use). | ||
120 | size_t memUsageIfLoaded() const; | ||
121 | #endif | ||
122 | |||
123 | /// @brief Return the position of the attribute array whose name is @a name, | ||
124 | /// or @c INVALID_POS if no match is found. | ||
125 | size_t find(const std::string& name) const; | ||
126 | |||
127 | /// @brief Replace the attribute array whose name is @a name. | ||
128 | /// @return The position of the updated attribute array or @c INVALID_POS | ||
129 | /// if the given name does not exist or if the replacement failed because | ||
130 | /// the new array type does not comply with the descriptor. | ||
131 | size_t replace(const std::string& name, const AttributeArray::Ptr&); | ||
132 | |||
133 | /// @brief Replace the attribute array stored at position @a pos in this container. | ||
134 | /// @return The position of the updated attribute array or @c INVALID_POS | ||
135 | /// if replacement failed because the new array type does not comply with | ||
136 | /// the descriptor. | ||
137 | size_t replace(size_t pos, const AttributeArray::Ptr&); | ||
138 | |||
139 | //@{ | ||
140 | /// @brief Return a pointer to the attribute array whose name is @a name or | ||
141 | /// a null pointer if no match is found. | ||
142 | const AttributeArray* getConst(const std::string& name) const; | ||
143 | const AttributeArray* get(const std::string& name) const; | ||
144 | AttributeArray* get(const std::string& name); | ||
145 | //@} | ||
146 | |||
147 | //@{ | ||
148 | /// @brief Return a pointer to the attribute array stored at position @a pos | ||
149 | /// in this set. | ||
150 | const AttributeArray* getConst(size_t pos) const; | ||
151 | const AttributeArray* get(size_t pos) const; | ||
152 | AttributeArray* get(size_t pos); | ||
153 | //@} | ||
154 | |||
155 | //@{ | ||
156 | /// @brief Return the group offset from the name or index of the group | ||
157 | /// A group attribute array is a single byte (8-bit), each bit of which | ||
158 | /// can denote a group. The group offset is the position of the bit that | ||
159 | /// denotes the requested group if all group attribute arrays in the set | ||
160 | /// (and only attribute arrays marked as group) were to be laid out linearly | ||
161 | /// according to their order in the set. | ||
162 | size_t groupOffset(const Name& groupName) const; | ||
163 | size_t groupOffset(const Util::GroupIndex& index) const; | ||
164 | //@} | ||
165 | |||
166 | /// Return the group index from the name of the group | ||
167 | Util::GroupIndex groupIndex(const Name& groupName) const; | ||
168 | /// Return the group index from the offset of the group | ||
169 | /// @note see offset description for groupOffset() | ||
170 | Util::GroupIndex groupIndex(const size_t offset) const; | ||
171 | |||
172 | /// Return the indices of the attribute arrays which are group attribute arrays | ||
173 | std::vector<size_t> groupAttributeIndices() const; | ||
174 | |||
175 | /// Return true if the attribute array stored at position @a pos is shared. | ||
176 | bool isShared(size_t pos) const; | ||
177 | /// @brief If the attribute array stored at position @a pos is shared, | ||
178 | /// replace the array with a deep copy of itself that is not | ||
179 | /// shared with anyone else. | ||
180 | void makeUnique(size_t pos); | ||
181 | |||
182 | /// Append attribute @a attribute (simple method) | ||
183 | AttributeArray::Ptr appendAttribute(const Name& name, | ||
184 | const NamePair& type, | ||
185 | const Index strideOrTotalSize = 1, | ||
186 | const bool constantStride = true, | ||
187 | const Metadata* defaultValue = nullptr); | ||
188 | |||
189 | /// Append attribute @a attribute (descriptor-sharing) | ||
190 | /// Requires current descriptor to match @a expected | ||
191 | /// On append, current descriptor is replaced with @a replacement | ||
192 | /// Provide a @a lock object to avoid contention from appending in parallel | ||
193 | AttributeArray::Ptr appendAttribute(const Descriptor& expected, DescriptorPtr& replacement, | ||
194 | const size_t pos, const Index strideOrTotalSize = 1, | ||
195 | const bool constantStride = true, | ||
196 | const Metadata* defaultValue = nullptr, | ||
197 | const AttributeArray::ScopedRegistryLock* lock = nullptr); | ||
198 | |||
199 | /// @brief Remove and return an attribute array by name | ||
200 | /// @param name the name of the attribute array to release | ||
201 | /// @details Detaches the attribute array from this attribute set and returns it, if | ||
202 | /// @a name is invalid, returns an empty shared pointer. This also updates the descriptor | ||
203 | /// to remove the reference to the attribute array. | ||
204 | /// @note AttributeArrays are stored as shared pointers, so they are not guaranteed | ||
205 | /// to be unique. Check the reference count before blindly re-using in a new AttributeSet. | ||
206 | AttributeArray::Ptr removeAttribute(const Name& name); | ||
207 | |||
208 | /// @brief Remove and return an attribute array by index | ||
209 | /// @param pos the position index of the attribute to release | ||
210 | /// @details Detaches the attribute array from this attribute set and returns it, if | ||
211 | /// @a pos is invalid, returns an empty shared pointer. This also updates the descriptor | ||
212 | /// to remove the reference to the attribute array. | ||
213 | /// @note AttributeArrays are stored as shared pointers, so they are not guaranteed | ||
214 | /// to be unique. Check the reference count before blindly re-using in a new AttributeSet. | ||
215 | AttributeArray::Ptr removeAttribute(const size_t pos); | ||
216 | |||
217 | /// @brief Remove and return an attribute array by index (unsafe method) | ||
218 | /// @param pos the position index of the attribute to release | ||
219 | /// @details Detaches the attribute array from this attribute set and returns it, if | ||
220 | /// @a pos is invalid, returns an empty shared pointer. | ||
221 | /// In cases where the AttributeSet is due to be destroyed, a small performance | ||
222 | /// advantage can be gained by leaving the attribute array as a nullptr and not | ||
223 | /// updating the descriptor. However, this leaves the AttributeSet in an invalid | ||
224 | /// state making it unsafe to call any methods that implicitly derefence the attribute array. | ||
225 | /// @note AttributeArrays are stored as shared pointers, so they are not guaranteed | ||
226 | /// to be unique. Check the reference count before blindly re-using in a new AttributeSet. | ||
227 | /// @warning Only use this method if you're an expert and know the risks of not | ||
228 | /// updating the array of attributes or the descriptor. | ||
229 | AttributeArray::Ptr removeAttributeUnsafe(const size_t pos); | ||
230 | |||
231 | /// Drop attributes with @a pos indices (simple method) | ||
232 | /// Creates a new descriptor for this attribute set | ||
233 | void dropAttributes(const std::vector<size_t>& pos); | ||
234 | |||
235 | /// Drop attributes with @a pos indices (descriptor-sharing method) | ||
236 | /// Requires current descriptor to match @a expected | ||
237 | /// On drop, current descriptor is replaced with @a replacement | ||
238 | void dropAttributes(const std::vector<size_t>& pos, | ||
239 | const Descriptor& expected, DescriptorPtr& replacement); | ||
240 | |||
241 | /// Re-name attributes in set to match a provided descriptor | ||
242 | /// Replaces own descriptor with @a replacement | ||
243 | void renameAttributes(const Descriptor& expected, const DescriptorPtr& replacement); | ||
244 | |||
245 | /// Re order attribute set to match a provided descriptor | ||
246 | /// Replaces own descriptor with @a replacement | ||
247 | void reorderAttributes(const DescriptorPtr& replacement); | ||
248 | |||
249 | /// Replace the current descriptor with a @a replacement | ||
250 | /// Note the provided Descriptor must be identical to the replacement | ||
251 | /// unless @a allowMismatchingDescriptors is true (default is false) | ||
252 | void resetDescriptor(const DescriptorPtr& replacement, const bool allowMismatchingDescriptors = false); | ||
253 | |||
254 | /// Read the entire set from a stream. | ||
255 | void read(std::istream&); | ||
256 | /// Write the entire set to a stream. | ||
257 | /// @param outputTransient if true, write out transient attributes | ||
258 | void write(std::ostream&, bool outputTransient = false) const; | ||
259 | |||
260 | /// This will read the attribute descriptor from a stream. | ||
261 | void readDescriptor(std::istream&); | ||
262 | /// This will write the attribute descriptor to a stream. | ||
263 | /// @param outputTransient if true, write out transient attributes | ||
264 | void writeDescriptor(std::ostream&, bool outputTransient = false) const; | ||
265 | |||
266 | /// This will read the attribute metadata from a stream. | ||
267 | void readMetadata(std::istream&); | ||
268 | /// This will write the attribute metadata to a stream. | ||
269 | /// @param outputTransient if true, write out transient attributes | ||
270 | /// @param paged if true, data is written out in pages | ||
271 | void writeMetadata(std::ostream&, bool outputTransient = false, bool paged = false) const; | ||
272 | |||
273 | /// This will read the attribute data from a stream. | ||
274 | void readAttributes(std::istream&); | ||
275 | /// This will write the attribute data to a stream. | ||
276 | /// @param outputTransient if true, write out transient attributes | ||
277 | void writeAttributes(std::ostream&, bool outputTransient = false) const; | ||
278 | |||
279 | /// Compare the descriptors and attribute arrays on the attribute sets | ||
280 | /// Exit early if the descriptors do not match | ||
281 | bool operator==(const AttributeSet& other) const; | ||
282 |
4/8✓ 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.
|
2 | bool operator!=(const AttributeSet& other) const { return !this->operator==(other); } |
283 | |||
284 | private: | ||
285 | using AttrArrayVec = std::vector<AttributeArray::Ptr>; | ||
286 | |||
287 | DescriptorPtr mDescr; | ||
288 | AttrArrayVec mAttrs; | ||
289 | }; // class AttributeSet | ||
290 | |||
291 | //////////////////////////////////////// | ||
292 | |||
293 | |||
294 | /// A container for ABI=5 to help ease introduction of upcoming features | ||
295 | namespace future { | ||
296 | class Container | ||
297 | { | ||
298 | class Element { }; | ||
299 | std::vector<std::shared_ptr<Element>> mElements; | ||
300 | }; | ||
301 | } | ||
302 | |||
303 | |||
304 | //////////////////////////////////////// | ||
305 | |||
306 | |||
307 | /// @brief An immutable object that stores name, type and AttributeSet position | ||
308 | /// for a constant collection of attribute arrays. | ||
309 | /// @note The attribute name is actually mutable, but the attribute type | ||
310 | /// and position can not be changed after creation. | ||
311 | class OPENVDB_API AttributeSet::Descriptor | ||
312 | { | ||
313 | public: | ||
314 | using Ptr = std::shared_ptr<Descriptor>; | ||
315 | |||
316 | using NameAndType = Util::NameAndType; | ||
317 | using NameAndTypeVec = Util::NameAndTypeVec; | ||
318 | using GroupIndex = Util::GroupIndex; | ||
319 | using NameToPosMap = Util::NameToPosMap; | ||
320 | using ConstIterator = NameToPosMap::const_iterator; | ||
321 | |||
322 | /// Utility method to construct a NameAndType sequence. | ||
323 | 7266 | struct Inserter { | |
324 | NameAndTypeVec vec; | ||
325 | Inserter& add(const NameAndType& nameAndType) { | ||
326 |
1/2✓ Branch 1 taken 7257 times.
✗ Branch 2 not taken.
|
7257 | vec.push_back(nameAndType); return *this; |
327 | } | ||
328 | Inserter& add(const Name& name, const NamePair& type) { | ||
329 |
21/42✓ Branch 1 taken 2 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.
✓ Branch 28 taken 1 times.
✗ Branch 29 not taken.
✓ Branch 31 taken 1 times.
✗ Branch 32 not taken.
✓ Branch 34 taken 1 times.
✗ Branch 35 not taken.
✓ Branch 37 taken 1 times.
✗ Branch 38 not taken.
✓ Branch 40 taken 1 times.
✗ Branch 41 not taken.
✓ Branch 43 taken 1 times.
✗ Branch 44 not taken.
✓ Branch 46 taken 1 times.
✗ Branch 47 not taken.
✓ Branch 49 taken 1 times.
✗ Branch 50 not taken.
✓ Branch 52 taken 1 times.
✗ Branch 53 not taken.
✓ Branch 55 taken 1 times.
✗ Branch 56 not taken.
✓ Branch 58 taken 1 times.
✗ Branch 59 not taken.
✓ Branch 61 taken 1 times.
✗ Branch 62 not taken.
|
22 | vec.emplace_back(name, type); return *this; |
330 | } | ||
331 | Inserter& add(const NameAndTypeVec& other) { | ||
332 | for (NameAndTypeVec::const_iterator it = other.begin(), itEnd = other.end(); it != itEnd; ++it) { | ||
333 | vec.emplace_back(it->name, it->type); | ||
334 | } | ||
335 | return *this; | ||
336 | } | ||
337 | }; | ||
338 | |||
339 | ////////// | ||
340 | |||
341 | Descriptor(); | ||
342 | |||
343 | /// Copy constructor | ||
344 | Descriptor(const Descriptor&); | ||
345 | |||
346 | /// Create a new descriptor from a position attribute type and assumes "P" (for convenience). | ||
347 | static Ptr create(const NamePair&); | ||
348 | |||
349 | /// Create a new descriptor as a duplicate with a new attribute appended | ||
350 | Ptr duplicateAppend(const Name& name, const NamePair& type) const; | ||
351 | |||
352 | /// Create a new descriptor as a duplicate with existing attributes dropped | ||
353 | Ptr duplicateDrop(const std::vector<size_t>& pos) const; | ||
354 | |||
355 | /// Return the number of attributes in this descriptor. | ||
356 | size_t size() const { return mTypes.size(); } | ||
357 | |||
358 | /// Return the number of attributes with this attribute type | ||
359 | size_t count(const NamePair& type) const; | ||
360 | |||
361 | /// Return the number of bytes of memory used by this attribute set. | ||
362 | size_t memUsage() const; | ||
363 | |||
364 | /// @brief Return the position of the attribute array whose name is @a name, | ||
365 | /// or @c INVALID_POS if no match is found. | ||
366 | size_t find(const std::string& name) const; | ||
367 | |||
368 | /// Rename an attribute array | ||
369 | size_t rename(const std::string& fromName, const std::string& toName); | ||
370 | |||
371 | /// Return the name of the attribute array's type. | ||
372 | const Name& valueType(size_t pos) const; | ||
373 | /// Return the name of the attribute array's type. | ||
374 | const NamePair& type(size_t pos) const; | ||
375 | |||
376 | /// Retrieve metadata map | ||
377 | MetaMap& getMetadata(); | ||
378 | const MetaMap& getMetadata() const; | ||
379 | |||
380 | /// Return true if the attribute has a default value | ||
381 | bool hasDefaultValue(const Name& name) const; | ||
382 | /// Get a default value for an existing attribute | ||
383 | template<typename ValueType> | ||
384 | 6 | ValueType getDefaultValue(const Name& name) const | |
385 | { | ||
386 | 6 | const size_t pos = find(name); | |
387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
6 | if (pos == INVALID_POS) { |
388 | ✗ | OPENVDB_THROW(LookupError, "Cannot find attribute name to set default value.") | |
389 | } | ||
390 | |||
391 | 12 | std::stringstream ss; | |
392 | ss << "default:" << name; | ||
393 | |||
394 |
4/6✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1 times.
|
12 | auto metadata = mMetadata.getMetadata<TypedMetadata<ValueType>>(ss.str()); |
395 | |||
396 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
6 | if (metadata) return metadata->value(); |
397 | |||
398 | return zeroVal<ValueType>(); | ||
399 | } | ||
400 | /// Set a default value for an existing attribute | ||
401 | void setDefaultValue(const Name& name, const Metadata& defaultValue); | ||
402 | // Remove the default value if it exists | ||
403 | void removeDefaultValue(const Name& name); | ||
404 | // Prune any default values for which the key is no longer present | ||
405 | void pruneUnusedDefaultValues(); | ||
406 | |||
407 | /// Return true if this descriptor is equal to the given one. | ||
408 | bool operator==(const Descriptor&) const; | ||
409 | /// Return true if this descriptor is not equal to the given one. | ||
410 |
2/4✓ Branch 1 taken 3950 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
48368 | bool operator!=(const Descriptor& rhs) const { return !this->operator==(rhs); } |
411 | /// Return true if this descriptor contains the same attributes | ||
412 | /// as the given descriptor, ignoring attribute order | ||
413 | bool hasSameAttributes(const Descriptor& rhs) const; | ||
414 | |||
415 | /// Return a reference to the name-to-position map. | ||
416 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const NameToPosMap& map() const { return mNameMap; } |
417 | /// Return a reference to the name-to-position group map. | ||
418 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | const NameToPosMap& groupMap() const { return mGroupMap; } |
419 | |||
420 | /// Return @c true if group exists | ||
421 | bool hasGroup(const Name& group) const; | ||
422 | /// @brief Define a group name to offset mapping | ||
423 | /// @param group group name | ||
424 | /// @param offset group offset | ||
425 | /// @param checkValidOffset throws if offset out-of-range or in-use | ||
426 | void setGroup(const Name& group, const size_t offset, | ||
427 | const bool checkValidOffset = false); | ||
428 | /// Drop any mapping keyed by group name | ||
429 | void dropGroup(const Name& group); | ||
430 | /// Clear all groups | ||
431 | void clearGroups(); | ||
432 | /// Rename a group | ||
433 | size_t renameGroup(const std::string& fromName, const std::string& toName); | ||
434 | /// Return a unique name for a group based on given name | ||
435 | const Name uniqueGroupName(const Name& name) const; | ||
436 | |||
437 | //@{ | ||
438 | /// @brief Return the group offset from the name or index of the group | ||
439 | /// A group attribute array is a single byte (8-bit), each bit of which | ||
440 | /// can denote a group. The group offset is the position of the bit that | ||
441 | /// denotes the requested group if all group attribute arrays in the set | ||
442 | /// (and only attribute arrays marked as group) were to be laid out linearly | ||
443 | /// according to their order in the set. | ||
444 | size_t groupOffset(const Name& groupName) const; | ||
445 | size_t groupOffset(const GroupIndex& index) const; | ||
446 | //@} | ||
447 | |||
448 | /// Return the group index from the name of the group | ||
449 | GroupIndex groupIndex(const Name& groupName) const; | ||
450 | /// Return the group index from the offset of the group | ||
451 | /// @note see offset description for groupOffset() | ||
452 | GroupIndex groupIndex(const size_t offset) const; | ||
453 | |||
454 | /// Return number of bits occupied by a group attribute array | ||
455 | static size_t groupBits() { return sizeof(GroupType) * CHAR_BIT; } | ||
456 | |||
457 | /// Return the total number of available groups | ||
458 | /// (group bits * number of group attributes) | ||
459 | size_t availableGroups() const; | ||
460 | |||
461 | /// Return the number of empty group slots which correlates to the number of groups | ||
462 | /// that can be stored without increasing the number of group attribute arrays | ||
463 | size_t unusedGroups() const; | ||
464 | |||
465 | /// Return @c true if there are sufficient empty slots to allow compacting | ||
466 | bool canCompactGroups() const; | ||
467 | |||
468 | /// @brief Return a group offset that is not in use | ||
469 | /// @param hint if provided, request a specific offset as a hint | ||
470 | /// @return index of an offset or size_t max if no available group offsets | ||
471 | size_t unusedGroupOffset(size_t hint = std::numeric_limits<size_t>::max()) const; | ||
472 | |||
473 | /// @brief Determine if a move is required to efficiently compact the data and store the | ||
474 | /// source name, offset and the target offset in the input parameters | ||
475 | /// @param sourceName source name | ||
476 | /// @param sourceOffset source offset | ||
477 | /// @param targetOffset target offset | ||
478 | /// @return @c true if move is required to compact the data | ||
479 | bool requiresGroupMove(Name& sourceName, size_t& sourceOffset, size_t& targetOffset) const; | ||
480 | |||
481 | /// @brief Test if there are any group names shared by both descriptors which | ||
482 | /// have a different index | ||
483 | /// @param rhs the descriptor to compare with | ||
484 | /// @return @c true if an index collision exists | ||
485 | bool groupIndexCollision(const Descriptor& rhs) const; | ||
486 | |||
487 | /// Return a unique name for an attribute array based on given name | ||
488 | const Name uniqueName(const Name& name) const; | ||
489 | |||
490 | /// Return true if the name is valid | ||
491 | static bool validName(const Name& name); | ||
492 | |||
493 | /// @brief Extract each name from @a nameStr into @a includeNames, or into @a excludeNames | ||
494 | /// if the name is prefixed with a caret. | ||
495 | /// @param nameStr the input string of names | ||
496 | /// @param includeNames on exit, the list of names that are not prefixed with a caret | ||
497 | /// @param excludeNames on exit, the list of names that are prefixed with a caret | ||
498 | /// @param includeAll on exit, @c true if a "*" wildcard is present in the @a includeNames | ||
499 | static void parseNames( std::vector<std::string>& includeNames, | ||
500 | std::vector<std::string>& excludeNames, | ||
501 | bool& includeAll, | ||
502 | const std::string& nameStr); | ||
503 | |||
504 | /// @brief Extract each name from @a nameStr into @a includeNames, or into @a excludeNames | ||
505 | /// if the name is prefixed with a caret. | ||
506 | static void parseNames( std::vector<std::string>& includeNames, | ||
507 | std::vector<std::string>& excludeNames, | ||
508 | const std::string& nameStr); | ||
509 | |||
510 | /// Serialize this descriptor to the given stream. | ||
511 | void write(std::ostream&) const; | ||
512 | /// Unserialize this transform from the given stream. | ||
513 | void read(std::istream&); | ||
514 | |||
515 | protected: | ||
516 | /// Append to a vector of names and types from this Descriptor in position order | ||
517 | void appendTo(NameAndTypeVec& attrs) const; | ||
518 | |||
519 | /// Create a new descriptor from the given attribute and type name pairs | ||
520 | /// and copy the group maps and metamap. | ||
521 | static Ptr create(const NameAndTypeVec&, const NameToPosMap&, const MetaMap&); | ||
522 | |||
523 | size_t insert(const std::string& name, const NamePair& typeName); | ||
524 | |||
525 | private: | ||
526 | friend class ::TestAttributeSet; | ||
527 | |||
528 | NameToPosMap mNameMap; | ||
529 | std::vector<NamePair> mTypes; | ||
530 | NameToPosMap mGroupMap; | ||
531 | MetaMap mMetadata; | ||
532 | // as this change is part of an ABI change, there's no good reason to reduce the reserved | ||
533 | // space aside from keeping the memory size of an AttributeSet the same for convenience | ||
534 | // (note that this assumes a typical three-pointer implementation for std::vector) | ||
535 | future::Container mFutureContainer; // occupies 3 reserved slots | ||
536 | int64_t mReserved[5]; // for future use | ||
537 | }; // class Descriptor | ||
538 | |||
539 | } // namespace points | ||
540 | } // namespace OPENVDB_VERSION_NAME | ||
541 | } // namespace openvdb | ||
542 | |||
543 | #endif // OPENVDB_POINTS_ATTRIBUTE_ARRAY_HAS_BEEN_INCLUDED | ||
544 |