📄 compress_lzma.cpp
字号:
// FIXME: tune these settings according to level switch (level) { case 1: pr[3].uintVal = 256 * 1024; pr[4].uintVal = 0; pr[5].uintVal = 8; break; case 2: pr[3].uintVal = 256 * 1024; pr[4].uintVal = 0; break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: break; case 8: break; case 9: pr[3].uintVal = 8 * 1024 * 1024; break; case 10: pr[3].uintVal = src_len; break; default: goto error; } // cconf overrides if (lcconf) { oassign(pr[0].uintVal, lcconf->pos_bits); oassign(pr[1].uintVal, lcconf->lit_pos_bits); oassign(pr[2].uintVal, lcconf->lit_context_bits); oassign(pr[3].uintVal, lcconf->dict_size); oassign(pr[5].uintVal, lcconf->num_fast_bytes); } // limit dictionary size if (pr[3].uintVal > src_len) pr[3].uintVal = src_len; // limit num_probs if (lcconf && lcconf->max_num_probs) { for (;;) { unsigned n = 1846 + (768 << (pr[2].uintVal + pr[1].uintVal)); if (n <= lcconf->max_num_probs) break; if (pr[1].uintVal > pr[2].uintVal) { if (pr[1].uintVal == 0) goto error; pr[1].uintVal -= 1; } else { if (pr[2].uintVal == 0) goto error; pr[2].uintVal -= 1; } } } res->pos_bits = pr[0].uintVal; res->lit_pos_bits = pr[1].uintVal; res->lit_context_bits = pr[2].uintVal; res->dict_size = pr[3].uintVal; res->fast_mode = pr[4].uintVal; res->num_fast_bytes = pr[5].uintVal; res->match_finder_cycles = pr[6].uintVal; //res->num_probs = LzmaGetNumProbs(&s.Properties)); //res->num_probs = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) res->num_probs = 1846 + (768 << (res->lit_context_bits + res->lit_pos_bits)); //printf("\nlzma_compress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs);#ifndef _NO_EXCEPTIONS try {#else# error#endif if (enc.SetCoderProperties(propIDs, pr, nprops) != S_OK) goto error; if (enc.WriteCoderProperties(&os) != S_OK) goto error; if (os.overflow) { //r = UPX_E_OUTPUT_OVERRUN; r = UPX_E_NOT_COMPRESSIBLE; goto error; } assert(os.b_pos == 5);#if defined(USE_LZMA_PROPERTIES) os.b_pos = 1;#else os.b_pos = 0; // extra stuff in first byte: 5 high bits convenience for stub decompressor unsigned t = res->lit_context_bits + res->lit_pos_bits; os.WriteByte((t << 3) | res->pos_bits); os.WriteByte((res->lit_pos_bits << 4) | (res->lit_context_bits));#endif rh = enc.Code(&is, &os, NULL, NULL, &progress);#ifndef _NO_EXCEPTIONS } catch (...) { rh = E_OUTOFMEMORY; }#endif assert(is.b_pos <= src_len); assert(os.b_pos <= *dst_len); if (rh == E_OUTOFMEMORY) r = UPX_E_OUT_OF_MEMORY; else if (os.overflow) { assert(os.b_pos == *dst_len); //r = UPX_E_OUTPUT_OVERRUN; r = UPX_E_NOT_COMPRESSIBLE; } else if (rh == S_OK) { assert(is.b_pos == src_len); r = UPX_E_OK; }error: *dst_len = os.b_pos; //printf("\nlzma_compress: %d: %u %u %u %u %u, %u - > %u\n", r, res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs, src_len, *dst_len); //printf("%u %u %u\n", is.__m_RefCount, os.__m_RefCount, progress.__m_RefCount); return r;}/*************************************************************************// decompress**************************************************************************/#undef _LZMA_IN_CB#undef _LZMA_OUT_READ#undef _LZMA_PROB32#undef _LZMA_LOC_OPT#if (WITH_LZMA >= 0x449)# include "C/Compress/Lzma/LzmaDecode.h"# include "C/Compress/Lzma/LzmaDecode.c"#else# include "C/7zip/Compress/LZMA_C/LzmaDecode.h"# include "C/7zip/Compress/LZMA_C/LzmaDecode.c"#endifint upx_lzma_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, const upx_compress_result_t *cresult ){ assert(M_IS_LZMA(method)); // see res->num_probs above COMPILE_TIME_ASSERT(sizeof(CProb) == 2) COMPILE_TIME_ASSERT(LZMA_BASE_SIZE == 1846) COMPILE_TIME_ASSERT(LZMA_LIT_SIZE == 768) CLzmaDecoderState s; memset(&s, 0, sizeof(s)); SizeT src_out = 0, dst_out = 0; int r = UPX_E_ERROR; int rh;#if defined(USE_LZMA_PROPERTIES) if (src_len < 2) goto error; rh = LzmaDecodeProperties(&s.Properties, src, src_len); if (rh != 0) goto error; src += 1; src_len -= 1;#else if (src_len < 3) goto error; s.Properties.pb = src[0] & 7; s.Properties.lp = (src[1] >> 4); s.Properties.lc = src[1] & 15; if (s.Properties.pb >= 5) goto error; if (s.Properties.lp >= 5) goto error; if (s.Properties.lc >= 9) goto error; // extra if ((src[0] >> 3) != s.Properties.lc + s.Properties.lp) goto error; src += 2; src_len -= 2;#endif if (cresult) { assert(cresult->method == method); assert(cresult->result_lzma.pos_bits == (unsigned) s.Properties.pb); assert(cresult->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp); assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc); assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties)); const lzma_compress_result_t *res = &cresult->result_lzma; UNUSED(res); //printf("\nlzma_decompress config: %u %u %u %u %u\n", res->pos_bits, res->lit_pos_bits, res->lit_context_bits, res->dict_size, res->num_probs); } s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties)); if (!s.Probs) { r = UPX_E_OUT_OF_MEMORY; goto error; } rh = LzmaDecode(&s, src, src_len, &src_out, dst, *dst_len, &dst_out); assert(src_out <= src_len); assert(dst_out <= *dst_len); if (rh == 0) { r = UPX_E_OK; if (src_out != src_len) r = UPX_E_INPUT_NOT_CONSUMED; }error: *dst_len = dst_out; free(s.Probs); UNUSED(cresult); return r;}/*************************************************************************// test_overlap - see <ucl/ucl.h> for semantics**************************************************************************/int upx_lzma_test_overlap ( const upx_bytep buf, const upx_bytep tbuf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, const upx_compress_result_t *cresult ){ assert(M_IS_LZMA(method)); MemBuffer b(src_off + src_len); memcpy(b + src_off, buf + src_off, src_len); unsigned saved_dst_len = *dst_len; int r = upx_lzma_decompress(b + src_off, src_len, b, dst_len, method, cresult); if (r != UPX_E_OK) return r; if (*dst_len != saved_dst_len) return UPX_E_ERROR; // NOTE: there is a very tiny possibility that decompression has // succeeded but the data is not restored correctly because of // in-place buffer overlapping. if (tbuf != NULL && memcmp(tbuf, b, *dst_len) != 0) return UPX_E_ERROR; return UPX_E_OK;}/*************************************************************************// misc**************************************************************************/const char *upx_lzma_version_string(void){#if (WITH_LZMA == 0x449) return "4.49";#elif (WITH_LZMA == 0x443) return "4.43";#else# error "unknown version" return NULL;#endif}#endif /* WITH_LZMA *//*vi:ts=4:et:nowrap*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -