diff options
Diffstat (limited to 'Swiften/Compress')
-rw-r--r-- | Swiften/Compress/Makefile.inc | 4 | ||||
-rw-r--r-- | Swiften/Compress/UnitTest/Makefile.inc | 3 | ||||
-rw-r--r-- | Swiften/Compress/UnitTest/ZLibCompressorTest.cpp | 35 | ||||
-rw-r--r-- | Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp | 71 | ||||
-rw-r--r-- | Swiften/Compress/ZLibCodecompressor.cpp | 43 | ||||
-rw-r--r-- | Swiften/Compress/ZLibCodecompressor.h | 22 | ||||
-rw-r--r-- | Swiften/Compress/ZLibCompressor.h | 31 | ||||
-rw-r--r-- | Swiften/Compress/ZLibDecompressor.h | 28 | ||||
-rw-r--r-- | Swiften/Compress/ZLibException.h | 11 |
9 files changed, 248 insertions, 0 deletions
diff --git a/Swiften/Compress/Makefile.inc b/Swiften/Compress/Makefile.inc new file mode 100644 index 0000000..bf502fb --- /dev/null +++ b/Swiften/Compress/Makefile.inc @@ -0,0 +1,4 @@ +SWIFTEN_SOURCES += \ + Swiften/Compress/ZLibCodecompressor.cpp + +include Swiften/Compress/UnitTest/Makefile.inc diff --git a/Swiften/Compress/UnitTest/Makefile.inc b/Swiften/Compress/UnitTest/Makefile.inc new file mode 100644 index 0000000..fcc1a2c --- /dev/null +++ b/Swiften/Compress/UnitTest/Makefile.inc @@ -0,0 +1,3 @@ +UNITTEST_SOURCES += \ + Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp \ + Swiften/Compress/UnitTest/ZLibCompressorTest.cpp diff --git a/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp b/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp new file mode 100644 index 0000000..7235f8e --- /dev/null +++ b/Swiften/Compress/UnitTest/ZLibCompressorTest.cpp @@ -0,0 +1,35 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Compress/ZLibCompressor.h" + +using namespace Swift; + + +class ZLibCompressorTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ZLibCompressorTest); + CPPUNIT_TEST(testProcess); + CPPUNIT_TEST(testProcess_Twice); + CPPUNIT_TEST_SUITE_END(); + + public: + ZLibCompressorTest() {} + + void testProcess() { + ZLibCompressor testling; + ByteArray result = testling.process("foo"); + + CPPUNIT_ASSERT_EQUAL(ByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11), result); + } + + void testProcess_Twice() { + ZLibCompressor testling; + testling.process("foo"); + ByteArray result = testling.process("bar"); + + CPPUNIT_ASSERT_EQUAL(ByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff",9), result); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ZLibCompressorTest); diff --git a/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp b/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp new file mode 100644 index 0000000..871a630 --- /dev/null +++ b/Swiften/Compress/UnitTest/ZLibDecompressorTest.cpp @@ -0,0 +1,71 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include "Swiften/Compress/ZLibDecompressor.h" +#include "Swiften/Compress/ZLibCompressor.h" +#include "Swiften/Compress/ZLibException.h" + +using namespace Swift; + + +class ZLibDecompressorTest : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ZLibDecompressorTest); + CPPUNIT_TEST(testProcess); + CPPUNIT_TEST(testProcess_Twice); + CPPUNIT_TEST(testProcess_Invalid); + CPPUNIT_TEST(testProcess_Huge); + CPPUNIT_TEST(testProcess_ChunkSize); + CPPUNIT_TEST_SUITE_END(); + + public: + ZLibDecompressorTest() {} + + void testProcess() { + ZLibDecompressor testling; + ByteArray result = testling.process(ByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); + + CPPUNIT_ASSERT_EQUAL(ByteArray("foo"), result); + } + + void testProcess_Twice() { + ZLibDecompressor testling; + testling.process(ByteArray("\x78\xda\x4a\xcb\xcf\x07\x00\x00\x00\xff\xff", 11)); + ByteArray result = testling.process(ByteArray("\x4a\x4a\x2c\x02\x00\x00\x00\xff\xff", 9)); + + CPPUNIT_ASSERT_EQUAL(ByteArray("bar"), result); + } + + void testProcess_Invalid() { + ZLibDecompressor testling; + CPPUNIT_ASSERT_THROW(testling.process(ByteArray("invalid")), ZLibException); + } + + void testProcess_Huge() { + std::vector<char> data; + data.reserve(2048); + for (unsigned int i = 0; i < 2048; ++i) { + data.push_back(static_cast<char>(i)); + } + ByteArray original(&data[0], data.size()); + ByteArray compressed = ZLibCompressor().process(original); + ByteArray decompressed = ZLibDecompressor().process(compressed); + + CPPUNIT_ASSERT_EQUAL(original, decompressed); + } + + void testProcess_ChunkSize() { + std::vector<char> data; + data.reserve(1024); + for (unsigned int i = 0; i < 1024; ++i) { + data.push_back(static_cast<char>(i)); + } + ByteArray original(&data[0], data.size()); + ByteArray compressed = ZLibCompressor().process(original); + ByteArray decompressed = ZLibDecompressor().process(compressed); + + CPPUNIT_ASSERT_EQUAL(original, decompressed); + } +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ZLibDecompressorTest); diff --git a/Swiften/Compress/ZLibCodecompressor.cpp b/Swiften/Compress/ZLibCodecompressor.cpp new file mode 100644 index 0000000..a14f09d --- /dev/null +++ b/Swiften/Compress/ZLibCodecompressor.cpp @@ -0,0 +1,43 @@ +#include "Swiften/Compress/ZLibCodecompressor.h" + +#include <cassert> + +#include "Swiften/Compress/ZLibException.h" + +namespace Swift { + +static const int CHUNK_SIZE = 1024; // If you change this, also change the unittest + +ZLibCodecompressor::ZLibCodecompressor() { + stream_.zalloc = Z_NULL; + stream_.zfree = Z_NULL; + stream_.opaque = Z_NULL; +} + +ZLibCodecompressor::~ZLibCodecompressor() { +} + +ByteArray ZLibCodecompressor::process(const ByteArray& input) { + ByteArray output; + stream_.avail_in = input.getSize(); + stream_.next_in = reinterpret_cast<Bytef*>(const_cast<char*>(input.getData())); + int outputPosition = 0; + do { + output.resize(outputPosition + CHUNK_SIZE); + stream_.avail_out = CHUNK_SIZE; + stream_.next_out = reinterpret_cast<Bytef*>(output.getData() + outputPosition); + int result = processZStream(); + if (result != Z_OK && result != Z_BUF_ERROR) { + throw ZLibException(/* stream_.msg */); + } + outputPosition += CHUNK_SIZE; + } + while (stream_.avail_out == 0); + if (stream_.avail_in != 0) { + throw ZLibException(); + } + output.resize(outputPosition - stream_.avail_out); + return output; +} + +} diff --git a/Swiften/Compress/ZLibCodecompressor.h b/Swiften/Compress/ZLibCodecompressor.h new file mode 100644 index 0000000..dd032fa --- /dev/null +++ b/Swiften/Compress/ZLibCodecompressor.h @@ -0,0 +1,22 @@ +#ifndef SWIFTEN_ZLibCodecompressor_H +#define SWIFTEN_ZLibCodecompressor_H + +#include <zlib.h> + +#include "Swiften/Base/ByteArray.h" + +namespace Swift { + class ZLibCodecompressor { + public: + ZLibCodecompressor(); + virtual ~ZLibCodecompressor(); + + ByteArray process(const ByteArray& data); + virtual int processZStream() = 0; + + protected: + z_stream stream_; + }; +} + +#endif diff --git a/Swiften/Compress/ZLibCompressor.h b/Swiften/Compress/ZLibCompressor.h new file mode 100644 index 0000000..b5bace6 --- /dev/null +++ b/Swiften/Compress/ZLibCompressor.h @@ -0,0 +1,31 @@ +#ifndef SWIFTEN_ZLibCompressor_H +#define SWIFTEN_ZLibCompressor_H + +#include <cassert> + +#include "Swiften/Compress/ZLibCodecompressor.h" +#include "Swiften/Base/ByteArray.h" + +namespace Swift { + class ZLibCompressor : public ZLibCodecompressor { + public: + ZLibCompressor() { + int result = deflateInit(&stream_, COMPRESSION_LEVEL); + assert(result == Z_OK); + (void) result; + } + + ~ZLibCompressor() { + deflateEnd(&stream_); + } + + virtual int processZStream() { + return deflate(&stream_, Z_SYNC_FLUSH); + } + + private: + static const int COMPRESSION_LEVEL = 9; + }; +} + +#endif diff --git a/Swiften/Compress/ZLibDecompressor.h b/Swiften/Compress/ZLibDecompressor.h new file mode 100644 index 0000000..808feb2 --- /dev/null +++ b/Swiften/Compress/ZLibDecompressor.h @@ -0,0 +1,28 @@ +#ifndef SWIFTEN_ZLibDecompressor_H +#define SWIFTEN_ZLibDecompressor_H + +#include <cassert> + +#include "Swiften/Compress/ZLibCodecompressor.h" +#include "Swiften/Base/ByteArray.h" + +namespace Swift { + class ZLibDecompressor : public ZLibCodecompressor { + public: + ZLibDecompressor() { + int result = inflateInit(&stream_); + assert(result == Z_OK); + (void) result; + } + + ~ZLibDecompressor() { + inflateEnd(&stream_); + } + + virtual int processZStream() { + return inflate(&stream_, Z_SYNC_FLUSH); + } + }; +} + +#endif diff --git a/Swiften/Compress/ZLibException.h b/Swiften/Compress/ZLibException.h new file mode 100644 index 0000000..f16b4ed --- /dev/null +++ b/Swiften/Compress/ZLibException.h @@ -0,0 +1,11 @@ +#ifndef SWIFTEN_ZLIBEXCEPTION_H +#define SWIFTEN_ZLIBEXCEPTION_H + +namespace Swift { + class ZLibException { + public: + ZLibException() {} + }; +} + +#endif |