summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-05-10 00:22:22 +0800
committerruki <[email protected]>2022-05-10 00:22:22 +0800
commit4fa936e0e4fa0ace1d00e7b2966950d63946d643 (patch)
tree8ce3b16e66d4cd84718ac400279b79281a649346
parent6f789c9db16eadf5c81b63221cddff59988da465 (diff)
decompress file
-rw-r--r--core/src/xmake/lz4/decompress_file.c61
-rw-r--r--core/src/xmake/lz4/prefix.h95
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