From: Christian P. <cp...@us...> - 2005-01-03 13:44:01
|
Update of /cvsroot/pclasses/pclasses2/src/IO In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv18256/src/IO Added Files: ZLib.cpp Log Message: Added zlib compression support (decompression will follow...) --- NEW FILE: ZLib.cpp --- /*************************************************************************** * Copyright (C) 2004 by Christian Prochnow * * cp...@se... * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "pclasses/IO/ZLib.h" #include <zlib.h> namespace P { namespace IO { ZLibError::ZLibError(int err, const char* msg, const char* what, const SourceInfo& si) : RuntimeError(what, si), _err(err), _msg(msg ? msg : "") { } ZLibError::~ZLibError() { } int ZLibError::errorNo() const throw() { return _err; } const std::string& ZLibError::msg() const throw() { return _msg; } ZLibStream::ZLibStream() { _strm = new z_stream; _buffer = new char[1024]; _bufferSize = 1024; _strm->zalloc = Z_NULL; _strm->zfree = Z_NULL; _strm->opaque = Z_NULL; _strm->next_in = Z_NULL; _strm->next_out = (Bytef*)_buffer; _strm->avail_in = 0; _strm->avail_out = _bufferSize; _crc32 = ::crc32(0L, Z_NULL, 0); } ZLibStream::~ZLibStream() { delete _strm; delete[] _buffer; } size_t ZLibStream::bytesAvail() const throw() { return _bufferSize - _strm->avail_out; } size_t ZLibStream::read(char* buffer, size_t count) throw(ZLibError) { size_t avail = bytesAvail(); if(count > avail) count = avail; memcpy(buffer, _strm->next_out - avail, count); // move remaining bytes to top of buffer ... if(count < avail) memmove(_buffer, _strm->next_out - avail + count, avail - count); _strm->next_out = (Bytef*)_buffer; _strm->avail_out = _bufferSize; return count; } UInt32 ZLibStream::crc32() const throw() { return _crc32; } void ZLibStream::put(const char* buffer, size_t count) throw(ZLibError) { if(_strm->avail_out < count) throw ZLibError(Z_BUF_ERROR, 0, "Could not put data into output buffer", P_SOURCEINFO); memcpy(_strm->next_out, buffer, count); _strm->next_out += count; _strm->avail_out -= count; } ZLibOutputStream::ZLibOutputStream(int level) throw(ZLibError) : ZLibStream(), _state(Ready) { int ret; if((ret = deflateInit(_strm, level)) != Z_OK) throw ZLibError(ret, _strm->msg, "Could not init zlib deflate", P_SOURCEINFO); putFooter(); } ZLibOutputStream::~ZLibOutputStream() throw() { } void ZLibOutputStream::putHeader() { char header[] = { 0x1f /*magic1*/, 0x8b /*magic2*/, Z_DEFLATED, 0 /*flags*/, 0, 0, 0, 0 /*time*/, 0 /*xflags*/, 0x03 /* OS code*/ }; put(header, sizeof(header)); } void ZLibOutputStream::putFooter() { UInt32 footer[2]; footer[0] = UInt32(_crc32).littleEndian(); footer[1] = UInt32(_strm->total_in).littleEndian(); put((const char*)footer, sizeof(footer)); } size_t ZLibOutputStream::deflate(const char* buffer, size_t count) throw(ZLibError) { if(!count) return 0; size_t deflated = 0; if(_state == Ready) { _strm->next_in = (Bytef*)buffer; _strm->avail_in = count; int ret = ::deflate(_strm, Z_NO_FLUSH); if(ret != Z_OK) throw ZLibError(ret, _strm->msg, "Could not deflate", P_SOURCEINFO); // update crc32 and return with number of bytes consumed ... deflated = count - _strm->avail_in; _crc32 = ::crc32(_crc32, (const Bytef*)buffer, deflated); } return deflated; } bool ZLibOutputStream::finish() throw(ZLibError) { if(_state < AboutToFinish) { int ret = ::deflate(_strm, Z_FINISH); // not enough buffer was avail... should call finish() again if(ret == Z_OK) return false; if(ret != Z_STREAM_END) throw ZLibError(Z_BUF_ERROR, 0, "Could not finish zlib stream", P_SOURCEINFO); _state = AboutToFinish; } if(_state == AboutToFinish) { if(_strm->avail_out < 8) return false; putHeader(); _state = Finished; } return true; } void ZLibOutputStream::reset() throw(ZLibError) { _strm->next_out = (Bytef*)_buffer; _strm->avail_out = _bufferSize; _crc32 = ::crc32(0L, Z_NULL, 0); _state = Ready; deflateReset(_strm); } } // !namespace IO } // !namespace P |