GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/AttributeSet.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 515 524 98.3%
Functions: 88 88 100.0%
Branches: 446 706 63.2%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file points/AttributeSet.cc
5
6 #include "AttributeSet.h"
7 #include "AttributeGroup.h"
8
9 #include <algorithm> // std::equal
10 #include <string>
11
12 namespace openvdb {
13 OPENVDB_USE_VERSION_NAMESPACE
14 namespace OPENVDB_VERSION_NAME {
15 namespace points {
16
17
18 namespace {
19 // remove the items from the vector corresponding to the indices
20 template <typename T>
21
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
240 void eraseIndices(std::vector<T>& vec,
22 const std::vector<size_t>& indices)
23 {
24 // early-exit if no indices to erase
25
26
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
240 if (indices.empty()) return;
27
28 // build the sorted, unique indices to remove
29
30 240 std::vector<size_t> toRemove(indices);
31 240 std::sort(toRemove.rbegin(), toRemove.rend());
32
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 120 times.
240 toRemove.erase(unique(toRemove.begin(), toRemove.end()), toRemove.end());
33
34 // throw if the largest index is out of range
35
36
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 120 times.
240 if (*toRemove.begin() >= vec.size()) {
37 OPENVDB_THROW(LookupError, "Cannot erase indices as index is out of range.")
38 }
39
40 // erase elements from the back
41
42
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 120 times.
532 for (auto it = toRemove.cbegin(); it != toRemove.cend(); ++it) {
43 292 vec.erase(vec.begin() + (*it));
44 }
45 }
46
47 // return true if a string begins with a particular substring
48 95 bool startsWith(const std::string& str, const std::string& prefix)
49 {
50 95 return str.compare(0, prefix.length(), prefix) == 0;
51 }
52 }
53
54 ////////////////////////////////////////
55
56
57 // AttributeSet implementation
58
59
60 50576 AttributeSet::AttributeSet()
61 50576 : mDescr(new Descriptor())
62 {
63 50576 }
64
65
66 2506 AttributeSet::AttributeSet(const AttributeSet& attrSet, Index arrayLength,
67 2506 const AttributeArray::ScopedRegistryLock* lock)
68 : mDescr(attrSet.descriptorPtr())
69
2/4
✓ Branch 1 taken 2506 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2508 , mAttrs(attrSet.descriptor().size(), AttributeArray::Ptr())
70 {
71 2506 std::unique_ptr<AttributeArray::ScopedRegistryLock> localLock;
72
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2500 times.
2506 if (!lock) {
73
2/4
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
6 localLock.reset(new AttributeArray::ScopedRegistryLock);
74 lock = localLock.get();
75 }
76
77
1/2
✓ Branch 1 taken 2506 times.
✗ Branch 2 not taken.
2506 const MetaMap& meta = mDescr->getMetadata();
78 bool hasMetadata = meta.metaCount();
79
80
2/2
✓ Branch 0 taken 5042 times.
✓ Branch 1 taken 2505 times.
7547 for (const auto& namePos : mDescr->map()) {
81 const size_t& pos = namePos.second;
82 5042 Metadata::ConstPtr metadata;
83
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5042 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
5042 if (hasMetadata) metadata = meta["default:" + namePos.first];
84
1/2
✓ Branch 1 taken 5042 times.
✗ Branch 2 not taken.
5042 const AttributeArray* existingArray = attrSet.getConst(pos);
85 const bool constantStride = existingArray->hasConstantStride();
86
4/6
✓ Branch 0 taken 5039 times.
✓ Branch 1 taken 3 times.
✓ Branch 3 taken 5039 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
5042 const Index stride = constantStride ? existingArray->stride() : existingArray->dataSize();
87
88 AttributeArray::Ptr array = AttributeArray::create(mDescr->type(pos), arrayLength,
89
3/4
✓ Branch 1 taken 5042 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5041 times.
✓ Branch 5 taken 1 times.
5042 stride, constantStride, metadata.get(), lock);
90
91 // transfer hidden and transient flags
92
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5040 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
5041 if (existingArray->isHidden()) array->setHidden(true);
93
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5040 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
5041 if (existingArray->isTransient()) array->setTransient(true);
94
95 5041 mAttrs[pos] = array;
96 }
97 2505 }
98
99
100 34990 AttributeSet::AttributeSet(const DescriptorPtr& descr, Index arrayLength,
101 34990 const AttributeArray::ScopedRegistryLock* lock)
102 : mDescr(descr)
103
1/4
✓ Branch 1 taken 34990 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
34990 , mAttrs(descr->size(), AttributeArray::Ptr())
104 {
105 34990 std::unique_ptr<AttributeArray::ScopedRegistryLock> localLock;
106
2/2
✓ Branch 0 taken 4073 times.
✓ Branch 1 taken 30917 times.
34990 if (!lock) {
107
2/4
✓ Branch 1 taken 4073 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4073 times.
✗ Branch 5 not taken.
4073 localLock.reset(new AttributeArray::ScopedRegistryLock);
108 lock = localLock.get();
109 }
110
111
1/2
✓ Branch 1 taken 34990 times.
✗ Branch 2 not taken.
34990 const MetaMap& meta = mDescr->getMetadata();
112 bool hasMetadata = meta.metaCount();
113
114
2/2
✓ Branch 0 taken 34991 times.
✓ Branch 1 taken 34990 times.
69981 for (const auto& namePos : mDescr->map()) {
115 const size_t& pos = namePos.second;
116 34991 Metadata::ConstPtr metadata;
117
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 34990 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
34992 if (hasMetadata) metadata = meta["default:" + namePos.first];
118
4/8
✓ Branch 1 taken 34991 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34991 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 34991 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 34991 times.
69982 mAttrs[pos] = AttributeArray::create(mDescr->type(pos), arrayLength,
119 /*stride=*/1, /*constantStride=*/true, metadata.get(), lock);
120 }
121 34990 }
122
123
124 11501 AttributeSet::AttributeSet(const AttributeSet& rhs)
125 : mDescr(rhs.mDescr)
126
1/2
✓ Branch 1 taken 11501 times.
✗ Branch 2 not taken.
11501 , mAttrs(rhs.mAttrs)
127 {
128 11501 }
129
130
131 size_t
132 26912 AttributeSet::memUsage() const
133 {
134 26912 size_t bytes = sizeof(*this) + mDescr->memUsage();
135
2/2
✓ Branch 0 taken 86508 times.
✓ Branch 1 taken 26912 times.
113420 for (const auto& attr : mAttrs) {
136 86508 bytes += attr->memUsage();
137 }
138 26912 return bytes;
139 }
140
141
142 #if OPENVDB_ABI_VERSION_NUMBER >= 10
143 size_t
144 AttributeSet::memUsageIfLoaded() const
145 {
146 size_t bytes = sizeof(*this) + mDescr->memUsage();
147 for (const auto& attr : mAttrs) {
148 bytes += attr->memUsageIfLoaded();
149 }
150 return bytes;
151 }
152 #endif
153
154
155 size_t
156 102501 AttributeSet::find(const std::string& name) const
157 {
158 102501 return mDescr->find(name);
159 }
160
161
162 size_t
163 1 AttributeSet::replace(const std::string& name, const AttributeArray::Ptr& attr)
164 {
165 1 const size_t pos = this->find(name);
166
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return pos != INVALID_POS ? this->replace(pos, attr) : INVALID_POS;
167 }
168
169
170 size_t
171 3 AttributeSet::replace(size_t pos, const AttributeArray::Ptr& attr)
172 {
173
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(pos != INVALID_POS);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(pos < mAttrs.size());
175
176
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
3 if (attr->type() != mDescr->type(pos)) {
177 return INVALID_POS;
178 }
179
180 mAttrs[pos] = attr;
181 2 return pos;
182 }
183
184
185 const AttributeArray*
186 104 AttributeSet::getConst(const std::string& name) const
187 {
188 104 const size_t pos = this->find(name);
189
1/2
✓ Branch 0 taken 104 times.
✗ Branch 1 not taken.
104 if (pos < mAttrs.size()) return this->getConst(pos);
190 return nullptr;
191 }
192
193
194 const AttributeArray*
195 8 AttributeSet::get(const std::string& name) const
196 {
197 8 return this->getConst(name);
198 }
199
200
201 AttributeArray*
202 2 AttributeSet::get(const std::string& name)
203 {
204 2 const size_t pos = this->find(name);
205
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (pos < mAttrs.size()) return this->get(pos);
206 return nullptr;
207 }
208
209
210 const AttributeArray*
211 228807 AttributeSet::getConst(size_t pos) const
212 {
213
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228807 times.
228807 assert(pos != INVALID_POS);
214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 228807 times.
228807 assert(pos < mAttrs.size());
215 228807 return mAttrs[pos].get();
216 }
217
218
219 const AttributeArray*
220 37 AttributeSet::get(size_t pos) const
221 {
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assert(pos != INVALID_POS);
223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 assert(pos < mAttrs.size());
224 37 return this->getConst(pos);
225 }
226
227
228 AttributeArray*
229 214636 AttributeSet::get(size_t pos)
230 {
231 214636 makeUnique(pos);
232 214636 return mAttrs[pos].get();
233 }
234
235
236 size_t
237 99 AttributeSet::groupOffset(const Name& group) const
238 {
239 99 return mDescr->groupOffset(group);
240 }
241
242
243 size_t
244 2 AttributeSet::groupOffset(const Util::GroupIndex& index) const
245 {
246 2 return mDescr->groupOffset(index);
247 }
248
249
250 AttributeSet::Descriptor::GroupIndex
251 345 AttributeSet::groupIndex(const Name& group) const
252 {
253 345 return mDescr->groupIndex(group);
254 }
255
256
257 AttributeSet::Descriptor::GroupIndex
258 16 AttributeSet::groupIndex(const size_t offset) const
259 {
260 16 return mDescr->groupIndex(offset);
261 }
262
263 std::vector<size_t>
264 11 AttributeSet::groupAttributeIndices() const
265 {
266 std::vector<size_t> indices;
267
268
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 11 times.
45 for (const auto& namePos : mDescr->map()) {
269
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 const AttributeArray* array = this->getConst(namePos.first);
270
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 18 times.
34 if (isGroup(*array)) {
271
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 indices.push_back(namePos.second);
272 }
273 }
274
275 11 return indices;
276 }
277
278 bool
279 22 AttributeSet::isShared(size_t pos) const
280 {
281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 assert(pos != INVALID_POS);
282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 assert(pos < mAttrs.size());
283 22 return !mAttrs[pos].unique();
284 }
285
286
287 void
288 214656 AttributeSet::makeUnique(size_t pos)
289 {
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 214656 times.
214656 assert(pos != INVALID_POS);
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 214656 times.
214656 assert(pos < mAttrs.size());
292
2/2
✓ Branch 0 taken 11665 times.
✓ Branch 1 taken 202991 times.
214656 if (!mAttrs[pos].unique()) {
293 23330 mAttrs[pos] = mAttrs[pos]->copy();
294 }
295 214656 }
296
297
298 AttributeArray::Ptr
299 54 AttributeSet::appendAttribute( const Name& name,
300 const NamePair& type,
301 const Index strideOrTotalSize,
302 const bool constantStride,
303 const Metadata* defaultValue)
304 {
305 54 Descriptor::Ptr descriptor = mDescr->duplicateAppend(name, type);
306
307 // store the attribute default value in the descriptor metadata
308
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
54 if (defaultValue) descriptor->setDefaultValue(name, *defaultValue);
309
310 // extract the index from the descriptor
311
1/2
✓ Branch 1 taken 54 times.
✗ Branch 2 not taken.
54 const size_t pos = descriptor->find(name);
312
313
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 2 times.
106 return this->appendAttribute(*mDescr, descriptor, pos, strideOrTotalSize, constantStride, defaultValue);
314 }
315
316
317 AttributeArray::Ptr
318 38096 AttributeSet::appendAttribute( const Descriptor& expected, DescriptorPtr& replacement,
319 const size_t pos, const Index strideOrTotalSize, const bool constantStride,
320 const Metadata* defaultValue,
321 const AttributeArray::ScopedRegistryLock* lock)
322 {
323 // ensure the descriptor is as expected
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38096 times.
38096 if (*mDescr != expected) {
325 OPENVDB_THROW(LookupError, "Cannot append attributes as descriptors do not match.")
326 }
327
328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38096 times.
38096 assert(replacement->size() >= mDescr->size());
329
330 const size_t offset = mDescr->size();
331
332 // extract the array length from the first attribute array if it exists
333
334
2/2
✓ Branch 0 taken 38094 times.
✓ Branch 1 taken 2 times.
38096 const Index arrayLength = offset > 0 ? this->get(0)->size() : 1;
335
336 // extract the type from the descriptor
337
338 38096 const NamePair& type = replacement->type(pos);
339
340 // append the new array
341
342 AttributeArray::Ptr array = AttributeArray::create(
343 type, arrayLength, strideOrTotalSize, constantStride,
344 38096 defaultValue, lock);
345
346 // if successful, update Descriptor and append the created array
347
348 mDescr = replacement;
349
350
1/2
✓ Branch 1 taken 38094 times.
✗ Branch 2 not taken.
38094 mAttrs.push_back(array);
351
352 38094 return array;
353 }
354
355
356 AttributeArray::Ptr
357 1 AttributeSet::removeAttribute(const Name& name)
358 {
359 1 const size_t pos = this->find(name);
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos == INVALID_POS) return AttributeArray::Ptr();
361 1 return this->removeAttribute(pos);
362 }
363
364
365 AttributeArray::Ptr
366
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 AttributeSet::removeAttribute(const size_t pos)
367 {
368
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (pos >= mAttrs.size()) return AttributeArray::Ptr();
369
370
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 assert(mAttrs[pos]);
371 AttributeArray::Ptr array;
372 std::swap(array, mAttrs[pos]);
373 assert(array);
374
375 // safely drop the attribute and update the descriptor
376
1/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 std::vector<size_t> toDrop{pos};
377
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 this->dropAttributes(toDrop);
378
379 return array;
380 }
381
382
383 AttributeArray::Ptr
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 AttributeSet::removeAttributeUnsafe(const size_t pos)
385 {
386
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (pos >= mAttrs.size()) return AttributeArray::Ptr();
387
388
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 assert(mAttrs[pos]);
389 AttributeArray::Ptr array;
390 std::swap(array, mAttrs[pos]);
391
392 return array;
393 }
394
395
396 void
397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 AttributeSet::dropAttributes(const std::vector<size_t>& pos)
398 {
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (pos.empty()) return;
400
401 4 Descriptor::Ptr descriptor = mDescr->duplicateDrop(pos);
402
403
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 this->dropAttributes(pos, *mDescr, descriptor);
404 }
405
406
407 void
408
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 AttributeSet::dropAttributes( const std::vector<size_t>& pos,
409 const Descriptor& expected, DescriptorPtr& replacement)
410 {
411
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 if (pos.empty()) return;
412
413 // ensure the descriptor is as expected
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (*mDescr != expected) {
415 OPENVDB_THROW(LookupError, "Cannot drop attributes as descriptors do not match.")
416 }
417
418 mDescr = replacement;
419
420 83 eraseIndices(mAttrs, pos);
421
422 // remove any unused default values
423
424 83 mDescr->pruneUnusedDefaultValues();
425 }
426
427
428 void
429 24 AttributeSet::renameAttributes(const Descriptor& expected, const DescriptorPtr& replacement)
430 {
431 // ensure the descriptor is as expected
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (*mDescr != expected) {
433 OPENVDB_THROW(LookupError, "Cannot rename attribute as descriptors do not match.")
434 }
435
436 mDescr = replacement;
437 24 }
438
439
440 void
441 1 AttributeSet::reorderAttributes(const DescriptorPtr& replacement)
442 {
443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (*mDescr == *replacement) {
444 this->resetDescriptor(replacement);
445 return;
446 }
447
448
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!mDescr->hasSameAttributes(*replacement)) {
449 OPENVDB_THROW(LookupError, "Cannot reorder attributes as descriptors do not contain the same attributes.")
450 }
451
452 2 AttrArrayVec attrs(replacement->size());
453
454 // compute target indices for attributes from the given decriptor
455
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 for (const auto& namePos : mDescr->map()) {
456
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 const size_t index = replacement->find(namePos.first);
457 8 attrs[index] = AttributeArray::Ptr(mAttrs[namePos.second]);
458 }
459
460 // copy the ordering to the member attributes vector and update descriptor to be target
461 1 std::copy(attrs.begin(), attrs.end(), mAttrs.begin());
462 mDescr = replacement;
463 }
464
465
466 void
467 16390 AttributeSet::resetDescriptor(const DescriptorPtr& replacement, const bool allowMismatchingDescriptors)
468 {
469 // ensure the descriptors match
470
4/4
✓ Branch 0 taken 6190 times.
✓ Branch 1 taken 10200 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 6189 times.
22580 if (!allowMismatchingDescriptors && *mDescr != *replacement) {
471
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
4 OPENVDB_THROW(LookupError, "Cannot swap descriptor as replacement does not match.")
472 }
473
474 mDescr = replacement;
475 16389 }
476
477
478 void
479 3 AttributeSet::read(std::istream& is)
480 {
481 3 this->readDescriptor(is);
482 3 this->readMetadata(is);
483 3 this->readAttributes(is);
484 3 }
485
486
487 void
488 3 AttributeSet::write(std::ostream& os, bool outputTransient) const
489 {
490 3 this->writeDescriptor(os, outputTransient);
491 3 this->writeMetadata(os, outputTransient);
492 3 this->writeAttributes(os, outputTransient);
493 3 }
494
495
496 void
497 24 AttributeSet::readDescriptor(std::istream& is)
498 {
499 24 mDescr->read(is);
500 24 }
501
502
503 void
504
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 AttributeSet::writeDescriptor(std::ostream& os, bool outputTransient) const
505 {
506 // build a vector of all attribute arrays that have a transient flag
507 // unless also writing transient attributes
508
509 std::vector<size_t> transientArrays;
510
511
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 if (!outputTransient) {
512
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 14 times.
43 for (size_t i = 0; i < size(); i++) {
513
1/2
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
29 const AttributeArray* array = this->getConst(i);
514
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 28 times.
29 if (array->isTransient()) {
515
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 transientArrays.push_back(i);
516 }
517 }
518 }
519
520 // write out a descriptor without transient attributes
521
522
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 if (transientArrays.empty()) {
523
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 mDescr->write(os);
524 }
525 else {
526
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 Descriptor::Ptr descr = mDescr->duplicateDrop(transientArrays);
527
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 descr->write(os);
528 }
529 15 }
530
531
532 void
533 10223 AttributeSet::readMetadata(std::istream& is)
534 {
535 10223 AttrArrayVec(mDescr->size()).swap(mAttrs); // allocate vector
536
537
2/2
✓ Branch 0 taken 36441 times.
✓ Branch 1 taken 10223 times.
46664 for (size_t n = 0, N = mAttrs.size(); n < N; ++n) {
538 72882 mAttrs[n] = AttributeArray::create(mDescr->type(n), 1, 1);
539 36441 mAttrs[n]->readMetadata(is);
540 }
541 10223 }
542
543
544 void
545 3962 AttributeSet::writeMetadata(std::ostream& os, bool outputTransient, bool paged) const
546 {
547 // write attribute metadata
548
549
2/2
✓ Branch 0 taken 17662 times.
✓ Branch 1 taken 3962 times.
21624 for (size_t i = 0; i < size(); i++) {
550 17662 const AttributeArray* array = this->getConst(i);
551 17662 array->writeMetadata(os, outputTransient, paged);
552 }
553 3962 }
554
555
556 void
557 3 AttributeSet::readAttributes(std::istream& is)
558 {
559
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 for (size_t i = 0; i < mAttrs.size(); i++) {
560 5 mAttrs[i]->readBuffers(is);
561 }
562 3 }
563
564
565 void
566 3 AttributeSet::writeAttributes(std::ostream& os, bool outputTransient) const
567 {
568
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 for (auto attr : mAttrs) {
569
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 attr->writeBuffers(os, outputTransient);
570 }
571 3 }
572
573
574 bool
575 12 AttributeSet::operator==(const AttributeSet& other) const {
576
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
12 if(*this->mDescr != *other.mDescr) return false;
577
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if(this->mAttrs.size() != other.mAttrs.size()) return false;
578
579
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 10 times.
32 for (size_t n = 0; n < this->mAttrs.size(); ++n) {
580
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (*this->mAttrs[n] != *other.mAttrs[n]) return false;
581 }
582 return true;
583 }
584
585 ////////////////////////////////////////
586
587 // AttributeSet::Descriptor implementation
588
589
590 58701 AttributeSet::Descriptor::Descriptor()
591 {
592 58701 }
593
594
595 211 AttributeSet::Descriptor::Descriptor(const Descriptor& rhs)
596 : mNameMap(rhs.mNameMap)
597 211 , mTypes(rhs.mTypes)
598 , mGroupMap(rhs.mGroupMap)
599
2/4
✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 211 times.
✗ Branch 5 not taken.
422 , mMetadata(rhs.mMetadata)
600 {
601 211 }
602
603
604 bool
605 48374 AttributeSet::Descriptor::operator==(const Descriptor& rhs) const
606 {
607
2/2
✓ Branch 0 taken 6207 times.
✓ Branch 1 taken 42167 times.
48374 if (this == &rhs) return true;
608
609
1/2
✓ Branch 0 taken 6204 times.
✗ Branch 1 not taken.
6204 if (mTypes.size() != rhs.mTypes.size() ||
610
4/4
✓ Branch 0 taken 6204 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6203 times.
✓ Branch 3 taken 1 times.
12411 mNameMap.size() != rhs.mNameMap.size() ||
611 mGroupMap.size() != rhs.mGroupMap.size()) {
612 return false;
613 }
614
615
2/2
✓ Branch 0 taken 24780 times.
✓ Branch 1 taken 6203 times.
30983 for (size_t n = 0, N = mTypes.size(); n < N; ++n) {
616
1/2
✓ Branch 0 taken 24780 times.
✗ Branch 1 not taken.
24780 if (mTypes[n] != rhs.mTypes[n]) return false;
617 }
618
619
2/2
✓ Branch 1 taken 6202 times.
✓ Branch 2 taken 1 times.
6203 if (this->mMetadata != rhs.mMetadata) return false;
620
621
3/4
✓ Branch 1 taken 6202 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 6200 times.
12404 return std::equal(mGroupMap.begin(), mGroupMap.end(), rhs.mGroupMap.begin()) &&
622 6202 std::equal(mNameMap.begin(), mNameMap.end(), rhs.mNameMap.begin());
623 }
624
625
626 bool
627 8 AttributeSet::Descriptor::hasSameAttributes(const Descriptor& rhs) const
628 {
629
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (this == &rhs) return true;
630
631
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 if (mTypes.size() != rhs.mTypes.size() ||
632
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 1 times.
16 mNameMap.size() != rhs.mNameMap.size() ||
633 mGroupMap.size() != rhs.mGroupMap.size()) {
634 return false;
635 }
636
637
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 5 times.
27 for (const auto& namePos : mNameMap) {
638 22 const size_t index = rhs.find(namePos.first);
639
640
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 1 times.
23 if (index == INVALID_POS) return false;
641
642
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1 times.
21 if (mTypes[namePos.second] != rhs.mTypes[index]) return false;
643 }
644
645 5 return std::equal(mGroupMap.begin(), mGroupMap.end(), rhs.mGroupMap.begin());
646 }
647
648
649 size_t
650 683 AttributeSet::Descriptor::count(const NamePair& matchType) const
651 {
652 683 return std::count(mTypes.begin(), mTypes.end(), matchType);
653 }
654
655
656 size_t
657 26912 AttributeSet::Descriptor::memUsage() const
658 {
659 26912 size_t bytes = sizeof(NameToPosMap::mapped_type) * this->size();
660
2/2
✓ Branch 0 taken 86508 times.
✓ Branch 1 taken 26912 times.
113420 for (const auto& namePos : mNameMap) {
661 86508 bytes += namePos.first.capacity();
662 }
663
664
2/2
✓ Branch 0 taken 86508 times.
✓ Branch 1 taken 26912 times.
113420 for (const NamePair& type : mTypes) {
665 86508 bytes += type.first.capacity();
666 86508 bytes += type.second.capacity();
667 }
668
669 26912 return sizeof(*this) + bytes;
670 }
671
672
673 size_t
674 162839 AttributeSet::Descriptor::find(const std::string& name) const
675 {
676
2/2
✓ Branch 0 taken 126902 times.
✓ Branch 1 taken 35937 times.
162839 auto it = mNameMap.find(name);
677
2/2
✓ Branch 0 taken 126902 times.
✓ Branch 1 taken 35937 times.
162839 if (it != mNameMap.end()) {
678 126902 return it->second;
679 }
680 return INVALID_POS;
681 }
682
683
684 size_t
685 8 AttributeSet::Descriptor::rename(const std::string& fromName, const std::string& toName)
686 {
687
3/4
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 7 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
9 if (!validName(toName)) throw RuntimeError("Attribute name contains invalid characters - " + toName);
688
689 size_t pos = INVALID_POS;
690
691 // check if the new name is already used.
692
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 auto it = mNameMap.find(toName);
693
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (it != mNameMap.end()) return pos;
694
695
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 it = mNameMap.find(fromName);
696
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (it != mNameMap.end()) {
697 7 pos = it->second;
698 7 mNameMap.erase(it);
699 7 mNameMap[toName] = pos;
700
701 // rename default value if it exists
702
703 14 std::stringstream ss;
704 ss << "default:" << fromName;
705
706
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
14 Metadata::Ptr defaultValue = mMetadata[ss.str()];
707
708
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 if (defaultValue) {
709
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 mMetadata.removeMeta(ss.str());
710
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
10 ss.str("");
711 ss << "default:" << toName;
712
1/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10 mMetadata.insertMeta(ss.str(), *defaultValue);
713 }
714 }
715 return pos;
716 }
717
718 size_t
719 2 AttributeSet::Descriptor::renameGroup(const std::string& fromName, const std::string& toName)
720 {
721
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
2 if (!validName(toName)) throw RuntimeError("Group name contains invalid characters - " + toName);
722
723 size_t pos = INVALID_POS;
724
725 // check if the new name is already used.
726
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 auto it = mGroupMap.find(toName);
727
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (it != mGroupMap.end()) return pos;
728
729
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 it = mGroupMap.find(fromName);
730
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (it != mGroupMap.end()) {
731 1 pos = it->second;
732 1 mGroupMap.erase(it);
733 1 mGroupMap[toName] = pos;
734 }
735
736 return pos;
737 }
738
739
740 const Name&
741 35091 AttributeSet::Descriptor::valueType(size_t pos) const
742 {
743 // pos is assumed to exist
744 35091 return this->type(pos).first;
745 }
746
747
748 const NamePair&
749 203272 AttributeSet::Descriptor::type(size_t pos) const
750 {
751 // assert that pos is valid and in-range
752
753
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203272 times.
203272 assert(pos != AttributeSet::INVALID_POS);
754
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 203272 times.
203272 assert(pos < mTypes.size());
755
756 203272 return mTypes[pos];
757 }
758
759
760 MetaMap&
761 38342 AttributeSet::Descriptor::getMetadata()
762 {
763 38342 return mMetadata;
764 }
765
766
767 const MetaMap&
768 9142 AttributeSet::Descriptor::getMetadata() const
769 {
770 9142 return mMetadata;
771 }
772
773
774 bool
775 4 AttributeSet::Descriptor::hasDefaultValue(const Name& name) const
776 {
777 4 std::stringstream ss;
778 ss << "default:" << name;
779
780 8 return bool(mMetadata[ss.str()]);
781 }
782
783
784 void
785 11 AttributeSet::Descriptor::setDefaultValue(const Name& name, const Metadata& defaultValue)
786 {
787 11 const size_t pos = find(name);
788
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (pos == INVALID_POS) {
789
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
4 OPENVDB_THROW(LookupError, "Cannot find attribute name to set default value.")
790 }
791
792 // check type of metadata matches attribute type
793
794 10 const Name& valueType = this->valueType(pos);
795
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 9 times.
20 if (valueType != defaultValue.typeName()) {
796
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
4 OPENVDB_THROW(TypeError, "Mis-matching Default Value Type");
797 }
798
799 9 std::stringstream ss;
800 ss << "default:" << name;
801
802
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
18 mMetadata.insertMeta(ss.str(), defaultValue);
803 9 }
804
805
806 void
807 1 AttributeSet::Descriptor::removeDefaultValue(const Name& name)
808 {
809 1 std::stringstream ss;
810 ss << "default:" << name;
811
812
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
2 mMetadata.removeMeta(ss.str());
813 1 }
814
815
816 void
817 120 AttributeSet::Descriptor::pruneUnusedDefaultValues()
818 {
819 // store any default metadata keys for which the attribute name is no longer present
820
821 120 std::vector<Name> metaToErase;
822
823
2/2
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 120 times.
184 for (auto it = mMetadata.beginMeta(), itEnd = mMetadata.endMeta(); it != itEnd; ++it) {
824
1/2
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
64 const Name name = it->first;
825
826 // ignore non-default metadata
827
4/6
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 64 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 46 times.
✓ Branch 7 taken 18 times.
128 if (!startsWith(name, "default:")) continue;
828
829
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 const Name defaultName = name.substr(8, it->first.size() - 8);
830
831
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 11 times.
18 if (mNameMap.find(defaultName) == mNameMap.end()) {
832
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 metaToErase.push_back(name);
833 }
834 }
835
836 // remove this metadata
837
838
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 120 times.
127 for (const Name& name : metaToErase) {
839
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 mMetadata.removeMeta(name);
840 }
841 120 }
842
843
844 size_t
845 55751 AttributeSet::Descriptor::insert(const std::string& name, const NamePair& typeName)
846 {
847
3/4
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 55750 times.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
55752 if (!validName(name)) throw RuntimeError("Attribute name contains invalid characters - " + name);
848
849 size_t pos = INVALID_POS;
850
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 55747 times.
55750 auto it = mNameMap.find(name);
851
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 55747 times.
55750 if (it != mNameMap.end()) {
852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 assert(it->second < mTypes.size());
853
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (mTypes[it->second] != typeName) {
854
2/6
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
8 OPENVDB_THROW(KeyError,
855 "Cannot insert into a Descriptor with a duplicate name, but different type.")
856 }
857 pos = it->second;
858 } else {
859
860
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 55746 times.
55747 if (!AttributeArray::isRegistered(typeName)) {
861
1/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
4 OPENVDB_THROW(KeyError, "Failed to insert '" << name
862 << "' with unregistered attribute type '" << typeName.first << "_" << typeName.second);
863 }
864
865 pos = mTypes.size();
866 55746 mTypes.push_back(typeName);
867 55746 mNameMap.insert(it, NameToPosMap::value_type(name, pos));
868 }
869 55747 return pos;
870 }
871
872 AttributeSet::Descriptor::Ptr
873 7301 AttributeSet::Descriptor::create(const NameAndTypeVec& attrs,
874 const NameToPosMap& groupMap,
875 const MetaMap& metadata)
876 {
877 7301 auto newDescriptor = std::make_shared<Descriptor>();
878
879
2/2
✓ Branch 0 taken 54936 times.
✓ Branch 1 taken 7298 times.
62234 for (const NameAndType& attr : attrs) {
880
2/2
✓ Branch 1 taken 54933 times.
✓ Branch 2 taken 3 times.
54936 newDescriptor->insert(attr.name, attr.type);
881 }
882
883 newDescriptor->mGroupMap = groupMap;
884
1/2
✓ Branch 1 taken 7298 times.
✗ Branch 2 not taken.
7298 newDescriptor->mMetadata = metadata;
885
886 7298 return newDescriptor;
887 }
888
889 AttributeSet::Descriptor::Ptr
890 813 AttributeSet::Descriptor::create(const NamePair& positionType)
891 {
892 813 auto descr = std::make_shared<Descriptor>();
893
2/4
✓ Branch 1 taken 813 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 813 times.
✗ Branch 5 not taken.
813 descr->insert("P", positionType);
894 813 return descr;
895 }
896
897 AttributeSet::Descriptor::Ptr
898
1/2
✓ Branch 1 taken 7257 times.
✗ Branch 2 not taken.
7257 AttributeSet::Descriptor::duplicateAppend(const Name& name, const NamePair& type) const
899 {
900 Inserter attributes;
901
902
1/2
✓ Branch 1 taken 7257 times.
✗ Branch 2 not taken.
7257 this->appendTo(attributes.vec);
903
1/2
✓ Branch 1 taken 7257 times.
✗ Branch 2 not taken.
14517 attributes.add(NameAndType(name, type));
904
905
2/2
✓ Branch 1 taken 7254 times.
✓ Branch 2 taken 3 times.
14511 return Descriptor::create(attributes.vec, mGroupMap, mMetadata);
906 }
907
908
909 AttributeSet::Descriptor::Ptr
910
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 AttributeSet::Descriptor::duplicateDrop(const std::vector<size_t>& pos) const
911 {
912 37 NameAndTypeVec vec;
913
1/2
✓ Branch 1 taken 37 times.
✗ Branch 2 not taken.
37 this->appendTo(vec);
914
915
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 34 times.
37 Descriptor::Ptr descriptor;
916
917 // If groups exist, check to see if those arrays are being dropped
918
919
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 34 times.
37 if (!mGroupMap.empty()) {
920
921 // extract all attribute array group indices and specific groups
922 // to drop
923
924 std::vector<size_t> groups, groupsToDrop;
925
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 3 times.
16 for (size_t i = 0; i < vec.size(); i++) {
926
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 4 times.
13 if (vec[i].type == GroupAttributeArray::attributeType()) {
927
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 groups.push_back(i);
928
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
9 if (std::find(pos.begin(), pos.end(), i) != pos.end()) {
929
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 groupsToDrop.push_back(i);
930 }
931 }
932 }
933
934 // drop the indices in indices from vec
935
936
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 eraseIndices(vec, pos);
937
938
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (!groupsToDrop.empty()) {
939
940 // configure group mapping if group arrays have been dropped
941
942 NameToPosMap droppedGroupMap = mGroupMap;
943
944 const size_t GROUP_BITS = sizeof(GroupType) * CHAR_BIT;
945
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 3 times.
19 for (auto iter = droppedGroupMap.begin(); iter != droppedGroupMap.end();) {
946 16 const size_t groupArrayPos = iter->second / GROUP_BITS;
947 16 const size_t arrayPos = groups[groupArrayPos];
948
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 14 times.
16 if (std::find(pos.begin(), pos.end(), arrayPos) != pos.end()) {
949 2 iter = droppedGroupMap.erase(iter);
950 }
951 else {
952 size_t offset(0);
953
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 for (const size_t& idx : groupsToDrop) {
954
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 12 times.
16 if (idx >= arrayPos) break;
955 4 ++offset;
956 }
957 14 iter->second -= (offset * GROUP_BITS);
958 ++iter;
959 }
960 }
961
962
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
6 descriptor = Descriptor::create(vec, droppedGroupMap, mMetadata);
963
964 // remove any unused default values
965
966
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 descriptor->pruneUnusedDefaultValues();
967
968 return descriptor;
969 }
970 }
971 else {
972
973 // drop the indices in pos from vec
974
975
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 eraseIndices(vec, pos);
976 }
977
978
2/4
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 34 times.
✗ Branch 5 not taken.
68 descriptor = Descriptor::create(vec, mGroupMap, mMetadata);
979
980 // remove any unused default values
981
982
1/2
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
34 descriptor->pruneUnusedDefaultValues();
983
984 return descriptor;
985 }
986
987 void
988 7295 AttributeSet::Descriptor::appendTo(NameAndTypeVec& attrs) const
989 {
990 // build a std::map<pos, name> (ie key and value swapped)
991
992 using PosToNameMap = std::map<size_t, std::string>;
993
994 PosToNameMap posToNameMap;
995
996
2/2
✓ Branch 0 taken 47712 times.
✓ Branch 1 taken 7295 times.
55007 for (const auto& namePos : mNameMap) {
997
1/2
✓ Branch 1 taken 47712 times.
✗ Branch 2 not taken.
47712 posToNameMap[namePos.second] = namePos.first;
998 }
999
1000 // std::map is sorted by key, so attributes can now be inserted in position order
1001
1002
2/2
✓ Branch 0 taken 47712 times.
✓ Branch 1 taken 7295 times.
55007 for (const auto& posName : posToNameMap) {
1003
2/4
✓ Branch 1 taken 47712 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 47712 times.
✗ Branch 5 not taken.
47712 attrs.emplace_back(posName.second, this->type(posName.first));
1004 }
1005 7295 }
1006
1007 bool
1008 449 AttributeSet::Descriptor::hasGroup(const Name& group) const
1009 {
1010 449 return mGroupMap.find(group) != mGroupMap.end();
1011 }
1012
1013 void
1014 220 AttributeSet::Descriptor::setGroup(const Name& group, const size_t offset,
1015 const bool checkValidOffset)
1016 {
1017
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 219 times.
220 if (!validName(group)) {
1018
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 throw RuntimeError("Group name contains invalid characters - " + group);
1019 }
1020
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 216 times.
219 if (checkValidOffset) {
1021 // check offset is not out-of-range
1022
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
3 if (offset >= this->availableGroups()) {
1023
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 throw RuntimeError("Group offset is out-of-range - " + group);
1024 }
1025 // check offset is not already in use
1026
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 times.
24 for (const auto& namePos : mGroupMap) {
1027
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 22 times.
23 if (namePos.second == offset) {
1028
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
2 throw RuntimeError("Group offset is already in use - " + group);
1029 }
1030 }
1031 }
1032
1033 217 mGroupMap[group] = offset;
1034 217 }
1035
1036 void
1037 34 AttributeSet::Descriptor::dropGroup(const Name& group)
1038 {
1039 mGroupMap.erase(group);
1040 34 }
1041
1042 void
1043 2 AttributeSet::Descriptor::clearGroups()
1044 {
1045 mGroupMap.clear();
1046 2 }
1047
1048 const Name
1049 83 AttributeSet::Descriptor::uniqueName(const Name& name) const
1050 {
1051
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 7 times.
83 auto it = mNameMap.find(name);
1052
2/2
✓ Branch 0 taken 76 times.
✓ Branch 1 taken 7 times.
83 if (it == mNameMap.end()) return name;
1053
1054 14 std::ostringstream ss;
1055 size_t i(0);
1056
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 7 times.
17 while (it != mNameMap.end()) {
1057
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
20 ss.str("");
1058
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 ss << name << i++;
1059 10 it = mNameMap.find(ss.str());
1060 }
1061 return ss.str();
1062 }
1063
1064 const Name
1065 3 AttributeSet::Descriptor::uniqueGroupName(const Name& name) const
1066 {
1067
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 auto it = mGroupMap.find(name);
1068
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (it == mGroupMap.end()) return name;
1069
1070 4 std::ostringstream ss;
1071 size_t i(0);
1072
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 while (it != mGroupMap.end()) {
1073
2/4
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
8 ss.str("");
1074
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 ss << name << i++;
1075 4 it = mGroupMap.find(ss.str());
1076 }
1077 return ss.str();
1078 }
1079
1080 size_t
1081 446 AttributeSet::Descriptor::groupOffset(const Name& group) const
1082 {
1083
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 73 times.
446 const auto it = mGroupMap.find(group);
1084
2/2
✓ Branch 0 taken 373 times.
✓ Branch 1 taken 73 times.
446 if (it == mGroupMap.end()) {
1085 return INVALID_POS;
1086 }
1087 373 return it->second;
1088 }
1089
1090 size_t
1091 2 AttributeSet::Descriptor::groupOffset(const Util::GroupIndex& index) const
1092 {
1093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (index.first >= mNameMap.size()) {
1094 OPENVDB_THROW(LookupError, "Out of range group index.")
1095 }
1096
1097
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (mTypes[index.first] != GroupAttributeArray::attributeType()) {
1098 OPENVDB_THROW(LookupError, "Group index invalid.")
1099 }
1100
1101 // find the relative index in the group attribute arrays
1102
1103 size_t relativeIndex = 0;
1104
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
18 for (const auto& namePos : mNameMap) {
1105
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9 times.
28 if (namePos.second < index.first &&
1106
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 mTypes[namePos.second] == GroupAttributeArray::attributeType()) {
1107 3 relativeIndex++;
1108 }
1109 }
1110
1111 const size_t GROUP_BITS = sizeof(GroupType) * CHAR_BIT;
1112
1113 2 return (relativeIndex * GROUP_BITS) + index.second;
1114 }
1115
1116 AttributeSet::Descriptor::GroupIndex
1117 345 AttributeSet::Descriptor::groupIndex(const Name& group) const
1118 {
1119 345 const size_t offset = this->groupOffset(group);
1120
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 344 times.
345 if (offset == INVALID_POS) {
1121
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
5 OPENVDB_THROW(LookupError, "Group not found - " << group << ".")
1122 }
1123 344 return this->groupIndex(offset);
1124 }
1125
1126 AttributeSet::Descriptor::GroupIndex
1127 360 AttributeSet::Descriptor::groupIndex(const size_t offset) const
1128 {
1129 // extract all attribute array group indices
1130
1131 std::vector<size_t> groups;
1132
2/2
✓ Branch 0 taken 1160 times.
✓ Branch 1 taken 360 times.
1520 for (const auto& namePos : mNameMap) {
1133
2/2
✓ Branch 0 taken 429 times.
✓ Branch 1 taken 731 times.
1160 if (mTypes[namePos.second] == GroupAttributeArray::attributeType()) {
1134
1/2
✓ Branch 1 taken 429 times.
✗ Branch 2 not taken.
429 groups.push_back(namePos.second);
1135 }
1136 }
1137
1138
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 359 times.
360 if (offset >= groups.size() * this->groupBits()) {
1139
2/6
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
5 OPENVDB_THROW(LookupError, "Out of range group offset - " << offset << ".")
1140 }
1141
1142 // adjust relative offset to find offset into the array vector
1143
1144 359 std::sort(groups.begin(), groups.end());
1145
1/2
✓ Branch 0 taken 359 times.
✗ Branch 1 not taken.
359 return Util::GroupIndex(groups[offset / this->groupBits()],
1146
1/2
✓ Branch 0 taken 359 times.
✗ Branch 1 not taken.
718 static_cast<uint8_t>(offset % this->groupBits()));
1147 }
1148
1149 size_t
1150 671 AttributeSet::Descriptor::availableGroups() const
1151 {
1152 // the number of group attributes * number of bits per group
1153
1154 const size_t groupAttributes =
1155 671 this->count(GroupAttributeArray::attributeType());
1156
1157 671 return groupAttributes * this->groupBits();
1158 }
1159
1160 size_t
1161 492 AttributeSet::Descriptor::unusedGroups() const
1162 {
1163 // compute total slots (one slot per bit of the group attributes)
1164
1165 492 const size_t availableGroups = this->availableGroups();
1166
1167
2/2
✓ Branch 0 taken 423 times.
✓ Branch 1 taken 69 times.
492 if (availableGroups == 0) return 0;
1168
1169 // compute slots in use
1170
1171 const size_t usedGroups = mGroupMap.size();
1172
1173 423 return availableGroups - usedGroups;
1174 }
1175
1176 bool
1177 21 AttributeSet::Descriptor::canCompactGroups() const
1178 {
1179 // can compact if more unused groups than in one group attribute array
1180
1181 21 return this->unusedGroups() >= this->groupBits();
1182 }
1183
1184 size_t
1185 176 AttributeSet::Descriptor::unusedGroupOffset(size_t hint) const
1186 {
1187 // all group offsets are in use
1188
1189
2/2
✓ Branch 1 taken 174 times.
✓ Branch 2 taken 2 times.
176 if (unusedGroups() == size_t(0)) {
1190 return std::numeric_limits<size_t>::max();
1191 }
1192
1193 // build a list of group indices
1194
1195 std::vector<size_t> indices;
1196
1/2
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
174 indices.reserve(mGroupMap.size());
1197
2/2
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 174 times.
585 for (const auto& namePos : mGroupMap) {
1198
1/2
✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
411 indices.push_back(namePos.second);
1199 }
1200
1201 174 std::sort(indices.begin(), indices.end());
1202
1203 // return hint if not already in use
1204
1205 348 if (hint != std::numeric_limits<Index>::max() &&
1206
6/8
✓ Branch 0 taken 174 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 174 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 168 times.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 2 times.
180 hint < availableGroups() &&
1207
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
176 std::find(indices.begin(), indices.end(), hint) == indices.end()) {
1208 4 return hint;
1209 }
1210
1211 // otherwise return first index not present
1212
1213 size_t offset = 0;
1214
2/2
✓ Branch 0 taken 403 times.
✓ Branch 1 taken 159 times.
562 for (const size_t& index : indices) {
1215
2/2
✓ Branch 0 taken 392 times.
✓ Branch 1 taken 11 times.
403 if (index != offset) break;
1216 392 offset++;
1217 }
1218
1219 170 return offset;
1220 }
1221
1222 bool
1223 23 AttributeSet::Descriptor::requiresGroupMove(Name& sourceName,
1224 size_t& sourceOffset, size_t& targetOffset) const
1225 {
1226 23 targetOffset = this->unusedGroupOffset();
1227
1228
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 15 times.
102 for (const auto& namePos : mGroupMap) {
1229
1230 // move only required if source comes after the target
1231
1232
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 79 times.
87 if (namePos.second >= targetOffset) {
1233 8 sourceName = namePos.first;
1234 8 sourceOffset = namePos.second;
1235 8 return true;
1236 }
1237 }
1238
1239 15 return false;
1240 }
1241
1242 bool
1243 16 AttributeSet::Descriptor::groupIndexCollision(const Descriptor& rhs) const
1244 {
1245 const auto& groupMap = this->groupMap();
1246 const auto& otherGroupMap = rhs.groupMap();
1247
1248 // iterate both group maps at the same time and find any keys that occur
1249 // in both maps and test their values for equality
1250
1251 16 auto groupsIt1 = groupMap.cbegin();
1252 16 auto groupsIt2 = otherGroupMap.cbegin();
1253
1254
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 1 times.
34 while (groupsIt1 != groupMap.cend() && groupsIt2 != otherGroupMap.cend()) {
1255
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (groupsIt1->first < groupsIt2->first) {
1256 ++groupsIt1;
1257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 } else if (groupsIt1->first > groupsIt2->first) {
1258 ++groupsIt2;
1259 } else {
1260
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 if (groupsIt1->second != groupsIt2->second) {
1261 return true;
1262 } else {
1263 ++groupsIt1;
1264 ++groupsIt2;
1265 }
1266 }
1267 }
1268
1269 return false;
1270 }
1271
1272 bool
1273
2/2
✓ Branch 0 taken 56069 times.
✓ Branch 1 taken 1 times.
56070 AttributeSet::Descriptor::validName(const Name& name)
1274 {
1275
2/2
✓ Branch 0 taken 56069 times.
✓ Branch 1 taken 1 times.
56070 if (name.empty()) return false;
1276 56069 return std::find_if(name.begin(), name.end(),
1277
6/6
✓ Branch 0 taken 5043 times.
✓ Branch 1 taken 326928 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 5032 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 10 times.
388040 [&](int c) { return !(isalnum(c) || (c == '_') || (c == '|') || (c == ':')); } ) == name.end();
1278 }
1279
1280 void
1281 11 AttributeSet::Descriptor::parseNames( std::vector<std::string>& includeNames,
1282 std::vector<std::string>& excludeNames,
1283 bool& includeAll,
1284 const std::string& nameStr)
1285 {
1286 11 includeAll = false;
1287
1288 22 std::stringstream tokenStream(nameStr);
1289
1290 Name token;
1291
3/4
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 9 times.
28 while (tokenStream >> token) {
1292
1293
10/18
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 7 times.
✓ Branch 9 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 12 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 times.
✓ Branch 15 taken 11 times.
✓ Branch 16 taken 12 times.
✓ Branch 17 taken 7 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
34 bool negate = startsWith(token, "^") || startsWith(token, "!");
1294
1295
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11 times.
19 if (negate) {
1296
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 7 times.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
9 if (token.length() < 2) throw RuntimeError("Negate character (^) must prefix a name.");
1297
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 token = token.substr(1, token.length()-1);
1298
2/6
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
7 if (!validName(token)) throw RuntimeError("Name contains invalid characters - " + token);
1299
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 excludeNames.push_back(token);
1300 }
1301
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 else if (!includeAll) {
1302
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (token == "*") {
1303 1 includeAll = true;
1304 includeNames.clear();
1305 1 continue;
1306 }
1307
4/6
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 9 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
11 if (!validName(token)) throw RuntimeError("Name contains invalid characters - " + token);
1308
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 includeNames.push_back(token);
1309 }
1310 }
1311 9 }
1312
1313 void
1314 9 AttributeSet::Descriptor::parseNames( std::vector<std::string>& includeNames,
1315 std::vector<std::string>& excludeNames,
1316 const std::string& nameStr)
1317 {
1318 9 bool includeAll = false;
1319 9 Descriptor::parseNames(includeNames, excludeNames, includeAll, nameStr);
1320 7 }
1321
1322 void
1323 16 AttributeSet::Descriptor::write(std::ostream& os) const
1324 {
1325 16 const Index64 arraylength = Index64(mTypes.size());
1326 16 os.write(reinterpret_cast<const char*>(&arraylength), sizeof(Index64));
1327
1328
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 16 times.
49 for (const NamePair& np : mTypes) {
1329 33 writeString(os, np.first);
1330 33 writeString(os, np.second);
1331 }
1332
1333
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 16 times.
49 for (auto it = mNameMap.begin(), endIt = mNameMap.end(); it != endIt; ++it) {
1334 33 writeString(os, it->first);
1335 33 os.write(reinterpret_cast<const char*>(&it->second), sizeof(Index64));
1336 }
1337
1338 16 const Index64 grouplength = Index64(mGroupMap.size());
1339 16 os.write(reinterpret_cast<const char*>(&grouplength), sizeof(Index64));
1340
1341
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 16 times.
20 for (auto groupIt = mGroupMap.cbegin(), endGroupIt = mGroupMap.cend(); groupIt != endGroupIt; ++groupIt) {
1342 4 writeString(os, groupIt->first);
1343 4 os.write(reinterpret_cast<const char*>(&groupIt->second), sizeof(Index64));
1344 }
1345
1346 16 mMetadata.writeMeta(os);
1347 16 }
1348
1349
1350 void
1351 27 AttributeSet::Descriptor::read(std::istream& is)
1352 {
1353 27 Index64 arraylength = 0;
1354 27 is.read(reinterpret_cast<char*>(&arraylength), sizeof(Index64));
1355
1356 27 std::vector<NamePair>(size_t(arraylength)).swap(mTypes);
1357
1358
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 27 times.
85 for (NamePair& np : mTypes) {
1359 58 np.first = readString(is);
1360 116 np.second = readString(is);
1361 }
1362
1363 mNameMap.clear();
1364 std::pair<std::string, size_t> nameAndOffset;
1365
1366
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 26 times.
84 for (Index64 n = 0; n < arraylength; ++n) {
1367
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 nameAndOffset.first = readString(is);
1368
4/6
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 57 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
59 if (!validName(nameAndOffset.first)) throw IoError("Attribute name contains invalid characters - " + nameAndOffset.first);
1369
1/2
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
57 is.read(reinterpret_cast<char*>(&nameAndOffset.second), sizeof(Index64));
1370 mNameMap.insert(nameAndOffset);
1371 }
1372
1373 26 Index64 grouplength = 0;
1374
1/2
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
26 is.read(reinterpret_cast<char*>(&grouplength), sizeof(Index64));
1375
1376
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 25 times.
30 for (Index64 n = 0; n < grouplength; ++n) {
1377
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 nameAndOffset.first = readString(is);
1378
4/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 1 times.
✗ Branch 8 not taken.
6 if (!validName(nameAndOffset.first)) throw IoError("Group name contains invalid characters - " + nameAndOffset.first);
1379
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 is.read(reinterpret_cast<char*>(&nameAndOffset.second), sizeof(Index64));
1380 mGroupMap.insert(nameAndOffset);
1381 }
1382
1383
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 mMetadata.readMeta(is);
1384 25 }
1385
1386
1387
1388 ////////////////////////////////////////
1389
1390
1391 } // namespace points
1392 } // namespace OPENVDB_VERSION_NAME
1393 } // namespace openvdb
1394