feat(util): add ZlibDecompress

This commit is contained in:
fallenoak 2026-01-08 22:05:25 -06:00
parent f183ee172c
commit 424b2c5227
No known key found for this signature in database
GPG Key ID: 7628F8E61AEA070D
3 changed files with 96 additions and 0 deletions

View File

@ -28,6 +28,8 @@ target_link_libraries(util
common
storm
tempest
PRIVATE
zlib-1.2
)
if(WHOA_SYSTEM_LINUX OR WHOA_SYSTEM_MAC)

76
src/util/Zlib.cpp Normal file
View File

@ -0,0 +1,76 @@
#include "util/Zlib.hpp"
#include <storm/Error.hpp>
#include <storm/Memory.hpp>
#include <zlib.h>
int zlib_uncompress(Bytef* dest, uInt* destLen, const Bytef* source, uInt sourceLen) {
char buffer[47000];
ZlibAllocBufferHeader header = { buffer, sizeof(buffer), buffer };
z_stream strm;
strm.next_in = const_cast<Bytef*>(source);
strm.avail_in = sourceLen;
strm.next_out = dest;
strm.avail_out = *destLen;
strm.zalloc = &ZlibAlloc;
strm.zfree = &ZlibFree;
strm.opaque = &header;
auto err = inflateInit(&strm);
if (err != Z_OK) {
return err;
}
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) {
*destLen = strm.total_out;
return inflateEnd(&strm);
}
inflateEnd(&strm);
return err ? err : Z_BUF_ERROR;
}
void* ZlibAlloc(void* opaque, uint32_t items, uint32_t size) {
auto buffer = static_cast<ZlibAllocBufferHeader*>(opaque);
STORM_ASSERT(buffer);
uint32_t total = items * size;
// Align to 4 bytes
if ((total & 3) != 0) {
total = (total & ~3) + 4;
}
auto ptr = buffer->nextPtr;
size_t used = buffer->nextPtr - buffer->bufStart;
size_t remaining = buffer->bufSize - used;
// Fall back to heap if stack allocated buffer is exhausted
if (total >= remaining) {
return STORM_ALLOC(total);
}
buffer->nextPtr = ptr + total;
return ptr;
}
void ZlibFree(void* opaque, void* ptr) {
auto* buffer = static_cast<ZlibAllocBufferHeader*>(opaque);
auto bufferStart = buffer->bufStart;
auto bufferEnd = buffer->bufStart + buffer->bufSize;
// Only free if pointer is outside of stack allocated buffer
if (ptr < bufferStart || ptr >= bufferEnd) {
STORM_FREE(ptr);
}
}
int32_t ZlibDecompress(void* dest, uint32_t* destLen, const void* source, uint32_t sourceLen) {
return zlib_uncompress(
static_cast<Bytef*>(dest),
destLen,
static_cast<const Bytef*>(source),
sourceLen
);
}

18
src/util/Zlib.hpp Normal file
View File

@ -0,0 +1,18 @@
#ifndef UTIL_ZLIB_HPP
#define UTIL_ZLIB_HPP
#include <cstdint>
struct ZlibAllocBufferHeader {
char* nextPtr;
uint32_t bufSize;
char* bufStart;
};
void* ZlibAlloc(void* opaque, uint32_t items, uint32_t size);
int32_t ZlibDecompress(void* dest, uint32_t* destLen, const void* source, uint32_t sourceLen);
void ZlibFree(void* opaque, void* ptr);
#endif