FU::Util: Add brotli_compress() and use it for FU output compression

Seems to compresses and perform better than libdeflate at level 6, so
certainly worth using.
This commit is contained in:
Yorhel 2025-03-19 10:12:06 +01:00
parent bc33fe53f0
commit 6159b33950
5 changed files with 99 additions and 14 deletions

View file

@ -124,5 +124,38 @@ static SV *fugz_compress(pTHX_ IV level, SV *in) {
if (fugz_imp == 1) return fugz_compress_ld(aTHX_ level, bytes, inlen);
else return fugz_compress_zlib(aTHX_ level, bytes, inlen);
return &PL_sv_undef;
}
/* Brotli */
typedef enum { BROTLI_MODE_GENERIC = 0, BROTLI_MODE_TEXT = 1, BROTLI_MODE_FONT = 2 } BrotliEncoderMode;
static size_t (*BrotliEncoderMaxCompressedSize)(size_t);
static int (*BrotliEncoderCompress)(int, int, BrotliEncoderMode, size_t, const char *, size_t *, char *);
static SV *fubr_compress(pTHX_ IV level, SV *in) {
if (!BrotliEncoderCompress) {
void *handle;
if (!(handle = dlopen("libbrotlienc.so", RTLD_LAZY))
|| !(BrotliEncoderMaxCompressedSize = dlsym(handle, "BrotliEncoderMaxCompressedSize"))
|| !(BrotliEncoderCompress = dlsym(handle, "BrotliEncoderCompress")))
fu_confess("Unable to load libbrotlienc.so: %s", dlerror());
}
if (level < 0 || level > 11) fu_confess("Invalid compression level: %"IVdf, level);
STRLEN inlen;
const char *bytes = SvPVbyte(in, inlen);
size_t outlen = BrotliEncoderMaxCompressedSize(inlen);
/* "Result is only valid if quality is at least 2", so let's use a (more conservative?) fallback */
if (level < 2 && outlen < inlen + 256) outlen = inlen + 256;
SV *out = sv_2mortal(newSV(outlen));
SvPOK_only(out);
if (!BrotliEncoderCompress(level, 22, BROTLI_MODE_GENERIC, inlen, bytes, &outlen, SvPVX(out)))
fu_confess("Brotli compression failed");
SvCUR_set(out, outlen);
return out;
}