src: update MemBuffer::getSizeForCompression()

This commit is contained in:
Markus F.X.J. Oberhumer 2023-08-21 22:32:28 +02:00
parent 38be230467
commit dd928cf956

View File

@ -96,51 +96,19 @@ void *MemBuffer::subref_impl(const char *errfmt, size_t skip, size_t take) {
return ptr + skip;
}
static unsigned width(unsigned x) {
unsigned w = 0;
if ((~0u << 16) & x) {
w += 16;
x >>= 16;
}
if ((~0u << 8) & x) {
w += 8;
x >>= 8;
}
if ((~0u << 4) & x) {
w += 4;
x >>= 4;
}
if ((~0u << 2) & x) {
w += 2;
x >>= 2;
}
if ((~0u << 1) & x) {
w += 1;
// x >>= 1;
}
return 1 + w;
}
static forceinline size_t umax(size_t a, size_t b) { return (a >= b) ? a : b; }
unsigned MemBuffer::getSizeForCompression(unsigned uncompressed_size, unsigned extra) {
if (uncompressed_size == 0)
throwCantPack("invalid uncompressed_size");
const size_t z = uncompressed_size; // fewer keystrokes and display columns
const size_t w = umax(8, width(z - 1)); // ignore tiny offsets
size_t bytes = mem_size(1, z); // check size
// Worst matching: All match at max_offset, which implies 3==min_match
const size_t z = uncompressed_size; // fewer keystrokes and display columns
size_t bytes = mem_size(1, z); // check size
// All literal: 1 bit overhead per literal byte; from UCL documentation
bytes = umax(bytes, z + z / 8 + 256);
// NRV2B: 1 byte plus 2 bits per width exceeding 8 ("ss11")
bytes = umax(bytes, (z / 3 * (8 + 2 * (w - 8) / 1)) / 8);
// NRV2E: 1 byte plus 3 bits per pair of width exceeding 7 ("ss12")
bytes = umax(bytes, (z / 3 * (8 + 3 * (w - 7) / 2)) / 8);
// zstd: ZSTD_COMPRESSBOUND
bytes = umax(bytes, z + (z >> 8) + ((z < (128 << 10)) ? (((128 << 10) - z) >> 11) : 0));
// add extra and 256 safety for various rounding/alignments
bytes = mem_size(1, bytes, extra, 256);
UNUSED(w);
return ACC_ICONV(unsigned, bytes);
}
@ -345,8 +313,10 @@ TEST_CASE("MemBuffer::getSizeForCompression") {
CHECK(MemBuffer::getSizeForCompression(1) == 513);
CHECK(MemBuffer::getSizeForCompression(256) == 800);
CHECK(MemBuffer::getSizeForCompression(1024) == 1664);
// CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 0); // TODO
// CHECK(MemBuffer::getSizeForCompression(UPX_RSIZE_MAX) == 0); // TODO
CHECK(MemBuffer::getSizeForCompression(1024 * 1024) == 1180160); // 0x00100000
CHECK(MemBuffer::getSizeForCompression(64 * 1024 * 1024) == 75497984); // 0x04000000
CHECK(MemBuffer::getSizeForCompression(512 * 1024 * 1024) == 603980288); // 0x20000000
CHECK(MemBuffer::getSizeForCompression(640 * 1024 * 1024) == 754975232); // 0x28000000
}
/* vim:set ts=4 sw=4 et: */