File indexing completed on 2024-04-06 11:56:21
0001 #include <cassert>
0002 #include <cstring>
0003 #include <memory>
0004
0005 #include "zlib.h"
0006
0007 #include "Alignment/Geners/interface/BZ2Handle.hh"
0008 #include "Alignment/Geners/interface/CStringStream.hh"
0009 #include "Alignment/Geners/interface/IOException.hh"
0010
0011 static void doZlibCompression(const char *data,
0012 const unsigned long long len,
0013 const bool defl,
0014 z_stream_s &strm,
0015 char *buffer,
0016 const unsigned long long bufLen,
0017 std::ostream &sink) {
0018 assert(buffer);
0019 assert(bufLen);
0020
0021 int status = Z_OK;
0022 strm.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(data));
0023 strm.avail_in = len;
0024 do {
0025 strm.next_out = reinterpret_cast<Bytef *>(buffer);
0026 strm.avail_out = bufLen;
0027 status = defl ? deflate(&strm, Z_FINISH) : inflate(&strm, Z_NO_FLUSH);
0028 assert(status == Z_OK || status == Z_STREAM_END);
0029 const unsigned have = bufLen - strm.avail_out;
0030 sink.write(buffer, have);
0031 if (sink.fail())
0032 throw gs::IOWriteFailure("In gs::doZlibCompression: sink stream failure");
0033 } while (strm.avail_out == 0);
0034
0035 if (defl) {
0036 assert(strm.avail_in == 0);
0037 assert(status == Z_STREAM_END);
0038 assert(deflateReset(&strm) == Z_OK);
0039 } else
0040 assert(inflateReset(&strm) == Z_OK);
0041 }
0042
0043 static void doBZ2Compression(const char *data,
0044 const unsigned long long len,
0045 const bool defl,
0046 bz_stream &strm,
0047 char *buffer,
0048 const unsigned long long bufLen,
0049 std::ostream &sink) {
0050 assert(buffer);
0051 assert(bufLen);
0052
0053 int status = BZ_OK;
0054 strm.next_in = const_cast<char *>(data);
0055 strm.avail_in = len;
0056 do {
0057 strm.next_out = buffer;
0058 strm.avail_out = bufLen;
0059 status = defl ? BZ2_bzCompress(&strm, BZ_FINISH) : BZ2_bzDecompress(&strm);
0060 assert(status == BZ_OK || status == BZ_STREAM_END);
0061 const unsigned have = bufLen - strm.avail_out;
0062 sink.write(buffer, have);
0063 if (sink.fail())
0064 throw gs::IOWriteFailure("In gs::doBZ2Compression: sink stream failure");
0065 } while (status != BZ_STREAM_END);
0066 }
0067
0068 namespace gs {
0069 CStringStream::CStringStream(const CompressionMode m,
0070 const int compressionLevel,
0071 const unsigned minSizeToCompress,
0072 const unsigned bufSize)
0073 : mode_(m),
0074 compressionLevel_(compressionLevel),
0075 minSizeToCompress_(minSizeToCompress),
0076
0077
0078
0079 comprBuf_(bufSize > 1024U ? bufSize : 1024U),
0080 sink_(nullptr) {
0081 this->init(&buf_);
0082 }
0083
0084 void CStringStream::setCompressionMode(const CompressionMode newmode) {
0085 reset();
0086 mode_ = newmode;
0087 }
0088
0089 void CStringStream::reset() {
0090 clear();
0091 seekp(0);
0092 seekg(0);
0093 }
0094
0095 void CStringStream::readCompressed(std::istream &in, const unsigned compressionCode, const unsigned long long len) {
0096 reset();
0097 if (!len)
0098 return;
0099
0100
0101 if (len > readBuf_.size())
0102 readBuf_.resize(len);
0103 in.read(&readBuf_[0], len);
0104
0105 switch (static_cast<CompressionMode>(compressionCode)) {
0106 case NOT_COMPRESSED:
0107 this->write(&readBuf_[0], len);
0108 return;
0109
0110 case ZLIB: {
0111 if (!inflator_.get())
0112 inflator_ = std::make_unique<ZlibInflateHandle>();
0113 doZlibCompression(&readBuf_[0], len, false, inflator_->strm(), &comprBuf_[0], comprBuf_.size(), *this);
0114 } break;
0115
0116 case BZIP2: {
0117
0118
0119 bz_stream strm;
0120 BZ2InflateHandle h(strm);
0121 doBZ2Compression(&readBuf_[0], len, false, strm, &comprBuf_[0], comprBuf_.size(), *this);
0122 } break;
0123
0124 default:
0125 assert(!"Unhandled switch case in "
0126 "CStringStream::readCompressed. "
0127 "This is a bug. Please report.");
0128 }
0129 }
0130
0131 CStringStream::CompressionMode CStringStream::writeCompressed() {
0132
0133 assert(sink_);
0134
0135 unsigned long long len = 0;
0136 const char *data = buf_.getPutBuffer(&len);
0137 if (len == 0)
0138 return NOT_COMPRESSED;
0139
0140 if (mode_ == NOT_COMPRESSED || len < minSizeToCompress_) {
0141 sink_->write(data, len);
0142 return NOT_COMPRESSED;
0143 }
0144
0145 switch (mode_) {
0146 case ZLIB: {
0147 if (!deflator_.get())
0148 deflator_ = std::make_unique<ZlibDeflateHandle>(compressionLevel_);
0149 doZlibCompression(data, len, true, deflator_->strm(), &comprBuf_[0], comprBuf_.size(), *sink_);
0150 } break;
0151
0152 case BZIP2: {
0153
0154
0155 bz_stream strm;
0156 BZ2DeflateHandle h(strm);
0157 doBZ2Compression(data, len, true, strm, &comprBuf_[0], comprBuf_.size(), *sink_);
0158 } break;
0159
0160 default:
0161 assert(!"Unhandled switch case in "
0162 "CStringStream::writeCompressed. "
0163 "This is a bug. Please report.");
0164 }
0165
0166 seekp(0);
0167 return mode_;
0168 }
0169
0170 bool CStringStream::getCompressionModeByName(const char *name, CompressionMode *m) {
0171 static const char *names[] = {"n", "z", "b"};
0172 if (!name || !m)
0173 return false;
0174 for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); ++i)
0175 if (strcasecmp(name, names[i]) == 0) {
0176 *m = static_cast<CompressionMode>(i);
0177 return true;
0178 }
0179 return false;
0180 }
0181
0182 std::string CStringStream::compressionModeName(const CompressionMode m, const bool useShortName) {
0183 std::string mode;
0184 switch (m) {
0185 case NOT_COMPRESSED:
0186 mode = useShortName ? "n" : "not compressed";
0187 break;
0188 case ZLIB:
0189 mode = useShortName ? "z" : "zlib";
0190 break;
0191 case BZIP2:
0192 mode = useShortName ? "b" : "bzip2";
0193 break;
0194 default:
0195 assert(!"Unhandled switch case in "
0196 "CStringStream::compressionModeName. "
0197 "This is a bug. Please report.");
0198 }
0199 return mode;
0200 }
0201 }