zoukankan      html  css  js  c++  java
  • zlib 简单封装

    下列代码用于压缩和解压字符串,使用标准库string。实现了对zlib的简单封装。

    
    #pragma once
    
    #include <boost/noncopyable.hpp>
    #include <zlib.h>
    #include <string>
    #include <cassert>
    #include <strings.h> // for bzero
    
    class ZlibDecompressor : boost::noncopyable {
     public:
      ZlibDecompressor(const std::string &input)
          : zerror_(Z_OK),
            z_init_error_(Z_OK),
            input_(input),
            output_()
      {
        ::bzero(&zstream_, sizeof(zstream_));
        z_init_error_ = inflateInit(&zstream_);
        if (z_init_error_ == Z_OK)
          zerror_ = decompress();
      }
    
      const char *zlibErrorMessage() const { return zstream_.msg; }
    
      int zlibErrorCode() const { return zerror_; }
    
      ~ZlibDecompressor()
      {
        if (z_init_error_ == Z_OK)
          inflateEnd(&zstream_);
      }
    
      std::string output() const
      {
        if(valid())
          return output_;
        return output_;
      }
      
      bool valid() const { return zerror_ == Z_OK; }
    
     private:
    
      const static int CHUNK = 8192;
    
      int decompress() {
        int ret;
        size_t begin = 0;
        size_t size = input_.size();
        unsigned char out[CHUNK];
        do {
          int chunk = ((size - begin) < CHUNK ? size - begin : CHUNK);
          if (chunk == 0)
            break;
          zstream_.avail_in = static_cast<uint>(chunk);
          zstream_.next_in = (Bytef *) &input_[begin];
          do
          {
            zstream_.avail_out = CHUNK;
            zstream_.next_out = (Bytef*)out;
            ret = inflate(&zstream_, Z_NO_FLUSH);
            assert(ret != Z_STREAM_ERROR);
            switch (ret)
            {
              case Z_NEED_DICT:
                ret = Z_DATA_ERROR;
              case Z_DATA_ERROR:
              case Z_MEM_ERROR:
                return ret;
            }
            int have = CHUNK - static_cast<int>(zstream_.avail_out);
            output_.append(out, out + have);
          } while (zstream_.avail_out == 0);
          begin += chunk;
        } while (ret != Z_STREAM_END);
        return ret;
      }
    
      z_stream zstream_;
      int zerror_;
      int z_init_error_;
      std::string input_;
      std::string output_;
    };
    
    class ZlibCompressor : boost::noncopyable {
     public:
      explicit ZlibCompressor(const std::string &input)
          : zerror_(Z_OK),
            z_init_error_(Z_OK),
            input_(input),
            output_()
      {
        ::bzero(&zstream_, sizeof(zstream_));
        z_init_error_ = deflateInit(&zstream_, -1);
        if(z_init_error_ == Z_OK)
          zerror_ = compress();
      }
    
      explicit ZlibCompressor(const std::string& input, int level)
      : zerror_(Z_OK),
        z_init_error_(Z_OK),
        input_(input),
        output_()
      {
        assert(level >= -1 && level <= 9);
        ::bzero(&zstream_, sizeof(zstream_));
        z_init_error_ = deflateInit(&zstream_, level);
        if(z_init_error_ == Z_OK)
          zerror_ = compress();
      }
    
      ~ZlibCompressor() {
        if(z_init_error_ == Z_OK)
          deflateEnd(&zstream_);
      }
    
      const char *zlibErrorMessage() const { return zstream_.msg; }
    
      int zlibErrorCode() const { return zerror_; }
    
      std::string output() const
      {
        if(valid())
          return output_;
        return "";
      }
        
      bool valid() const { return zerror_ == Z_OK; }
    
     private:
    
      const static int CHUNK = 8192;
    
      int compress() {
        unsigned char out[CHUNK];
        size_t size = input_.size();
        size_t begin = 0;
        int ret;
        int flush;
        do
        {
          int chunk;
          if(size - begin <= CHUNK)
          {
            chunk = size - begin;
            flush = Z_FINISH;
          }
          else
          {
            chunk = CHUNK;
            flush = Z_NO_FLUSH;
          }
          zstream_.avail_in = chunk;
          zstream_.next_in = (Bytef *)&input_[begin];
          do
          {
            zstream_.avail_out = CHUNK;
            zstream_.next_out = out;
            ret = deflate(&zstream_, flush);
            assert(ret != Z_STREAM_ERROR);
            int have = CHUNK - static_cast<int>(zstream_.avail_out);
            output_.append(out, out + have);
          }while(zstream_.avail_out == 0);
          assert(zstream_.avail_in == 0);
          begin += chunk;
        }while(flush != Z_FINISH);
        assert(ret == Z_STREAM_END);
        return Z_OK;
      }
    
      z_stream zstream_;
      int zerror_;
      int z_init_error_;
      std::string input_;
      std::string output_;
    };
    
  • 相关阅读:
    React PC端悬浮锚点吸顶导航
    LESS 移动端一像素1px线条CSS解决方案
    React Swiper轮播图
    Win10 虚拟机安装mac系统
    ReactNative Windows环境初始化项目
    Win10 安装AndroidStudio
    Win10 环境安装JDK
    【mysql基础学习篇】mysql服务器架构简介
    uniapp封装小程序雷达图组件实现
    这12道Spring面试题要是还不会的话?就白干了!
  • 原文地址:https://www.cnblogs.com/zhoudayang/p/6617252.html
Copyright © 2011-2022 走看看