Last active
August 29, 2015 14:09
-
-
Save melpon/69e6fb45ce791dffe2ef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ========================================================================= */ | |
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; | |
{ | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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