From 124e182581cd6bc168e206b20d70a6fabf2e5854 Mon Sep 17 00:00:00 2001
From: randomdan <randomdan@localhost>
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 Impl, typename... Params>
+class GenLoader : public ComponentLoader {
+	public:
+		template <class T>
+		class For : public GenLoader<Impl, Params...> {
+			public:
+				inline Impl * create(const Params & ... p) const
+				{
+					return new T(p...);
+				}
+		};
+		virtual Impl * create(const Params & ...) const = 0;
+		inline static boost::shared_ptr<GenLoader<Impl, Params...>> getFor(const char * n)
+		{
+			return LoaderBase::getLoader<GenLoader<Impl, Params...>, NotSupported>(n);
+		}
+};
+#define DECLARE_GENERIC_LOADER(N, B, T) \
+	DECLARE_CUSTOM_COMPONENT_LOADER(N, T, B::For<T>, 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<ElementLoader>(&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<Decompressor> DecompressorPtr;
+typedef GenLoader<Decompressor> 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 <zlib.h>
+
+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<const char *>(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 <zlib.h>
-
-class DecompressStream : public Stream {
-	public:
-		DecompressStream(ScriptNodePtr p) :
-			Stream(p),
-			method(p, "method")
-		{
-			p->script->loader.addLoadTarget(p, Storer::into<ElementLoader>(&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<const char *>(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