diff --git a/src/lib/compress.c b/src/lib/compress.c index a91f632..41b7282 100644 --- a/src/lib/compress.c +++ b/src/lib/compress.c @@ -13,23 +13,25 @@ int compress_init(compress_ctx *ctx, int mode) { ctx->brotli = NULL; - ctx->mode = 0; - int ret; + if (mode & COMPRESS_GZ) { ctx->mode |= COMPRESS_GZ; ctx->gzip.zalloc = Z_NULL; ctx->gzip.zfree = Z_NULL; ctx->gzip.opaque = Z_NULL; - ret = deflateInit2(&ctx->gzip, COMPRESS_LEVEL_GZIP, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY); - if (ret != Z_OK) return -1; + ctx->gzip.data_type = (mode & COMPRESS_UTF8) ? Z_TEXT : Z_UNKNOWN; + if (deflateInit2(&ctx->gzip, COMPRESS_LEVEL_GZIP, Z_DEFLATED, 15 + 16, 9, Z_DEFAULT_STRATEGY) != Z_OK) + return -1; } + if (mode & COMPRESS_BR) { ctx->mode |= COMPRESS_BR; - ctx->brotli = BrotliEncoderCreateInstance(NULL, NULL, NULL); - if (ctx->brotli == NULL) return -1; - BrotliEncoderSetParameter(ctx->brotli, BROTLI_PARAM_MODE, BROTLI_MODE_GENERIC); + if ((ctx->brotli = BrotliEncoderCreateInstance(NULL, NULL, NULL)) == NULL) + return -1; + BrotliEncoderSetParameter(ctx->brotli, BROTLI_PARAM_MODE, (mode & COMPRESS_UTF8) ? BROTLI_MODE_TEXT : ((mode & COMPRESS_WOFF) ? BROTLI_MODE_FONT : BROTLI_MODE_GENERIC)); BrotliEncoderSetParameter(ctx->brotli, BROTLI_PARAM_QUALITY, COMPRESS_LEVEL_BROTLI); } + return 0; } @@ -41,26 +43,35 @@ int compress_compress(compress_ctx *ctx, const char *in, unsigned long *in_len, return compress_compress_mode(ctx, ctx->mode, in, in_len, out, out_len, finish); } +static int compress_brotli(BrotliEncoderState *ctx, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish) { + int ret = BrotliEncoderCompressStream( + ctx, finish ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS, + in_len, (const unsigned char**) &in, out_len, (unsigned char **) &out, NULL); + return (ret == BROTLI_TRUE) ? 0 : -1; +} + +static int compress_gzip(z_stream *gzip, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish) { + gzip->next_in = (unsigned char*) in; + gzip->avail_in = *in_len; + gzip->next_out = (unsigned char*) out; + gzip->avail_out = *out_len; + int ret = deflate(gzip, finish ? Z_FINISH : Z_NO_FLUSH); + *in_len = gzip->avail_in; + *out_len = gzip->avail_out; + return ret; +} + int compress_compress_mode(compress_ctx *ctx, int mode, const char *in, unsigned long *in_len, char *out, unsigned long *out_len, int finish) { if ((mode & COMPRESS_GZ) && (mode & COMPRESS_BR)) { errno = EINVAL; return -1; } else if (mode & COMPRESS_GZ) { - ctx->gzip.next_in = (unsigned char*) in; - ctx->gzip.avail_in = *in_len; - ctx->gzip.next_out = (unsigned char*) out; - ctx->gzip.avail_out = *out_len; - int ret = deflate(&ctx->gzip, finish ? Z_FINISH : Z_NO_FLUSH); - *in_len = ctx->gzip.avail_in; - *out_len = ctx->gzip.avail_out; - return ret; + return compress_gzip(&ctx->gzip, in, in_len, out, out_len, finish); } else if (mode & COMPRESS_BR) { - int ret = BrotliEncoderCompressStream(ctx->brotli, finish ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS, - in_len, (const unsigned char**) &in, out_len, (unsigned char **) &out, NULL); - return (ret == BROTLI_TRUE) ? 0 : -1; + return compress_brotli(ctx->brotli, in, in_len, out, out_len, finish); } else { errno = EINVAL; - return -2; + return -1; } } diff --git a/src/lib/compress.h b/src/lib/compress.h index e9db34a..4b1a83b 100644 --- a/src/lib/compress.h +++ b/src/lib/compress.h @@ -18,6 +18,8 @@ #define COMPRESS_GZ 1 #define COMPRESS_BR 2 #define COMPRESS 3 +#define COMPRESS_UTF8 4 +#define COMPRESS_WOFF 8 typedef struct { int mode;