1 //===- lib/Support/Compressor.cpp -------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Reid Spencer and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the llvm::Compressor class, an abstraction for memory
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/Compressor.h"
17 #include "llvm/ADT/StringExtras.h"
31 # warning No compression library is available!!
37 inline int getdata(char*& buffer, unsigned& size,
38 llvm::Compressor::OutputDataCallback* cb, void* context) {
41 int result = (*cb)(buffer, size, context);
42 assert(buffer != 0 && "Invalid result from Compressor callback");
43 assert(size != 0 && "Invalid result from Compressor callback");
47 //===----------------------------------------------------------------------===//
48 //=== RLCOMP - very simple run length compression scheme
49 //=== The code below transforms the input into blocks that are either
50 //=== compressed or not. Each block starts with a header byte that provides
51 //=== the length of the block. Values < 128 are uncompressed, values >128
52 //=== are compressed. The value 128 is illegal. Currently, the algorithm is
53 //=== not completed and is #if'd out.
54 //===----------------------------------------------------------------------===//
57 MAX_RLCOMP_OUT = 32768
60 struct RLCOMP_stream {
61 // User provided fields
68 uint64_t output_count; // Total count of output bytes
72 unsigned block_len; // Length of current block
73 unsigned compression; // State of compression 0=no, 1=yes, 2=indeterminate
74 char buffer[128]; // compression buffer (not used for decompress)
75 unsigned buflen; // bytes in compression buffer
76 bool pending; // is data pending to be written
77 char pending_data; // the pending data
78 unsigned clen; // length of the compressed block
82 void RLCOMP_init(RLCOMP_stream* s) {
94 inline bool RLCOMP_getchar(RLCOMP_stream* s, unsigned& data) {
105 inline bool RLCOMP_putchar(RLCOMP_stream* s, unsigned data) {
108 *s->next_out++ = data;
114 s->pending_data = data;
122 bool RLCOMP_compress(RLCOMP_stream* s) {
123 assert(s && "Invalid RLCOMP_stream");
124 assert(s->next_in != 0);
125 assert(s->next_out != 0);
126 assert(s->avail_in >= 1);
127 assert(s->avail_out >= 1);
131 // Handle pending data from the last time in
133 RLCOMP_putchar(s,s->pending_data);
139 // Handle the degenerate len=1 case
140 if (!RLCOMP_getchar(s,lastc)) {
142 return RLCOMP_putchar(s,lastc);
145 while (RLCOMP_getchar(s,c)) {
146 switch(s->compression) {
152 if (!RLCOMP_putchar(s, c))
160 if (!RLCOMP_putchar(s, s->clen))
173 if (s->avail_out >= s->avail_in) {
174 ::memcpy(s->next_out, s->next_in, s->avail_in);
175 s->output_count += s->avail_in;
176 s->avail_out -= s->avail_in;
177 s->next_in += s->avail_in;
181 ::memcpy(s->next_out, s->next_in, s->avail_out);
182 s->output_count += s->avail_out;
183 s->avail_in -= s->avail_out;
184 s->next_in += s->avail_out;
190 bool RLCOMP_decompress(RLCOMP_stream* s) {
191 assert(s && "Invalid RLCOMP_stream");
192 assert(s->next_in != 0);
193 assert(s->next_out != 0);
194 assert(s->avail_in >= 1);
195 assert(s->avail_out >= 1);
199 while (RLCOMP_getchar(s,c)) {
200 switch(s->compression) {
201 case 0: // This is not a compressed block
203 if (!RLCOMP_putchar(s,c))
207 case 1: // This is a comperssed block
208 while (s->block_len-- > 0)
209 if (!RLCOMP_putchar(s,c))
213 case 2: // This is the length field
219 s->block_len = c - 128;
224 throw std::string("Invalid compression state");
226 if (s->block_len <= 0)
231 throw std::string("Invalid compression state");
233 if (s->avail_out >= s->avail_in) {
234 ::memcpy(s->next_out, s->next_in, s->avail_in);
235 s->output_count += s->avail_in;
236 s->avail_out -= s->avail_in;
237 s->next_in += s->avail_in;
241 ::memcpy(s->next_out, s->next_in, s->avail_out);
242 s->output_count += s->avail_out;
243 s->avail_in -= s->avail_out;
244 s->next_in += s->avail_out;
250 void RLCOMP_end(RLCOMP_stream* strm) {
257 // Compress in one of three ways
258 uint64_t Compressor::compress(char* in, unsigned size, OutputDataCallback* cb,
259 Algorithm hint, void* context ) {
260 assert(in && "Can't compress null buffer");
261 assert(size && "Can't compress empty buffer");
262 assert(cb && "Can't compress without a callback function");
267 case COMP_TYPE_BZIP2: {
268 #if defined(HAVE_BZIP2)
269 // Set up the bz_stream
275 bzdata.avail_in = size;
277 bzdata.avail_out = 0;
278 switch ( BZ2_bzCompressInit(&bzdata, 9, 0, 0) ) {
279 case BZ_CONFIG_ERROR: throw std::string("bzip2 library mis-compiled");
280 case BZ_PARAM_ERROR: throw std::string("Compressor internal error");
281 case BZ_MEM_ERROR: throw std::string("Out of memory");
287 // Get a block of memory
288 if (0 != getdata(bzdata.next_out, bzdata.avail_out,cb,context)) {
289 BZ2_bzCompressEnd(&bzdata);
290 throw std::string("Can't allocate output buffer");
293 // Put compression code in first byte
294 (*bzdata.next_out++) = COMP_TYPE_BZIP2;
298 int bzerr = BZ_FINISH_OK;
299 while (BZ_FINISH_OK == (bzerr = BZ2_bzCompress(&bzdata, BZ_FINISH))) {
300 if (0 != getdata(bzdata.next_out, bzdata.avail_out,cb,context)) {
301 BZ2_bzCompressEnd(&bzdata);
302 throw std::string("Can't allocate output buffer");
306 case BZ_SEQUENCE_ERROR:
307 case BZ_PARAM_ERROR: throw std::string("Param/Sequence error");
309 case BZ_STREAM_END: break;
310 default: throw std::string("Oops: ") + utostr(unsigned(bzerr));
314 result = (static_cast<uint64_t>(bzdata.total_out_hi32) << 32) |
315 bzdata.total_out_lo32 + 1;
317 BZ2_bzCompressEnd(&bzdata);
324 case COMP_TYPE_ZLIB: {
325 #if defined(HAVE_ZLIB)
327 zdata.zalloc = Z_NULL;
328 zdata.zfree = Z_NULL;
329 zdata.opaque = Z_NULL;
330 zdata.next_in = reinterpret_cast<Bytef*>(in);
331 zdata.avail_in = size;
332 if (Z_OK != deflateInit(&zdata,Z_BEST_COMPRESSION))
333 throw std::string(zdata.msg ? zdata.msg : "zlib error");
335 if (0 != getdata((char*&)(zdata.next_out), zdata.avail_out,cb,context)) {
337 throw std::string("Can't allocate output buffer");
340 (*zdata.next_out++) = COMP_TYPE_ZLIB;
344 while ( Z_OK == deflate(&zdata,0) && zdata.avail_out == 0) {
345 if (0 != getdata((char*&)zdata.next_out, zdata.avail_out, cb,context)) {
347 throw std::string("Can't allocate output buffer");
351 while ( Z_STREAM_END != deflate(&zdata, Z_FINISH)) {
352 if (0 != getdata((char*&)zdata.next_out, zdata.avail_out, cb,context)) {
354 throw std::string("Can't allocate output buffer");
358 result = static_cast<uint64_t>(zdata.total_out) + 1;
367 case COMP_TYPE_SIMPLE: {
370 sdata.avail_in = size;
373 if (0 != getdata(sdata.next_out, sdata.avail_out,cb,context)) {
374 throw std::string("Can't allocate output buffer");
377 *(sdata.next_out++) = COMP_TYPE_SIMPLE;
380 while (!RLCOMP_compress(&sdata)) {
381 if (0 != getdata(sdata.next_out, sdata.avail_out,cb,context)) {
382 throw std::string("Can't allocate output buffer");
386 result = sdata.output_count + 1;
391 throw std::string("Invalid compression type hint");
396 // Decompress in one of three ways
397 uint64_t Compressor::decompress(char *in, unsigned size,
398 OutputDataCallback* cb, void* context) {
399 assert(in && "Can't decompress null buffer");
400 assert(size > 1 && "Can't decompress empty buffer");
401 assert(cb && "Can't decompress without a callback function");
406 case COMP_TYPE_BZIP2: {
407 #if !defined(HAVE_BZIP2)
408 throw std::string("Can't decompress BZIP2 data");
410 // Set up the bz_stream
416 bzdata.avail_in = size - 1;
418 bzdata.avail_out = 0;
419 switch ( BZ2_bzDecompressInit(&bzdata, 0, 0) ) {
420 case BZ_CONFIG_ERROR: throw std::string("bzip2 library mis-compiled");
421 case BZ_PARAM_ERROR: throw std::string("Compressor internal error");
422 case BZ_MEM_ERROR: throw std::string("Out of memory");
428 // Get a block of memory
429 if (0 != getdata(bzdata.next_out, bzdata.avail_out,cb,context)) {
430 BZ2_bzDecompressEnd(&bzdata);
431 throw std::string("Can't allocate output buffer");
436 while (BZ_OK == (bzerr = BZ2_bzDecompress(&bzdata))) {
437 if (0 != getdata(bzdata.next_out, bzdata.avail_out,cb,context)) {
438 BZ2_bzDecompressEnd(&bzdata);
439 throw std::string("Can't allocate output buffer");
444 case BZ_PARAM_ERROR: throw std::string("Compressor internal error");
445 case BZ_MEM_ERROR: throw std::string("Out of memory");
446 case BZ_DATA_ERROR: throw std::string("Data integrity error");
447 case BZ_DATA_ERROR_MAGIC:throw std::string("Data is not BZIP2");
448 default: throw("Ooops");
454 result = (static_cast<uint64_t>(bzdata.total_out_hi32) << 32) |
455 bzdata.total_out_lo32;
456 BZ2_bzDecompressEnd(&bzdata);
461 case COMP_TYPE_ZLIB: {
462 #if !defined(HAVE_ZLIB)
463 throw std::string("Can't decompress ZLIB data");
466 zdata.zalloc = Z_NULL;
467 zdata.zfree = Z_NULL;
468 zdata.opaque = Z_NULL;
469 zdata.next_in = reinterpret_cast<Bytef*>(in);
470 zdata.avail_in = size - 1;
471 if ( Z_OK != inflateInit(&zdata))
472 throw std::string(zdata.msg ? zdata.msg : "zlib error");
474 if (0 != getdata((char*&)zdata.next_out, zdata.avail_out,cb,context)) {
476 throw std::string("Can't allocate output buffer");
480 while (Z_OK == (zerr = inflate(&zdata,0))) {
481 if (0 != getdata((char*&)zdata.next_out, zdata.avail_out,cb,context)) {
483 throw std::string("Can't allocate output buffer");
487 if (zerr != Z_STREAM_END)
488 throw std::string(zdata.msg?zdata.msg:"zlib error");
490 result = static_cast<uint64_t>(zdata.total_out);
496 case COMP_TYPE_SIMPLE: {
499 sdata.avail_in = size - 1;
502 if (0 != getdata(sdata.next_out, sdata.avail_out,cb,context)) {
503 throw std::string("Can't allocate output buffer");
506 while (!RLCOMP_decompress(&sdata)) {
507 if (0 != getdata(sdata.next_out, sdata.avail_out,cb,context)) {
508 throw std::string("Can't allocate output buffer");
512 result = sdata.output_count;
518 throw std::string("Unknown type of compressed data");