GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/io/DelayedLoadMetadata.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 124 133 93.2%
Functions: 15 17 88.2%
Branches: 84 144 58.3%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #include "DelayedLoadMetadata.h"
5
6 #include <openvdb/points/StreamCompression.h>
7
8 #ifdef OPENVDB_USE_BLOSC
9 #include <blosc.h>
10
11 namespace {
12
13 inline size_t padMask(size_t bytes)
14 {
15 30 return size_t(std::ceil(static_cast<float>(bytes+1) /
16 30 sizeof(openvdb::io::DelayedLoadMetadata::MaskType)));
17 }
18
19 inline size_t padCompressedSize(size_t bytes)
20 {
21
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 return size_t(std::ceil(static_cast<float>(bytes+1) /
22 25 sizeof(openvdb::io::DelayedLoadMetadata::CompressedSizeType)));
23 }
24
25 } // namespace
26
27 #endif
28
29 namespace openvdb {
30 OPENVDB_USE_VERSION_NAMESPACE
31 namespace OPENVDB_VERSION_NAME {
32 namespace io {
33
34 1 DelayedLoadMetadata::DelayedLoadMetadata(const DelayedLoadMetadata& other)
35 : Metadata()
36 1 , mMask(other.mMask)
37
1/2
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
1 , mCompressedSize(other.mCompressedSize)
38 {
39 1 }
40
41 12934 Name DelayedLoadMetadata::typeName() const
42 {
43 12934 return DelayedLoadMetadata::staticTypeName();
44 }
45
46 316 Metadata::Ptr DelayedLoadMetadata::copy() const
47 {
48 316 Metadata::Ptr metadata(new DelayedLoadMetadata());
49
1/2
✓ Branch 1 taken 316 times.
✗ Branch 2 not taken.
316 metadata->copy(*this);
50 316 return metadata;
51 }
52
53 316 void DelayedLoadMetadata::copy(const Metadata& other)
54 {
55 316 const DelayedLoadMetadata* t = dynamic_cast<const DelayedLoadMetadata*>(&other);
56
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 316 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
316 if (t == nullptr) OPENVDB_THROW(TypeError, "Incompatible type during copy");
57 316 mMask = t->mMask;
58 316 mCompressedSize = t->mCompressedSize;
59 316 }
60
61 std::string DelayedLoadMetadata::str() const
62 {
63 return "";
64 }
65
66 bool DelayedLoadMetadata::asBool() const
67 {
68 return false;
69 }
70
71
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 139 times.
143 Index32 DelayedLoadMetadata::size() const
72 {
73
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 139 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
143 if (mMask.empty() && mCompressedSize.empty()) return Index32(0);
74
75 // count
76 size_t size = sizeof(Index32);
77
78 { // mask
79 size += sizeof(Index32);
80 139 size_t compressedSize = compression::bloscCompressedSize(
81 reinterpret_cast<const char*>(mMask.data()), mMask.size()*sizeof(MaskType));
82
83
2/2
✓ Branch 0 taken 93 times.
✓ Branch 1 taken 46 times.
139 if (compressedSize > 0) size += compressedSize;
84 46 else size += mMask.size()*sizeof(MaskType);
85 }
86 { // compressed size
87
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 9 times.
139 size += sizeof(Index32);
88
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 9 times.
139 if (!mCompressedSize.empty()) {
89 130 size_t compressedSize = compression::bloscCompressedSize(
90 reinterpret_cast<const char*>(mCompressedSize.data()), mCompressedSize.size()*sizeof(CompressedSizeType));
91
92
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 42 times.
130 if (compressedSize > 0) size += compressedSize;
93 42 else size += mCompressedSize.size()*sizeof(CompressedSizeType);
94 }
95 }
96
97 139 return static_cast<Index32>(size);
98 }
99
100
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 times.
5 void DelayedLoadMetadata::clear()
101 {
102 mMask.clear();
103 mCompressedSize.clear();
104 5 }
105
106
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 bool DelayedLoadMetadata::empty() const
107 {
108
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
7 return mMask.empty() && mCompressedSize.empty();
109 }
110
111 135 void DelayedLoadMetadata::resizeMask(size_t size)
112 {
113 135 mMask.resize(size);
114 135 }
115
116 127 void DelayedLoadMetadata::resizeCompressedSize(size_t size)
117 {
118 127 mCompressedSize.resize(size);
119 127 }
120
121 12886 DelayedLoadMetadata::MaskType DelayedLoadMetadata::getMask(size_t index) const
122 {
123
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12886 times.
12886 assert(DelayedLoadMetadata::isRegisteredType());
124
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12886 times.
12886 assert(index < mMask.size());
125 12886 return mMask[index];
126 }
127
128
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24808 times.
24808 void DelayedLoadMetadata::setMask(size_t index, const MaskType& value)
129 {
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24808 times.
24808 assert(index < mMask.size());
131 24808 mMask[index] = value;
132 24808 }
133
134 10870 DelayedLoadMetadata::CompressedSizeType DelayedLoadMetadata::getCompressedSize(size_t index) const
135 {
136
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10870 times.
10870 assert(DelayedLoadMetadata::isRegisteredType());
137
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10870 times.
10870 assert(index < mCompressedSize.size());
138 10870 return mCompressedSize[index];
139 }
140
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23627 times.
23627 void DelayedLoadMetadata::setCompressedSize(size_t index, const CompressedSizeType& value)
142 {
143
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23627 times.
23627 assert(index < mCompressedSize.size());
144 23627 mCompressedSize[index] = value;
145 23627 }
146
147 90 void DelayedLoadMetadata::readValue(std::istream& is, Index32 numBytes)
148 {
149
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 83 times.
90 if (numBytes == 0) return;
150
151 // initial header size
152 size_t total = sizeof(Index32);
153
154 83 Index32 count = 0;
155 83 is.read(reinterpret_cast<char*>(&count), sizeof(Index32));
156 total += sizeof(Index32);
157
158 83 Index32 bytes = 0;
159 83 is.read(reinterpret_cast<char*>(&bytes), sizeof(Index32));
160 total += sizeof(Index32);
161
162
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 53 times.
83 if (bytes > Index32(0)) {
163 30 std::unique_ptr<char[]> compressedBuffer(new char[bytes]);
164
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 is.read(reinterpret_cast<char*>(compressedBuffer.get()), bytes);
165
166 30 total += bytes;
167
168 #ifdef OPENVDB_USE_BLOSC
169 // pad to include BLOSC_MAX_OVERHEAD
170
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 size_t uncompressedBytes = openvdb::compression::bloscUncompressedSize(compressedBuffer.get());
171 const size_t paddedCount = padMask(uncompressedBytes + BLOSC_MAX_OVERHEAD);
172
173
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 mMask.reserve(paddedCount);
174
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 mMask.resize(count);
175
176 // resize should never modify capacity for smaller vector sizes
177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 assert(mMask.capacity() >= paddedCount);
178
179
1/2
✓ Branch 1 taken 30 times.
✗ Branch 2 not taken.
30 compression::bloscDecompress(reinterpret_cast<char*>(mMask.data()), count*sizeof(MaskType), mMask.capacity()*sizeof(MaskType), compressedBuffer.get());
180 #endif
181 } else {
182 53 mMask.resize(count);
183 53 is.read(reinterpret_cast<char*>(mMask.data()), count*sizeof(MaskType));
184 53 total += count*sizeof(MaskType);
185 }
186
187 83 is.read(reinterpret_cast<char*>(&bytes), sizeof(Index32));
188
189
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 8 times.
83 if (bytes != std::numeric_limits<Index32>::max()) {
190
2/2
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 50 times.
75 if (bytes > Index32(0)) {
191 25 std::unique_ptr<char[]> compressedBuffer(new char[bytes]);
192
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 is.read(reinterpret_cast<char*>(compressedBuffer.get()), bytes);
193
194 25 total += size_t(bytes);
195
196 #ifdef OPENVDB_USE_BLOSC
197 // pad to include BLOSC_MAX_OVERHEAD
198
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 size_t uncompressedBytes = openvdb::compression::bloscUncompressedSize(compressedBuffer.get());
199 const size_t paddedCount = padCompressedSize(uncompressedBytes + BLOSC_MAX_OVERHEAD);
200
201
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 mCompressedSize.reserve(paddedCount);
202
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 mCompressedSize.resize(count);
203
204 // resize should never modify capacity for smaller vector sizes
205
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
25 assert(mCompressedSize.capacity() >= paddedCount);
206
207
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 compression::bloscDecompress(reinterpret_cast<char*>(mCompressedSize.data()), count*sizeof(CompressedSizeType), mCompressedSize.capacity()*sizeof(CompressedSizeType), compressedBuffer.get());
208 #endif
209 } else {
210 50 mCompressedSize.resize(count);
211 50 is.read(reinterpret_cast<char*>(mCompressedSize.data()), count*sizeof(CompressedSizeType));
212 50 total += count*sizeof(CompressedSizeType);
213 }
214 }
215
216 83 Index32 totalBytes = static_cast<Index32>(total);
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (totalBytes < numBytes) {
219 // Read and discard any unknown bytes at the end of the metadata for forwards-compatibility
220 // (without seeking, because the stream might not be seekable).
221 const size_t BUFFER_SIZE = 1024;
222 std::vector<char> buffer(BUFFER_SIZE);
223 for (Index32 bytesRemaining = numBytes - totalBytes; bytesRemaining > 0; ) {
224 const Index32 bytesToSkip = std::min<Index32>(bytesRemaining, BUFFER_SIZE);
225 is.read(&buffer[0], bytesToSkip);
226 bytesRemaining -= bytesToSkip;
227 }
228 }
229 }
230
231
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 void DelayedLoadMetadata::writeValue(std::ostream& os) const
232 {
233 // metadata has a limit of 2^32 bytes
234
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 assert(mMask.size() < std::numeric_limits<Index32>::max());
235
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 assert(mCompressedSize.size() < std::numeric_limits<Index32>::max());
236
237
3/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
138 if (mMask.empty() && mCompressedSize.empty()) return;
238
239
3/4
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
134 assert(mCompressedSize.empty() || (mMask.size() == mCompressedSize.size()));
240
241 134 Index32 count = static_cast<Index32>(mMask.size());
242 134 os.write(reinterpret_cast<const char*>(&count), sizeof(Index32));
243
244 134 const Index32 zeroSize(0);
245 134 const Index32 maxSize(std::numeric_limits<Index32>::max());
246
247 { // mask buffer
248 134 size_t compressedBytes(0);
249 134 std::unique_ptr<char[]> compressedBuffer;
250
2/4
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
✗ Branch 4 not taken.
134 if (compression::bloscCanCompress()) {
251
1/2
✓ Branch 1 taken 134 times.
✗ Branch 2 not taken.
134 compressedBuffer = compression::bloscCompress(
252 reinterpret_cast<const char*>(mMask.data()),
253 mMask.size()*sizeof(MaskType), compressedBytes, /*resize=*/false);
254 }
255
256
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 44 times.
134 if (compressedBuffer) {
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
90 assert(compressedBytes < std::numeric_limits<Index32>::max());
258 90 Index32 bytes(static_cast<Index32>(compressedBytes));
259
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index32));
260
1/2
✓ Branch 1 taken 90 times.
✗ Branch 2 not taken.
90 os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
261 }
262 else {
263
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 os.write(reinterpret_cast<const char*>(&zeroSize), sizeof(Index32));
264 os.write(reinterpret_cast<const char*>(mMask.data()),
265
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 mMask.size()*sizeof(MaskType));
266 }
267 }
268
269 // compressed size buffer
270
271
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 126 times.
134 if (mCompressedSize.empty()) {
272 // write out maximum Index32 value to denote no compressed sizes stored
273 8 os.write(reinterpret_cast<const char*>(&maxSize), sizeof(Index32));
274 } else {
275 126 size_t compressedBytes(0);
276 126 std::unique_ptr<char[]> compressedBuffer;
277
2/4
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 126 times.
✗ Branch 4 not taken.
126 if (compression::bloscCanCompress()) {
278
1/2
✓ Branch 1 taken 126 times.
✗ Branch 2 not taken.
126 compressedBuffer = compression::bloscCompress(
279 reinterpret_cast<const char*>(mCompressedSize.data()),
280 mCompressedSize.size()*sizeof(CompressedSizeType), compressedBytes, /*resize=*/false);
281 }
282
283
2/2
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 41 times.
126 if (compressedBuffer) {
284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 assert(compressedBytes < std::numeric_limits<Index32>::max());
285 85 Index32 bytes(static_cast<Index32>(compressedBytes));
286
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 os.write(reinterpret_cast<const char*>(&bytes), sizeof(Index32));
287
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 os.write(reinterpret_cast<const char*>(compressedBuffer.get()), compressedBytes);
288 }
289 else {
290
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
41 os.write(reinterpret_cast<const char*>(&zeroSize), sizeof(Index32));
291 os.write(reinterpret_cast<const char*>(mCompressedSize.data()),
292
1/2
✓ Branch 1 taken 41 times.
✗ Branch 2 not taken.
41 mCompressedSize.size()*sizeof(CompressedSizeType));
293 }
294 }
295 }
296
297 } // namespace io
298 } // namespace OPENVDB_VERSION_NAME
299 } // namespace openvdb
300