The test script combines the sources then builds and runs an example. A futher example is built if the Emscripten compiler is available on the system. Documentation covers building.
# Single File Zstandard Decompression Library
-Create the file using the shell script:
+The script `combine.sh` creates an _amalgamted_ source file that can be used with out without `zstd.h`. This isn't a _header-only_ file but it does offer a similar level of simplicity when integrating into a project.
+
+Create `zstddeclib.c` from the Zstd source using:
```
cd zstd/contrib/declib
./combine.sh -r ../../lib -r ../../lib/common -r ../../lib/decompress -o zstddeclib.c zstddeclib-in.c
```
-Then add the resulting file to your project (see the [test sources](tests) for examples).
+Then add the resulting file to your project (see the [example files](examples)).
+
+`build.sh` will run the above script then compile and test the resulting library.
--- /dev/null
+#!/bin/bash
+
+# Where to find the sources
+ZSTD_SRC_ROOT="../../lib"
+
+# Temporary compiled binary
+OUT_FILE="tempbin"
+
+# Optional temporary compiled WebAssembly
+OUT_WASM="temp.wasm"
+
+# Amalgamate the sources
+./combine.sh -r "$ZSTD_SRC_ROOT" -r "$ZSTD_SRC_ROOT/common" -r "$ZSTD_SRC_ROOT/decompress" -o zstddeclib.c zstddeclib-in.c
+# Did combining work?
+if [ $? -ne 0 ]; then
+ echo "Combine script: FAILED"
+ exit 1
+fi
+echo "Combine script: PASSED"
+
+# Compile the generated output
+cc -Os -g0 -o $OUT_FILE examples/simple.c
+# Did compilation work?
+if [ $? -ne 0 ]; then
+ echo "Compiling simple.c: FAILED"
+ exit 1
+fi
+echo "Compiling simple.c: PASSED"
+
+# Run then delete the compiled output
+./$OUT_FILE
+retVal=$?
+rm -f $OUT_FILE
+# Did the test work?
+if [ $retVal -ne 0 ]; then
+ echo "Running simple.c: FAILED"
+ exit 1
+fi
+echo "Running simple.c: PASSED"
+
+# Is Emscripten available?
+which emcc > /dev/null
+if [ $? -ne 0 ]; then
+ echo "(Skipping Emscripten test)"
+fi
+# Compile the Emscripten example
+CC_FLAGS="-Wall -Wextra -Os -g0 -flto --llvm-lto 3 -lGL -DNDEBUG=1"
+emcc $CC_FLAGS -s WASM=1 -o $OUT_WASM examples/emscripten.c
+# Did compilation work?
+if [ $? -ne 0 ]; then
+ echo "Compiling emscripten.c: FAILED"
+ exit 1
+fi
+echo "Compiling emscripten.c: PASSED"
+rm -f $OUT_WASM
+
+exit 0
--- /dev/null
+# Single File ZStandard Examples
+
+The examples `#include` the generated `zstddeclib.c` directly but work equally as well when including `zstd.h` and compiling the amalgamated source separately.
+
+`simple.c` is the most basic example of decompressing content and verifying the result.
+
+`emscripten.c` is a bare-bones [Emscripten](https://github.com/emscripten-core/emscripten) compiled WebGL demo using Zstd to further compress a DXT1 texture. The 256x256 texture would normally be 32kB, but even when bundled with the Zstd decompressor the resulting WebAssembly weighs in at 45kB.
* \n
* Compile using:
* \code
- * emcc -Wall -Wextra -Os -g0 -lGL -s WASM=1 -o out.html emscripten.c
+ * export CC_FLAGS="-Wall -Wextra -Os -g0 -flto --llvm-lto 3 -lGL -DNDEBUG=1"
+ * export EM_FLAGS="-s WASM=1 -s ENVIRONMENT=web --shell-file shell.html --closure 1"
+ * emcc $CC_FLAGS $EM_FLAGS -o out.html emscripten.c
* \endcode
*/
/**
* Zstd compressed DXT1 256x256 texture source.
+ *
+ * File credit: https://commons.wikimedia.org/wiki/File:FuBK-Testbild.png
*/
static uint8_t const srcZstd[] = {
0x28, 0xb5, 0x2f, 0xfd, 0x60, 0x00, 0x7f, 0xfd, 0xe2, 0x00, 0x8a, 0x05,
*/
static GLint uRotId = -1;
-/**
- * Draw colour ID.
- */
-static GLint uColId = -1;
-
/**
* Draw colour ID.
*/
*/
#define GL_VERT_POSXY_ID 0
-/**
- * Vertex colour index.
- */
-#define GL_VERT_COLOR_ID 1
-
/**
* Vertex UV0 index.
*/
-#define GL_VERT_TXUV0_ID 2
+#define GL_VERT_TXUV0_ID 1
/**
* \c GL vec2 storage type.
* and 'uploads' the resulting texture.
*
* As a (naive) comparison, removing Zstd and building with "-Os -g0 s WASM=1
- * -lGL emscripten.c" results in a 23kB WebAssembly file; re-adding Zstd
+ * -lGL emscripten.c" results in a 19kB WebAssembly file; re-adding Zstd
* increases the Wasm by 25kB.
*/
int main() {
fragId = compileShader(GL_FRAGMENT_SHADER, fragShader2D);
glBindAttribLocation(progId, GL_VERT_POSXY_ID, "aPos");
- glBindAttribLocation(progId, GL_VERT_COLOR_ID, "aCol");
glBindAttribLocation(progId, GL_VERT_TXUV0_ID, "aUV0");
glAttachShader(progId, vertId);
glLinkProgram (progId);
glUseProgram (progId);
uRotId = glGetUniformLocation(progId, "uRot");
- uColId = glGetUniformLocation(progId, "uCol");
uTx0Id = glGetUniformLocation(progId, "uTx0");
if (uTx0Id >= 0) {
glUniform1i(uTx0Id, 0);
</style>
</head>
<body>
- <canvas class="game" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
+ <canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
<script>
function trace(msg) {
console.log(msg);
/**
* \file simple.c
* Simple standalone example of using the single-file \c zstddeclib.
+ *
+ * \note In this simple example we include the amalgamated source and compile
+ * just this single file, but we could equally (and more conventionally)
+ * include \c zstd.h and compile both this file and \c zstddeclib.c (the
+ * resulting binaries differ slightly in size but perform the same).
*/
#include <stddef.h>
/**
* Raw 256x256 DXT1 data (used to compare the result).
+ *
+ * File credit: https://commons.wikimedia.org/wiki/File:FuBK-Testbild.png
*/
static uint8_t const rawDxt1[] = {
0x3c, 0xe7, 0xc7, 0x39, 0x25, 0x25, 0x25, 0x00, 0x28, 0x42, 0xba, 0xd6,
/**
* Zstd compressed version of \c #rawDxt1.
+ *
+ * File credit: https://commons.wikimedia.org/wiki/File:FuBK-Testbild.png
*/
static uint8_t const srcZstd[] = {
0x28, 0xb5, 0x2f, 0xfd, 0x60, 0x00, 0x7f, 0xfd, 0xe2, 0x00, 0x8a, 0x05,
* dummy function to fake the process and stop the buffers being optimised out.
*/
size_t ZSTD_decompress(void* dst, size_t dstLen, const void* src, size_t srcLen) {
- return (memcmp(dst, src, (srcLen < dstLen) ? srcLen : dstLen)) ? dstLen : 0;
+ return (memcmp(dst, src, (srcLen < dstLen) ? srcLen : dstLen)) ? 0 : dstLen;
}
#endif
* \n
* As a (naive) comparison, removing Zstd and building with "-Os -g0 simple.c"
* results in a 48kB binary (macOS 10.14, Clang 10); re-adding Zstd increases
- * the binary by 74kB.
+ * the binary by 67kB (after calling \c strip).
*/
int main() {
size_t size = ZSTD_decompress(dstDxt1, sizeof dstDxt1, srcZstd, sizeof srcZstd);
int compare = memcmp(rawDxt1, dstDxt1, sizeof dstDxt1);
- printf("Decompressed size: %s\n", (size == sizeof dstDxt1) ? "OK" : "FAILED");
- printf("Byte comparison: %s\n", (compare == 0) ? "OK" : "FAILED");
+ printf("Decompressed size: %s\n", (size == sizeof dstDxt1) ? "PASSED" : "FAILED");
+ printf("Byte comparison: %s\n", (compare == 0) ? "PASSED" : "FAILED");
if (size == sizeof dstDxt1 && compare == 0) {
return EXIT_SUCCESS;
}
*/
/*
* Settings to bake for the standalone decompressor.
+ *
+ * Note: It's important that none of these affects 'zstd.h' (only the
+ * implementation files we're amalgamating).
*/
#define DEBUGLEVEL 0
#define XXH_NAMESPACE ZSTD_
#define ZSTD_LIB_COMPRESSION 0
#define ZSTD_LIB_DEPRECATED 0
#define ZSTD_NOBENCH
-#define ZSTD_STATIC_LINKING_ONLY
#define ZSTD_STRIP_ERROR_STRINGS
#include "debug.c"