Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 12:44:55

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