From 124e182581cd6bc168e206b20d70a6fabf2e5854 Mon Sep 17 00:00:00 2001 From: randomdan Date: Thu, 22 Mar 2012 01:22:51 +0000 Subject: A generic variadic template loader A nocomp (pass through) stream decompressor A tidy up and plugin implementation for stream decompressors --- project2/common/genericLoader.h | 27 +++++++++++++ project2/compression/decompressStream.cpp | 30 ++++++++++++++ project2/compression/decompressor.h | 18 +++++++++ project2/compression/gzip.cpp | 53 ++++++++++++++++++++++++ project2/compression/nocomp.cpp | 14 +++++++ project2/compression/z.cpp | 67 ------------------------------- 6 files changed, 142 insertions(+), 67 deletions(-) create mode 100644 project2/common/genericLoader.h create mode 100644 project2/compression/decompressStream.cpp create mode 100644 project2/compression/decompressor.h create mode 100644 project2/compression/gzip.cpp create mode 100644 project2/compression/nocomp.cpp delete mode 100644 project2/compression/z.cpp diff --git a/project2/common/genericLoader.h b/project2/common/genericLoader.h new file mode 100644 index 0000000..cd129f0 --- /dev/null +++ b/project2/common/genericLoader.h @@ -0,0 +1,27 @@ +#ifndef GENERICLOADER_H +#define GENERICLOADER_H + +#include "scriptLoader.h" + +template +class GenLoader : public ComponentLoader { + public: + template + class For : public GenLoader { + public: + inline Impl * create(const Params & ... p) const + { + return new T(p...); + } + }; + virtual Impl * create(const Params & ...) const = 0; + inline static boost::shared_ptr> getFor(const char * n) + { + return LoaderBase::getLoader, NotSupported>(n); + } +}; +#define DECLARE_GENERIC_LOADER(N, B, T) \ + DECLARE_CUSTOM_COMPONENT_LOADER(N, T, B::For, B); + +#endif + diff --git a/project2/compression/decompressStream.cpp b/project2/compression/decompressStream.cpp new file mode 100644 index 0000000..eb32833 --- /dev/null +++ b/project2/compression/decompressStream.cpp @@ -0,0 +1,30 @@ +#include "stream.h" +#include "scriptLoader.h" +#include "decompressor.h" +#include "scripts.h" +#include "scopeObject.h" +#include "scriptStorage.h" + +class DecompressStream : public Stream { + public: + DecompressStream(ScriptNodePtr p) : + Stream(p), + method(p, "method") + { + p->script->loader.addLoadTarget(p, Storer::into(&stream)); + } + + void runStream(const Sink & sink) const + { + DecompressorPtr decomp = DecompressorLoader::getFor(method())->create(); + stream->runStream([&](const char * data, size_t len) -> size_t { + decomp->decompress(data, len, sink); + return len; + }); + } + + StreamPtr stream; + const Variable method; +}; + +DECLARE_LOADER("decompstream", DecompressStream); diff --git a/project2/compression/decompressor.h b/project2/compression/decompressor.h new file mode 100644 index 0000000..dfa1db7 --- /dev/null +++ b/project2/compression/decompressor.h @@ -0,0 +1,18 @@ +#ifndef DECOMPRESSOR +#define DECOMPRESSOR + +#include "stream.h" +#include "genericLoader.h" +#include "intrusivePtrBase.h" + +class Decompressor : public IntrusivePtrBase { + public: + virtual ~Decompressor() + { + } + virtual void decompress(const char * dataIn, size_t lengthIn, const Stream::Sink &) = 0; +}; +typedef boost::intrusive_ptr DecompressorPtr; +typedef GenLoader DecompressorLoader; + +#endif diff --git a/project2/compression/gzip.cpp b/project2/compression/gzip.cpp new file mode 100644 index 0000000..2bf0a8d --- /dev/null +++ b/project2/compression/gzip.cpp @@ -0,0 +1,53 @@ +#include "stream.h" +#include "scriptLoader.h" +#include "decompressor.h" +#include + +class GZip : public Decompressor { + public: + GZip() + { + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + strm.avail_in = 0; + strm.next_in = Z_NULL; + status = inflateInit2(&strm, 16+MAX_WBITS); + if (status != Z_OK) + throw std::runtime_error("inflateInit failed"); + } + ~GZip() + { + inflateEnd(&strm); + if (status != Z_STREAM_END) { + throw std::runtime_error("decompression of stream failed"); + } + } + void decompress(const char * data, size_t len, const Stream::Sink & sink) + { + unsigned char out[BUFSIZ]; + strm.avail_in = len; + strm.next_in = (unsigned char *)data; + do { + strm.avail_out = BUFSIZ; + strm.next_out = out; + status = inflate(&strm, Z_NO_FLUSH); + assert(status != Z_STREAM_ERROR); + switch (status) { + case Z_NEED_DICT: + status = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + throw std::runtime_error("inflate failed"); + } + unsigned int have; + have = BUFSIZ - strm.avail_out; + sink(reinterpret_cast(out), have); + } while (strm.avail_out == 0); + } + private: + z_stream strm; + int status; +}; +DECLARE_GENERIC_LOADER("gz", DecompressorLoader, GZip); + diff --git a/project2/compression/nocomp.cpp b/project2/compression/nocomp.cpp new file mode 100644 index 0000000..6861171 --- /dev/null +++ b/project2/compression/nocomp.cpp @@ -0,0 +1,14 @@ +#include "stream.h" +#include "scriptLoader.h" +#include "decompressor.h" + +class NoComp : public Decompressor { + public: + void decompress(const char * data, size_t len, const Stream::Sink & sink) + { + sink(data, len); + } +}; +DECLARE_GENERIC_LOADER("nocomp", DecompressorLoader, NoComp); + + diff --git a/project2/compression/z.cpp b/project2/compression/z.cpp deleted file mode 100644 index 7d5d06b..0000000 --- a/project2/compression/z.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "stream.h" -#include "scriptLoader.h" -#include "scripts.h" -#include "scopeObject.h" -#include "scriptStorage.h" -#include - -class DecompressStream : public Stream { - public: - DecompressStream(ScriptNodePtr p) : - Stream(p), - method(p, "method") - { - p->script->loader.addLoadTarget(p, Storer::into(&stream)); - } - - void runStream(const Sink & sink) const - { - unsigned have; - z_stream strm; - unsigned char out[BUFSIZ]; - - /* allocate inflate state */ - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - strm.opaque = Z_NULL; - strm.avail_in = 0; - strm.next_in = Z_NULL; - int ret = inflateInit2(&strm, 16+MAX_WBITS); - if (ret != Z_OK) - throw std::runtime_error("inflateInit failed"); - ScopeObject tidy([&]{ inflateEnd(&strm); }); - - /* decompress until deflate stream ends or end of file */ - stream->runStream([&](const char * data, size_t len) -> size_t { - strm.avail_in = len; - strm.next_in = (unsigned char *)data; - - /* run inflate() on input until output buffer not full */ - do { - strm.avail_out = BUFSIZ; - strm.next_out = out; - ret = inflate(&strm, Z_NO_FLUSH); - assert(ret != Z_STREAM_ERROR); /* state not clobbered */ - switch (ret) { - case Z_NEED_DICT: - ret = Z_DATA_ERROR; /* and fall through */ - case Z_DATA_ERROR: - case Z_MEM_ERROR: - throw std::runtime_error("inflate failed"); - } - have = BUFSIZ - strm.avail_out; - sink(reinterpret_cast(out), have); - } while (strm.avail_out == 0); - - return len; }); - - if (ret != Z_STREAM_END) { - throw std::runtime_error("decompression of stream failed"); - } - } - - StreamPtr stream; - const Variable method; -}; - -DECLARE_LOADER("decompstream", DecompressStream); -- cgit v1.2.3