Skip to content

Instantly share code, notes, and snippets.

@melpon
Last active August 29, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melpon/69e6fb45ce791dffe2ef to your computer and use it in GitHub Desktop.
Save melpon/69e6fb45ce791dffe2ef to your computer and use it in GitHub Desktop.
/* ========================================================================= */
int ZEXPORT deflateInit_(strm, level, version, stream_size)
z_streamp strm;
int level;
const char *version;
int stream_size;
{
return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY, version, stream_size);
/* To do: ignore strm->next_in if we use it as window */
}
/* ========================================================================= */
int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
version, stream_size)
z_streamp strm;
int level;
int method;
int windowBits;
int memLevel;
int strategy;
const char *version;
int stream_size;
{
...
}
#include "zlibpp.hpp"
#include <new>
#include <zlib.h>
namespace zlibpp {
const int NO_FLUSH = Z_NO_FLUSH;
const int PARTIAL_FLUSH = Z_PARTIAL_FLUSH;
const int SYNC_FLUSH = Z_SYNC_FLUSH;
const int FULL_FLUSH = Z_FULL_FLUSH;
const int FINISH = Z_FINISH;
const int BLOCK = Z_BLOCK;
const int TREES = Z_TREES;
const int OK = Z_OK;
const int STREAM_END = Z_STREAM_END;
const int NEED_DICT = Z_NEED_DICT;
const int ERRNO = Z_ERRNO;
const int STREAM_ERROR = Z_STREAM_ERROR;
const int DATA_ERROR = Z_DATA_ERROR;
const int MEM_ERROR = Z_MEM_ERROR;
const int BUF_ERROR = Z_BUF_ERROR;
const int VERSION_ERROR = Z_VERSION_ERROR;
const int NO_COMPRESSION = Z_NO_COMPRESSION;
const int BEST_SPEED = Z_BEST_SPEED;
const int BEST_COMPRESSION = Z_BEST_COMPRESSION;
const int DEFAULT_COMPRESSION = Z_DEFAULT_COMPRESSION;
struct stream_impl : stream {
z_stream z;
};
void deflate_end(stream* p) {
stream_impl* si = static_cast<stream_impl*>(p);
deflateEnd(&si->z);
delete si;
}
void inflate_end(stream* p) {
stream_impl* si = static_cast<stream_impl*>(p);
inflateEnd(&si->z);
delete si;
}
void make_stream(stream_ptr& z, void (*f)(stream* p)) {
stream_impl* si = new (std::nothrow) stream_impl();
if (!si) return;
z.reset(stream_ptr(si, f).release());
}
template<class F>
int do_zlib(const stream_ptr& sp, int flush, F f) {
if (!sp) return Z_MEM_ERROR;
stream_impl* si = static_cast<stream_impl*>(sp.get());
si->z.next_in =
const_cast<Bytef*>(static_cast<const Bytef*>(si->next_in));
si->z.avail_in = static_cast<uInt>(si->avail_in);
si->z.total_in = static_cast<uLong>(si->total_in);
si->z.next_out = static_cast<Bytef*>(si->next_out);
si->z.avail_out = static_cast<uInt>(si->avail_out);
si->z.total_out = static_cast<uLong>(si->total_out);
const int result = f(&si->z, flush);
si->next_in = si->z.next_in;
si->avail_in = static_cast<std::size_t>(si->z.avail_in);
si->total_in = static_cast<std::size_t>(si->z.total_in);
si->next_out = si->z.next_out;
si->avail_out = static_cast<std::size_t>(si->z.avail_out);
si->total_out = static_cast<std::size_t>(si->z.total_out);
return result;
}
void deflate_init(stream_ptr& sp, int level) {
make_stream(sp, deflate_end);
if (!sp) return;
stream_impl* si = static_cast<stream_impl*>(sp.get());
deflateInit(&si->z, level);
}
int deflate(const stream_ptr& sp, int flush) {
return do_zlib(sp, flush, ::deflate);
}
void inflate_init(stream_ptr& sp) {
make_stream(sp, inflate_end);
if (!sp) return;
stream_impl* si = static_cast<stream_impl*>(sp.get());
inflateInit(&si->z);
}
int inflate(const stream_ptr& sp, int flush) {
return do_zlib(sp, flush, ::inflate);
}
}
#ifndef ZLIBPP_ZLIBPP_HPP_INCLUDED
#define ZLIBPP_ZLIBPP_HPP_INCLUDED
// zlib のラッパー
#include <cstddef>
namespace zlibpp {
extern const int NO_FLUSH;
extern const int PARTIAL_FLUSH;
extern const int SYNC_FLUSH;
extern const int FULL_FLUSH;
extern const int FINISH;
extern const int BLOCK;
extern const int TREES;
extern const int OK;
extern const int STREAM_END;
extern const int NEED_DICT;
extern const int ERRNO;
extern const int STREAM_ERROR;
extern const int DATA_ERROR;
extern const int MEM_ERROR;
extern const int BUF_ERROR;
extern const int VERSION_ERROR;
extern const int NO_COMPRESSION;
extern const int BEST_SPEED;
extern const int BEST_COMPRESSION;
extern const int DEFAULT_COMPRESSION;
struct stream {
const void* next_in;
std::size_t avail_in;
std::size_t total_in;
void* next_out;
std::size_t avail_out;
std::size_t total_out;
};
class stream_ptr {
stream* p;
typedef void (*deleter)(stream*);
deleter d;
stream_ptr(const stream_ptr&);
stream_ptr& operator=(const stream_ptr&);
public:
struct move_type {
stream* p;
deleter d;
};
stream_ptr() : p(0), d(0) { }
explicit stream_ptr(stream* p, deleter d) : p(p), d(d) { }
stream_ptr(const move_type& m) : p(m.p), d(m.d) { }
~stream_ptr() { reset(); }
void reset() {
if (p) {
d(p);
p = 0;
d = 0;
}
}
void reset(const move_type& m) {
if (p == m.p && d == m.d) return;
reset();
p = m.p;
d = m.d;
}
move_type release() {
move_type m = { p, d };
p = 0;
d = 0;
return m;
}
stream* get() const { return p; }
stream* operator->() const { return p; }
stream& operator*() const { return *p; }
typedef stream* stream_ptr::*unspecified_bool_type;
operator unspecified_bool_type() const {
return p ? &stream_ptr::p : 0;
}
};
extern void deflate_init(stream_ptr& sp, int level);
extern int deflate(const stream_ptr& sp, int flush);
extern void inflate_init(stream_ptr& sp);
extern int inflate(const stream_ptr& sp, int flush);
class deflate_stream {
stream_ptr sp;
public:
deflate_stream(int level) {
deflate_init(sp, level);
}
int deflate(int flush) {
return zlibpp::deflate(sp, flush);
}
stream* get() const { return sp.get(); }
stream* operator->() const { return sp.get(); }
stream& operator*() const { return *sp; }
typedef stream_ptr deflate_stream::*unspecified_bool_type;
operator unspecified_bool_type() const {
return sp ? &deflate_stream::sp : 0;
}
};
class inflate_stream {
stream_ptr sp;
public:
inflate_stream() {
inflate_init(sp);
}
int inflate(int flush) {
return zlibpp::inflate(sp, flush);
}
stream* get() const { return sp.get(); }
stream* operator->() const { return sp.get(); }
stream& operator*() const { return *sp; }
typedef stream_ptr inflate_stream::*unspecified_bool_type;
operator unspecified_bool_type() const {
return sp ? &inflate_stream::sp : 0;
}
};
}
#endif // ZLIBPP_ZLIBPP_HPP_INCLUDED
#include <memory>
#include <exception>
#include <algorithm>
#include <zlibpp/zlibpp.hpp>
std::pair<unsigned char*, int> zlib_compress(const void* in, int in_size, int out_init_size) {
typedef unsigned char byte;
zlibpp::deflate_stream z(zlibpp::BEST_COMPRESSION);
std::auto_ptr<byte> p(new byte[out_init_size]);
z->next_in = static_cast<const byte*>(in);
z->avail_in = in_size;
z->next_out = p.get();
z->avail_out = out_init_size;
while (true) {
const int result = z.deflate(z->avail_in == 0 ? zlibpp::FINISH : zlibpp::NO_FLUSH);
if (result == zlibpp::STREAM_END) break;
if (result != zlibpp::OK)
std::terminate();
if (z->avail_out == 0) {
const int newsize = z->total_out + z->total_out / 2;
std::auto_ptr<byte> p2(new byte[newsize]);
std::copy(p.get(), p.get() + z->total_out, p2.get());
p.reset(p2.release());
z->next_out = p.get() + z->total_out;
z->avail_out = newsize - z->total_out;
}
}
return std::make_pair(p.release(), z->total_out);
}
std::pair<unsigned char*, int> zlib_decompress(const void* in, int in_size, int out_init_size) {
typedef unsigned char byte;
zlibpp::inflate_stream z;
std::auto_ptr<byte> p(new byte[out_init_size]);
z->next_in = static_cast<const byte*>(in);
z->avail_in = in_size;
z->next_out = p.get();
z->avail_out = out_init_size;
while (true) {
const int result = z.inflate(z->avail_in == 0 ? zlibpp::FINISH : zlibpp::NO_FLUSH);
if (result == zlibpp::STREAM_END) break;
if (result != zlibpp::OK)
std::terminate();
if (z->avail_out == 0) {
const int newsize = z->total_out + z->total_out / 2;
std::auto_ptr<byte> p2(new byte[newsize]);
std::copy(p.get(), p.get() + z->total_out, p2.get());
p.reset(p2.release());
z->next_out = p.get() + z->total_out;
z->avail_out = newsize - z->total_out;
}
}
return std::make_pair(p.release(), z->total_out);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment