CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/Alignment/Geners/src/CStringStream.cc

Go to the documentation of this file.
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           // Have a reasonable minimum buffer size to maintain
00080           // performance even if the user wants to shoot himself
00081           // in a foot
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         // Decompress and dump to this string stream
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             // bzlib2 can not be reset, so we have to make
00133             // a new inflator every time
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         // Compress and dump to sink
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             // bzlib2 can not be reset, so we have to make
00179             // a new deflator every time
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 }