GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/points/StreamCompression.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 205 216 94.9%
Functions: 28 28 100.0%
Branches: 132 224 58.9%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 /// @file points/StreamCompression.cc
5
6 #include "StreamCompression.h"
7 #include <openvdb/util/logging.h>
8 #include <map>
9 #ifdef OPENVDB_USE_BLOSC
10 #include <blosc.h>
11 #endif
12
13 namespace openvdb {
14 OPENVDB_USE_VERSION_NAMESPACE
15 namespace OPENVDB_VERSION_NAME {
16 namespace compression {
17
18
19 #ifdef OPENVDB_USE_BLOSC
20
21
22 bool
23 261 bloscCanCompress()
24 {
25 261 return true;
26 }
27
28
29 size_t
30 32047 bloscUncompressedSize(const char* buffer)
31 {
32 size_t bytes, _1, _2;
33 32047 blosc_cbuffer_sizes(buffer, &bytes, &_1, &_2);
34 32047 return bytes;
35 }
36
37
38 void
39 9175 bloscCompress(char* compressedBuffer, size_t& compressedBytes, const size_t bufferBytes,
40 const char* uncompressedBuffer, const size_t uncompressedBytes)
41 {
42
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9173 times.
9175 if (bufferBytes > BLOSC_MAX_BUFFERSIZE) {
43 OPENVDB_LOG_DEBUG("Blosc compress failed due to exceeding maximum buffer size.");
44 2 compressedBytes = 0;
45 compressedBuffer = nullptr;
46 299 return;
47 }
48
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9173 times.
9173 if (bufferBytes < uncompressedBytes + BLOSC_MAX_OVERHEAD) {
49 OPENVDB_LOG_DEBUG("Blosc compress failed due to insufficient space in compressed buffer.");
50 compressedBytes = 0;
51 compressedBuffer = nullptr;
52 return;
53 }
54
55
2/2
✓ Branch 0 taken 297 times.
✓ Branch 1 taken 8876 times.
9173 if (uncompressedBytes <= BLOSC_MINIMUM_BYTES) {
56 // no Blosc compression performed below this limit
57 297 compressedBytes = 0;
58 compressedBuffer = nullptr;
59 297 return;
60 }
61
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8876 times.
8876 if (uncompressedBytes < BLOSC_PAD_BYTES && bufferBytes < BLOSC_PAD_BYTES + BLOSC_MAX_OVERHEAD) {
63 OPENVDB_LOG_DEBUG(
64 "Blosc compress failed due to insufficient space in compressed buffer for padding.");
65 compressedBytes = 0;
66 compressedBuffer = nullptr;
67 return;
68 }
69
70 size_t inputBytes = uncompressedBytes;
71
72 const char* buffer = uncompressedBuffer;
73
74 8876 std::unique_ptr<char[]> paddedBuffer;
75
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 8688 times.
8876 if (uncompressedBytes < BLOSC_PAD_BYTES) {
76 // input array padded with zeros below this limit to improve compression
77
1/2
✓ Branch 1 taken 188 times.
✗ Branch 2 not taken.
188 paddedBuffer.reset(new char[BLOSC_PAD_BYTES]);
78 188 std::memcpy(paddedBuffer.get(), buffer, uncompressedBytes);
79
2/2
✓ Branch 0 taken 7394 times.
✓ Branch 1 taken 188 times.
7582 for (int i = static_cast<int>(uncompressedBytes); i < BLOSC_PAD_BYTES; i++) {
80 7394 paddedBuffer.get()[i] = 0;
81 }
82 buffer = paddedBuffer.get();
83 inputBytes = BLOSC_PAD_BYTES;
84 }
85
86
1/2
✓ Branch 1 taken 8876 times.
✗ Branch 2 not taken.
8876 int _compressedBytes = blosc_compress_ctx(
87 /*clevel=*/9, // 0 (no compression) to 9 (maximum compression)
88 /*doshuffle=*/true,
89 /*typesize=*/sizeof(float), // hard-coded to 4-bytes for better compression
90 /*srcsize=*/inputBytes,
91 /*src=*/buffer,
92 /*dest=*/compressedBuffer,
93 /*destsize=*/bufferBytes,
94 BLOSC_LZ4_COMPNAME,
95 /*blocksize=*/inputBytes,
96 /*numthreads=*/1);
97
98
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8876 times.
8876 if (_compressedBytes <= 0) {
99 std::ostringstream ostr;
100 ostr << "Blosc failed to compress " << uncompressedBytes << " byte"
101 << (uncompressedBytes == 1 ? "" : "s");
102 if (_compressedBytes < 0) ostr << " (internal error " << _compressedBytes << ")";
103 OPENVDB_LOG_DEBUG(ostr.str());
104 compressedBytes = 0;
105 return;
106 }
107
108 8876 compressedBytes = _compressedBytes;
109
110 // fail if compression does not result in a smaller buffer
111
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8873 times.
8876 if (compressedBytes >= uncompressedBytes) {
112 3 compressedBytes = 0;
113 }
114 }
115
116
117 std::unique_ptr<char[]>
118 8820 bloscCompress(const char* buffer, const size_t uncompressedBytes, size_t& compressedBytes,
119 const bool resize)
120 {
121 size_t tempBytes = uncompressedBytes;
122 // increase temporary buffer for padding if necessary
123
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 8709 times.
8820 if (tempBytes >= BLOSC_MINIMUM_BYTES && tempBytes < BLOSC_PAD_BYTES) {
124 111 tempBytes += BLOSC_PAD_BYTES;
125 }
126 // increase by Blosc max overhead
127 8820 tempBytes += BLOSC_MAX_OVERHEAD;
128 const bool outOfRange = tempBytes > BLOSC_MAX_BUFFERSIZE;
129
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8818 times.
8820 std::unique_ptr<char[]> outBuffer(outOfRange ? new char[1] : new char[tempBytes]);
130
131
1/2
✓ Branch 1 taken 8820 times.
✗ Branch 2 not taken.
8820 bloscCompress(outBuffer.get(), compressedBytes, tempBytes, buffer, uncompressedBytes);
132
133
2/2
✓ Branch 0 taken 239 times.
✓ Branch 1 taken 8581 times.
8820 if (compressedBytes == 0) {
134 return nullptr;
135 }
136
137 // buffer size is larger due to Blosc overhead so resize
138 // (resize can be skipped if the buffer is only temporary)
139
140
2/2
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 8370 times.
8581 if (resize) {
141
1/2
✓ Branch 1 taken 211 times.
✗ Branch 2 not taken.
211 std::unique_ptr<char[]> newBuffer(new char[compressedBytes]);
142
1/2
✓ Branch 0 taken 211 times.
✗ Branch 1 not taken.
211 std::memcpy(newBuffer.get(), outBuffer.get(), compressedBytes);
143 outBuffer.reset(newBuffer.release());
144 }
145
146 return outBuffer;
147 }
148
149
150 size_t
151 4332 bloscCompressedSize( const char* buffer, const size_t uncompressedBytes)
152 {
153 size_t compressedBytes;
154 4332 bloscCompress(buffer, uncompressedBytes, compressedBytes, /*resize=*/false);
155 4332 return compressedBytes;
156 }
157
158
159 void
160 16023 bloscDecompress(char* uncompressedBuffer, const size_t expectedBytes,
161 const size_t bufferBytes, const char* compressedBuffer)
162 {
163 16023 size_t uncompressedBytes = bloscUncompressedSize(compressedBuffer);
164
165
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16023 times.
16023 if (bufferBytes > BLOSC_MAX_BUFFERSIZE) {
166 OPENVDB_THROW(RuntimeError,
167 "Blosc decompress failed due to exceeding maximum buffer size.");
168 }
169
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16023 times.
16023 if (bufferBytes < uncompressedBytes + BLOSC_MAX_OVERHEAD) {
170 OPENVDB_THROW(RuntimeError,
171 "Blosc decompress failed due to insufficient space in uncompressed buffer.");
172 }
173
174 16023 uncompressedBytes = blosc_decompress_ctx( /*src=*/compressedBuffer,
175 /*dest=*/uncompressedBuffer,
176 bufferBytes,
177 /*numthreads=*/1);
178
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16023 times.
16023 if (uncompressedBytes < 1) {
180 OPENVDB_THROW(RuntimeError, "Blosc decompress returned error code " << uncompressedBytes);
181 }
182
183
2/2
✓ Branch 0 taken 15931 times.
✓ Branch 1 taken 92 times.
16023 if (uncompressedBytes == BLOSC_PAD_BYTES && expectedBytes <= BLOSC_PAD_BYTES) {
184 // padded array to improve compression
185 }
186
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 15926 times.
15931 else if (uncompressedBytes != expectedBytes) {
187
6/12
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 times.
✓ Branch 6 taken 5 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 5 times.
✗ Branch 12 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
39 OPENVDB_THROW(RuntimeError, "Expected to decompress " << expectedBytes
188 << " byte" << (expectedBytes == 1 ? "" : "s") << ", got "
189 << uncompressedBytes << " byte" << (uncompressedBytes == 1 ? "" : "s"));
190 }
191 16018 }
192
193
194 std::unique_ptr<char[]>
195 15652 bloscDecompress(const char* buffer, const size_t expectedBytes, const bool resize)
196 {
197 15652 size_t uncompressedBytes = bloscUncompressedSize(buffer);
198 15652 size_t tempBytes = uncompressedBytes + BLOSC_MAX_OVERHEAD;
199 const bool outOfRange = tempBytes > BLOSC_MAX_BUFFERSIZE;
200
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15652 times.
15652 if (outOfRange) tempBytes = 1;
201 15652 std::unique_ptr<char[]> outBuffer(new char[tempBytes]);
202
203
2/2
✓ Branch 1 taken 15647 times.
✓ Branch 2 taken 5 times.
15652 bloscDecompress(outBuffer.get(), expectedBytes, tempBytes, buffer);
204
205 // buffer size is larger due to Blosc overhead so resize
206 // (resize can be skipped if the buffer is only temporary)
207
208
2/2
✓ Branch 0 taken 210 times.
✓ Branch 1 taken 15437 times.
15647 if (resize) {
209
1/2
✓ Branch 1 taken 210 times.
✗ Branch 2 not taken.
210 std::unique_ptr<char[]> newBuffer(new char[expectedBytes]);
210
1/2
✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
210 std::memcpy(newBuffer.get(), outBuffer.get(), expectedBytes);
211 outBuffer.reset(newBuffer.release());
212 }
213
214 15647 return outBuffer;
215 }
216
217
218 #else
219
220
221 bool
222 bloscCanCompress()
223 {
224 OPENVDB_LOG_DEBUG("Can't compress array data without the blosc library.");
225 return false;
226 }
227
228
229 size_t
230 bloscUncompressedSize(const char*)
231 {
232 OPENVDB_THROW(RuntimeError, "Can't extract compressed data without the blosc library.");
233 }
234
235
236 void
237 bloscCompress(char*, size_t& compressedBytes, const size_t, const char*, const size_t)
238 {
239 OPENVDB_LOG_DEBUG("Can't compress array data without the blosc library.");
240 compressedBytes = 0;
241 }
242
243
244 std::unique_ptr<char[]>
245 bloscCompress(const char*, const size_t, size_t& compressedBytes, const bool)
246 {
247 OPENVDB_LOG_DEBUG("Can't compress array data without the blosc library.");
248 compressedBytes = 0;
249 return nullptr;
250 }
251
252
253 size_t
254 bloscCompressedSize(const char*, const size_t)
255 {
256 OPENVDB_LOG_DEBUG("Can't compress array data without the blosc library.");
257 return 0;
258 }
259
260
261 void
262 bloscDecompress(char*, const size_t, const size_t, const char*)
263 {
264 OPENVDB_THROW(RuntimeError, "Can't extract compressed data without the blosc library.");
265 }
266
267
268 std::unique_ptr<char[]>
269 bloscDecompress(const char*, const size_t, const bool)
270 {
271 OPENVDB_THROW(RuntimeError, "Can't extract compressed data without the blosc library.");
272 }
273
274
275 #endif // OPENVDB_USE_BLOSC
276
277
278 ////////////////////////////////////////
279
280
281 void
282 327 Page::load() const
283 {
284 327 this->doLoad();
285 327 }
286
287
288 long
289
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732 times.
732 Page::uncompressedBytes() const
290 {
291
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 732 times.
732 assert(mInfo);
292 732 return mInfo->uncompressedBytes;
293 }
294
295
296 const char*
297 38534 Page::buffer(const int index) const
298 {
299
2/2
✓ Branch 1 taken 327 times.
✓ Branch 2 taken 38207 times.
38534 if (this->isOutOfCore()) this->load();
300
301 38534 return mData.get() + index;
302 }
303
304
305 void
306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 Page::readHeader(std::istream& is)
307 {
308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 assert(mInfo);
309
310 // read the (compressed) size of the page
311 int compressedSize;
312 366 is.read(reinterpret_cast<char*>(&compressedSize), sizeof(int));
313
314 int uncompressedSize;
315 // if uncompressed, read the (compressed) size of the page
316
2/2
✓ Branch 0 taken 350 times.
✓ Branch 1 taken 16 times.
366 if (compressedSize > 0) is.read(reinterpret_cast<char*>(&uncompressedSize), sizeof(int));
317 16 else uncompressedSize = -compressedSize;
318
319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 assert(compressedSize != 0);
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 assert(uncompressedSize != 0);
321
322 366 mInfo->compressedBytes = compressedSize;
323 366 mInfo->uncompressedBytes = uncompressedSize;
324 366 }
325
326
327 void
328
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 Page::readBuffers(std::istream&is, bool delayed)
329 {
330
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 366 times.
366 assert(mInfo);
331
332 366 bool isCompressed = mInfo->compressedBytes > 0;
333
334 366 io::MappedFile::Ptr mappedFile = io::getMappedFilePtr(is);
335
336
3/4
✓ Branch 0 taken 363 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 363 times.
✗ Branch 3 not taken.
366 if (delayed && mappedFile) {
337
1/2
✓ Branch 1 taken 363 times.
✗ Branch 2 not taken.
363 SharedPtr<io::StreamMetadata> meta = io::getStreamMetadataPtr(is);
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 363 times.
363 assert(meta);
339
340
1/2
✓ Branch 1 taken 363 times.
✗ Branch 2 not taken.
363 std::streamoff filepos = is.tellg();
341
342 // seek over the page
343 15 is.seekg((isCompressed ? mInfo->compressedBytes : -mInfo->compressedBytes),
344
3/4
✓ Branch 0 taken 348 times.
✓ Branch 1 taken 15 times.
✓ Branch 3 taken 363 times.
✗ Branch 4 not taken.
363 std::ios_base::cur);
345
346 mInfo->mappedFile = mappedFile;
347 mInfo->meta = meta;
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 363 times.
363 mInfo->filepos = filepos;
349
350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 363 times.
363 assert(mInfo->mappedFile);
351 }
352 else {
353 std::unique_ptr<char[]> buffer(new char[
354
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 (isCompressed ? mInfo->compressedBytes : -mInfo->compressedBytes)]);
355
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
3 is.read(buffer.get(), (isCompressed ? mInfo->compressedBytes : -mInfo->compressedBytes));
356
357
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
3 if (mInfo->compressedBytes > 0) {
358
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 this->decompress(buffer);
359 } else {
360
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 this->copy(buffer, -static_cast<int>(mInfo->compressedBytes));
361 }
362 3 mInfo.reset();
363 }
364 366 }
365
366
367 bool
368 39196 Page::isOutOfCore() const
369 {
370 39196 return bool(mInfo);
371 }
372
373
374 void
375 11 Page::copy(const std::unique_ptr<char[]>& temp, int pageSize)
376 {
377 11 mData.reset(new char[pageSize]);
378 11 std::memcpy(mData.get(), temp.get(), pageSize);
379 11 }
380
381
382 void
383 316 Page::decompress(const std::unique_ptr<char[]>& temp)
384 {
385 316 size_t uncompressedBytes = bloscUncompressedSize(temp.get());
386 size_t tempBytes = uncompressedBytes;
387 #ifdef OPENVDB_USE_BLOSC
388 316 tempBytes += uncompressedBytes;
389 #endif
390 316 mData.reset(new char[tempBytes]);
391
392 316 bloscDecompress(mData.get(), uncompressedBytes, tempBytes, temp.get());
393 316 }
394
395
396 void
397 327 Page::doLoad() const
398 {
399
1/2
✓ Branch 1 taken 327 times.
✗ Branch 2 not taken.
330 if (!this->isOutOfCore()) return;
400
401 Page* self = const_cast<Page*>(this);
402
403 // This lock will be contended at most once, after which this buffer
404 // will no longer be out-of-core.
405 327 tbb::spin_mutex::scoped_lock lock(self->mMutex);
406
3/4
✓ Branch 1 taken 327 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 324 times.
327 if (!this->isOutOfCore()) return;
407
408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(self->mInfo);
409
410 324 int compressedBytes = static_cast<int>(self->mInfo->compressedBytes);
411 bool compressed = compressedBytes > 0;
412
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 314 times.
324 if (!compressed) compressedBytes = -compressedBytes;
413
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(compressedBytes);
415
416
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 std::unique_ptr<char[]> temp(new char[compressedBytes]);
417
418
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(self->mInfo->mappedFile);
419
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 SharedPtr<std::streambuf> buf = self->mInfo->mappedFile->createBuffer();
420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 324 times.
324 assert(buf);
421
422
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 std::istream is(buf.get());
423
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 io::setStreamMetadataPtr(is, self->mInfo->meta, /*transfer=*/true);
424
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 is.seekg(self->mInfo->filepos);
425
426
1/2
✓ Branch 1 taken 324 times.
✗ Branch 2 not taken.
324 is.read(temp.get(), compressedBytes);
427
428
3/4
✓ Branch 0 taken 314 times.
✓ Branch 1 taken 10 times.
✓ Branch 3 taken 314 times.
✗ Branch 4 not taken.
324 if (compressed) self->decompress(temp);
429
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 else self->copy(temp, compressedBytes);
430
431 324 self->mInfo.reset();
432 }
433
434
435 ////////////////////////////////////////
436
437
438 42751 PageHandle::PageHandle( const Page::Ptr& page, const int index, const int size)
439 : mPage(page)
440 , mIndex(index)
441 42751 , mSize(size)
442 {
443 42751 }
444
445
446 Page&
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36489 times.
36489 PageHandle::page()
448 {
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36489 times.
36489 assert(mPage);
450 36489 return *mPage;
451 }
452
453
454 std::unique_ptr<char[]>
455 38534 PageHandle::read()
456 {
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38534 times.
38534 assert(mIndex >= 0);
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38534 times.
38534 assert(mSize > 0);
459 38534 std::unique_ptr<char[]> buffer(new char[mSize]);
460
1/2
✓ Branch 1 taken 38534 times.
✗ Branch 2 not taken.
38534 std::memcpy(buffer.get(), mPage->buffer(mIndex), mSize);
461 38534 return buffer;
462 }
463
464
465 ////////////////////////////////////////
466
467
468 22 PagedInputStream::PagedInputStream(std::istream& is)
469 22 : mIs(&is)
470 {
471 22 }
472
473
474 PageHandle::Ptr
475 36485 PagedInputStream::createHandle(std::streamsize n)
476 {
477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36485 times.
36485 assert(mByteIndex <= mUncompressedBytes);
478
479
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 36119 times.
36485 if (mByteIndex == mUncompressedBytes) {
480
481 732 mPage = std::make_shared<Page>();
482 366 mPage->readHeader(*mIs);
483 366 mUncompressedBytes = static_cast<int>(mPage->uncompressedBytes());
484 366 mByteIndex = 0;
485 }
486
487 // TODO: C++14 introduces std::make_unique
488
1/2
✓ Branch 2 taken 36485 times.
✗ Branch 3 not taken.
36485 PageHandle::Ptr pageHandle(new PageHandle(mPage, mByteIndex, int(n)));
489
490 36485 mByteIndex += int(n);
491
492 36485 return pageHandle;
493 }
494
495
496 void
497 36485 PagedInputStream::read(PageHandle::Ptr& pageHandle, std::streamsize n, bool delayed)
498 {
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36485 times.
36485 assert(mByteIndex <= mUncompressedBytes);
500
501 36485 Page& page = pageHandle->page();
502
503
2/2
✓ Branch 0 taken 366 times.
✓ Branch 1 taken 36119 times.
36485 if (mByteIndex == mUncompressedBytes) {
504 366 mUncompressedBytes = static_cast<int>(page.uncompressedBytes());
505 366 page.readBuffers(*mIs, delayed);
506 366 mByteIndex = 0;
507 }
508
509 36485 mByteIndex += int(n);
510 36485 }
511
512
513 ////////////////////////////////////////
514
515
516 44 PagedOutputStream::PagedOutputStream()
517 {
518 #ifdef OPENVDB_USE_BLOSC
519
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 mCompressedData.reset(new char[PageSize + BLOSC_MAX_OVERHEAD]);
520 #endif
521 44 }
522
523
524 20 PagedOutputStream::PagedOutputStream(std::ostream& os)
525 20 : mOs(&os)
526 {
527 #ifdef OPENVDB_USE_BLOSC
528
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
20 mCompressedData.reset(new char[PageSize + BLOSC_MAX_OVERHEAD]);
529 #endif
530 20 }
531
532
533 PagedOutputStream&
534 1083966 PagedOutputStream::write(const char* str, std::streamsize n)
535 {
536
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1083964 times.
1083966 if (n > PageSize) {
537 2 this->flush();
538 // write out the block as if a whole page
539 2 this->compressAndWrite(str, size_t(n));
540 }
541 else {
542 // if the size of this block will overflow the page, flush to disk
543
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 1083833 times.
1083964 if ((int(n) + mBytes) > PageSize) {
544 131 this->flush();
545 }
546
547 // store and increment the data in the current page
548 1083964 std::memcpy(mData.get() + mBytes, str, n);
549 1083964 mBytes += int(n);
550 }
551
552 1083966 return *this;
553 }
554
555
556 void
557 195 PagedOutputStream::flush()
558 {
559 195 this->compressAndWrite(mData.get(), mBytes);
560 195 mBytes = 0;
561 195 }
562
563
564 void
565 197 PagedOutputStream::compressAndWrite(const char* buffer, size_t size)
566 {
567
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 195 times.
197 if (size == 0) return;
568
569
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195 times.
195 assert(size < std::numeric_limits<int>::max());
570
571 195 this->resize(size);
572
573 195 size_t compressedBytes(0);
574
2/2
✓ Branch 0 taken 95 times.
✓ Branch 1 taken 100 times.
195 if (mSizeOnly) {
575 #ifdef OPENVDB_USE_BLOSC
576 95 compressedBytes = bloscCompressedSize(buffer, size);
577 #endif
578 }
579 else {
580 #ifdef OPENVDB_USE_BLOSC
581 100 bloscCompress(mCompressedData.get(), compressedBytes, mCapacity + BLOSC_MAX_OVERHEAD, buffer, size);
582 #endif
583 }
584
585
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 167 times.
195 if (compressedBytes == 0) {
586 28 int uncompressedBytes = -static_cast<int>(size);
587
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 15 times.
28 if (mSizeOnly) {
588 13 mOs->write(reinterpret_cast<const char*>(&uncompressedBytes), sizeof(int));
589 }
590 else {
591 15 mOs->write(buffer, size);
592 }
593 }
594 else {
595
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 85 times.
167 if (mSizeOnly) {
596 82 mOs->write(reinterpret_cast<const char*>(&compressedBytes), sizeof(int));
597 82 mOs->write(reinterpret_cast<const char*>(&size), sizeof(int));
598 }
599 else {
600 #ifdef OPENVDB_USE_BLOSC
601 85 mOs->write(mCompressedData.get(), compressedBytes);
602 #else
603 OPENVDB_THROW(RuntimeError, "Cannot write out compressed data without Blosc.");
604 #endif
605 }
606 }
607 }
608
609
610 void
611 195 PagedOutputStream::resize(size_t size)
612 {
613 // grow the capacity if not sufficient space
614 size_t requiredSize = size;
615
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 185 times.
195 if (size < BLOSC_PAD_BYTES && size >= BLOSC_MINIMUM_BYTES) {
616 requiredSize = BLOSC_PAD_BYTES;
617 }
618
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 194 times.
195 if (requiredSize > mCapacity) {
619 1 mCapacity = requiredSize;
620 1 mData.reset(new char[mCapacity]);
621 #ifdef OPENVDB_USE_BLOSC
622 1 mCompressedData.reset(new char[mCapacity + BLOSC_MAX_OVERHEAD]);
623 #endif
624 }
625 195 }
626
627 } // namespace compression
628 } // namespace OPENVDB_VERSION_NAME
629 } // namespace openvdb
630