diff --git a/cmake/files.cmake b/cmake/files.cmake index cebc946..107fe1c 100644 --- a/cmake/files.cmake +++ b/cmake/files.cmake @@ -10,7 +10,11 @@ set(libfrogfs_INC ) if ("${CONFIG_FROGFS_USE_DEFLATE}" STREQUAL "y") - list(APPEND libfrogfs_SRC ${frogfs_DIR}/src/decomp_deflate.c) + if(ESP_PLATFORM) + list(APPEND libfrogfs_SRC ${frogfs_DIR}/src/decomp_miniz_deflate.c) + else() + list(APPEND libfrogfs_SRC ${frogfs_DIR}/src/decomp_zlib_deflate.c) + endif() endif() if ("${CONFIG_FROGFS_USE_HEATSHRINK}" STREQUAL "y") diff --git a/idf_component.yml b/idf_component.yml index 3547dda..bf1947a 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -4,4 +4,3 @@ url: https://github.com/jkent/frogfs dependencies: idf: version: ">=5.0.0" - zlib: "~1.2" diff --git a/src/decomp_heatshrink.c b/src/decomp_heatshrink.c index b5f881e..29fc336 100644 --- a/src/decomp_heatshrink.c +++ b/src/decomp_heatshrink.c @@ -137,20 +137,20 @@ static ssize_t seek_heatshrink(frogfs_fh_t *f, long offset, int mode) return -1; } - if (PRIV(f)->file_pos > new_pos) { + if (new_pos < PRIV(f)->file_pos) { f->data_ptr = f->data_start; PRIV(f)->file_pos = 0; heatshrink_decoder_reset(PRIV(f)->hsd); } - while (PRIV(f)->file_pos < new_pos) { + while (new_pos > PRIV(f)->file_pos) { uint8_t buf[BUFFER_LEN]; size_t len = new_pos - PRIV(f)->file_pos < BUFFER_LEN ? new_pos - PRIV(f)->file_pos : BUFFER_LEN; ssize_t res = frogfs_read(f, buf, len); if (res < 0) { - LOGE("frogfs_fread"); + LOGE("frogfs_read"); return -1; } } diff --git a/src/decomp_miniz_deflate.c b/src/decomp_miniz_deflate.c new file mode 100644 index 0000000..b8650c7 --- /dev/null +++ b/src/decomp_miniz_deflate.c @@ -0,0 +1,165 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "log.h" +#include "frogfs_priv.h" +#include "frogfs_format.h" +#include "frogfs/frogfs.h" + +#include "miniz.h" + +#include +#include +#include +#include +#include +#include + + +#define BUFFER_LEN 16 + +typedef struct { + tinfl_decompressor inflator; + uint8_t buf[TINFL_LZ_DICT_SIZE]; + size_t buf_pos; + size_t buf_len; + size_t out_pos; +} priv_data_t; + +static int open_deflate(frogfs_fh_t *f, unsigned int flags) +{ + priv_data_t *priv = malloc(sizeof(priv_data_t)); + if (priv == NULL) { + LOGE("malloc failed"); + return -1; + } + + tinfl_init(&priv->inflator); + priv->buf_pos = 0; + priv->buf_len = 0; + priv->out_pos = 0; + f->decomp_priv = priv; + return 0; +} + +static void close_deflate(frogfs_fh_t *f) +{ + priv_data_t *priv = f->decomp_priv; + free(priv); + f->decomp_priv = NULL; +} + +static ssize_t read_deflate(frogfs_fh_t *f, void *buf, size_t len) +{ + priv_data_t *priv = f->decomp_priv; + tinfl_status status; + size_t start_len = len; + size_t in_bytes; + size_t out_bytes; + + while (len) { + size_t chunk = len < priv->buf_len - priv->buf_pos ? len : + priv->buf_len - priv->buf_pos; + memcpy(buf, priv->buf + priv->buf_pos, chunk); + priv->buf_pos += chunk; + priv->out_pos += chunk; + buf += chunk; + len -= chunk; + + if (priv->buf_len == priv->buf_pos) { + priv->buf_len = 0; + priv->buf_pos = 0; + } + + in_bytes = f->data_sz - (f->data_ptr - f->data_start); + out_bytes = sizeof(priv->buf) - priv->buf_len; + status = tinfl_decompress(&priv->inflator, f->data_ptr, &in_bytes, + priv->buf, &priv->buf[priv->buf_len], &out_bytes, + TINFL_FLAG_PARSE_ZLIB_HEADER); + f->data_ptr += in_bytes; + priv->buf_len += out_bytes; + + if (status < TINFL_STATUS_DONE) { + LOGE("tinfl_decompress"); + return -1; + } + + if (priv->buf_len - priv->buf_pos == 0) { + break; + } + } + + return start_len - len; +} + +static ssize_t seek_deflate(frogfs_fh_t *f, long offset, int mode) +{ + priv_data_t *priv = f->decomp_priv; + const frogfs_comp_t *comp = (const void *) f->file; + ssize_t new_pos = priv->out_pos; + + if (mode == SEEK_SET) { + if (offset < 0) { + return -1; + } + if (offset > comp->real_sz) { + offset = comp->real_sz; + } + new_pos = offset; + } else if (mode == SEEK_CUR) { + if (new_pos + offset < 0) { + new_pos = 0; + } else if (new_pos > comp->real_sz) { + new_pos = comp->real_sz; + } else { + new_pos += offset; + } + } else if (mode == SEEK_END) { + if (offset > 0) { + return -1; + } + if (offset < -(ssize_t) comp->real_sz) { + offset = 0; + } + new_pos = comp->real_sz + offset; + } else { + return -1; + } + + if (new_pos < priv->out_pos) { + f->data_ptr = f->data_start; + tinfl_init(&priv->inflator); + priv->buf_len = 0; + priv->buf_pos = 0; + priv->out_pos = 0; + } + + while (new_pos > priv->out_pos) { + uint8_t buf[BUFFER_LEN]; + size_t len = new_pos - priv->out_pos < BUFFER_LEN ? + new_pos - priv->out_pos : BUFFER_LEN; + + ssize_t res = frogfs_read(f, buf, len); + if (res < 0) { + LOGE("frogfs_read"); + return -1; + } + } + + return priv->out_pos; +} + +static size_t tell_deflate(frogfs_fh_t *f) +{ + priv_data_t *priv = f->decomp_priv; + return priv->out_pos; +} + +const frogfs_decomp_funcs_t frogfs_decomp_deflate = { + .open = open_deflate, + .close = close_deflate, + .read = read_deflate, + .seek = seek_deflate, + .tell = tell_deflate, +}; diff --git a/src/decomp_deflate.c b/src/decomp_zlib_deflate.c similarity index 96% rename from src/decomp_deflate.c rename to src/decomp_zlib_deflate.c index a92fcea..a71143f 100644 --- a/src/decomp_deflate.c +++ b/src/decomp_zlib_deflate.c @@ -117,19 +117,19 @@ static ssize_t seek_deflate(frogfs_fh_t *f, long offset, int mode) return -1; } - if (STREAM(f)->total_out > new_pos) { + if (new_pos < STREAM(f)->total_out) { f->data_ptr = f->data_start; inflateReset(STREAM(f)); } - while (STREAM(f)->total_out < new_pos) { + while (new_pos > STREAM(f)->total_out) { uint8_t buf[BUFFER_LEN]; size_t len = new_pos - STREAM(f)->total_out < BUFFER_LEN ? new_pos - STREAM(f)->total_out : BUFFER_LEN; ssize_t res = frogfs_read(f, buf, len); if (res < 0) { - LOGE("frogfs_fread"); + LOGE("frogfs_read"); return -1; } }