diff options
| author | ruki <[email protected]> | 2022-05-10 00:22:22 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2022-05-10 00:22:22 +0800 |
| commit | 4fa936e0e4fa0ace1d00e7b2966950d63946d643 (patch) | |
| tree | 8ce3b16e66d4cd84718ac400279b79281a649346 | |
| parent | 6f789c9db16eadf5c81b63221cddff59988da465 (diff) | |
decompress file
| -rw-r--r-- | core/src/xmake/lz4/decompress_file.c | 61 | ||||
| -rw-r--r-- | core/src/xmake/lz4/prefix.h | 95 |
2 files changed, 140 insertions, 16 deletions
diff --git a/core/src/xmake/lz4/decompress_file.c b/core/src/xmake/lz4/decompress_file.c index 62d0a0b8b..758d39275 100644 --- a/core/src/xmake/lz4/decompress_file.c +++ b/core/src/xmake/lz4/decompress_file.c @@ -15,14 +15,14 @@ * Copyright (C) 2015-present, TBOOX Open Source Group. * * @author ruki - * @file decompress_file.c + * @file dedecompress_file.c * */ /* ////////////////////////////////////////////////////////////////////////////////////// * trace */ -#define TB_TRACE_MODULE_NAME "decompress_file" +#define TB_TRACE_MODULE_NAME "dedecompress_file" #define TB_TRACE_MODULE_DEBUG (0) /* ////////////////////////////////////////////////////////////////////////////////////// @@ -38,6 +38,61 @@ tb_int_t xm_lz4_decompress_file(lua_State* lua) // check tb_assert_and_check_return_val(lua, 0); - return 0; + // get the file paths + tb_char_t const* srcpath = luaL_checkstring(lua, 1); + tb_char_t const* dstpath = luaL_checkstring(lua, 2); + tb_check_return_val(srcpath && dstpath, 0); + + // init lz4 stream + xm_lz4_stream_t stream_lz4; + xm_lz4_stream_init(&stream_lz4); + + // do decompress + tb_bool_t ok = tb_false; + tb_stream_ref_t istream = tb_stream_init_from_file(srcpath, TB_FILE_MODE_RO); + tb_stream_ref_t ostream = tb_stream_init_from_file(dstpath, TB_FILE_MODE_RW | TB_FILE_MODE_CREAT | TB_FILE_MODE_TRUNC); + if (istream && ostream && tb_stream_open(istream) && tb_stream_open(ostream)) + { + tb_bool_t write_ok = tb_false; + tb_byte_t idata[TB_STREAM_BLOCK_MAXN]; + while (!tb_stream_beof(istream)) + { + write_ok = tb_false; + tb_int_t ireal = (tb_int_t)tb_stream_read(istream, idata, sizeof(idata)); + if (ireal > 0) + { + tb_byte_t* odata = tb_null; + tb_int_t oreal = xm_lz4_stream_decompress(&stream_lz4, idata, ireal, &odata); + tb_assert_and_check_break(oreal >= 0 && odata); + if (oreal > 0) + { + if (!tb_stream_bwrit(ostream, odata, oreal)) + break; + } + } + else break; + write_ok = tb_true; + } + + if (tb_stream_beof(istream) && write_ok) + ok = tb_true; + } + + // exit stream + if (istream) + { + tb_stream_exit(istream); + istream = tb_null; + } + if (ostream) + { + tb_stream_exit(ostream); + ostream = tb_null; + } + xm_lz4_stream_exit(&stream_lz4); + + // ok? + lua_pushboolean(lua, ok); + return 1; } diff --git a/core/src/xmake/lz4/prefix.h b/core/src/xmake/lz4/prefix.h index b88dfbbfe..0cf8e9b00 100644 --- a/core/src/xmake/lz4/prefix.h +++ b/core/src/xmake/lz4/prefix.h @@ -1,12 +1,12 @@ /*!A cross-platform build utility based on Lua * * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. + * you may not use this file except idata compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software + * Unless required by applicable law or agreed to idata writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and @@ -45,13 +45,14 @@ // the lz4 stream type typedef struct __xm_lz4_stream_t { - tb_byte_t buffer[TB_STREAM_BLOCK_MAXN]; - tb_int_t buffer_size; - tb_int_t buffer_position; - tb_byte_t* output; - tb_int_t output_maxn; - tb_int_t accelerate; - LZ4_stream_t handle; + tb_byte_t buffer[TB_STREAM_BLOCK_MAXN]; + tb_int_t buffer_size; + tb_int_t buffer_position; + tb_byte_t* output; + tb_int_t output_maxn; + tb_int_t accelerate; + LZ4_stream_t encoder; + LZ4_streamDecode_t decoder; }xm_lz4_stream_t; /* ////////////////////////////////////////////////////////////////////////////////////// @@ -68,6 +69,23 @@ static __tb_inline__ tb_int_t xm_lz4_stream_buffer_policy(tb_int_t buffer_size, return LZ4_STREAM_BUFFER_POLICY_RESET; } +static __tb_inline__ tb_void_t xm_lz4_stream_buffer_save_dict(xm_lz4_stream_t* stream, tb_char_t const* dict, tb_int_t dict_size) +{ + tb_int_t limit_len = LZ4_STREAM_DICTSIZE; + if (limit_len > stream->buffer_size) + limit_len = stream->buffer_size; + + if (dict_size > limit_len) + { + dict += dict_size - limit_len; + dict_size = limit_len; + } + + tb_memmov(stream->buffer, dict, dict_size); + LZ4_setStreamDecode(&stream->decoder, (tb_char_t*)stream->buffer, dict_size); + stream->buffer_position = dict_size; +} + static __tb_inline__ tb_void_t xm_lz4_stream_init(xm_lz4_stream_t* stream) { stream->accelerate = 1; @@ -75,7 +93,8 @@ static __tb_inline__ tb_void_t xm_lz4_stream_init(xm_lz4_stream_t* stream) stream->buffer_size = sizeof(stream->buffer); stream->output = tb_null; stream->output_maxn = 0; - LZ4_resetStream(&stream->handle); + LZ4_resetStream(&stream->encoder); + LZ4_setStreamDecode(&stream->decoder, tb_null, 0); } static __tb_inline__ tb_void_t xm_lz4_stream_exit(xm_lz4_stream_t* stream) @@ -119,20 +138,70 @@ static __tb_inline__ tb_int_t xm_lz4_stream_compress(xm_lz4_stream_t* stream, tb stream->buffer_position = isize; } tb_memcpy(buffer, idata, isize); - real = LZ4_compress_fast_continue(&stream->handle, (tb_char_t*)buffer, (tb_char_t*)stream->output, isize, bound, stream->accelerate); + real = LZ4_compress_fast_continue(&stream->encoder, (tb_char_t*)buffer, (tb_char_t*)stream->output, isize, bound, stream->accelerate); tb_assert_and_check_return_val(real > 0, -1); } else { - real = LZ4_compress_fast_continue(&stream->handle, (tb_char_t*)idata, (tb_char_t*)stream->output, isize, bound, stream->accelerate); + real = LZ4_compress_fast_continue(&stream->encoder, (tb_char_t*)idata, (tb_char_t*)stream->output, isize, bound, stream->accelerate); tb_assert_and_check_return_val(real > 0, -1); - stream->buffer_position = LZ4_saveDict(&stream->handle, (tb_char_t*)stream->buffer, stream->buffer_size); + stream->buffer_position = LZ4_saveDict(&stream->encoder, (tb_char_t*)stream->buffer, stream->buffer_size); } *podata = stream->output; return real; } +static __tb_inline__ tb_int_t xm_lz4_stream_decompress(xm_lz4_stream_t* stream, tb_byte_t const* idata, tb_int_t isize, tb_byte_t** podata) +{ + // check + tb_assert_and_check_return_val(stream && idata && isize && podata, -1); + + // ensure the output buffer + tb_int_t bound = isize << 2; + if (bound > 0 && bound > stream->output_maxn) + { + if (!stream->output) stream->output = tb_malloc_bytes(bound); + else stream->output = (tb_byte_t*)tb_ralloc(stream->output, bound); + stream->output_maxn = bound; + } + tb_assert_and_check_return_val(stream->output && stream->output_maxn > 0, -1); + + // do decompress + tb_int_t real = -1; + tb_int_t policy = xm_lz4_stream_buffer_policy(stream->buffer_size, stream->buffer_position, isize); + if (policy == LZ4_STREAM_BUFFER_POLICY_APPEND || policy == LZ4_STREAM_BUFFER_POLICY_RESET) + { + tb_byte_t* buffer; + tb_size_t new_position; + if (policy == LZ4_STREAM_BUFFER_POLICY_APPEND) + { + buffer = stream->buffer + stream->buffer_position; + new_position = stream->buffer_position + bound; + } + else + { + buffer = stream->buffer; + new_position = bound; + } + real = LZ4_decompress_safe_continue(&stream->decoder, (tb_char_t*)idata, (tb_char_t*)buffer, isize, bound); + tb_assert_and_check_return_val(real >= 0, -1); + stream->buffer_position = new_position; + + *podata = buffer; + } + else + { + real = LZ4_decompress_safe_continue(&stream->decoder, (tb_char_t*)idata, (tb_char_t*)stream->output, isize, bound); + tb_assert_and_check_return_val(real >= 0, -1); + + xm_lz4_stream_buffer_save_dict(stream, (tb_char_t*)stream->output, real); + + *podata = stream->output; + } + return real; +} + #endif |
