DataBuffer ZLibCompression::compress(const DataBuffer &data, bool raw, int compression_level, CompressionMode mode) { const int window_bits = 15; DataBuffer zbuffer(1024*1024); IODevice_Memory output; int strategy = MZ_DEFAULT_STRATEGY; switch (mode) { case default_strategy: strategy = MZ_DEFAULT_STRATEGY; break; case filtered: strategy = MZ_FILTERED; break; case huffman_only: strategy = MZ_HUFFMAN_ONLY; break; case rle: strategy = MZ_RLE; break; case fixed: strategy = MZ_FIXED; break; } mz_stream zs = { nullptr }; int result = mz_deflateInit2(&zs, compression_level, MZ_DEFLATED, raw ? -window_bits : window_bits, 8, strategy); // Undocumented: if wbits is negative, zlib skips header check if (result != MZ_OK) throw Exception("Zlib deflateInit failed"); try { zs.next_in = (unsigned char *) data.get_data(); zs.avail_in = data.get_size(); while (true) { zs.next_out = (unsigned char *) zbuffer.get_data(); zs.avail_out = zbuffer.get_size(); int result = mz_deflate(&zs, MZ_FINISH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib deflate failed while compressing zip file!"); int zsize = zbuffer.get_size() - zs.avail_out; if (zsize == 0) break; output.write(zbuffer.get_data(), zsize); if (result == MZ_STREAM_END) break; } mz_deflateEnd(&zs); } catch (...) { mz_deflateEnd(&zs); throw; } return output.get_data(); }
~ZipWriter_Impl() { if (file_begun && compress) { mz_deflateEnd(&zs); } }
void ZipWriter::end_file() { if (!impl->file_begun) return; if (impl->compress) { impl->zs.next_in = nullptr; impl->zs.avail_in = 0; while (true) { impl->zs.next_out = (unsigned char *)impl->zbuffer; impl->zs.avail_out = 16 * 1024; int result = mz_deflate(&impl->zs, MZ_FINISH); if (result == MZ_NEED_DICT) throw Exception("Zlib deflate wants a dictionary!"); if (result == MZ_DATA_ERROR) throw Exception("Zip data stream is corrupted"); if (result == MZ_STREAM_ERROR) throw Exception("Zip stream structure was inconsistent!"); if (result == MZ_MEM_ERROR) throw Exception("Zlib did not have enough memory to compress file!"); if (result == MZ_BUF_ERROR) throw Exception("Not enough data in buffer when Z_FINISH was used"); if (result != MZ_OK && result != MZ_STREAM_END) throw Exception("Zlib deflate failed while compressing zip file!"); int64_t zsize = 16 * 1024 - impl->zs.avail_out; if (zsize == 0) break; impl->output.write(impl->zbuffer, zsize); impl->compressed_length += zsize; if (result == MZ_STREAM_END) break; } mz_deflateEnd(&impl->zs); impl->compress = false; } impl->local_header.uncompressed_size = impl->uncompressed_length; impl->local_header.compressed_size = impl->compressed_length; impl->local_header.crc32 = ZipArchive_Impl::calc_crc32(nullptr, 0, impl->crc32, true); int64_t current_offset = impl->output.get_position(); impl->output.seek(impl->local_header_offset); impl->local_header.save(impl->output); impl->output.seek(current_offset); ZipWriter_Impl::FileEntry file_entry; file_entry.local_header = impl->local_header; file_entry.local_header_offset = impl->local_header_offset; impl->written_files.push_back(file_entry); impl->file_begun = false; }
static int lmz_deflator_gc(lua_State* L) { lmz_stream_t* stream = luaL_checkudata(L, 1, "miniz_deflator"); mz_deflateEnd(&(stream->stream)); return 0; }