RuNTiME
|
|
« Ответ #7 : 21-10-2011 17:39 » |
|
Добавил поддержку выбора стратегии сжатия zlib и исправил ошибки компиляции под Windows. fzstream.h (click to show) // ============================================================================ // fzstream.h // // Created on : 08.09.2011 // Last modify: 21.10.2011 // Author : RuNTiME // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files // (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ============================================================================
#ifndef FZSTREAM_H_ #define FZSTREAM_H_
#include <iostream> #include <fstream> #include <zlib.h>
// ---------------------------------------------------------------------------- // fzstreambuf // ----------------------------------------------------------------------------
class fzstreambuf: public std::streambuf { friend class fzstreambase; friend class ifzstream; friend class ofzstream; private: enum { InputBufSize = 16384, OutputBufSize = 16384 };
typedef enum { NotOpened, Ready, StreamEnd, Eof, Error } bufstate;
std::fstream _fs; std::streampos _zdleft; std::ios::openmode _mode; bufstate _state; char _ibuf[InputBufSize]; char _obuf[OutputBufSize]; z_stream _zs;
fzstreambuf();
int flush(int mode = Z_NO_FLUSH); void open(const char *filename, std::ios::openmode mode, int level, int strategy); void close(); protected: virtual ~fzstreambuf() { close(); }
virtual int_type overflow(int_type c = traits_type::eof()); virtual int_type underflow(); virtual int sync(); };
// ---------------------------------------------------------------------------- // fzstreambase // ----------------------------------------------------------------------------
class fzstreambase: virtual public std::ios { protected: fzstreambuf _zbuf;
fzstreambase(): std::ios(&_zbuf) { } public: fzstreambuf *rdbuf() { return &_zbuf; } void close() { _zbuf.close(); } bool fail() const { return _zbuf._state == fzstreambuf::Error; } bool good() const { return !fail(); } bool bad() const { return fail(); } bool eof() const { return _zbuf._state == fzstreambuf::Eof; } bool is_open() const { return _zbuf._state != fzstreambuf::NotOpened; } uLong total_in() const { return _zbuf._zs.total_in; } uLong total_out() const { return _zbuf._zs.total_out;} };
// ---------------------------------------------------------------------------- // ifzstream // ----------------------------------------------------------------------------
class ifzstream: public fzstreambase, public std::istream { public: ifzstream() : std::istream(&_zbuf) { }
ifzstream(const char *filename) : std::istream(&_zbuf) { open(filename); }
ifzstream(const std::string &filename) : std::istream(&_zbuf) { open( filename.c_str() ); }
void open(const char *filename) { _zbuf.open(filename, in | binary, 0, 0); } };
// ---------------------------------------------------------------------------- // ofzstream // ----------------------------------------------------------------------------
class ofzstream: public fzstreambase, public std::ostream { public: typedef enum { DefaultCompression = Z_DEFAULT_COMPRESSION, NoCompression = Z_NO_COMPRESSION, BestSpeed = Z_BEST_SPEED, CompressionLevel2 = 2, CompressionLevel3 = 3, CompressionLevel4 = 4, CompressionLevel5 = 5, CompressionLevel6 = 6, CompressionLevel7 = 7, CompressionLevel8 = 8, BestCompression = Z_BEST_COMPRESSION } comprlevel;
typedef enum { DefaultStrategy = Z_DEFAULT_STRATEGY, Filtered = Z_FILTERED, HuffmanOnly = Z_HUFFMAN_ONLY, Rle = Z_RLE, Fixed = Z_FIXED } comprstrategy;
ofzstream() : std::ostream(&_zbuf) { }
ofzstream(const char *filename, comprlevel level = DefaultCompression, comprstrategy strategy = DefaultStrategy) : std::ostream(&_zbuf) { open(filename, level, strategy); }
ofzstream(const std::string &filename, comprlevel level = DefaultCompression, comprstrategy strategy = DefaultStrategy) : std::ostream(&_zbuf) { open(filename.c_str(), level, strategy); }
void open(const char *filename, comprlevel level = DefaultCompression, comprstrategy strategy = DefaultStrategy) { _zbuf.open(filename, out | binary, level, strategy); } };
#endif /* FZSTREAM_H_ */ fzstream.cpp (click to show) // ============================================================================ // fzstream.cpp // // Created on : 08.09.2011 // Last modify: 21.10.2011 // Author : RuNTiME // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files // (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ============================================================================
#include "fzstream.h" #include <cstring>
using namespace std;
fzstreambuf::fzstreambuf() : _state(NotOpened) { memset(&_zs, 0, sizeof(z_stream)); setp(_ibuf, _ibuf + (InputBufSize-1)); }
int fzstreambuf::flush(int mode) { int len = pptr() - pbase(); pbump(-len);
_zs.avail_in = len; _zs.next_in = (Bytef*)pbase();
if(_zs.avail_out == 0) { _zs.avail_out = OutputBufSize; _zs.next_out = (Bytef*)_obuf; }
while(1) { if( deflate(&_zs, mode) == Z_STREAM_ERROR ) { _state = Error; return -1; }
if(_zs.avail_out == 0) { _fs.write(_obuf, OutputBufSize); if( _fs.fail() ) { _state = Error; return -1; }
_zs.avail_out = OutputBufSize; _zs.next_out = (Bytef*)_obuf;
continue; }
break; }
if(mode == Z_FINISH) { len = OutputBufSize - _zs.avail_out; if(len > 0) { _fs.write(_obuf, len); if( _fs.fail() ) { _state = Error; return -1; } } }
return 0; }
fzstreambuf::int_type fzstreambuf::overflow(int_type c) { if(_state != Ready || _mode & ios::in) { return traits_type::eof(); }
if( c != traits_type::eof() ) { *pptr() = c; pbump(1); }
if( flush() == -1 ) { return traits_type::eof(); }
return c; }
fzstreambuf::int_type fzstreambuf::underflow() { if(_state != Ready || _mode & ios::out) { if(_state == StreamEnd) { _state = Eof; } return traits_type::eof(); }
_zs.avail_out = OutputBufSize; _zs.next_out = (Bytef*)_obuf;
do { if(_zs.avail_in == 0) { _zs.avail_in = (_zdleft >= InputBufSize) ? InputBufSize : (uInt)_zdleft; _zdleft -= _zs.avail_in;
_fs.read(_ibuf, _zs.avail_in); if( _fs.fail() ) { _state = Error; return traits_type::eof(); }
_zs.next_in = (Bytef*)_ibuf; }
int rc = inflate(&_zs, Z_NO_FLUSH);
if(rc == Z_STREAM_END) { if(OutputBufSize - _zs.avail_out > 0) { _state = StreamEnd; break; } else { _state = Eof; return traits_type::eof(); } } if(rc != Z_OK) { _state = Error; return traits_type::eof(); } } while(_zs.avail_out != 0);
setg(_obuf, _obuf, _obuf + (OutputBufSize - _zs.avail_out));
return * reinterpret_cast<fzstreambuf::int_type*>( gptr() ); }
int fzstreambuf::sync() { if(_state != Ready) { return -1; }
if( pptr() > pbase() ) { return flush(); }
return 0; }
void fzstreambuf::open(const char *filename, ios::openmode mode, int level, int strategy) { close(); _mode = mode;
_fs.open(filename, mode); if( _fs.fail() ) { _state = Error; return; }
if(mode & ios::in) { _fs.seekg(0, ios::end); _zdleft = _fs.tellg(); _fs.seekg(0, ios::beg);
if( inflateInit(&_zs) != Z_OK ) { _state = Error; return; } } else { if( deflateInit2(&_zs, level, Z_DEFLATED, MAX_WBITS, MAX_MEM_LEVEL, strategy) != Z_OK ) { _state = Error; return; } }
_state = Ready; }
void fzstreambuf::close() { if(_state != NotOpened) { if(_mode & ios::in) { inflateEnd(&_zs); } else { if(_state != Error) { flush(Z_FINISH); } deflateEnd(&_zs); } memset(&_zs, 0, sizeof(z_stream));
_fs.close();
_state = NotOpened; } }
|