Educational Decoder
===================
-`zstd_decompress.c` is a self-contained implementation of a decoder according
-to the Zstandard format specification written in C99.
+`zstd_decompress.c` is a self-contained implementation in C99 of a decoder,
+according to the [Zstandard format specification].
While it does not implement as many features as the reference decoder,
such as the streaming API or content checksums, it is written to be easy to
follow and understand, to help understand how the Zstandard format works.
It's laid out to match the [format specification],
-so it can be used to understand how confusing segments could be implemented.
+so it can be used to understand how complex segments could be implemented.
It also contains implementations of Huffman and FSE table decoding.
+[Zstandard format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
[format specification]: https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
`harness.c` provides a simple test harness around the decoder:
+/*
+ * Copyright (c) 2017-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
/// Zstandard educational decoder implementation
/// See https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md
size_t ZSTD_get_decompressed_size(const void *src, size_t src_len);
/******* UTILITY MACROS AND TYPES *********************************************/
-#define MAX_WINDOW_SIZE ((size_t)512 << 20)
+// Specification recommends supporting at least 8MB. The maximum possible value
+// is 1.875TB, but this implementation limits it to 512MB to avoid allocating
+// too much memory.
+#define MAX_WINDOW_SIZE ((size_t)512 * 1024 * 1024)
// Max block size decompressed size is 128 KB and literal blocks must be smaller
// than that
-#define MAX_LITERALS_SIZE ((size_t)(1024 * 128))
+#define MAX_LITERALS_SIZE ((size_t)128 * 1024)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
dtable->num_bits = malloc(size * sizeof(u8));
dtable->new_state_base = malloc(size * sizeof(u16));
+ if (!dtable->symbols || !dtable->num_bits || !dtable->new_state_base) {
+ BAD_ALLOC();
+ }
+
// Used to determine how many bits need to be read for each state,
// and where the destination range should start
// Needs to be u16 because max value is 2 * max number of symbols,
dtable->num_bits = malloc(sizeof(u8));
dtable->new_state_base = malloc(sizeof(u16));
+ if (!dtable->symbols || !dtable->num_bits || !dtable->new_state_base) {
+ BAD_ALLOC();
+ }
+
// This setup will always have a state of 0, always return symbol `symb`,
// and never consume any bits
dtable->symbols[0] = symb;
+/*
+ * Copyright (c) 2017-present, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ */
+
size_t ZSTD_decompress(void *dst, size_t dst_len, const void *src,
size_t src_len);
size_t ZSTD_decompress_with_dict(void *dst, size_t dst_len, const void *src,