Skip to content

Instantly share code, notes, and snippets.

@nemequ
Created September 16, 2013 16:41
Show Gist options
  • Save nemequ/6583163 to your computer and use it in GitHub Desktop.
Save nemequ/6583163 to your computer and use it in GitHub Desktop.
From ac471e882642849bdf94aa280d694b692c18780e Mon Sep 17 00:00:00 2001
From: Evan Nemerson <evan@coeus-group.com>
Date: Mon, 16 Sep 2013 09:39:09 -0700
Subject: [PATCH] Add wfLZ plugin.
https://github.com/quixdb/squash/issues/56
Signed-off-by: Evan Nemerson <evan@coeus-group.com>
---
.gitmodules | 3 +
configure.ac | 3 +-
docs/index.md | 1 +
plugins/Makefile.am | 1 +
plugins/wflz/Makefile.am | 37 +++++++++
plugins/wflz/squash-wflz.c | 201 +++++++++++++++++++++++++++++++++++++++++++++
plugins/wflz/wflz | 1 +
plugins/wflz/wflz.codecs | 1 +
plugins/wflz/wflz.m4 | 5 ++
plugins/wflz/wflz.md | 23 ++++++
10 files changed, 275 insertions(+), 1 deletion(-)
create mode 100644 plugins/wflz/Makefile.am
create mode 100644 plugins/wflz/squash-wflz.c
create mode 160000 plugins/wflz/wflz
create mode 100644 plugins/wflz/wflz.codecs
create mode 100644 plugins/wflz/wflz.m4
create mode 100644 plugins/wflz/wflz.md
diff --git a/.gitmodules b/.gitmodules
index be8e0c4..9c2d813 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -25,3 +25,6 @@
[submodule "plugins/fastlz/fastlz"]
path = plugins/fastlz/fastlz
url = https://github.com/svn2github/fastlz.git
+[submodule "plugins/wflz/wflz"]
+ path = plugins/wflz/wflz
+ url = https://github.com/svn2github/wflz.git
diff --git a/configure.ac b/configure.ac
index 07bdbf5..059f0aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -188,7 +188,7 @@ AC_SUBST(PLUGIN_LIBTOOL_FLAGS)
SQUASH_PLUGINS=""
SQUASH_PLUGINS_ENABLED=""
-m4_foreach([plugin],[blosc, bzip2, doboz, fastlz, lz4, lzg, lzma, lzmat, lzf, lzo, quicklz, sharc, snappy, zlib, zpaq], [
+m4_foreach([plugin],[blosc, bzip2, doboz, fastlz, lz4, lzg, lzma, lzmat, lzf, lzo, quicklz, sharc, snappy, wflz, zlib, zpaq], [
m4_include(plugins/plugin/plugin[.m4])
SQUASH_PLUGINS="${SQUASH_PLUGINS} plugin"
])
@@ -261,6 +261,7 @@ AC_CONFIG_FILES([Makefile
plugins/quicklz/Makefile
plugins/sharc/Makefile
plugins/snappy/Makefile
+ plugins/wflz/Makefile
plugins/zlib/Makefile
plugins/zpaq/Makefile
utils/Makefile
diff --git a/docs/index.md b/docs/index.md
index 737a1b0..886db76 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -45,6 +45,7 @@ Squash currently contains plugins for the following libraries:
- [QuickLZ](@ref md_quicklz)
- [SHARC](@ref md_sharc)
- [Snappy](@ref md_snappy)
+- [wfLZ](@ref md_wflz)
- [zlib](@ref md_zlib)
- [ZPAQ](@ref md_zpaq)
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index efc6fe5..249a354 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -12,6 +12,7 @@ SUBDIRS = \
quicklz \
sharc \
snappy \
+ wflz \
zlib \
zpaq
diff --git a/plugins/wflz/Makefile.am b/plugins/wflz/Makefile.am
new file mode 100644
index 0000000..45e8478
--- /dev/null
+++ b/plugins/wflz/Makefile.am
@@ -0,0 +1,37 @@
+COMMON_CFLAGS = \
+ -O3 \
+ -I$(top_srcdir) \
+ @WARN_CFLAGS@ \
+ -Wno-strict-prototypes \
+ -Wno-missing-prototypes \
+ -DSQUASH_IS_UNSTABLE
+
+WFLZ_FILES = \
+ wflz/wfLZ.c
+
+COMMON_LIBS = $(top_builddir)/squash/libsquash@SQUASH_API_VERSION@.la
+
+plugindir = $(libdir)/squash/@SQUASH_API_VERSION@/plugins/wflz
+plugin_DATA = wflz.codecs
+
+plugin_LTLIBRARIES = \
+ libsquash@SQUASH_API_VERSION@-plugin-wflz.la
+
+libsquash@SQUASH_API_VERSION@_plugin_wflz_la_CFLAGS = \
+ $(COMMON_CFLAGS)
+
+libsquash@SQUASH_API_VERSION@_plugin_wflz_la_LDFLAGS = \
+ $(PLUGIN_LIBTOOL_FLAGS)
+
+libsquash@SQUASH_API_VERSION@_plugin_wflz_la_LIBADD = \
+ $(COMMON_LIBS)
+
+libsquash@SQUASH_API_VERSION@_plugin_wflz_la_SOURCES = \
+ $(WFLZ_FILES) \
+ squash-wflz.c
+
+EXTRA_DIST = \
+ $(plugin_DATA) \
+ wflz.md
+
+include $(top_srcdir)/git.mk
diff --git a/plugins/wflz/squash-wflz.c b/plugins/wflz/squash-wflz.c
new file mode 100644
index 0000000..9fe2a2b
--- /dev/null
+++ b/plugins/wflz/squash-wflz.c
@@ -0,0 +1,201 @@
+/* Copyright (c) 2013 The Squash Authors
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Evan Nemerson <evan@coeus-group.com>
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include <squash/squash.h>
+
+#include "wflz/wfLZ.h"
+
+enum {
+ SQUASH_WFLZ_LITTLE_ENDIAN = 0x03020100ul,
+ SQUASH_WFLZ_BIG_ENDIAN = 0x00010203ul
+};
+
+static const union {
+ unsigned char bytes[4];
+ uint32_t value;
+} squash_wflz_host_order = { { 0, 1, 2, 3 } };
+
+#define SQUASH_WFLZ_HOST_ORDER (squash_wflz_host_order.value)
+
+typedef struct SquashWflzOptions_s {
+ SquashOptions base_object;
+
+ int level;
+ uint32_t endianness;
+} SquashWflzOptions;
+
+#define SQUASH_WFLZ_DEFAULT_LEVEL 2
+#define SQUASH_WFLZ_DEFAULT_ENDIAN SQUASH_WFLZ_LITTLE_ENDIAN
+
+SquashStatus squash_plugin_init_codec (SquashCodec* codec, SquashCodecFuncs* funcs);
+
+static void squash_wflz_options_init (SquashWflzOptions* options, SquashCodec* codec, SquashDestroyNotify destroy_notify);
+static SquashWflzOptions* squash_wflz_options_new (SquashCodec* codec);
+static void squash_wflz_options_destroy (void* options);
+static void squash_wflz_options_free (void* options);
+
+static void
+squash_wflz_options_init (SquashWflzOptions* options, SquashCodec* codec, SquashDestroyNotify destroy_notify) {
+ assert (options != NULL);
+
+ squash_options_init ((SquashOptions*) options, codec, destroy_notify);
+
+ options->level = SQUASH_WFLZ_DEFAULT_LEVEL;
+ options->endianness = SQUASH_WFLZ_LITTLE_ENDIAN;
+}
+
+static SquashWflzOptions*
+squash_wflz_options_new (SquashCodec* codec) {
+ SquashWflzOptions* options;
+
+ options = (SquashWflzOptions*) malloc (sizeof (SquashWflzOptions));
+ squash_wflz_options_init (options, codec, squash_wflz_options_free);
+
+ return options;
+}
+
+static void
+squash_wflz_options_destroy (void* options) {
+ squash_options_destroy ((SquashOptions*) options);
+}
+
+static void
+squash_wflz_options_free (void* options) {
+ squash_wflz_options_destroy ((SquashWflzOptions*) options);
+ free (options);
+}
+
+static SquashOptions*
+squash_wflz_create_options (SquashCodec* codec) {
+ return (SquashOptions*) squash_wflz_options_new (codec);
+}
+
+static SquashStatus
+squash_wflz_parse_option (SquashOptions* options, const char* key, const char* value) {
+ SquashWflzOptions* opts = (SquashWflzOptions*) options;
+ char* endptr = NULL;
+
+ assert (opts != NULL);
+
+ if (strcasecmp (key, "level") == 0) {
+ const long level = strtol (value, &endptr, 0);
+ if ( *endptr == '\0' && level >= 1 && level <= 2 ) {
+ opts->level = (int) level;
+ } else {
+ return SQUASH_BAD_VALUE;
+ }
+ } else if (strcasecmp (key, "endianness") == 0) {
+ if (strcasecmp (value, "little") == 0) {
+ opts->endianness = SQUASH_WFLZ_LITTLE_ENDIAN;
+ } else if (strcasecmp (value, "big")) {
+ opts->endianness = SQUASH_WFLZ_BIG_ENDIAN;
+ } else {
+ return SQUASH_BAD_VALUE;
+ }
+ } else {
+ return SQUASH_BAD_PARAM;
+ }
+
+ return SQUASH_OK;
+}
+
+static size_t
+squash_wflz_get_max_compressed_size (SquashCodec* codec, size_t uncompressed_length) {
+ return (size_t) wfLZ_GetMaxCompressedSize ((uint32_t) uncompressed_length);
+}
+
+static size_t
+squash_wflz_get_uncompressed_size (SquashCodec* codec, const uint8_t* compressed, size_t compressed_length) {
+ if (compressed_length < 12)
+ return 0;
+
+ return (size_t) wfLZ_GetDecompressedSize (compressed);
+}
+
+static SquashStatus
+squash_wflz_compress_buffer (SquashCodec* codec,
+ uint8_t* compressed, size_t* compressed_length,
+ const uint8_t* uncompressed, size_t uncompressed_length,
+ SquashOptions* options) {
+ const uint32_t swap = ((options == NULL) ? SQUASH_WFLZ_DEFAULT_ENDIAN : ((SquashWflzOptions*) options)->endianness) != SQUASH_WFLZ_HOST_ORDER;
+ const int level = (options == NULL) ? SQUASH_WFLZ_DEFAULT_LEVEL : ((SquashWflzOptions*) options)->level;
+
+ if (*compressed_length < wfLZ_GetMaxCompressedSize ((uint32_t) uncompressed_length)) {
+ return SQUASH_BUFFER_FULL;
+ }
+
+ uint8_t* work_mem = (uint8_t*) malloc (wfLZ_GetWorkMemSize ());
+
+ if (level == 1) {
+ *compressed_length = (size_t) wfLZ_CompressFast (uncompressed, (uint32_t) uncompressed_length,
+ compressed, work_mem, swap);
+ } else {
+ *compressed_length = (size_t) wfLZ_Compress (uncompressed, (uint32_t) uncompressed_length,
+ compressed, work_mem, swap);
+ }
+
+ free (work_mem);
+
+ return (*compressed_length > 0) ? SQUASH_OK : SQUASH_FAILED;
+}
+
+static SquashStatus
+squash_wflz_decompress_buffer (SquashCodec* codec,
+ uint8_t* decompressed, size_t* decompressed_length,
+ const uint8_t* compressed, size_t compressed_length,
+ SquashOptions* options) {
+ uint32_t decompressed_size;
+
+ if (compressed_length < 12 || (decompressed_size = wfLZ_GetDecompressedSize (compressed)) > *decompressed_length) {
+ return SQUASH_FAILED;
+ }
+
+ wfLZ_Decompress (compressed, decompressed);
+ return SQUASH_OK;
+}
+
+SquashStatus
+squash_plugin_init_codec (SquashCodec* codec, SquashCodecFuncs* funcs) {
+ const char* name = squash_codec_get_name (codec);
+
+ if (strcmp ("wflz", name) == 0) {
+ funcs->create_options = squash_wflz_create_options;
+ funcs->parse_option = squash_wflz_parse_option;
+ funcs->get_uncompressed_size = squash_wflz_get_uncompressed_size;
+ funcs->get_max_compressed_size = squash_wflz_get_max_compressed_size;
+ funcs->decompress_buffer = squash_wflz_decompress_buffer;
+ funcs->compress_buffer = squash_wflz_compress_buffer;
+ } else {
+ return SQUASH_UNABLE_TO_LOAD;
+ }
+
+ return SQUASH_OK;
+}
diff --git a/plugins/wflz/wflz b/plugins/wflz/wflz
new file mode 160000
index 0000000..1e5e0ef
--- /dev/null
+++ b/plugins/wflz/wflz
@@ -0,0 +1 @@
+Subproject commit 1e5e0ef46d1f4a4bb872e22502c08f9d6fb0e726
diff --git a/plugins/wflz/wflz.codecs b/plugins/wflz/wflz.codecs
new file mode 100644
index 0000000..e829f9e
--- /dev/null
+++ b/plugins/wflz/wflz.codecs
@@ -0,0 +1 @@
+[wflz]
diff --git a/plugins/wflz/wflz.m4 b/plugins/wflz/wflz.m4
new file mode 100644
index 0000000..df9b2d9
--- /dev/null
+++ b/plugins/wflz/wflz.m4
@@ -0,0 +1,5 @@
+AC_ARG_ENABLE([wflz],
+ [AC_HELP_STRING([--enable-wflz=@<:@yes/no@:>@], [Enable wflz plugin @<:@default=yes@:>@])],,
+ [enable_wflz=yes])
+
+AM_CONDITIONAL([ENABLE_WFLZ], test x$enable_wflz = "xyes")
diff --git a/plugins/wflz/wflz.md b/plugins/wflz/wflz.md
new file mode 100644
index 0000000..9ccff7f
--- /dev/null
+++ b/plugins/wflz/wflz.md
@@ -0,0 +1,23 @@
+# wflz Plugin #
+
+For information about wfLZ, see https://code.google.com/p/wflz/
+
+## Codecs ##
+
+- **wflz** — Raw wfLZ data.
+
+## Options ##
+
+- **level** (integer, 1-2, default 2) — compression level. Lower is
+ faster, higher has a better compression ratio.
+
+### Compression Only ###
+
+- **endianness** (enum, "little" or "big", default "little") —
+ Endianness of the compressed file.
+
+## License ##
+
+The wflz plugin is licensed under the [MIT
+License](http://opensource.org/licenses/MIT), and wfLZ is licensed
+under the [WTFPL](http://www.wtfpl.net/).
--
1.8.3.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment