fix: Add framebuffer release/realloc and improved lazy indexing (#2563)
This commit is contained in:
+22
-22
@@ -1,13 +1,12 @@
|
||||
#include "ZipFile.h"
|
||||
|
||||
#include <HalStorage.h>
|
||||
#include <InflateReader.h>
|
||||
#include <InflateStream.h>
|
||||
#include <Logging.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
struct ZipInflateCtx {
|
||||
InflateReader reader; // Must be first — callback casts uzlib_uncomp* to ZipInflateCtx*
|
||||
HalFile* file = nullptr;
|
||||
size_t fileRemaining = 0;
|
||||
uint8_t* readBuf = nullptr;
|
||||
@@ -40,19 +39,16 @@ class ScopedOpenClose final {
|
||||
bool ok = true; // true when zip was already open (no open() call needed)
|
||||
};
|
||||
|
||||
int zipReadCallback(uzlib_uncomp* uncomp) {
|
||||
auto* ctx = reinterpret_cast<ZipInflateCtx*>(uncomp);
|
||||
if (ctx->fileRemaining == 0) return -1;
|
||||
size_t zipFillCallback(void* vctx, const uint8_t** data) {
|
||||
auto* ctx = static_cast<ZipInflateCtx*>(vctx);
|
||||
if (ctx->fileRemaining == 0) return 0;
|
||||
|
||||
const size_t toRead = ctx->fileRemaining < ctx->readBufSize ? ctx->fileRemaining : ctx->readBufSize;
|
||||
const size_t bytesRead = ctx->file->read(ctx->readBuf, toRead);
|
||||
ctx->fileRemaining -= bytesRead;
|
||||
|
||||
if (bytesRead == 0) return -1;
|
||||
|
||||
uncomp->source = ctx->readBuf + 1;
|
||||
uncomp->source_limit = ctx->readBuf + bytesRead;
|
||||
return ctx->readBuf[0];
|
||||
*data = ctx->readBuf;
|
||||
return bytesRead;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -410,15 +406,18 @@ uint8_t* ZipFile::readFileToMemory(const char* filename, size_t* size, const boo
|
||||
ctx.readBuf = fileReadBuffer;
|
||||
ctx.readBufSize = 1024;
|
||||
|
||||
if (!ctx.reader.init(true)) {
|
||||
LOG_ERR("ZIP", "Failed to init inflate reader");
|
||||
// One-shot mode: `data` holds the entire output, so back-references
|
||||
// resolve inside it and no 32KB window is allocated.
|
||||
InflateStream inflate;
|
||||
if (!inflate.init(false)) {
|
||||
LOG_ERR("ZIP", "Failed to init inflate stream");
|
||||
free(fileReadBuffer);
|
||||
free(data);
|
||||
return nullptr;
|
||||
}
|
||||
ctx.reader.setReadCallback(zipReadCallback);
|
||||
inflate.setFill(zipFillCallback, &ctx);
|
||||
|
||||
if (!ctx.reader.read(data, inflatedDataSize)) {
|
||||
if (!inflate.read(data, inflatedDataSize)) {
|
||||
LOG_ERR("ZIP", "Failed to inflate file");
|
||||
free(fileReadBuffer);
|
||||
free(data);
|
||||
@@ -501,20 +500,21 @@ bool ZipFile::readFileToStream(const char* filename, Print& out, const size_t ch
|
||||
ctx.readBuf = fileReadBuffer;
|
||||
ctx.readBufSize = chunkSize;
|
||||
|
||||
if (!ctx.reader.init(true)) {
|
||||
LOG_ERR("ZIP", "Failed to init inflate reader");
|
||||
InflateStream inflate;
|
||||
if (!inflate.init(true)) {
|
||||
LOG_ERR("ZIP", "Failed to init inflate stream");
|
||||
free(outputBuffer);
|
||||
free(fileReadBuffer);
|
||||
return false;
|
||||
}
|
||||
ctx.reader.setReadCallback(zipReadCallback);
|
||||
inflate.setFill(zipFillCallback, &ctx);
|
||||
|
||||
bool success = false;
|
||||
size_t totalProduced = 0;
|
||||
|
||||
while (true) {
|
||||
size_t produced;
|
||||
const InflateStatus status = ctx.reader.readAtMost(outputBuffer, chunkSize, &produced);
|
||||
const InflateStream::Status status = inflate.readAtMost(outputBuffer, chunkSize, &produced);
|
||||
|
||||
totalProduced += produced;
|
||||
if (totalProduced > static_cast<size_t>(inflatedDataSize)) {
|
||||
@@ -530,7 +530,7 @@ bool ZipFile::readFileToStream(const char* filename, Print& out, const size_t ch
|
||||
}
|
||||
}
|
||||
|
||||
if (status == InflateStatus::Done) {
|
||||
if (status == InflateStream::Status::Done) {
|
||||
if (totalProduced != static_cast<size_t>(inflatedDataSize)) {
|
||||
LOG_ERR("ZIP", "Decompressed size mismatch (expected %zu, got %zu)", static_cast<size_t>(inflatedDataSize),
|
||||
totalProduced);
|
||||
@@ -541,16 +541,16 @@ bool ZipFile::readFileToStream(const char* filename, Print& out, const size_t ch
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == InflateStatus::Error) {
|
||||
if (status == InflateStream::Status::Error) {
|
||||
LOG_ERR("ZIP", "Decompression failed");
|
||||
break;
|
||||
}
|
||||
// InflateStatus::Ok: output buffer full, continue
|
||||
// InflateStream::Status::Ok: output buffer full, continue
|
||||
}
|
||||
|
||||
free(outputBuffer);
|
||||
free(fileReadBuffer);
|
||||
return success; // ctx.reader destructor frees the ring buffer
|
||||
return success; // inflate destructor frees the decompressor state + window
|
||||
}
|
||||
|
||||
LOG_ERR("ZIP", "Unsupported compression method");
|
||||
|
||||
Reference in New Issue
Block a user