| 1 | /* |
| 2 | * Copyright (c) Yann Collet, Meta Platforms, Inc. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This source code is licensed under both the BSD-style license (found in the |
| 6 | * LICENSE file in the root directory of this source tree) and the GPLv2 (found |
| 7 | * in the COPYING file in the root directory of this source tree). |
| 8 | * You may select, at your option, one of the above-listed licenses. |
| 9 | */ |
| 10 | |
| 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
| 13 | #include <string.h> |
| 14 | #include <assert.h> |
| 15 | |
| 16 | #define ZSTD_STATIC_LINKING_ONLY |
| 17 | #include "zstd.h" |
| 18 | #include "zstd_errors.h" |
| 19 | #include "sequence_producer.h" // simpleSequenceProducer |
| 20 | |
| 21 | #define CHECK(res) \ |
| 22 | do { \ |
| 23 | if (ZSTD_isError(res)) { \ |
| 24 | printf("ERROR: %s\n", ZSTD_getErrorName(res)); \ |
| 25 | return 1; \ |
| 26 | } \ |
| 27 | } while (0) \ |
| 28 | |
| 29 | int main(int argc, char *argv[]) { |
| 30 | if (argc != 2) { |
| 31 | printf("Usage: externalSequenceProducer <file>\n"); |
| 32 | return 1; |
| 33 | } |
| 34 | |
| 35 | ZSTD_CCtx* const zc = ZSTD_createCCtx(); |
| 36 | |
| 37 | int simpleSequenceProducerState = 0xdeadbeef; |
| 38 | |
| 39 | // Here is the crucial bit of code! |
| 40 | ZSTD_registerSequenceProducer( |
| 41 | zc, |
| 42 | &simpleSequenceProducerState, |
| 43 | simpleSequenceProducer |
| 44 | ); |
| 45 | |
| 46 | { |
| 47 | size_t const res = ZSTD_CCtx_setParameter(zc, ZSTD_c_enableSeqProducerFallback, 1); |
| 48 | CHECK(res); |
| 49 | } |
| 50 | |
| 51 | FILE *f = fopen(argv[1], "rb"); |
| 52 | assert(f); |
| 53 | { |
| 54 | int const ret = fseek(f, 0, SEEK_END); |
| 55 | assert(ret == 0); |
| 56 | } |
| 57 | size_t const srcSize = ftell(f); |
| 58 | { |
| 59 | int const ret = fseek(f, 0, SEEK_SET); |
| 60 | assert(ret == 0); |
| 61 | } |
| 62 | |
| 63 | char* const src = malloc(srcSize + 1); |
| 64 | assert(src); |
| 65 | { |
| 66 | size_t const ret = fread(src, srcSize, 1, f); |
| 67 | assert(ret == 1); |
| 68 | int const ret2 = fclose(f); |
| 69 | assert(ret2 == 0); |
| 70 | } |
| 71 | |
| 72 | size_t const dstSize = ZSTD_compressBound(srcSize); |
| 73 | char* const dst = malloc(dstSize); |
| 74 | assert(dst); |
| 75 | |
| 76 | size_t const cSize = ZSTD_compress2(zc, dst, dstSize, src, srcSize); |
| 77 | CHECK(cSize); |
| 78 | |
| 79 | char* const val = malloc(srcSize); |
| 80 | assert(val); |
| 81 | |
| 82 | { |
| 83 | size_t const res = ZSTD_decompress(val, srcSize, dst, cSize); |
| 84 | CHECK(res); |
| 85 | } |
| 86 | |
| 87 | if (memcmp(src, val, srcSize) == 0) { |
| 88 | printf("Compression and decompression were successful!\n"); |
| 89 | printf("Original size: %lu\n", srcSize); |
| 90 | printf("Compressed size: %lu\n", cSize); |
| 91 | } else { |
| 92 | printf("ERROR: input and validation buffers don't match!\n"); |
| 93 | for (size_t i = 0; i < srcSize; i++) { |
| 94 | if (src[i] != val[i]) { |
| 95 | printf("First bad index: %zu\n", i); |
| 96 | break; |
| 97 | } |
| 98 | } |
| 99 | return 1; |
| 100 | } |
| 101 | |
| 102 | ZSTD_freeCCtx(zc); |
| 103 | free(src); |
| 104 | free(dst); |
| 105 | free(val); |
| 106 | return 0; |
| 107 | } |