| 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;
 }
 }
 |