bool inno_lzma1_decompressor_impl::filter(const char * & begin_in, const char * end_in, char * & begin_out, char * end_out, bool flush) { // Decode the header. if(!stream) { // Read enough bytes to decode the header. while(nread != 5) { if(begin_in == end_in) { return true; } header[nread++] = *begin_in++; } lzma_options_lzma options; uint8_t properties = uint8_t(header[0]); if(properties > (9 * 5 * 5)) { throw lzma_error("inno lzma1 property error", LZMA_FORMAT_ERROR); } options.pb = properties / (9 * 5); options.lp = (properties % (9 * 5)) / 9; options.lc = properties % 9; options.dict_size = 0; for(size_t i = 0; i < 4; i++) { options.dict_size += uint32_t(uint8_t(header[i + 1])) << (i * 8); } stream = init_raw_lzma_stream(LZMA_FILTER_LZMA1, options); } return lzma_decompressor_impl_base::filter(begin_in, end_in, begin_out, end_out, flush); }
bool inno_lzma2_decompressor_impl::filter(const char * & begin_in, const char * end_in, char * & begin_out, char * end_out, bool flush) { // Decode the header. if(!stream) { if(begin_in == end_in) { return true; } lzma_options_lzma options; uint8_t prop = uint8_t(*begin_in++); if(prop > 40) { throw lzma_error("inno lzma2 property error", LZMA_FORMAT_ERROR); } if(prop == 40) { options.dict_size = 0xffffffff; } else { options.dict_size = ((uint32_t(2) | uint32_t((prop) & 1)) << ((prop) / 2 + 11)); } stream = init_raw_lzma_stream(LZMA_FILTER_LZMA2, options); } return lzma_decompressor_impl_base::filter(begin_in, end_in, begin_out, end_out, flush); }
void lzma_error::check( int error ) { switch ( error ) { case LZMA_OK: case LZMA_STREAM_END: return; case LZMA_MEM_ERROR: throw std::bad_alloc(); default: throw lzma_error( error ); } }
static lzma_stream * init_raw_lzma_stream(lzma_vli filter, lzma_options_lzma & options) { options.preset_dict = NULL; if(options.dict_size > (uint32_t(1) << 28)) { throw lzma_error("inno lzma dict size too large", LZMA_FORMAT_ERROR); } lzma_stream * strm = new lzma_stream; lzma_stream tmp = LZMA_STREAM_INIT; *strm = tmp; strm->allocator = NULL; const lzma_filter filters[2] = { { filter, &options }, { LZMA_VLI_UNKNOWN, NULL } }; lzma_ret ret = lzma_raw_decoder(strm, filters); if(ret != LZMA_OK) { delete strm; throw lzma_error("inno lzma init error", ret); } return strm; }
Array<uint8_t> compress(RawArray<const uint8_t> data, int level, event_t event) { thread_time_t time(compress_kind,event); if (level<20) { // zlib size_t dest_size = compressBound(data.size()); Array<uint8_t> compressed(CHECK_CAST_INT(dest_size),uninit); int z = compress2(compressed.data(),&dest_size,(uint8_t*)data.data(),data.size(),level); if (z!=Z_OK) THROW(IOError,"zlib failure in compress_and_write: %s",zlib_error(z)); return compressed.slice_own(0,CHECK_CAST_INT(dest_size)); } else { // lzma size_t dest_size = lzma_stream_buffer_bound(data.size()); Array<uint8_t> compressed(CHECK_CAST_INT(dest_size),uninit); size_t pos = 0; lzma_ret r = lzma_easy_buffer_encode(level-20,LZMA_CHECK_CRC64,0,data.data(),data.size(),compressed.data(),&pos,dest_size); if (r!=LZMA_OK) THROW(RuntimeError,"lzma compression error: %s (%d)",lzma_error(r),r); return compressed.slice_own(0,CHECK_CAST_INT(pos)); } }
Array<uint8_t> decompress(RawArray<const uint8_t> compressed, const size_t uncompressed_size, event_t event) { GEODE_ASSERT(uncompressed_size<(uint64_t)1<<31); thread_time_t time(decompress_kind,event); size_t dest_size = uncompressed_size; Array<uint8_t> uncompressed = aligned_buffer<uint8_t>(CHECK_CAST_INT(dest_size)); if (!is_lzma(compressed)) { // zlib int z = uncompress((uint8_t*)uncompressed.data(),&dest_size,compressed.data(),compressed.size()); if (z!=Z_OK) THROW(IOError,"zlib failure in read_and_uncompress: %s",zlib_error(z)); } else { // lzma const uint32_t flags = LZMA_TELL_NO_CHECK | LZMA_TELL_UNSUPPORTED_CHECK; uint64_t memlimit = UINT64_MAX; size_t in_pos = 0, out_pos = 0; lzma_ret r = lzma_stream_buffer_decode(&memlimit,flags,0,compressed.data(),&in_pos,compressed.size(),uncompressed.data(),&out_pos,dest_size); if (r!=LZMA_OK) THROW(IOError,"lzma failure in read_and_uncompress: %s (%d)",lzma_error(r),r); } if (dest_size != uncompressed_size) THROW(IOError,"read_and_compress: expected uncompressed size %zu, got %zu",uncompressed_size,dest_size); return uncompressed; }
bool lzma_decompressor_impl_base::filter(const char * & begin_in, const char * end_in, char * & begin_out, char * end_out, bool flush) { (void)flush; lzma_stream * strm = static_cast<lzma_stream *>(stream); strm->next_in = reinterpret_cast<const uint8_t *>(begin_in); strm->avail_in = size_t(end_in - begin_in); strm->next_out = reinterpret_cast<uint8_t *>(begin_out); strm->avail_out = size_t(end_out - begin_out); lzma_ret ret = lzma_code(strm, LZMA_RUN); begin_in = reinterpret_cast<const char *>(strm->next_in); begin_out = reinterpret_cast<char *>(strm->next_out); if(ret != LZMA_OK && ret != LZMA_STREAM_END && ret != LZMA_BUF_ERROR) { throw lzma_error("lzma decrompression error", ret); } return (ret != LZMA_STREAM_END); }