Back to home page

Project CMSSW displayed by LXR

 
 

    


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         // Have a reasonable minimum buffer size to maintain
0077         // performance even if the user wants to shoot himself
0078         // in a foot
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     // Decompress and dump to this string stream
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         // bzlib2 can not be reset, so we have to make
0118         // a new inflator every time
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     // Compress and dump to sink
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         // bzlib2 can not be reset, so we have to make
0154         // a new deflator every time
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 }  // namespace gs