aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/compression
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/compression')
-rw-r--r--src/lib/compression/bzip2/bzip2.cpp112
-rw-r--r--src/lib/compression/bzip2/bzip2.h50
-rw-r--r--src/lib/compression/bzip2/info.txt7
-rw-r--r--src/lib/compression/comp_util.cpp34
-rw-r--r--src/lib/compression/comp_util.h90
-rw-r--r--src/lib/compression/compression.cpp152
-rw-r--r--src/lib/compression/compression.h99
-rw-r--r--src/lib/compression/info.txt9
-rw-r--r--src/lib/compression/lzma/info.txt7
-rw-r--r--src/lib/compression/lzma/lzma.cpp94
-rw-r--r--src/lib/compression/lzma/lzma.h51
-rw-r--r--src/lib/compression/zlib/info.txt7
-rw-r--r--src/lib/compression/zlib/zlib.cpp106
-rw-r--r--src/lib/compression/zlib/zlib.h61
14 files changed, 879 insertions, 0 deletions
diff --git a/src/lib/compression/bzip2/bzip2.cpp b/src/lib/compression/bzip2/bzip2.cpp
new file mode 100644
index 000000000..440c21477
--- /dev/null
+++ b/src/lib/compression/bzip2/bzip2.cpp
@@ -0,0 +1,112 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007,2014 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/bzip2.h>
+#include <botan/internal/comp_util.h>
+
+#define BZ_NO_STDIO
+#include <bzlib.h>
+
+namespace Botan {
+
+namespace {
+
+class Bzip_Stream : public Zlib_Style_Stream<bz_stream, char>
+ {
+ public:
+ Bzip_Stream()
+ {
+ streamp()->opaque = alloc();
+ streamp()->bzalloc = Compression_Alloc_Info::malloc<int>;
+ streamp()->bzfree = Compression_Alloc_Info::free;
+ }
+
+ u32bit run_flag() const override { return BZ_RUN; }
+ u32bit flush_flag() const override { return BZ_FLUSH; }
+ u32bit finish_flag() const override { return BZ_FINISH; }
+ };
+
+class Bzip_Compression_Stream : public Bzip_Stream
+ {
+ public:
+ Bzip_Compression_Stream(size_t level)
+ {
+ int rc = BZ2_bzCompressInit(streamp(), level, 0, 0);
+
+ if(rc == BZ_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != BZ_OK)
+ throw std::runtime_error("bzip compress initialization failed");
+ }
+
+ ~Bzip_Compression_Stream()
+ {
+ BZ2_bzCompressEnd(streamp());
+ }
+
+ bool run(u32bit flags) override
+ {
+ int rc = BZ2_bzCompress(streamp(), flags);
+
+ if(rc == BZ_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc < 0)
+ throw std::runtime_error("bzip compress error");
+
+ return (rc == BZ_STREAM_END);
+ }
+
+ private:
+ size_t m_level;
+ };
+
+class Bzip_Decompression_Stream : public Bzip_Stream
+ {
+ public:
+ Bzip_Decompression_Stream()
+ {
+ int rc = BZ2_bzDecompressInit(streamp(), 0, 0);
+
+ if(rc == BZ_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != BZ_OK)
+ throw std::runtime_error("bzip decompress initialization failed");
+ }
+
+ ~Bzip_Decompression_Stream()
+ {
+ BZ2_bzDecompressEnd(streamp());
+ }
+
+ bool run(u32bit flags) override
+ {
+ int rc = BZ2_bzDecompress(streamp());
+
+ if(rc == BZ_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != BZ_OK && rc != BZ_STREAM_END)
+ throw std::runtime_error("bzip decompress error");
+
+ return (rc == BZ_STREAM_END);
+ }
+ };
+
+}
+
+Compression_Stream* Bzip_Compression::make_stream() const
+ {
+ return new Bzip_Compression_Stream(m_level);
+ }
+
+Compression_Stream* Bzip_Decompression::make_stream() const
+ {
+ return new Bzip_Decompression_Stream;
+ }
+
+}
diff --git a/src/lib/compression/bzip2/bzip2.h b/src/lib/compression/bzip2/bzip2.h
new file mode 100644
index 000000000..945f6a051
--- /dev/null
+++ b/src/lib/compression/bzip2/bzip2.h
@@ -0,0 +1,50 @@
+/*
+* Bzip Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_BZIP2_H__
+#define BOTAN_BZIP2_H__
+
+#include <botan/compression.h>
+
+namespace Botan {
+
+/**
+* Bzip Compression
+*/
+class BOTAN_DLL Bzip_Compression : public Stream_Compression
+ {
+ public:
+ /**
+ * @param level how much effort to use on compressing (0 to 9);
+ * higher levels are slower but tend to give better
+ * compression
+ */
+ Bzip_Compression(size_t level = 6) : m_level(level) {}
+
+ std::string name() const override { return "Bzip_Compression"; }
+
+ private:
+ Compression_Stream* make_stream() const;
+
+ const size_t m_level;
+ };
+
+/**
+* Bzip Deccompression
+*/
+class BOTAN_DLL Bzip_Decompression : public Stream_Decompression
+ {
+ public:
+ std::string name() const override { return "Bzip_Decompression"; }
+ private:
+ Compression_Stream* make_stream() const;
+ };
+
+}
+
+#endif
diff --git a/src/lib/compression/bzip2/info.txt b/src/lib/compression/bzip2/info.txt
new file mode 100644
index 000000000..a0f8d82ee
--- /dev/null
+++ b/src/lib/compression/bzip2/info.txt
@@ -0,0 +1,7 @@
+define BZIP2_TRANSFORM 20141118
+
+load_on request
+
+<libs>
+all -> bz2
+</libs>
diff --git a/src/lib/compression/comp_util.cpp b/src/lib/compression/comp_util.cpp
new file mode 100644
index 000000000..7fca1852d
--- /dev/null
+++ b/src/lib/compression/comp_util.cpp
@@ -0,0 +1,34 @@
+/*
+* Allocation Tracker
+* (C) 2014 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/internal/comp_util.h>
+#include <cstring>
+#include <cstdlib>
+
+namespace Botan {
+
+void* Compression_Alloc_Info::do_malloc(size_t n, size_t size)
+ {
+ const size_t total_sz = n * size;
+
+ void* ptr = std::malloc(total_sz);
+ m_current_allocs[ptr] = total_sz;
+ return ptr;
+ }
+
+void Compression_Alloc_Info::do_free(void* ptr)
+ {
+ auto i = m_current_allocs.find(ptr);
+ if(i == m_current_allocs.end())
+ throw std::runtime_error("Compression_Alloc_Info::free got pointer not allocated by us");
+
+ std::memset(ptr, 0, i->second);
+ std::free(ptr);
+ m_current_allocs.erase(i);
+ }
+
+}
diff --git a/src/lib/compression/comp_util.h b/src/lib/compression/comp_util.h
new file mode 100644
index 000000000..15fc23418
--- /dev/null
+++ b/src/lib/compression/comp_util.h
@@ -0,0 +1,90 @@
+/*
+* Shared code for compression libraries
+* (C) 2014 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_COMPRESSION_UTILS_H__
+#define BOTAN_COMPRESSION_UTILS_H__
+
+#include <botan/compression.h>
+#include <cstring>
+#include <memory>
+#include <unordered_map>
+
+namespace Botan {
+
+/*
+* Allocation Size Tracking Helper for Zlib/Bzlib/LZMA
+*/
+class Compression_Alloc_Info
+ {
+ public:
+ template<typename T>
+ static void* malloc(void* self, T n, T size)
+ {
+ return static_cast<Compression_Alloc_Info*>(self)->do_malloc(n, size);
+ }
+
+ static void free(void* self, void* ptr)
+ {
+ static_cast<Compression_Alloc_Info*>(self)->do_free(ptr);
+ }
+
+ private:
+ void* do_malloc(size_t n, size_t size);
+ void do_free(void* ptr);
+
+ std::unordered_map<void*, size_t> m_current_allocs;
+ };
+
+/**
+* Wrapper for Zlib/Bzlib/LZMA stream types
+*/
+template<typename Stream, typename ByteType>
+class Zlib_Style_Stream : public Compression_Stream
+ {
+ public:
+ void next_in(byte* b, size_t len) override
+ {
+ m_stream.next_in = reinterpret_cast<ByteType*>(b);
+ m_stream.avail_in = len;
+ }
+
+ void next_out(byte* b, size_t len) override
+ {
+ m_stream.next_out = reinterpret_cast<ByteType*>(b);
+ m_stream.avail_out = len;
+ }
+
+ size_t avail_in() const override { return m_stream.avail_in; }
+
+ size_t avail_out() const override { return m_stream.avail_out; }
+
+ Zlib_Style_Stream()
+ {
+ std::memset(&m_stream, 0, sizeof(stream_t));
+ m_allocs.reset(new Compression_Alloc_Info);
+ }
+
+ ~Zlib_Style_Stream()
+ {
+ std::memset(&m_stream, 0, sizeof(stream_t));
+ m_allocs.reset();
+ }
+
+ protected:
+ typedef Stream stream_t;
+
+ stream_t* streamp() { return &m_stream; }
+
+ Compression_Alloc_Info* alloc() { return m_allocs.get(); }
+ private:
+ stream_t m_stream;
+ std::unique_ptr<Compression_Alloc_Info> m_allocs;
+ };
+
+}
+
+#endif
diff --git a/src/lib/compression/compression.cpp b/src/lib/compression/compression.cpp
new file mode 100644
index 000000000..3eb26e81b
--- /dev/null
+++ b/src/lib/compression/compression.cpp
@@ -0,0 +1,152 @@
+/*
+* Compression Transform
+* (C) 2014 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/compression.h>
+
+namespace Botan {
+
+void Stream_Compression::clear()
+ {
+ m_stream.reset();
+ }
+
+secure_vector<byte> Stream_Compression::start_raw(const byte[], size_t nonce_len)
+ {
+ if(!valid_nonce_length(nonce_len))
+ throw Invalid_IV_Length(name(), nonce_len);
+
+ clear();
+ m_stream.reset(make_stream());
+ return secure_vector<byte>();
+ }
+
+void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit flags)
+ {
+ BOTAN_ASSERT(m_stream, "Initialized");
+ BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
+
+ if(m_buffer.size() < buf.size() + offset)
+ m_buffer.resize(buf.size() + offset);
+
+ m_stream->next_in(&buf[offset], buf.size() - offset);
+ m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset);
+
+ while(true)
+ {
+ const bool end = m_stream->run(flags);
+
+ if(m_stream->avail_out() == 0)
+ {
+ const size_t added = 8 + m_buffer.size();
+ m_buffer.resize(m_buffer.size() + added);
+ m_stream->next_out(&m_buffer[m_buffer.size() - added], added);
+ }
+ else if(m_stream->avail_in() == 0)
+ {
+ m_buffer.resize(m_buffer.size() - m_stream->avail_out());
+ break;
+ }
+ }
+
+ copy_mem(&m_buffer[0], &buf[0], offset);
+ buf.swap(m_buffer);
+ }
+
+void Stream_Compression::update(secure_vector<byte>& buf, size_t offset)
+ {
+ process(buf, offset, m_stream->run_flag());
+ }
+
+void Stream_Compression::flush(secure_vector<byte>& buf, size_t offset)
+ {
+ process(buf, offset, m_stream->flush_flag());
+ }
+
+void Stream_Compression::finish(secure_vector<byte>& buf, size_t offset)
+ {
+ process(buf, offset, m_stream->finish_flag());
+ clear();
+ }
+
+void Stream_Decompression::clear()
+ {
+ m_stream.reset();
+ }
+
+secure_vector<byte> Stream_Decompression::start_raw(const byte[], size_t nonce_len)
+ {
+ if(!valid_nonce_length(nonce_len))
+ throw Invalid_IV_Length(name(), nonce_len);
+
+ clear();
+ m_stream.reset(make_stream());
+
+ return secure_vector<byte>();
+ }
+
+void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32bit flags)
+ {
+ BOTAN_ASSERT(m_stream, "Initialized");
+ BOTAN_ASSERT(buf.size() >= offset, "Offset is sane");
+
+ if(m_buffer.size() < buf.size() + offset)
+ m_buffer.resize(buf.size() + offset);
+
+ m_stream->next_in(&buf[offset], buf.size() - offset);
+ m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset);
+
+ while(true)
+ {
+ const bool stream_end = m_stream->run(flags);
+
+ if(stream_end)
+ {
+ if(m_stream->avail_in() == 0) // all data consumed?
+ {
+ m_buffer.resize(m_buffer.size() - m_stream->avail_out());
+ clear();
+ break;
+ }
+
+ // More data follows: try to process as a following stream
+ const size_t read = (buf.size() - offset) - m_stream->avail_in();
+ start();
+ m_stream->next_in(&buf[offset + read], buf.size() - offset - read);
+ }
+
+ if(m_stream->avail_out() == 0)
+ {
+ const size_t added = 8 + m_buffer.size();
+ m_buffer.resize(m_buffer.size() + added);
+ m_stream->next_out(&m_buffer[m_buffer.size() - added], added);
+ }
+ else if(m_stream->avail_in() == 0)
+ {
+ m_buffer.resize(m_buffer.size() - m_stream->avail_out());
+ break;
+ }
+ }
+
+ copy_mem(&m_buffer[0], &buf[0], offset);
+ buf.swap(m_buffer);
+ }
+
+void Stream_Decompression::update(secure_vector<byte>& buf, size_t offset)
+ {
+ process(buf, offset, m_stream->run_flag());
+ }
+
+void Stream_Decompression::finish(secure_vector<byte>& buf, size_t offset)
+ {
+ if(buf.size() != offset || m_stream.get())
+ process(buf, offset, m_stream->finish_flag());
+
+ if(m_stream.get())
+ throw std::runtime_error(name() + " finished but not at stream end");
+ }
+
+}
diff --git a/src/lib/compression/compression.h b/src/lib/compression/compression.h
new file mode 100644
index 000000000..10c7f1a64
--- /dev/null
+++ b/src/lib/compression/compression.h
@@ -0,0 +1,99 @@
+/*
+* Compression Transform
+* (C) 2014 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_COMPRESSION_TRANSFORM_H__
+#define BOTAN_COMPRESSION_TRANSFORM_H__
+
+#include <botan/transform.h>
+
+namespace Botan {
+
+class BOTAN_DLL Compressor_Transformation : public Transformation
+ {
+ public:
+ size_t update_granularity() const override { return 1; }
+
+ size_t minimum_final_size() const override { return 0; }
+
+ size_t default_nonce_length() const override { return 0; }
+
+ bool valid_nonce_length(size_t nonce_len) const override
+ { return nonce_len == 0; }
+
+ virtual void flush(secure_vector<byte>& buf, size_t offset = 0) { update(buf, offset); }
+
+ size_t output_length(size_t) const override
+ {
+ throw std::runtime_error(name() + " output length indeterminate");
+ }
+ };
+
+class Compression_Stream
+ {
+ public:
+ virtual ~Compression_Stream() {}
+
+ virtual void next_in(byte* b, size_t len) = 0;
+
+ virtual void next_out(byte* b, size_t len) = 0;
+
+ virtual size_t avail_in() const = 0;
+
+ virtual size_t avail_out() const = 0;
+
+ virtual u32bit run_flag() const = 0;
+ virtual u32bit flush_flag() const = 0;
+ virtual u32bit finish_flag() const = 0;
+
+ virtual bool run(u32bit flags) = 0;
+ };
+
+class BOTAN_DLL Stream_Compression : public Compressor_Transformation
+ {
+ public:
+ void update(secure_vector<byte>& buf, size_t offset = 0) override;
+
+ void flush(secure_vector<byte>& buf, size_t offset = 0) override;
+
+ void finish(secure_vector<byte>& buf, size_t offset = 0) override;
+
+ void clear() override;
+
+ private:
+ secure_vector<byte> start_raw(const byte[], size_t) override;
+
+ void process(secure_vector<byte>& buf, size_t offset, u32bit flags);
+
+ virtual Compression_Stream* make_stream() const = 0;
+
+ secure_vector<byte> m_buffer;
+ std::unique_ptr<Compression_Stream> m_stream;
+ };
+
+class BOTAN_DLL Stream_Decompression : public Compressor_Transformation
+ {
+ public:
+ void update(secure_vector<byte>& buf, size_t offset = 0) override;
+
+ void finish(secure_vector<byte>& buf, size_t offset = 0) override;
+
+ void clear() override;
+
+ private:
+ secure_vector<byte> start_raw(const byte[], size_t) override;
+
+ void process(secure_vector<byte>& buf, size_t offset, u32bit flags);
+
+ virtual Compression_Stream* make_stream() const = 0;
+
+ secure_vector<byte> m_buffer;
+ std::unique_ptr<Compression_Stream> m_stream;
+ };
+
+}
+
+#endif
diff --git a/src/lib/compression/info.txt b/src/lib/compression/info.txt
new file mode 100644
index 000000000..f1a3fa696
--- /dev/null
+++ b/src/lib/compression/info.txt
@@ -0,0 +1,9 @@
+define COMPRESSION 20141117
+
+<header:internal>
+comp_util.h
+</header:internal>
+
+<header:public>
+compression.h
+</header:public>
diff --git a/src/lib/compression/lzma/info.txt b/src/lib/compression/lzma/info.txt
new file mode 100644
index 000000000..1ec668ca8
--- /dev/null
+++ b/src/lib/compression/lzma/info.txt
@@ -0,0 +1,7 @@
+define LZMA_TRANSFORM 20141118
+
+load_on request
+
+<libs>
+all -> lzma
+</libs>
diff --git a/src/lib/compression/lzma/lzma.cpp b/src/lib/compression/lzma/lzma.cpp
new file mode 100644
index 000000000..d145ed305
--- /dev/null
+++ b/src/lib/compression/lzma/lzma.cpp
@@ -0,0 +1,94 @@
+/*
+* Lzma Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007,2014 Jack Lloyd
+* 2006 Matt Johnston
+* 2012 Vojtech Kral
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/lzma.h>
+#include <botan/internal/comp_util.h>
+#include <lzma.h>
+
+namespace Botan {
+
+namespace {
+
+class LZMA_Stream : public Zlib_Style_Stream<lzma_stream, byte>
+ {
+ public:
+ LZMA_Stream()
+ {
+ streamp()->allocator = new ::lzma_allocator;
+ streamp()->allocator->opaque = alloc();
+ streamp()->allocator->alloc = Compression_Alloc_Info::malloc<size_t>;
+ streamp()->allocator->free = Compression_Alloc_Info::free;
+ }
+
+ ~LZMA_Stream()
+ {
+ ::lzma_end(streamp());
+ delete streamp()->allocator;
+ }
+
+ bool run(u32bit flags) override
+ {
+ lzma_ret rc = ::lzma_code(streamp(), static_cast<lzma_action>(flags));
+
+ if(rc == LZMA_MEM_ERROR)
+ throw std::bad_alloc();
+ else if (rc != LZMA_OK && rc != LZMA_STREAM_END)
+ throw std::runtime_error("Lzma error");
+
+ return (rc == LZMA_STREAM_END);
+ }
+
+ u32bit run_flag() const override { return LZMA_RUN; }
+ u32bit flush_flag() const override { return LZMA_FULL_FLUSH; }
+ u32bit finish_flag() const override { return LZMA_FINISH; }
+ };
+
+class LZMA_Compression_Stream : public LZMA_Stream
+ {
+ public:
+ LZMA_Compression_Stream(size_t level)
+ {
+ lzma_ret rc = ::lzma_easy_encoder(streamp(), level, LZMA_CHECK_CRC64);
+
+ if(rc == LZMA_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != LZMA_OK)
+ throw std::runtime_error("lzma compress initialization failed");
+ }
+ };
+
+class LZMA_Decompression_Stream : public LZMA_Stream
+ {
+ public:
+ LZMA_Decompression_Stream()
+ {
+ lzma_ret rc = ::lzma_stream_decoder(streamp(), UINT64_MAX,
+ LZMA_TELL_UNSUPPORTED_CHECK);
+
+ if(rc == LZMA_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != LZMA_OK)
+ throw std::runtime_error("Bad setting in lzma_stream_decoder");
+ }
+ };
+
+}
+
+Compression_Stream* LZMA_Compression::make_stream() const
+ {
+ return new LZMA_Compression_Stream(m_level);
+ }
+
+Compression_Stream* LZMA_Decompression::make_stream() const
+ {
+ return new LZMA_Decompression_Stream;
+ }
+
+}
diff --git a/src/lib/compression/lzma/lzma.h b/src/lib/compression/lzma/lzma.h
new file mode 100644
index 000000000..0761a8194
--- /dev/null
+++ b/src/lib/compression/lzma/lzma.h
@@ -0,0 +1,51 @@
+/*
+* Lzma Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+* 2012 Vojtech Kral
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_LZMA_H__
+#define BOTAN_LZMA_H__
+
+#include <botan/compression.h>
+
+namespace Botan {
+
+/**
+* LZMA Compression
+*/
+class BOTAN_DLL LZMA_Compression : public Stream_Compression
+ {
+ public:
+ /**
+ * @param level how much effort to use on compressing (0 to 9);
+ * higher levels are slower but tend to give better
+ * compression
+ */
+ LZMA_Compression(size_t level = 6) : m_level(level) {}
+
+ std::string name() const override { return "LZMA_Compression"; }
+
+ private:
+ Compression_Stream* make_stream() const;
+
+ const size_t m_level;
+ };
+
+/**
+* LZMA Deccompression
+*/
+class BOTAN_DLL LZMA_Decompression : public Stream_Decompression
+ {
+ public:
+ std::string name() const override { return "LZMA_Decompression"; }
+ private:
+ Compression_Stream* make_stream() const;
+ };
+
+}
+
+#endif
diff --git a/src/lib/compression/zlib/info.txt b/src/lib/compression/zlib/info.txt
new file mode 100644
index 000000000..ba5abd4ec
--- /dev/null
+++ b/src/lib/compression/zlib/info.txt
@@ -0,0 +1,7 @@
+define ZLIB_TRANSFORM 20141118
+
+load_on request
+
+<libs>
+all -> z
+</libs>
diff --git a/src/lib/compression/zlib/zlib.cpp b/src/lib/compression/zlib/zlib.cpp
new file mode 100644
index 000000000..b18621640
--- /dev/null
+++ b/src/lib/compression/zlib/zlib.cpp
@@ -0,0 +1,106 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007,2014 Jack Lloyd
+* 2006 Matt Johnston
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/zlib.h>
+#include <botan/internal/comp_util.h>
+#include <zlib.h>
+
+namespace Botan {
+
+namespace {
+
+class Zlib_Stream : public Zlib_Style_Stream<z_stream, Bytef>
+ {
+ public:
+ Zlib_Stream()
+ {
+ streamp()->opaque = alloc();
+ streamp()->zalloc = Compression_Alloc_Info::malloc<unsigned int>;
+ streamp()->zfree = Compression_Alloc_Info::free;
+ }
+
+ u32bit run_flag() const override { return Z_NO_FLUSH; }
+ u32bit flush_flag() const override { return Z_FULL_FLUSH; }
+ u32bit finish_flag() const override { return Z_FINISH; }
+ };
+
+class Zlib_Compression_Stream : public Zlib_Stream
+ {
+ public:
+ Zlib_Compression_Stream(size_t level, bool raw_deflate)
+ {
+ // FIXME: allow specifiying memLevel and strategy
+ int rc = deflateInit2(streamp(), level, Z_DEFLATED,
+ (raw_deflate ? -15 : 15), 8, Z_DEFAULT_STRATEGY);
+ if(rc != Z_OK)
+ throw std::runtime_error("zlib deflate initialization failed");
+ }
+
+ ~Zlib_Compression_Stream()
+ {
+ deflateEnd(streamp());
+ }
+
+ bool run(u32bit flags) override
+ {
+ int rc = deflate(streamp(), flags);
+
+ if(rc == Z_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != Z_OK && rc != Z_STREAM_END)
+ throw std::runtime_error("zlib deflate error");
+
+ return (rc == Z_STREAM_END);
+ }
+ };
+
+class Zlib_Decompression_Stream : public Zlib_Stream
+ {
+ public:
+ Zlib_Decompression_Stream(bool raw_deflate)
+ {
+ int rc = inflateInit2(streamp(), (raw_deflate ? -15 : 15));
+
+ if(rc == Z_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != Z_OK)
+ throw std::runtime_error("zlib inflate initialization failed");
+ }
+
+ ~Zlib_Decompression_Stream()
+ {
+ inflateEnd(streamp());
+ }
+
+ bool run(u32bit flags) override
+ {
+ int rc = inflate(streamp(), flags);
+
+ if(rc == Z_MEM_ERROR)
+ throw std::bad_alloc();
+ else if(rc != Z_OK && rc != Z_STREAM_END)
+ throw std::runtime_error("zlib deflate error");
+
+ return (rc == Z_STREAM_END);
+ }
+ };
+
+}
+
+Compression_Stream* Zlib_Compression::make_stream() const
+ {
+ return new Zlib_Compression_Stream(m_level, m_raw_deflate);
+ }
+
+Compression_Stream* Zlib_Decompression::make_stream() const
+ {
+ return new Zlib_Decompression_Stream(m_raw_deflate);
+ }
+
+}
diff --git a/src/lib/compression/zlib/zlib.h b/src/lib/compression/zlib/zlib.h
new file mode 100644
index 000000000..55da47a0d
--- /dev/null
+++ b/src/lib/compression/zlib/zlib.h
@@ -0,0 +1,61 @@
+/*
+* Zlib Compressor
+* (C) 2001 Peter J Jones
+* 2001-2007 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_ZLIB_H__
+#define BOTAN_ZLIB_H__
+
+#include <botan/compression.h>
+
+namespace Botan {
+
+/**
+* Zlib Compression
+*/
+class BOTAN_DLL Zlib_Compression : public Stream_Compression
+ {
+ public:
+ /**
+ * @param level how much effort to use on compressing (0 to 9);
+ * higher levels are slower but tend to give better
+ * compression
+ * @param raw_deflate if true no zlib header/trailer will be used
+ */
+ Zlib_Compression(size_t level = 6, bool raw_deflate = false) :
+ m_level(level), m_raw_deflate(raw_deflate) {}
+
+ std::string name() const override { return "Zlib_Compression"; }
+
+ private:
+ Compression_Stream* make_stream() const;
+
+ const size_t m_level;
+ const bool m_raw_deflate;
+ };
+
+/**
+* Zlib Deccompression
+*/
+class BOTAN_DLL Zlib_Decompression : public Stream_Decompression
+ {
+ public:
+ /**
+ * @param raw_deflate if true no zlib header/trailer will be used
+ */
+ Zlib_Decompression( bool raw_deflate = false) : m_raw_deflate(raw_deflate) {}
+
+ std::string name() const override { return "Zlib_Decompression"; }
+
+ private:
+ Compression_Stream* make_stream() const;
+
+ const bool m_raw_deflate;
+ };
+
+}
+
+#endif