luat_lib_miniz.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. @module miniz
  3. @summary 简易zlib压缩
  4. @version 1.0
  5. @date 2022.8.11
  6. @tag LUAT_USE_MINIZ
  7. @usage
  8. -- 准备好数据
  9. local bigdata = "123jfoiq4hlkfjbnasdilfhuqwo;hfashfp9qw38hrfaios;hfiuoaghfluaeisw"
  10. -- 压缩之, 压缩得到的数据是zlib兼容的,其他语言可通过zlib相关的库进行解压
  11. local cdata = miniz.compress(bigdata)
  12. -- lua 的 字符串相当于有长度的char[],可存放包括0x00的一切数据
  13. if cdata then
  14. -- 检查压缩前后的数据大小
  15. log.info("miniz", "before", #bigdata, "after", #cdata)
  16. log.info("miniz", "cdata as hex", cdata:toHex())
  17. -- 解压, 得到原文
  18. local udata = miniz.uncompress(cdata)
  19. log.info("miniz", "udata", udata)
  20. end
  21. */
  22. #include "luat_base.h"
  23. #include "luat_mem.h"
  24. #define LUAT_LOG_TAG "miniz"
  25. #include "luat_log.h"
  26. #include "miniz.h"
  27. static mz_bool luat_output_buffer_putter(const void *pBuf, int len, void *pUser) {
  28. luaL_addlstring((luaL_Buffer*)pUser, pBuf, len);
  29. return MZ_TRUE;
  30. }
  31. /*
  32. 快速压缩,需要165kb的系统内存和32kb的LuaVM内存
  33. @api miniz.compress(data, flags)
  34. @string 待压缩的数据, 少于400字节的数据不建议压缩, 且压缩后的数据不能大于32k.
  35. @flags 压缩参数,默认是 miniz.WRITE_ZLIB_HEADER , 即写入zlib头部
  36. @return string 若压缩成功,返回数据字符串, 否则返回nil
  37. @usage
  38. local bigdata = "123jfoiq4hlkfjbnasdilfhuqwo;hfashfp9qw38hrfaios;hfiuoaghfluaeisw"
  39. local cdata = miniz.compress(bigdata)
  40. if cdata then
  41. log.info("miniz", "before", #bigdata, "after", #cdata)
  42. log.info("miniz", "cdata as hex", cdata:toHex())
  43. end
  44. */
  45. static int l_miniz_compress(lua_State* L) {
  46. size_t len = 0;
  47. tdefl_compressor *pComp;
  48. mz_bool succeeded;
  49. const char* data = luaL_checklstring(L, 1, &len);
  50. int flags = luaL_optinteger(L, 2, TDEFL_WRITE_ZLIB_HEADER);
  51. if (len > 32* 1024) {
  52. LLOGE("only 32k data is allow");
  53. return 0;
  54. }
  55. luaL_Buffer buff;
  56. if (NULL == luaL_buffinitsize(L, &buff, 4096)) {
  57. LLOGE("out of memory when malloc dst buff");
  58. return 0;
  59. }
  60. pComp = (tdefl_compressor *)luat_heap_malloc(sizeof(tdefl_compressor));
  61. if (!pComp) {
  62. LLOGE("out of memory when malloc tdefl_compressor size 0x%04X", sizeof(tdefl_compressor));
  63. return 0;
  64. }
  65. succeeded = (tdefl_init(pComp, luat_output_buffer_putter, &buff, flags) == TDEFL_STATUS_OKAY);
  66. succeeded = succeeded && (tdefl_compress_buffer(pComp, data, len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
  67. luat_heap_free(pComp);
  68. if (!succeeded) {
  69. LLOGW("compress fail ret=0");
  70. return 0;
  71. }
  72. luaL_pushresult(&buff);
  73. return 1;
  74. }
  75. /*
  76. 快速解压,需要32kb的LuaVM内存
  77. @api miniz.uncompress(data, flags)
  78. @string 待解压的数据, 解压后的数据不能大于32k
  79. @flags 解压参数,默认是 miniz.PARSE_ZLIB_HEADER , 即解析zlib头部
  80. @return string 若解压成功,返回数据字符串, 否则返回nil
  81. @usage
  82. local bigdata = "123jfoiq4hlkfjbnasdilfhuqwo;hfashfp9qw38hrfaios;hfiuoaghfluaeisw"
  83. local cdata = miniz.compress(bigdata)
  84. if cdata then
  85. log.info("miniz", "before", #bigdata, "after", #cdata)
  86. log.info("miniz", "cdata as hex", cdata:toHex())
  87. local udata = miniz.uncompress(cdata)
  88. log.info("miniz", "udata", udata)
  89. end
  90. */
  91. static int l_miniz_uncompress(lua_State* L) {
  92. size_t len = 0;
  93. const char* data = luaL_checklstring(L, 1, &len);
  94. int flags = luaL_optinteger(L, 2, TINFL_FLAG_PARSE_ZLIB_HEADER);
  95. if (len > 32* 1024) {
  96. LLOGE("only 32k data is allow");
  97. return 0;
  98. }
  99. luaL_Buffer buff;
  100. char* dst = luaL_buffinitsize(L, &buff, TDEFL_OUT_BUF_SIZE);
  101. if (dst == NULL) {
  102. LLOGE("out of memory when malloc dst buff");
  103. return 0;
  104. }
  105. size_t out_buf_len = TDEFL_OUT_BUF_SIZE;
  106. tinfl_status status;
  107. tinfl_decompressor *decomp = luat_heap_malloc(sizeof(tinfl_decompressor));
  108. if (decomp == NULL) {
  109. LLOGE("out of memory when malloc tinfl_decompressor");
  110. return 0;
  111. }
  112. tinfl_init(decomp);
  113. status = tinfl_decompress(decomp, (const mz_uint8 *)data, &len, (mz_uint8 *)dst, (mz_uint8 *)dst, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
  114. size_t ret = (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
  115. luat_heap_free(decomp);
  116. if (ret == TINFL_DECOMPRESS_MEM_TO_MEM_FAILED) {
  117. LLOGW("decompress fail");
  118. return 0;
  119. }
  120. luaL_pushresultsize(&buff, ret);
  121. return 1;
  122. }
  123. #include "rotable2.h"
  124. static const rotable_Reg_t reg_miniz[] = {
  125. {"compress", ROREG_FUNC(l_miniz_compress)},
  126. {"uncompress", ROREG_FUNC(l_miniz_uncompress)},
  127. // {"inflate", ROREG_FUNC(l_miniz_inflate)},
  128. // {"deflate", ROREG_FUNC(l_miniz_deflate)},
  129. // 放些常量
  130. // 压缩参数-------------------------
  131. //@const WRITE_ZLIB_HEADER int 压缩参数,是否写入zlib头部数据,compress函数的默认值
  132. {"WRITE_ZLIB_HEADER", ROREG_INT(TDEFL_WRITE_ZLIB_HEADER)},
  133. //@const COMPUTE_ADLER32 int 压缩/解压参数,是否计算/校验adler-32
  134. {"COMPUTE_ADLER32", ROREG_INT(TDEFL_COMPUTE_ADLER32)},
  135. //@const GREEDY_PARSING_FLAG int 压缩参数,是否快速greedy处理, 默认使用较慢的处理模式
  136. {"GREEDY_PARSING_FLAG", ROREG_INT(TDEFL_GREEDY_PARSING_FLAG)},
  137. //@const NONDETERMINISTIC_PARSING_FLAG int 压缩参数,是否快速初始化压缩器
  138. {"NONDETERMINISTIC_PARSING_FLAG", ROREG_INT(TDEFL_NONDETERMINISTIC_PARSING_FLAG)},
  139. //@const RLE_MATCHES int 压缩参数, 仅扫描RLE
  140. {"RLE_MATCHES", ROREG_INT(TDEFL_RLE_MATCHES)},
  141. //@const FILTER_MATCHES int 压缩参数,过滤少于5次的字符
  142. {"FILTER_MATCHES", ROREG_INT(TDEFL_FILTER_MATCHES)},
  143. //@const FORCE_ALL_STATIC_BLOCKS int 压缩参数,是否禁用优化过的Huffman表
  144. {"FORCE_ALL_STATIC_BLOCKS", ROREG_INT(TDEFL_FORCE_ALL_STATIC_BLOCKS)},
  145. //@const FORCE_ALL_RAW_BLOCKS int 压缩参数,是否只要raw块
  146. {"FORCE_ALL_RAW_BLOCKS", ROREG_INT(TDEFL_FORCE_ALL_RAW_BLOCKS)},
  147. // 解压参数
  148. //@const PARSE_ZLIB_HEADER int 解压参数,是否处理zlib头部,uncompress函数的默认值
  149. {"PARSE_ZLIB_HEADER", ROREG_INT(TINFL_FLAG_PARSE_ZLIB_HEADER)},
  150. //@const HAS_MORE_INPUT int 解压参数,是否还有更多数据,仅流式解压可用,暂不支持
  151. {"HAS_MORE_INPUT", ROREG_INT(TINFL_FLAG_HAS_MORE_INPUT)},
  152. //@const USING_NON_WRAPPING_OUTPUT_BUF int 解压参数,解压区间是否够全部数据,,仅流式解压可用,暂不支持
  153. {"USING_NON_WRAPPING_OUTPUT_BUF", ROREG_INT(TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)},
  154. //@const COMPUTE_ADLER32 int 解压参数,是否强制校验adler-32
  155. // {"COMPUTE_ADLER32", ROREG_INT(TINFL_FLAG_COMPUTE_ADLER32)},
  156. {NULL, ROREG_INT(0)}
  157. };
  158. LUAMOD_API int luaopen_miniz( lua_State *L ) {
  159. luat_newlib2(L, reg_miniz);
  160. return 1;
  161. }