gzstream.cpp

来自「2009 ROBOCUP 仿真2DSERVER 源码」· C++ 代码 · 共 486 行

CPP
486
字号
// -*-c++-*-/***************************************************************************                                 gzstream.cpp                      Compression and decompression streams                             -------------------    begin                : 14-DEC-2003    copyright            : (C) 2002, 2003 by The RoboCup Soccer Server                           Maintenance Group.    email                : sserver-admin@lists.sourceforge.net***************************************************************************//*************************************************************************** *                                                                         * *   This program is free software; you can redistribute it and/or modify  * *   it under the terms of the GNU LGPL as published by the Free Software  * *   Foundation; either version 2 of the License, or (at your option) any  * *   later version.                                                        * *                                                                         * ***************************************************************************/#include "gzstream.hpp"#ifdef HAVE_CONFIG_H#include "config.h"#endif#ifdef HAVE_LIBZ#include <zlib.h>#endif#ifndef EOF#define EOF (-1)#endifnamespace rcss {namespace gz {class gzstreambuf_impl {public:    gzstreambuf_impl()#ifdef HAVE_LIBZ        : M_compression_stream( NULL ),          M_decompression_stream( NULL )#endif      { }#ifdef HAVE_LIBZ    z_stream * M_compression_stream; // used to perform the compression    z_stream * M_decompression_stream; // used to perform the decompression#endif};gzstreambuf::gzstreambuf( std::streambuf & strm,                          unsigned int bufsize )    : std::streambuf(),      M_strmbuf( strm ),      M_output_stream( NULL ),      M_input_stream( NULL ),      M_buffer_size( bufsize ),      M_read_buffer( NULL ),      M_input_buffer( NULL ),      M_output_buffer( NULL ),      M_write_buffer( NULL ),      M_remained( 0 ),      m_streams( new gzstreambuf_impl ),      M_level(#ifdef HAVE_LIBZ              Z_DEFAULT_COMPRESSION#else              -1#endif              ){}gzstreambuf::~gzstreambuf (){    writeData(#ifdef HAVE_LIBZ              Z_FINISH#endif              );#ifdef HAVE_LIBZ    if ( m_streams->M_compression_stream )    {        deflateEnd( m_streams->M_compression_stream );    }    if ( m_streams->M_decompression_stream )    {        deflateEnd( m_streams->M_decompression_stream );    }#endif    delete M_output_stream;    delete M_input_stream;    delete[] M_read_buffer;    delete[] M_input_buffer;    delete[] M_output_buffer;    delete[] M_write_buffer;#ifdef HAVE_LIBZ    delete m_streams->M_compression_stream;    delete m_streams->M_decompression_stream;#endif}boolgzstreambuf::setLevel( int level ){#ifdef HAVE_LIBZ    if ( level <= Z_BEST_COMPRESSION )    {        sync(); // make sure there is room for the deflate to flush        if ( level >= 0 )        {            if( m_streams->M_compression_stream )                deflateParams( m_streams->M_compression_stream, level, Z_DEFAULT_STRATEGY );            sync(); // write any data that was flushed by deflateParams        }        M_level = level;        return true;    }    else        return false;#else    if ( M_level >= 0 )    {        return false;    }    else    {        return true;    }#endif}boolgzstreambuf::writeData( int sync ){    int size = ( pptr() - M_output_buffer ) * sizeof( char_type );    if ( size == 0 )    {        return true;    }    if ( M_output_stream == NULL )    {        M_output_stream = new std::ostream( &M_strmbuf );    }#ifdef HAVE_LIBZ    if( M_level < 0 )    {#endif        M_output_stream->write( M_output_buffer, size );#ifdef HAVE_LIBZ    }    else    {        if ( m_streams->M_compression_stream == NULL )        {            m_streams->M_compression_stream = new z_stream;            m_streams->M_compression_stream->zalloc = Z_NULL;            m_streams->M_compression_stream->zfree = Z_NULL;            m_streams->M_compression_stream->opaque = NULL;            m_streams->M_compression_stream->avail_in = 0;            m_streams->M_compression_stream->next_in = 0;            m_streams->M_compression_stream->next_out = 0;            m_streams->M_compression_stream->avail_out = 0;            if( deflateInit( m_streams->M_compression_stream, M_level ) != Z_OK )            {                //                     cerr << "error in init\n";                return false;            }            if( M_write_buffer == NULL )                M_write_buffer = new char[ M_buffer_size ];            m_streams->M_compression_stream->next_out = (Bytef*)M_write_buffer;            m_streams->M_compression_stream->avail_out = M_buffer_size;        }        m_streams->M_compression_stream->next_in = (Bytef*)M_output_buffer;        m_streams->M_compression_stream->avail_in = size;        do        {            int bytes_out = -m_streams->M_compression_stream->total_out;            int err = deflate( m_streams->M_compression_stream, sync );            if( err != Z_OK && err != Z_STREAM_END )            {                //                      cerr << "error deflating\n";                //                      cerr << M_compression_stream->msg << endl;                deflateReset( m_streams->M_compression_stream );                return false;            }            bytes_out += m_streams->M_compression_stream->total_out;            M_output_stream->write( M_write_buffer, bytes_out );            m_streams->M_compression_stream->next_out = (Bytef*)M_write_buffer;            m_streams->M_compression_stream->avail_out = M_buffer_size;        }        while( m_streams->M_compression_stream->avail_in != 0 );        // we want to keep writing until all the data has been        // consumed by the compression stream        deflateReset( m_streams->M_compression_stream );    }#endif    if( sync !=#ifdef HAVE_LIBZ        Z_NO_FLUSH#else        0#endif        )        M_output_stream->flush(); // flush the underlying stream if a flush has    // been used    return true;}intgzstreambuf::readData( char * dest,                       int & dest_size ){    if ( M_input_stream == NULL )    {        M_input_stream = new std::istream( &M_strmbuf );    }    int rval = 0;    if ( ! M_input_stream->good() )    {        M_input_stream->setstate( std::istream::failbit );        return rval;    }    int bytes_to_read = M_strmbuf.in_avail();    if ( bytes_to_read < 0 )    {        M_input_stream->setstate( std::istream::eofbit );    }    else if ( bytes_to_read == 0 )    {        rval = M_input_stream->read( dest, 1 ).gcount();        bytes_to_read = M_strmbuf.in_avail();        if ( bytes_to_read > dest_size - 1 )        {            bytes_to_read = dest_size - 1;        }        rval += M_input_stream->read( dest + 1, bytes_to_read ).gcount();        dest_size = bytes_to_read + 1;    }    else    {        if ( bytes_to_read > dest_size )        {            bytes_to_read = dest_size;        }        rval = M_input_stream->read( dest, bytes_to_read ).gcount();        dest_size = bytes_to_read;    }    return rval;}gzstreambuf::int_typegzstreambuf::overflow( int_type c ){    // this method is supposed to flush the put area of the buffer    // to the I/O device    // if the buffer was not already allocated nor set by user,    // do it just now    if ( pptr() == NULL )    {        M_output_buffer = new char_type[ M_buffer_size ];    }    else    {        if ( ! writeData() )        {            return EOF;        }    }    setp( M_output_buffer, M_output_buffer + M_buffer_size );    if ( c != EOF )    {        sputc( c );    }    return 0;}intgzstreambuf::sync(){    if ( pptr() != NULL )    {        // just flush the put area        if ( ! writeData(#ifdef HAVE_LIBZ                         Z_SYNC_FLUSH#else                         1#endif                         ) )            return -1;        setp( M_output_buffer, M_output_buffer + M_buffer_size );    }    return 0;}gzstreambuf::int_typegzstreambuf::underflow(){    // this method is supposed to read some bytes from the I/O device    // if the buffer was not already allocated nor set by user,    // do it just now    if ( gptr() == NULL )    {        M_input_buffer = new char_type[ M_buffer_size ];    }    int readn = 0;#ifdef HAVE_LIBZ    if ( M_level < 0 )    {#endif        if ( M_remained != 0 )        {            M_input_buffer[ 0 ] = M_remaining_char;        }        readn = M_buffer_size * sizeof(char_type) - M_remained;        readData( M_input_buffer + M_remained, readn );        int totalbytes = readn + M_remained;        setg( M_input_buffer, M_input_buffer,              M_input_buffer + totalbytes / sizeof( char_type ) );        M_remained = totalbytes % sizeof( char_type );        if ( M_remained != 0 )        {            M_remaining_char = M_input_buffer[ totalbytes / sizeof(char_type) ];        }#ifdef HAVE_LIBZ    }    else    {        if ( M_read_buffer == NULL )        {            M_read_buffer = new char_type[ M_buffer_size ];        }        if ( M_remained != 0 )        {            M_input_buffer[ 0 ] = M_remaining_char;        }        if ( m_streams->M_decompression_stream == NULL )        {            m_streams->M_decompression_stream = new z_stream;            m_streams->M_decompression_stream->zalloc = Z_NULL;            m_streams->M_decompression_stream->zfree = Z_NULL;            m_streams->M_decompression_stream->opaque = NULL;            m_streams->M_decompression_stream->avail_in = 0;            m_streams->M_decompression_stream->next_in = 0;            m_streams->M_decompression_stream->avail_out = 0;            m_streams->M_decompression_stream->next_out = 0;            if( inflateInit( m_streams->M_decompression_stream ) != Z_OK )                return false;        }        m_streams->M_decompression_stream->next_out = (Bytef*)( M_input_buffer                                                                + M_remained );        m_streams->M_decompression_stream->avail_out = ( M_buffer_size                                                         * sizeof(char_type)                                                         - M_remained );        do        {            if ( m_streams->M_decompression_stream->avail_in == 0 )            {                int bytes_read = M_buffer_size;                readData( M_read_buffer, bytes_read );                m_streams->M_decompression_stream->next_in = (Bytef*)M_read_buffer;                m_streams->M_decompression_stream->avail_in = bytes_read;            }            readn -= m_streams->M_decompression_stream->total_out;            if( inflate( m_streams->M_decompression_stream, Z_NO_FLUSH ) != Z_OK )            {                //cerr << M_decompression_stream->msg << endl;                inflateReset( m_streams->M_decompression_stream );                return EOF;            }            readn += m_streams->M_decompression_stream->total_out;        }        while( readn == 0 );        int totalbytes = readn + M_remained;        setg( M_input_buffer, M_input_buffer,              M_input_buffer + totalbytes / sizeof( char_type ) );        M_remained = totalbytes % sizeof( char_type );        if ( M_remained != 0 )        {            M_remaining_char = M_input_buffer[ ( totalbytes                                                 / sizeof( char_type ) ) ];        }        inflateReset( m_streams->M_decompression_stream );    }#endif    // if (readn == 0 && remained_ != 0)    // error - there is not enough bytes for completing    // the last character before the end of the stream    // - this can mean error on the remote end    if ( readn == 0 )    {        return EOF;    }    return sgetc();}// Gzstream Classgzstream::gzstream( std::streambuf & strm,                    unsigned int buffer_size )    : std::iostream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( strm, buffer_size ){    this->init( &M_gzstreambuf );}gzstream::gzstream( std::iostream & strm,                    unsigned int buffer_size )    : std::iostream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( *(strm.rdbuf()), buffer_size ){    this->init( &M_gzstreambuf );}// Gzistream Classgzistream::gzistream( std::streambuf & src,                      unsigned int buffer_size )    : std::istream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( src, buffer_size ){    this->init( &M_gzstreambuf );}gzistream::gzistream( std::istream & src,                      unsigned int buffer_size )    : std::istream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( *(src.rdbuf()), buffer_size ){    this->init( &M_gzstreambuf );}// Gzostream Classgzostream::gzostream( std::streambuf & dest,                      unsigned int buffer_size )    : std::ostream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( dest, buffer_size ){    this->init( &M_gzstreambuf );}gzostream::gzostream( std::ostream & dest,                      unsigned int buffer_size )    : std::ostream( static_cast< std::streambuf * >( 0 ) )    , M_gzstreambuf( *(dest.rdbuf()), buffer_size ){    this->init( &M_gzstreambuf );}} // namespace gz} // namespace rcss

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?