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