00001 #include <cassert>
00002 #include <cstring>
00003
00004 #include "zlib.h"
00005
00006 #include "Alignment/Geners/interface/BZ2Handle.hh"
00007 #include "Alignment/Geners/interface/CStringStream.hh"
00008 #include "Alignment/Geners/interface/IOException.hh"
00009
00010 static void doZlibCompression(const char* data, const unsigned long long len,
00011 const bool defl, z_stream_s& strm,
00012 char* buffer, const unsigned long long bufLen,
00013 std::ostream& sink)
00014 {
00015 assert(buffer);
00016 assert(bufLen);
00017
00018 int status = Z_OK;
00019 strm.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
00020 strm.avail_in = len;
00021 do
00022 {
00023 strm.next_out = reinterpret_cast<Bytef*>(buffer);
00024 strm.avail_out = bufLen;
00025 status = defl ? deflate(&strm, Z_FINISH) :
00026 inflate(&strm, Z_NO_FLUSH);
00027 assert(status == Z_OK || status == Z_STREAM_END);
00028 const unsigned have = bufLen - strm.avail_out;
00029 sink.write(buffer, have);
00030 if (sink.fail()) throw gs::IOWriteFailure(
00031 "In gs::doZlibCompression: sink stream failure");
00032 } while (strm.avail_out == 0);
00033
00034 if (defl)
00035 {
00036 assert(strm.avail_in == 0);
00037 assert(status == Z_STREAM_END);
00038 assert(deflateReset(&strm) == Z_OK);
00039 }
00040 else
00041 assert(inflateReset(&strm) == Z_OK);
00042 }
00043
00044
00045 static void doBZ2Compression(const char* data, const unsigned long long len,
00046 const bool defl, bz_stream& strm,
00047 char* buffer, const unsigned long long bufLen,
00048 std::ostream& sink)
00049 {
00050 assert(buffer);
00051 assert(bufLen);
00052
00053 int status = BZ_OK;
00054 strm.next_in = const_cast<char*>(data);
00055 strm.avail_in = len;
00056 do
00057 {
00058 strm.next_out = buffer;
00059 strm.avail_out = bufLen;
00060 status = defl ? BZ2_bzCompress(&strm, BZ_FINISH) :
00061 BZ2_bzDecompress(&strm);
00062 assert(status == BZ_OK || status == BZ_STREAM_END);
00063 const unsigned have = bufLen - strm.avail_out;
00064 sink.write(buffer, have);
00065 if (sink.fail()) throw gs::IOWriteFailure(
00066 "In gs::doBZ2Compression: sink stream failure");
00067 } while (status != BZ_STREAM_END);
00068 }
00069
00070
00071 namespace gs {
00072 CStringStream::CStringStream(const CompressionMode m,
00073 const int compressionLevel,
00074 const unsigned minSizeToCompress,
00075 const unsigned bufSize)
00076 : mode_(m),
00077 compressionLevel_(compressionLevel),
00078 minSizeToCompress_(minSizeToCompress),
00079
00080
00081
00082 comprBuf_(bufSize > 1024U ? bufSize : 1024U),
00083 sink_(0)
00084 {
00085 this->init(&buf_);
00086 }
00087
00088 void CStringStream::setCompressionMode(const CompressionMode newmode)
00089 {
00090 reset();
00091 mode_ = newmode;
00092 }
00093
00094 void CStringStream::reset()
00095 {
00096 clear();
00097 seekp(0);
00098 seekg(0);
00099 }
00100
00101 void CStringStream::readCompressed(std::istream& in,
00102 const unsigned compressionCode,
00103 const unsigned long long len)
00104 {
00105 reset();
00106 if (!len)
00107 return;
00108
00109
00110 if (len > readBuf_.size())
00111 readBuf_.resize(len);
00112 in.read(&readBuf_[0], len);
00113
00114 switch (static_cast<CompressionMode>(compressionCode))
00115 {
00116 case NOT_COMPRESSED:
00117 this->write(&readBuf_[0], len);
00118 return;
00119
00120 case ZLIB:
00121 {
00122 if (!inflator_.get())
00123 inflator_ = CPP11_auto_ptr<ZlibInflateHandle>(
00124 new ZlibInflateHandle());
00125 doZlibCompression(&readBuf_[0], len, false, inflator_->strm(),
00126 &comprBuf_[0], comprBuf_.size(), *this);
00127 }
00128 break;
00129
00130 case BZIP2:
00131 {
00132
00133
00134 bz_stream strm;
00135 BZ2InflateHandle h(strm);
00136 doBZ2Compression(&readBuf_[0], len, false, strm,
00137 &comprBuf_[0], comprBuf_.size(), *this);
00138 }
00139 break;
00140
00141 default:
00142 assert(!"Unhandled switch case in "
00143 "CStringStream::readCompressed. "
00144 "This is a bug. Please report.");
00145 }
00146 }
00147
00148 CStringStream::CompressionMode CStringStream::writeCompressed()
00149 {
00150
00151 assert(sink_);
00152
00153 unsigned long long len = 0;
00154 const char* data = buf_.getPutBuffer(&len);
00155 if (len == 0)
00156 return NOT_COMPRESSED;
00157
00158 if (mode_ == NOT_COMPRESSED || len < minSizeToCompress_)
00159 {
00160 sink_->write(data, len);
00161 return NOT_COMPRESSED;
00162 }
00163
00164 switch (mode_)
00165 {
00166 case ZLIB:
00167 {
00168 if (!deflator_.get())
00169 deflator_ = CPP11_auto_ptr<ZlibDeflateHandle>(
00170 new ZlibDeflateHandle(compressionLevel_));
00171 doZlibCompression(data, len, true, deflator_->strm(),
00172 &comprBuf_[0], comprBuf_.size(), *sink_);
00173 }
00174 break;
00175
00176 case BZIP2:
00177 {
00178
00179
00180 bz_stream strm;
00181 BZ2DeflateHandle h(strm);
00182 doBZ2Compression(data, len, true, strm,
00183 &comprBuf_[0], comprBuf_.size(), *sink_);
00184 }
00185 break;
00186
00187 default:
00188 assert(!"Unhandled switch case in "
00189 "CStringStream::writeCompressed. "
00190 "This is a bug. Please report.");
00191 }
00192
00193 seekp(0);
00194 return mode_;
00195 }
00196
00197 bool CStringStream::getCompressionModeByName(const char* name,
00198 CompressionMode* m)
00199 {
00200 static const char* names[] = {
00201 "n",
00202 "z",
00203 "b"
00204 };
00205 if (!name || !m)
00206 return false;
00207 for (unsigned i=0; i<sizeof(names)/sizeof(names[0]); ++i)
00208 if (strcasecmp(name, names[i]) == 0)
00209 {
00210 *m = static_cast<CompressionMode>(i);
00211 return true;
00212 }
00213 return false;
00214 }
00215
00216 std::string CStringStream::compressionModeName(const CompressionMode m,
00217 const bool useShortName)
00218 {
00219 std::string mode;
00220 switch (m)
00221 {
00222 case NOT_COMPRESSED:
00223 mode = useShortName ? "n" : "not compressed";
00224 break;
00225 case ZLIB:
00226 mode = useShortName ? "z" : "zlib";
00227 break;
00228 case BZIP2:
00229 mode = useShortName ? "b" : "bzip2";
00230 break;
00231 default:
00232 assert(!"Unhandled switch case in "
00233 "CStringStream::compressionModeName. "
00234 "This is a bug. Please report.");
00235 }
00236 return mode;
00237 }
00238 }