GCC Code Coverage Report


Directory: ./
File: openvdb/openvdb/io/Compression.cc
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 72 92 78.3%
Functions: 8 8 100.0%
Branches: 48 168 28.6%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0
3
4 #include "Compression.h"
5
6 #include <openvdb/Exceptions.h>
7 #include <openvdb/util/logging.h>
8 #include <boost/algorithm/string/join.hpp>
9 #ifdef OPENVDB_USE_ZLIB
10 #include <zlib.h>
11 #endif
12 #ifdef OPENVDB_USE_BLOSC
13 #include <blosc.h>
14 #endif
15
16
17 namespace openvdb {
18 OPENVDB_USE_VERSION_NAMESPACE
19 namespace OPENVDB_VERSION_NAME {
20 namespace io {
21
22 std::string
23 141 compressionToString(uint32_t flags)
24 {
25
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 136 times.
141 if (flags == COMPRESS_NONE) return "none";
26
27 136 std::vector<std::string> words;
28
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 134 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
138 if (flags & COMPRESS_ZIP) words.push_back("zip");
29
3/4
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 129 times.
✗ Branch 4 not taken.
265 if (flags & COMPRESS_BLOSC) words.push_back("blosc");
30
3/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 132 times.
✗ Branch 4 not taken.
268 if (flags & COMPRESS_ACTIVE_MASK) words.push_back("active values");
31
1/2
✓ Branch 1 taken 136 times.
✗ Branch 2 not taken.
136 return boost::join(words, " + ");
32 }
33
34
35 ////////////////////////////////////////
36
37
38 #ifdef OPENVDB_USE_ZLIB
39 namespace {
40 const int ZIP_COMPRESSION_LEVEL = Z_DEFAULT_COMPRESSION; ///< @todo use Z_BEST_SPEED?
41 }
42 #endif
43
44
45 #ifndef OPENVDB_USE_ZLIB
46 size_t
47 zipToStreamSize(const char*, size_t)
48 {
49 OPENVDB_THROW(IoError, "Zip encoding is not supported");
50 }
51 #else
52 size_t
53 1180 zipToStreamSize(const char* data, size_t numBytes)
54 {
55 // Get an upper bound on the size of the compressed data.
56 1180 uLongf numZippedBytes = compressBound(numBytes);
57 // Compress the data.
58 1180 std::unique_ptr<Bytef[]> zippedData(new Bytef[numZippedBytes]);
59
1/2
✓ Branch 1 taken 1180 times.
✗ Branch 2 not taken.
1180 int status = compress2(
60 /*dest=*/zippedData.get(), &numZippedBytes,
61 /*src=*/reinterpret_cast<const Bytef*>(data), numBytes,
62 /*level=*/ZIP_COMPRESSION_LEVEL);
63
3/4
✓ Branch 0 taken 1180 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
✓ Branch 3 taken 1111 times.
1180 if (status == Z_OK && numZippedBytes < numBytes) {
64 return size_t(numZippedBytes);
65 } else {
66 69 return size_t(numBytes);
67 }
68 }
69 #endif
70
71 #ifndef OPENVDB_USE_ZLIB
72 void
73 zipToStream(std::ostream&, const char*, size_t)
74 {
75 OPENVDB_THROW(IoError, "Zip encoding is not supported");
76 }
77 #else
78 void
79 578 zipToStream(std::ostream& os, const char* data, size_t numBytes)
80 {
81 // Get an upper bound on the size of the compressed data.
82 578 uLongf numZippedBytes = compressBound(numBytes);
83 // Compress the data.
84 578 std::unique_ptr<Bytef[]> zippedData(new Bytef[numZippedBytes]);
85
1/2
✓ Branch 1 taken 578 times.
✗ Branch 2 not taken.
578 int status = compress2(
86 /*dest=*/zippedData.get(), &numZippedBytes,
87 /*src=*/reinterpret_cast<const Bytef*>(data), numBytes,
88 /*level=*/ZIP_COMPRESSION_LEVEL);
89
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 578 times.
578 if (status != Z_OK) {
90 std::string errDescr;
91 if (const char* s = zError(status)) errDescr = s;
92 if (!errDescr.empty()) errDescr = " (" + errDescr + ")";
93 OPENVDB_LOG_DEBUG("zlib compress2() returned error code " << status << errDescr);
94 }
95
3/4
✓ Branch 0 taken 578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 569 times.
✓ Branch 3 taken 9 times.
578 if (status == Z_OK && numZippedBytes < numBytes) {
96 // Write the size of the compressed data.
97 569 Int64 outZippedBytes = numZippedBytes;
98
1/2
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
569 os.write(reinterpret_cast<char*>(&outZippedBytes), 8);
99 // Write the compressed data.
100
1/2
✓ Branch 1 taken 569 times.
✗ Branch 2 not taken.
569 os.write(reinterpret_cast<char*>(zippedData.get()), outZippedBytes);
101 } else {
102 // Write the size of the uncompressed data.
103 // numBytes expected to be <= the max value + 1 of a signed int64
104
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 assert(numBytes < size_t(std::numeric_limits<Int64>::max()));
105 9 Int64 negBytes = -Int64(numBytes);
106
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 os.write(reinterpret_cast<char*>(&negBytes), 8);
107 // Write the uncompressed data.
108
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 os.write(reinterpret_cast<const char*>(data), numBytes);
109 }
110 578 }
111 #endif
112
113
114 #ifndef OPENVDB_USE_ZLIB
115 void
116 unzipFromStream(std::istream&, char*, size_t)
117 {
118 OPENVDB_THROW(IoError, "Zip decoding is not supported");
119 }
120 #else
121 void
122 564 unzipFromStream(std::istream& is, char* data, size_t numBytes)
123 {
124 // Read the size of the compressed data.
125 // A negative size indicates uncompressed data.
126 Int64 numZippedBytes;
127 564 is.read(reinterpret_cast<char*>(&numZippedBytes), 8);
128
129
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 562 times.
564 if (numZippedBytes <= 0) {
130 // Read the uncompressed data.
131
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (data == nullptr) {
132 is.seekg(-numZippedBytes, std::ios_base::cur);
133 } else {
134 2 is.read(data, -numZippedBytes);
135 }
136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (size_t(-numZippedBytes) != numBytes) {
137 OPENVDB_THROW(RuntimeError, "Expected to read a " << numBytes
138 << "-byte chunk, got a " << -numZippedBytes << "-byte chunk");
139 }
140 } else {
141
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 562 times.
562 if (data == nullptr) {
142 // Seek over the compressed data.
143 is.seekg(numZippedBytes, std::ios_base::cur);
144 } else {
145 // Read the compressed data.
146 562 std::unique_ptr<Bytef[]> zippedData(new Bytef[numZippedBytes]);
147
1/2
✓ Branch 1 taken 562 times.
✗ Branch 2 not taken.
562 is.read(reinterpret_cast<char*>(zippedData.get()), numZippedBytes);
148 // Uncompress the data.
149 562 uLongf numUnzippedBytes = numBytes;
150
1/2
✓ Branch 1 taken 562 times.
✗ Branch 2 not taken.
562 int status = uncompress(
151 /*dest=*/reinterpret_cast<Bytef*>(data), &numUnzippedBytes,
152 /*src=*/zippedData.get(), static_cast<uLongf>(numZippedBytes));
153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 562 times.
562 if (status != Z_OK) {
154 std::string errDescr;
155 if (const char* s = zError(status)) errDescr = s;
156 if (!errDescr.empty()) errDescr = " (" + errDescr + ")";
157 OPENVDB_LOG_DEBUG("zlib uncompress() returned error code " << status << errDescr);
158 }
159
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 562 times.
562 if (numUnzippedBytes != numBytes) {
160 OPENVDB_THROW(RuntimeError, "Expected to decompress " << numBytes
161 << " byte" << (numBytes == 1 ? "" : "s") << ", got "
162 << numZippedBytes << " byte" << (numZippedBytes == 1 ? "" : "s"));
163 }
164 }
165 }
166 564 }
167 #endif
168
169
170 namespace {
171
172 #ifdef OPENVDB_USE_BLOSC
173 43366 int bloscCompress(size_t inBytes, const char* data, char* compressedData, int outBytes)
174 {
175 43366 return blosc_compress_ctx(
176 /*clevel=*/9, // 0 (no compression) to 9 (maximum compression)
177 /*doshuffle=*/true,
178 /*typesize=*/sizeof(float), //for optimal float and Vec3f compression
179 /*srcsize=*/inBytes,
180 /*src=*/data,
181 /*dest=*/compressedData,
182 /*destsize=*/outBytes,
183 BLOSC_LZ4_COMPNAME,
184 /*blocksize=*/inBytes,//previously set to 256 (in v3.x)
185 43366 /*numthreads=*/1);
186 }
187 #endif
188
189 } // namespace
190
191
192 #ifndef OPENVDB_USE_BLOSC
193 size_t
194 bloscToStreamSize(const char*, size_t, size_t)
195 {
196 OPENVDB_THROW(IoError, "Blosc encoding is not supported");
197 }
198 #else
199 size_t
200 21443 bloscToStreamSize(const char* data, size_t valSize, size_t numVals)
201 {
202 21443 const size_t inBytes = valSize * numVals;
203
204 21443 int outBytes = int(inBytes) + BLOSC_MAX_OVERHEAD;
205 21443 std::unique_ptr<char[]> compressedData(new char[outBytes]);
206
207
1/2
✓ Branch 1 taken 21443 times.
✗ Branch 2 not taken.
21443 outBytes = bloscCompress(inBytes, data, compressedData.get(), outBytes);
208
209
1/2
✓ Branch 0 taken 21443 times.
✗ Branch 1 not taken.
21443 if (outBytes <= 0) {
210 return size_t(inBytes);
211 }
212
213 21443 return size_t(outBytes);
214 }
215 #endif
216
217
218 #ifndef OPENVDB_USE_BLOSC
219 void
220 bloscToStream(std::ostream&, const char*, size_t, size_t)
221 {
222 OPENVDB_THROW(IoError, "Blosc encoding is not supported");
223 }
224 #else
225 void
226 21923 bloscToStream(std::ostream& os, const char* data, size_t valSize, size_t numVals)
227 {
228 21923 const size_t inBytes = valSize * numVals;
229 // inBytes expected to be <= the max value + 1 of a signed int64
230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21923 times.
21923 assert(inBytes < size_t(std::numeric_limits<Int64>::max()));
231
232 21923 int outBytes = int(inBytes) + BLOSC_MAX_OVERHEAD;
233 21923 std::unique_ptr<char[]> compressedData(new char[outBytes]);
234
235
1/2
✓ Branch 1 taken 21923 times.
✗ Branch 2 not taken.
21923 outBytes = bloscCompress(inBytes, data, compressedData.get(), outBytes);
236
237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21923 times.
21923 if (outBytes <= 0) {
238 std::ostringstream ostr;
239 ostr << "Blosc failed to compress " << inBytes << " byte" << (inBytes == 1 ? "" : "s");
240 if (outBytes < 0) ostr << " (internal error " << outBytes << ")";
241 OPENVDB_LOG_DEBUG(ostr.str());
242
243 // Write the size of the uncompressed data.
244 Int64 negBytes = -Int64(inBytes);
245 os.write(reinterpret_cast<char*>(&negBytes), 8);
246 // Write the uncompressed data.
247 os.write(reinterpret_cast<const char*>(data), inBytes);
248 } else {
249 // Write the size of the compressed data.
250 21923 Int64 numBytes = outBytes;
251
1/2
✓ Branch 1 taken 21923 times.
✗ Branch 2 not taken.
21923 os.write(reinterpret_cast<char*>(&numBytes), 8);
252 // Write the compressed data.
253
1/2
✓ Branch 1 taken 21923 times.
✗ Branch 2 not taken.
21923 os.write(reinterpret_cast<char*>(compressedData.get()), outBytes);
254 }
255 21923 }
256 #endif
257
258
259 #ifndef OPENVDB_USE_BLOSC
260 void
261 bloscFromStream(std::istream&, char*, size_t)
262 {
263 OPENVDB_THROW(IoError, "Blosc decoding is not supported");
264 }
265 #else
266 void
267 1880 bloscFromStream(std::istream& is, char* data, size_t numBytes)
268 {
269 // Read the size of the compressed data.
270 // A negative size indicates uncompressed data.
271 Int64 numCompressedBytes;
272 1880 is.read(reinterpret_cast<char*>(&numCompressedBytes), 8);
273
274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1880 times.
1880 if (numCompressedBytes <= 0) {
275 // Read the uncompressed data.
276 if (data == nullptr) {
277 is.seekg(-numCompressedBytes, std::ios_base::cur);
278 } else {
279 is.read(data, -numCompressedBytes);
280 }
281 if (size_t(-numCompressedBytes) != numBytes) {
282 OPENVDB_THROW(RuntimeError, "Expected to read a " << numBytes
283 << "-byte uncompressed chunk, got a " << -numCompressedBytes << "-byte chunk");
284 }
285 } else {
286
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1876 times.
1880 if (data == nullptr) {
287 // Seek over the compressed data.
288 4 is.seekg(numCompressedBytes, std::ios_base::cur);
289 } else {
290 // Read the compressed data.
291 1876 std::unique_ptr<char[]> compressedData(new char[numCompressedBytes]);
292
1/2
✓ Branch 1 taken 1876 times.
✗ Branch 2 not taken.
1876 is.read(reinterpret_cast<char*>(compressedData.get()), numCompressedBytes);
293 // Uncompress the data.
294
1/2
✓ Branch 1 taken 1876 times.
✗ Branch 2 not taken.
1876 const int numUncompressedBytes = blosc_decompress_ctx(
295 /*src=*/compressedData.get(), /*dest=*/data, numBytes, /*numthreads=*/1);
296 if (numUncompressedBytes < 1) {
297 OPENVDB_LOG_DEBUG("blosc_decompress() returned error code "
298 << numUncompressedBytes);
299 }
300
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1876 times.
1876 if (numUncompressedBytes != Int64(numBytes)) {
301 OPENVDB_THROW(RuntimeError, "Expected to decompress " << numBytes
302 << " byte" << (numBytes == 1 ? "" : "s") << ", got "
303 << numUncompressedBytes << " byte" << (numUncompressedBytes == 1 ? "" : "s"));
304 }
305 }
306 }
307 1880 }
308 #endif
309
310 } // namespace io
311 } // namespace OPENVDB_VERSION_NAME
312 } // namespace openvdb
313