Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <blob/compression.h>
00030
00031 #ifndef HAVE_BZIP2
00032 #define HAVE_BZIP2
00033 #endif
00034
00035 #ifdef HAVE_BZIP2
00036
00037 #include <bzlib.h>
00038
00039 namespace blob
00040 {
00041 static const std::size_t CHUNK_SIZE = 10 * 1024;
00042 static const int VERBOSITY = 1;
00043
00044 bool compressionAvailable() { return true; }
00045
00046 bool deflate(const uint8_t *data, uint32_t size, std::vector<uint8_t>& deflated)
00047 {
00048 static int BLOCK_SIZE_100K = 5;
00049 deflated.clear();
00050
00051 bz_stream stream;
00052 stream.next_in = reinterpret_cast<char *>(const_cast<uint8_t *>(data));
00053 stream.avail_in = size;
00054 stream.bzalloc = NULL;
00055 stream.bzfree = NULL;
00056 stream.opaque = NULL;
00057
00058 if (BZ2_bzCompressInit(&stream, BLOCK_SIZE_100K, 0, 0) != BZ_OK) {
00059 return false;
00060 }
00061
00062 deflated.resize(CHUNK_SIZE);
00063 stream.next_out = reinterpret_cast<char *>(deflated.data());
00064 stream.avail_out = deflated.size();
00065
00066 int result = BZ_RUN_OK;
00067 int state = BZ_RUN;
00068 while(result == BZ_RUN_OK || result == BZ_FLUSH_OK || result == BZ_FINISH_OK) {
00069 if (stream.avail_in == 0) {
00070 state = BZ_FINISH;
00071 }
00072
00073 if (stream.avail_out == 0) {
00074 deflated.resize(deflated.size() + CHUNK_SIZE);
00075 stream.next_out = reinterpret_cast<char *>(deflated.data() + deflated.size() - CHUNK_SIZE);
00076 stream.avail_out = CHUNK_SIZE;
00077 }
00078
00079 result = BZ2_bzCompress(&stream, state);
00080 }
00081
00082 if (result != BZ_STREAM_END) {
00083 deflated.clear();
00084 BZ2_bzCompressEnd(&stream);
00085 return false;
00086 }
00087
00088 deflated.resize(deflated.size() - stream.avail_out);
00089 BZ2_bzCompressEnd(&stream);
00090 return true;
00091 }
00092
00093 bool inflate(const uint8_t *data, uint32_t size, std::vector<uint8_t>& inflated)
00094 {
00095 static const int SMALL = 1;
00096 inflated.clear();
00097
00098 bz_stream stream;
00099 stream.next_in = reinterpret_cast<char *>(const_cast<uint8_t *>(data));
00100 stream.avail_in = size;
00101 stream.bzalloc = NULL;
00102 stream.bzfree = NULL;
00103 stream.opaque = NULL;
00104
00105 if (BZ2_bzDecompressInit(&stream, VERBOSITY, SMALL) != BZ_OK) {
00106 return false;
00107 }
00108
00109 inflated.resize(CHUNK_SIZE);
00110 stream.next_out = reinterpret_cast<char *>(inflated.data());
00111 stream.avail_out = inflated.size();
00112
00113 int result = BZ_OK;
00114 while(result == BZ_OK || result == BZ_FLUSH_OK || result == BZ_FINISH_OK) {
00115 if (stream.avail_out == 0) {
00116 inflated.resize(inflated.size() + CHUNK_SIZE);
00117 stream.next_out = reinterpret_cast<char *>(inflated.data() + inflated.size() - CHUNK_SIZE);
00118 stream.avail_out = CHUNK_SIZE;
00119 }
00120
00121 result = BZ2_bzDecompress(&stream);
00122 }
00123
00124 if (result != BZ_STREAM_END) {
00125 inflated.clear();
00126 BZ2_bzDecompressEnd(&stream);
00127 return false;
00128 }
00129
00130 inflated.resize(inflated.size() - stream.avail_out);
00131 BZ2_bzDecompressEnd(&stream);
00132 return true;
00133 }
00134
00135 }
00136
00137 #else // HAVE_BZIP2
00138
00139 namespace blob
00140 {
00141 bool compressionAvailable() { return false; }
00142 bool deflate(const uint8_t *data, uint32_t size, std::vector<uint8_t>& deflated) { return false; }
00143 bool inflate(const uint8_t *data, uint32_t size, std::vector<uint8_t>& inflated) { return false; }
00144 }
00145
00146 #endif // HAVE_BZIP2