File: | external/xstream/src/bz.cpp |
Location: | line 563, column 13 |
Description: | Value stored to 'cret' is never read |
1 | #include <xstream/config.h> |
2 | |
3 | #if HAVE_LIBBZ21 |
4 | |
5 | #include <stdint.h> |
6 | #include <string.h> |
7 | #include <algorithm> |
8 | #include <cassert> |
9 | |
10 | #include <xstream/bz.h> |
11 | #include <xstream/except/bz.h> |
12 | |
13 | #include <bzlib.h> |
14 | #include <arpa/inet.h> |
15 | |
16 | #include "debug.h" |
17 | |
18 | namespace xstream { |
19 | namespace bz { |
20 | |
21 | // define a set of compressed stream headers that can be used |
22 | // to remove arbitrary bit-alignment offsets in an input stream |
23 | |
24 | static const int bz_header_length[8] = {35,36,34,44,40,38,40,43}; |
25 | static const unsigned char bz_header[8][48] = { |
26 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
27 | 0x53, 0x59, 0x86, 0xad, 0x3f, 0xf0, 0x00, 0x00, |
28 | 0x02, 0x48, 0x00, 0x04, 0x00, 0x20, 0x00, 0x20, |
29 | 0x00, 0x21, 0x00, 0x82, 0x0b, 0x31, 0x41, 0x59, |
30 | 0x26, 0x53, 0x59 }, |
31 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
32 | 0x53, 0x59, 0x7b, 0x68, 0x3e, 0x4a, 0x00, 0x00, |
33 | 0x01, 0x88, 0x00, 0x0f, 0xc0, 0x20, 0x00, 0x21, |
34 | 0x80, 0x0c, 0x01, 0x37, 0xa4, 0xbb, 0x98, 0xa0, |
35 | 0xac, 0x93, 0x29, 0xac }, |
36 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
37 | 0x53, 0x59, 0x83, 0x69, 0xfc, 0x04, 0x00, 0x00, |
38 | 0x01, 0x88, 0x00, 0x30, 0x00, 0x20, 0x00, 0x30, |
39 | 0x80, 0x2a, 0x69, 0x11, 0xcc, 0x50, 0x56, 0x49, |
40 | 0x94, 0xd6 }, |
41 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
42 | 0x53, 0x59, 0xd5, 0x0d, 0x1c, 0x28, 0x00, 0x00, |
43 | 0x01, 0x51, 0x80, 0x00, 0x10, 0x01, 0x01, 0x80, |
44 | 0x02, 0x01, 0x80, 0x20, 0x00, 0x31, 0x0c, 0x01, |
45 | 0x06, 0x9b, 0x47, 0xe7, 0x38, 0x04, 0xa6, 0x28, |
46 | 0x2b, 0x24, 0xca, 0x6b }, |
47 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
48 | 0x53, 0x59, 0x44, 0x1f, 0x23, 0x2f, 0x00, 0x00, |
49 | 0x02, 0x11, 0x00, 0x00, 0x00, 0xa5, 0xa2, 0xa0, |
50 | 0x00, 0x22, 0x06, 0x9a, 0x7a, 0x10, 0xc0, 0x8e, |
51 | 0x10, 0xd8, 0x43, 0x14, 0x15, 0x92, 0x65, 0x35 }, |
52 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
53 | 0x53, 0x59, 0x83, 0x90, 0x27, 0xae, 0x00, 0x00, |
54 | 0x01, 0x81, 0x80, 0x0c, 0x00, 0x14, 0x20, 0x20, |
55 | 0x00, 0x21, 0x86, 0x81, 0x9a, 0x09, 0x4d, 0xa8, |
56 | 0xb9, 0x8a, 0x0a, 0xc9, 0x32, 0x9a }, |
57 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
58 | 0x53, 0x59, 0x8d, 0x4f, 0x1e, 0x72, 0x00, 0x00, |
59 | 0x04, 0x41, 0x80, 0x40, 0x00, 0x00, 0x20, 0x14, |
60 | 0x60, 0x20, 0x00, 0x30, 0xc0, 0x08, 0x63, 0x45, |
61 | 0x84, 0x0f, 0xb8, 0xc5, 0x05, 0x64, 0x99, 0x4d }, |
62 | { 0x42, 0x5a, 0x68, 0x39, 0x31, 0x41, 0x59, 0x26, |
63 | 0x53, 0x59, 0x64, 0xf2, 0x3a, 0xdc, 0x00, 0x00, |
64 | 0x00, 0x9e, 0x00, 0x04, 0x00, 0x30, 0x00, 0x02, |
65 | 0x08, 0x08, 0x80, 0x20, 0x00, 0x31, 0x0c, 0x01, |
66 | 0x06, 0x99, 0xa4, 0xe4, 0x4c, 0x0a, 0x62, 0x82, |
67 | 0xb2, 0x4c, 0xa6 } |
68 | }; |
69 | |
70 | static const int eof = std::streambuf::traits_type::eof(); |
71 | |
72 | struct pimpl: public bz_stream {}; |
73 | |
74 | static inline int flush_macro(const flush_kind f) { |
75 | switch (f) { |
76 | case no_sync: |
77 | return BZ_RUN0; |
78 | case full_sync: |
79 | return BZ_FLUSH1; |
80 | case finish_sync: |
81 | return BZ_FINISH2; |
82 | default: |
83 | //should probably throw |
84 | return BZ_RUN0; |
85 | } |
86 | } |
87 | |
88 | common::common(std::streambuf *sb) |
89 | : xstream::common_buffer(sb), z_strm(0), block_offset(0) |
90 | { |
91 | LOG("bz::common"); |
92 | |
93 | z_strm = new pimpl; |
94 | |
95 | //initialize zlib structure |
96 | z_strm->bzalloc = NULL__null; |
97 | z_strm->bzfree = NULL__null; |
98 | z_strm->opaque = NULL__null; |
99 | //buffers |
100 | z_strm->avail_out = out.size; |
101 | z_strm->next_out = out.buf; |
102 | |
103 | z_strm->avail_in = 0; |
104 | z_strm->next_in = in.buf; |
105 | } |
106 | |
107 | unsigned long int common::input_count() const { |
108 | // return (z_strm->total_in_hi32 * (1L << 32)) + z_strm->total_in_lo32; |
109 | return ((uint64_t)(z_strm->total_in_hi32)<< 32) + (uint64_t)(z_strm->total_in_lo32); |
110 | } |
111 | |
112 | unsigned long int common::output_count() const { |
113 | // return (z_strm->total_out_hi32 * (1L << 32)) + z_strm->total_out_lo32; |
114 | return ((uint64_t)(z_strm->total_out_hi32)<< 32) + (uint64_t)(z_strm->total_out_lo32); |
115 | } |
116 | |
117 | common::~common() { |
118 | LOG("bz::~common"); |
119 | delete z_strm; |
120 | } |
121 | |
122 | |
123 | //default compression 9 |
124 | ostreambuf::ostreambuf(std::streambuf * sb) |
125 | : common(sb), level(9) { |
126 | LOG("bz::ostreambuf without compression level"); |
127 | init (); |
128 | } |
129 | |
130 | ostreambuf::ostreambuf (std::streambuf * sb, int l) |
131 | : common(sb), level(l) { |
132 | LOG("bz::ostreambuf with compression level " << l); |
133 | init (); |
134 | } |
135 | |
136 | const char* error_str(int err) { |
137 | switch(err) { |
138 | case BZ_MEM_ERROR(-3): |
139 | return "out of memory"; |
140 | case BZ_CONFIG_ERROR(-9): |
141 | return "bzlib badly configured (bad sizes of int32 (4), int16 (2) or char (1), check and recompile)"; |
142 | case BZ_PARAM_ERROR(-2): |
143 | return "invalid parameter, possibly invalid compression level"; |
144 | case BZ_SEQUENCE_ERROR(-1): |
145 | return "bad sequence (this means xstream is buggy)"; |
146 | case BZ_DATA_ERROR(-4): |
147 | return "invalid or incomplete data (crc failed)"; |
148 | case BZ_DATA_ERROR_MAGIC(-5): |
149 | return "magic bytes not found in stream"; |
150 | case BZ_IO_ERROR(-6): |
151 | return "io error"; |
152 | case BZ_UNEXPECTED_EOF(-7): |
153 | return "premature end of data"; |
154 | case BZ_OUTBUFF_FULL(-8): |
155 | return "output buffer full"; |
156 | } |
157 | |
158 | return "unknown error"; |
159 | } |
160 | |
161 | void ostreambuf::raise_error(int err) { |
162 | std::string what = error_str(err); |
163 | |
164 | LOG("bz::ostreambuf::raise_error (" << err << ") = " << what); |
165 | |
166 | if (what.size() > 0) { |
167 | throw compress_error(this,what); |
168 | } else { |
169 | throw compress_error(this); |
170 | } |
171 | } |
172 | |
173 | |
174 | void ostreambuf::init() { |
175 | LOG("bz::ostreambuf::init"); |
176 | int cret =::BZ2_bzCompressInit( |
177 | z_strm, |
178 | level, |
179 | 0, //verbosity |
180 | 30 //workFactor (default value) controls when to switch to the fallback algorithm |
181 | ); |
182 | |
183 | if (BZ_OK0 != cret) { |
184 | LOG("bz::ostreambuf::init: error creating zstream " << cret); |
185 | raise_error(cret); |
186 | } |
187 | //initialize streambuf interface functions |
188 | setp(in.buf, in.buf + in.size); |
189 | } |
190 | |
191 | ostreambuf::~ostreambuf() { |
192 | LOG("bz::ostreambuf::~ostreambuf"); |
193 | //fullsync (write remaining data) |
194 | flush(finish_sync); |
195 | |
196 | //sync underlying streambuf |
197 | _sb->pubsync(); |
198 | |
199 | if (0 != z_strm) { |
200 | //XXX should I throw an exception in case of error? |
201 | //remember this is a destructor |
202 | int cret = ::BZ2_bzCompressEnd(z_strm); |
203 | if (BZ_OK0 != cret) { |
204 | LOG("\tERROR: BZ2_bzCompressEnd returned " << cret); |
205 | } |
206 | } |
207 | } |
208 | |
209 | int ostreambuf::sync () { |
210 | LOG("bz::ostreambuf::sync"); |
211 | int ret = flush(full_sync); |
212 | _sb->pubsync(); |
213 | return ret; |
214 | } |
215 | |
216 | |
217 | int ostreambuf::overflow (int c) { |
218 | LOG("bz::ostreambuf::overflow(" << c << ")\t available=" << (available ()) << "\tEOF=" << eof); |
219 | if (eof == c) { |
220 | LOG("\tEOF"); |
221 | flush(no_sync); |
222 | return eof; |
223 | } else { |
224 | if (0 == available()) { |
225 | LOG("\t have to flush :[]"); |
226 | flush(no_sync); |
227 | } |
228 | *pptr() = static_cast < char >(c); |
229 | pbump(1); |
230 | } |
231 | return c; |
232 | } |
233 | |
234 | std::streamsize ostreambuf::xsputn(const char *buffer, std::streamsize n) { |
235 | LOG("bz::ostreambuf::xsputn(" << buffer << "," << n << ")"); |
236 | |
237 | return flush(no_sync, buffer, n); |
238 | } |
239 | |
240 | int ostreambuf::flush(flush_kind f, const char *appendbuf, int appendsize) { |
241 | LOG("bz::ostreambuf::flush(" << f << ")"); |
242 | std::streamsize in_s = taken(); |
243 | LOG("\tinput_size=" << in_s); |
244 | |
245 | //set up compression engine input feed |
246 | int written; |
247 | if (in_s > 0) { |
248 | z_strm->next_in = pbase(); |
249 | z_strm->avail_in = in_s; |
250 | written = in_s; |
251 | } else if (appendsize > 0) { |
252 | z_strm->next_in = (char*)appendbuf; |
253 | z_strm->avail_in = appendsize; |
254 | written = appendsize; |
255 | appendsize = 0; |
256 | } else { |
257 | z_strm->next_in = pbase(); |
258 | z_strm->avail_in = 0; |
259 | written = 0; |
260 | } |
261 | block_offset += written; |
262 | if (block_offset > (std::streamoff)level * 100000) { |
263 | f = (f == no_sync)? full_sync : f; |
264 | } |
265 | |
266 | bool redo = false; |
267 | |
268 | do { |
269 | int cret; |
270 | redo = false; |
271 | bool error = false; |
272 | |
273 | cret = ::BZ2_bzCompress(z_strm, flush_macro(f)); |
274 | |
275 | //error handling |
276 | if (finish_sync == f) { |
277 | if (BZ_STREAM_END4 == cret) { |
278 | redo = false; |
279 | } |
280 | else if (BZ_FINISH_OK3 == cret) { |
281 | redo = true; |
282 | } else { |
283 | //serious error, throw exception |
284 | LOG("\terror in finish:" << cret); |
285 | error = true; |
286 | } |
287 | } else if (full_sync == f) { |
288 | if (BZ_FLUSH_OK2 == cret) { |
289 | LOG("\tanother go at sync"); |
290 | redo = true; |
291 | } else if (BZ_RUN_OK1 == cret) { |
292 | LOG("\tsync ok"); |
293 | redo = false; |
294 | } else { |
295 | LOG("\terror in sync: " << cret); |
296 | error = true; |
297 | } |
298 | } else if (no_sync == f) { |
299 | if (BZ_RUN_OK1 != cret) { |
300 | LOG("\terror compressing " << cret); |
301 | error = true; |
302 | } |
303 | } else { |
304 | LOG("\tERROR: unknown flush mode " << flush_macro(f)); |
305 | throw general_error(); |
306 | error = true; |
307 | } |
308 | |
309 | if (error) { |
310 | raise_error(cret); |
311 | } |
312 | |
313 | if (f != no_sync) { |
314 | std::streamsize count = out.size - z_strm->avail_out; |
315 | LOG("\twriting " << count << " bytes"); |
316 | int size = htonl(count)(__extension__ ({ register unsigned int __v, __x = (count); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000 ) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x ) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v ; })); |
317 | const std::streamsize wrote = _sb->sputn((char*)&size, 4) + |
318 | _sb->sputn(out.buf, count); |
319 | if (wrote != count + 4) { |
320 | LOG("\terror writting, only wrote " << wrote |
321 | << " but asked for " << count); |
322 | raise_error(BZ_IO_ERROR(-6)); |
323 | } |
324 | |
325 | //reset output |
326 | z_strm->next_out = out.buf; |
327 | z_strm->avail_out = out.size; |
328 | block_offset = 0; |
329 | } |
330 | |
331 | if ((0 == z_strm->avail_out) && (0 != z_strm->avail_in)) { |
332 | LOG("\tavail_out=0 => redo"); |
333 | redo = true; |
334 | } |
335 | |
336 | if (!redo && appendbuf && appendsize > 0) { |
337 | z_strm->next_in = (char*)appendbuf; |
338 | z_strm->avail_in = appendsize; |
339 | written += appendsize; |
340 | appendsize = 0; |
341 | redo = true; |
342 | } |
343 | } while (redo); |
344 | assert (0 == z_strm->avail_in)((0 == z_strm->avail_in) ? static_cast<void> (0) : __assert_fail ("0 == z_strm->avail_in", "external/xstream/src/bz.cpp", 344 , __PRETTY_FUNCTION__)); |
345 | |
346 | //reset buffer |
347 | setp(in.buf, in.buf + in.size); |
348 | return written; |
349 | } |
350 | |
351 | ///////////////////// |
352 | // istream follows // |
353 | ///////////////////// |
354 | |
355 | istreambuf::istreambuf(std::streambuf * sb) |
356 | : common(sb), end(false), block_size(0), block_pending(0) { |
357 | LOG("bz::istreambuf"); |
358 | |
359 | int cret =::BZ2_bzDecompressInit(z_strm, |
360 | 0, //verbosity |
361 | 0 //no small memory |
362 | ); |
363 | |
364 | if (BZ_OK0 != cret) { |
365 | LOG("\terror creating zstream " << cret); |
366 | raise_error(cret); |
367 | } |
368 | //initialize streambuf interface functions |
369 | //first call will call uflow and this will set the buffer accordingly |
370 | //no buffering |
371 | setg(out.buf, out.buf, out.buf); |
372 | } |
373 | |
374 | void istreambuf::raise_error(int err){ |
375 | std::string what = error_str(err); |
376 | |
377 | LOG("bz::istreambuf::raise_error (" << err << ") = " << what); |
378 | |
379 | if (what.size() > 0) { |
380 | throw decompress_error(this, what); |
381 | } else { |
382 | throw decompress_error(this); |
383 | } |
384 | } |
385 | |
386 | int istreambuf::underflow() { |
387 | LOG("z:istreambuf::underflow"); |
388 | |
389 | if (end) { |
390 | LOG("\tend of stream (EOF)"); |
391 | //signal the stream has reached it's end |
392 | return eof; |
393 | } |
394 | |
395 | z_strm->avail_out = out.size; |
396 | z_strm->next_out = out.buf; |
397 | if (0 < z_strm->avail_in) { |
398 | LOG("\tdata in queue, inflating"); |
399 | decompress(); |
400 | } |
401 | while (!end && z_strm->avail_out > 0) { |
402 | read_decompress(); |
403 | } |
404 | if (end && z_strm->avail_out > 0) { |
405 | LOG("\tend of stream (EOF)"); |
406 | //signal the stream has reached it's end |
407 | return eof; |
408 | } |
409 | |
410 | //set streambuf pointers |
411 | setg(out.buf, out.buf, z_strm->next_out); |
412 | |
413 | return int(out.buf[0]); |
414 | } |
415 | |
416 | //read to buffer in place (apart from data already buffered) |
417 | std::streamsize istreambuf::xsgetn(char *buffer, std::streamsize n) { |
418 | LOG("bz::istreambuf::xsgetn (" << n << ")"); |
419 | |
420 | //try to satisfy request from buffered input |
421 | std::streamsize available = egptr() - gptr(); |
422 | int read = (available >= n)? n : available; |
423 | if (read) { |
424 | std::copy(gptr(), gptr() + read, buffer); |
425 | gbump(read); |
426 | block_offset += read; |
427 | } |
428 | |
429 | //inflate the rest directly into the user's buffer |
430 | if (read < n) { |
431 | if (end) { |
432 | LOG("\tend of stream (EOF)"); |
433 | //signal the stream has reached it's end |
434 | return eof; |
435 | } |
436 | |
437 | z_strm->next_out = buffer + read; |
438 | z_strm->avail_out = n - read; |
439 | |
440 | if (0 < z_strm->avail_in) { |
441 | decompress(); |
442 | } |
443 | while (!end && z_strm->avail_out > 0) { |
444 | read_decompress(); |
445 | } |
446 | if (end && z_strm->avail_out > 0) { |
447 | LOG("\tend of stream (EOF)"); |
448 | //signal the stream has reached it's end |
449 | return eof; |
450 | } |
451 | block_offset += n - read; |
452 | } |
453 | return n; |
454 | } |
455 | |
456 | void istreambuf::read_decompress() { |
457 | LOG("bz::istreambuf::read_decompress "); |
458 | int read; |
459 | if (block_size < 0) { // stream has no blocksize markers |
460 | read = _sb->sgetn(in.buf, in.size); |
461 | } |
462 | else { // look for prefixed blocksize: leading byte = 0 |
463 | block_size = block_pending; |
464 | read = _sb->sgetn(in.buf, 4); |
465 | if (read < 4) { |
466 | end = true; |
467 | return; |
468 | } |
469 | if (in.buf[0] == 0) { // bz2 blocks have prefixed blocksize |
470 | int *size = (int*)in.buf; |
471 | block_pending = ntohl(*size)(__extension__ ({ register unsigned int __v, __x = (*size); if (__builtin_constant_p (__x)) __v = ((((__x) & 0xff000000 ) >> 24) | (((__x) & 0x00ff0000) >> 8) | (((__x ) & 0x0000ff00) << 8) | (((__x) & 0x000000ff) << 24)); else __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); __v ; })); |
472 | read = _sb->sgetn(in.buf, block_pending); |
473 | } |
474 | else { // bz2 blocks are jammed together, no blocksize available |
475 | read += _sb->sgetn(in.buf + 4, in.size - 4); |
476 | block_size = -1; |
477 | } |
478 | } |
479 | LOG("\tread " << read << " bytes"); |
480 | block_offset = 0; |
481 | |
482 | if (0 == read) { |
483 | end = true; |
484 | return; |
485 | } |
486 | |
487 | // We want to be able to start decompression at an arbitrary position |
488 | // in the input stream. This is possible with bzip2 streams, but there |
489 | // is a problem that the compressed blocks are arbitrary numbers of |
490 | // bits long and they are catenated one after another in a bit stream |
491 | // without any reference to byte boundaries. This makes it difficult |
492 | // to jump into the middle of a stream and start the decompressor |
493 | // since it expects a stream header followed by the first block that |
494 | // happens to start on a byte boundary. To make this work, I splice |
495 | // an artificial stream header followed by a dummy compressed block |
496 | // onto the beginning of the input stream, where the length of the |
497 | // dummy block in bits is chosen so that it abutts without padding |
498 | // the next block in the input stream. I have prepared 8 dummy blocks |
499 | // so there should be one to match the alignment of any input block. |
500 | // To match them, I look for the first place in the input stream |
501 | // with a byte string that matches the last 5 bytes in one of my |
502 | // dummy headers, and then I inject the dummy header into the |
503 | // decompressor ahead of the actual data. The dummy blocks are all |
504 | // contrived to decompress to an 8-byte string, so throwing away the |
505 | // first 8 bytes out of the decompressor, it is primed to decompress |
506 | // the remaining stream without any need for bit-shifting the input. |
507 | |
508 | const char* head = (const char*)bz_header[0]; |
509 | if (block_size == 0 && strncmp(head, in.buf, 4) != 0) { |
510 | int hdr; |
511 | int splice; |
512 | int match = 10; |
513 | for (hdr = 0; hdr < 8; ++hdr) { |
514 | splice = bz_header_length[hdr] - 5; |
515 | const char* shead = (const char*)bz_header[hdr]; |
516 | for (match = 1; match < 10; ++match) { |
517 | if (strncmp(&in.buf[match], &shead[splice], 5) == 0) |
518 | break; |
519 | } |
520 | if (match < 10) |
521 | break; |
522 | } |
523 | if (hdr > 7) { |
524 | LOG("\tbz2 stream format error on input"); |
525 | raise_error(BZ_DATA_ERROR_MAGIC(-5)); |
526 | } |
527 | int saved_buflen = z_strm->avail_out; |
528 | char *saved_buffer = z_strm->next_out; |
529 | char dummy_buffer[8]; |
530 | z_strm->avail_out = 8; |
531 | z_strm->next_out = dummy_buffer; |
532 | while (match > 0) |
533 | in.buf[--match] = (const char)bz_header[hdr][--splice]; |
534 | z_strm->avail_in = splice; |
535 | z_strm->next_in = (char*)bz_header[hdr]; |
536 | decompress(); // waste the first 8 bytes |
537 | z_strm->next_in = in.buf; |
538 | z_strm->avail_in = read; |
539 | decompress(); |
540 | z_strm->avail_out = saved_buflen; |
541 | z_strm->next_out = saved_buffer; |
542 | decompress(); |
543 | } |
544 | else { |
545 | z_strm->next_in = in.buf; |
546 | z_strm->avail_in = read; |
547 | decompress(); |
548 | } |
549 | } |
550 | |
551 | void istreambuf::decompress() { |
552 | LOG("bz::istreambuf::decompress "); |
553 | |
554 | int cret = ::BZ2_bzDecompress(z_strm); |
555 | |
556 | if (BZ_STREAM_END4 == cret) { |
557 | end = true; |
558 | } |
559 | else if (cret == BZ_DATA_ERROR(-4) && z_strm->avail_in == 0) { |
560 | // Ignore CRC errors at the end of stream because we may not have |
561 | // started decompressing at the beginning. We can rely on the CRC |
562 | // checks that are present within each compressed block anyway. |
563 | cret = BZ_OK0; |
Value stored to 'cret' is never read | |
564 | end = true; |
565 | } |
566 | else if (BZ_OK0 != cret) { |
567 | LOG("\terror decompressing: " << cret); |
568 | raise_error(cret); |
569 | } |
570 | } |
571 | |
572 | istreambuf::~istreambuf() { |
573 | LOG("bz::~istreambuf"); |
574 | if (0 != z_strm) { |
575 | int cret = ::BZ2_bzDecompressEnd(z_strm); |
576 | if (BZ_OK0 != cret) { |
577 | LOG("\tERROR: BZ2_bzDecompressEnd returned " << cret); |
578 | } |
579 | } |
580 | } |
581 | |
582 | }//namespace bz |
583 | }//namespace xstream |
584 | |
585 | #endif //bzlib |