Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Расширение istream / ostream библиотеки STL  (Прочитано 6151 раз)
0 Пользователей и 1 Гость смотрят эту тему.
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« : 08-09-2011 06:44 » 

Возникла тут необходимость создать поток совместимый с STL, который будет сжимать / распаковывать данные при помощи библиотеки zlib (интересует именно расширение STL, а zlib - там все просто). Кто чего может посоветовать? Может есть чего почитать по данной теме?
Записан

Любимая игрушка - debugger ...
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 08-09-2011 07:24 » 

Видимо тебе нужно реализовать класс, порожденный от iostream.
http://www.cplusplus.com/reference/iostream/iostream/
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 08-09-2011 07:33 » 

RXL, Верно. И это я понимаю, ищу пример, как правильно это сделать... Какие функции мне нужно перегрузить, как правильно работать с буфером и другие сопутствующие вопросы...
Записан

Любимая игрушка - debugger ...
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


WWW
« Ответ #3 : 08-09-2011 07:38 » 

RuNTiME, по ходу дела само прояснится, что переопределить )
Записан

RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #4 : 09-09-2011 11:24 » 

в общем разобрался и написал Улыбаюсь Выкладываю код, может кому пригодится...

fzstream.h (click to show)
Код: (C++)
// ============================================================================
// fzstream.h
//
//  Created on: 08.09.2011
//      Author: RuNTiME
// ============================================================================

#ifndef FZSTREAM_H_
#define FZSTREAM_H_

#include <iostream>
#include <fstream>
#include <zlib.h>

using namespace std;

// ----------------------------------------------------------------------------
//    fzstreambuf
// ----------------------------------------------------------------------------

class fzstreambuf: public streambuf {
    friend class fzstreambase;
    friend class ifzstream;
    friend class ofzstream;
private:
    enum {
        InputBufSize  = 16384,
        OutputBufSize = 16384
    };

    typedef enum {
        NotOpened,
        Ready,
        StreamEnd,
        Eof,
        Error
    } bufstate;

    fstream _fs;
    streampos _zdleft;
    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, ios::openmode mode, int level);
    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 ios {
protected:
    fzstreambuf _zbuf;

    fzstreambase(): 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 istream {
public:
    ifzstream()
    : istream(&_zbuf)
    { }

    ifzstream(const char *filename)
    : istream(&_zbuf)
    { open(filename); }

    void open(const char *filename) {
        _zbuf.open(filename, in | binary, 0);
    }
};

// ----------------------------------------------------------------------------
//    ofzstream
// ----------------------------------------------------------------------------

class ofzstream: public fzstreambase, public 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;

    ofzstream()
    : ostream(&_zbuf)
    { }

    ofzstream(const char *filename, comprlevel level = DefaultCompression)
    : ostream(&_zbuf)
    { open(filename, level); }

    void open(const char *filename, comprlevel level = DefaultCompression) {
        _zbuf.open(filename, out | binary, level);
    }
};

#endif /* FZSTREAM_H_ */
fzstream.cpp (click to show)
Код: (C++)
// ============================================================================
// fzstream.cpp
//
//  Created on: 08.09.2011
//      Author: RuNTiME
// ============================================================================

#include <fzstream.h>
#include <cstring>

using namespace std;

fzstreambuf::fzstreambuf()
: _state(NotOpened)
{
    bzero(&_zs, 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 : _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) {
    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( deflateInit(&_zs, level) != 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);
        }
        bzero(&_zs, sizeof(::z_stream));

        _fs.close();

        _state = NotOpened;
    }
}
« Последнее редактирование: 09-09-2011 12:08 от RuNTiME » Записан

Любимая игрушка - debugger ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 09-09-2011 11:36 » 

RuNTiME, я бы посоветовал не "загрязнять" пространство имён std стандартной библиотеки своими классами. Заведи собственное пространство имён.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 09-09-2011 11:45 » 

Dimka, Думал над этим. Согласен. Поправил код.
Записан

Любимая игрушка - debugger ...
RuNTiME
Помогающий

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 21-10-2011 17:39 » 

Добавил поддержку выбора стратегии сжатия zlib и исправил ошибки компиляции под Windows.

fzstream.h (click to show)
Код: (C++)
// ============================================================================
// 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)
Код: (C++)
// ============================================================================
// 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;
    }
}
Записан

Любимая игрушка - debugger ...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines