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 |