1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+ OR Apache-2.0
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker * Copyright (C) 2018-2019 HUAWEI, Inc.
4*33b1fccfSAndroid Build Coastguard Worker * http://www.huawei.com/
5*33b1fccfSAndroid Build Coastguard Worker * Created by Gao Xiang <[email protected]>
6*33b1fccfSAndroid Build Coastguard Worker */
7*33b1fccfSAndroid Build Coastguard Worker #define LZ4_HC_STATIC_LINKING_ONLY (1)
8*33b1fccfSAndroid Build Coastguard Worker #include <lz4hc.h>
9*33b1fccfSAndroid Build Coastguard Worker #include "erofs/internal.h"
10*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
11*33b1fccfSAndroid Build Coastguard Worker #include "compressor.h"
12*33b1fccfSAndroid Build Coastguard Worker
13*33b1fccfSAndroid Build Coastguard Worker #ifndef LZ4_DISTANCE_MAX /* history window size */
14*33b1fccfSAndroid Build Coastguard Worker #define LZ4_DISTANCE_MAX 65535 /* set to maximum value by default */
15*33b1fccfSAndroid Build Coastguard Worker #endif
16*33b1fccfSAndroid Build Coastguard Worker
lz4hc_compress_destsize(const struct erofs_compress * c,const void * src,unsigned int * srcsize,void * dst,unsigned int dstsize)17*33b1fccfSAndroid Build Coastguard Worker static int lz4hc_compress_destsize(const struct erofs_compress *c,
18*33b1fccfSAndroid Build Coastguard Worker const void *src, unsigned int *srcsize,
19*33b1fccfSAndroid Build Coastguard Worker void *dst, unsigned int dstsize)
20*33b1fccfSAndroid Build Coastguard Worker {
21*33b1fccfSAndroid Build Coastguard Worker int srcSize = (int)*srcsize;
22*33b1fccfSAndroid Build Coastguard Worker int rc = LZ4_compress_HC_destSize(c->private_data, src, dst,
23*33b1fccfSAndroid Build Coastguard Worker &srcSize, (int)dstsize,
24*33b1fccfSAndroid Build Coastguard Worker c->compression_level);
25*33b1fccfSAndroid Build Coastguard Worker if (!rc)
26*33b1fccfSAndroid Build Coastguard Worker return -EFAULT;
27*33b1fccfSAndroid Build Coastguard Worker *srcsize = srcSize;
28*33b1fccfSAndroid Build Coastguard Worker return rc;
29*33b1fccfSAndroid Build Coastguard Worker }
30*33b1fccfSAndroid Build Coastguard Worker
compressor_lz4hc_exit(struct erofs_compress * c)31*33b1fccfSAndroid Build Coastguard Worker static int compressor_lz4hc_exit(struct erofs_compress *c)
32*33b1fccfSAndroid Build Coastguard Worker {
33*33b1fccfSAndroid Build Coastguard Worker if (!c->private_data)
34*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
35*33b1fccfSAndroid Build Coastguard Worker
36*33b1fccfSAndroid Build Coastguard Worker LZ4_freeStreamHC(c->private_data);
37*33b1fccfSAndroid Build Coastguard Worker return 0;
38*33b1fccfSAndroid Build Coastguard Worker }
39*33b1fccfSAndroid Build Coastguard Worker
compressor_lz4hc_init(struct erofs_compress * c)40*33b1fccfSAndroid Build Coastguard Worker static int compressor_lz4hc_init(struct erofs_compress *c)
41*33b1fccfSAndroid Build Coastguard Worker {
42*33b1fccfSAndroid Build Coastguard Worker c->private_data = LZ4_createStreamHC();
43*33b1fccfSAndroid Build Coastguard Worker if (!c->private_data)
44*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
45*33b1fccfSAndroid Build Coastguard Worker
46*33b1fccfSAndroid Build Coastguard Worker c->sbi->lz4.max_distance = max_t(u16, c->sbi->lz4.max_distance,
47*33b1fccfSAndroid Build Coastguard Worker LZ4_DISTANCE_MAX);
48*33b1fccfSAndroid Build Coastguard Worker return 0;
49*33b1fccfSAndroid Build Coastguard Worker }
50*33b1fccfSAndroid Build Coastguard Worker
compressor_lz4hc_setlevel(struct erofs_compress * c,int compression_level)51*33b1fccfSAndroid Build Coastguard Worker static int compressor_lz4hc_setlevel(struct erofs_compress *c,
52*33b1fccfSAndroid Build Coastguard Worker int compression_level)
53*33b1fccfSAndroid Build Coastguard Worker {
54*33b1fccfSAndroid Build Coastguard Worker if (compression_level > erofs_compressor_lz4hc.best_level) {
55*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid compression level %d", compression_level);
56*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
57*33b1fccfSAndroid Build Coastguard Worker }
58*33b1fccfSAndroid Build Coastguard Worker
59*33b1fccfSAndroid Build Coastguard Worker c->compression_level = compression_level < 0 ?
60*33b1fccfSAndroid Build Coastguard Worker LZ4HC_CLEVEL_DEFAULT : compression_level;
61*33b1fccfSAndroid Build Coastguard Worker return 0;
62*33b1fccfSAndroid Build Coastguard Worker }
63*33b1fccfSAndroid Build Coastguard Worker
64*33b1fccfSAndroid Build Coastguard Worker const struct erofs_compressor erofs_compressor_lz4hc = {
65*33b1fccfSAndroid Build Coastguard Worker .default_level = LZ4HC_CLEVEL_DEFAULT,
66*33b1fccfSAndroid Build Coastguard Worker .best_level = LZ4HC_CLEVEL_MAX,
67*33b1fccfSAndroid Build Coastguard Worker .init = compressor_lz4hc_init,
68*33b1fccfSAndroid Build Coastguard Worker .exit = compressor_lz4hc_exit,
69*33b1fccfSAndroid Build Coastguard Worker .setlevel = compressor_lz4hc_setlevel,
70*33b1fccfSAndroid Build Coastguard Worker .compress_destsize = lz4hc_compress_destsize,
71*33b1fccfSAndroid Build Coastguard Worker };
72