static void squash_brotli_stream_init (SquashBrotliStream* s, SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options, SquashDestroyNotify destroy_notify) { SquashStream* stream = (SquashStream*) s; squash_stream_init (stream, codec, stream_type, (SquashOptions*) options, destroy_notify); s->finished = false; if (stream_type == SQUASH_STREAM_COMPRESS) { brotli::BrotliParams params; params.quality = squash_options_get_int_at (stream->options, stream->codec, SQUASH_BROTLI_OPT_LEVEL); params.mode = (brotli::BrotliParams::Mode) squash_options_get_int_at (stream->options, stream->codec, SQUASH_BROTLI_OPT_MODE); s->compressor = new brotli::BrotliCompressor (params); s->remaining_block_in = s->compressor->input_block_size(); s->remaining_out = 0; s->next_out = NULL; s->should_flush = false; s->should_seal = false; } else if (stream_type == SQUASH_STREAM_DECOMPRESS) { s->decompressor = BrotliCreateState(squash_brotli_malloc, squash_brotli_free, squash_codec_get_context (codec)); } else { squash_assert_unreachable(); } }
static SquashStatus squash_wflz_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { const char* codec_name = squash_codec_get_name (codec); const uint32_t swap = ((uint32_t) squash_options_get_int_at (options, codec, SQUASH_WFLZ_OPT_ENDIANNESS) != SQUASH_WFLZ_HOST_ORDER); const int level = squash_options_get_int_at (options, codec, SQUASH_WFLZ_OPT_LEVEL); #if UINT32_MAX < SIZE_MAX if (SQUASH_UNLIKELY(UINT32_MAX < uncompressed_size)) return squash_error (SQUASH_RANGE); #endif if (*compressed_size < wfLZ_GetMaxCompressedSize ((uint32_t) uncompressed_size)) { return squash_error (SQUASH_BUFFER_FULL); } uint8_t* work_mem = (uint8_t*) malloc (wfLZ_GetWorkMemSize ()); uint32_t wres; if (codec_name[4] == '\0') { if (level == 1) { wres = wfLZ_CompressFast (uncompressed, (uint32_t) uncompressed_size, compressed, work_mem, swap); } else { wres = wfLZ_Compress (uncompressed, (uint32_t) uncompressed_size, compressed, work_mem, swap); } } else { wres = wfLZ_ChunkCompress ((uint8_t*) uncompressed, (uint32_t) uncompressed_size, squash_options_get_size_at (options, codec, SQUASH_WFLZ_OPT_CHUNK_SIZE), compressed, work_mem, swap, level == 1 ? 1 : 0); } #if SIZE_MAX < UINT32_MAX if (SQUASH_UNLIKELY(SIZE_MAX < wres)) { free (work_mem); return squash_error (SQUASH_RANGE); } #endif *compressed_size = (size_t) wres; free (work_mem); return SQUASH_LIKELY(*compressed_size > 0) ? SQUASH_OK : squash_error (SQUASH_FAILED); }
static SquashStatus squash_brotli_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { const int quality = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_LEVEL); const int lgwin = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_WINDOW_SIZE); const BrotliEncoderMode mode = (BrotliEncoderMode) squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_MODE); const int res = BrotliEncoderCompress (quality, lgwin, mode, uncompressed_size, uncompressed, compressed_size, compressed); return SQUASH_LIKELY(res == 1) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL); }
static SquashStatus squash_zling_splice (SquashCodec* codec, SquashOptions* options, SquashStreamType stream_type, SquashReadFunc read_cb, SquashWriteFunc write_cb, void* user_data) { try { SquashZlingIO stream(user_data, read_cb, write_cb); int zres = 0; if (stream_type == SQUASH_STREAM_COMPRESS) { zres = baidu::zling::Encode(&stream, &stream, NULL, squash_options_get_int_at (options, codec, SQUASH_ZLING_OPT_LEVEL)); } else { zres = baidu::zling::Decode(&stream, &stream, NULL); } if (zres == 0) return SQUASH_OK; else if (HEDLEY_LIKELY(stream.last_res < 0)) return stream.last_res; else return squash_error (SQUASH_FAILED); } catch (const std::bad_alloc& e) { return squash_error (SQUASH_MEMORY); } catch (const SquashStatus e) { return e; } catch (...) { return squash_error (SQUASH_FAILED); } HEDLEY_UNREACHABLE (); }
static SquashStatus squash_fastlz_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { #if INT_MAX < SIZE_MAX if (HEDLEY_UNLIKELY(INT_MAX < uncompressed_size) || HEDLEY_UNLIKELY(INT_MAX < *compressed_size)) return squash_error (SQUASH_RANGE); #endif const int fastlz_e = fastlz_compress_level (squash_options_get_int_at (options, codec, SQUASH_FASTLZ_OPT_LEVEL), (const void*) uncompressed, (int) uncompressed_size, (void*) compressed); #if SIZE_MAX < INT_MAX if (HEDLEY_UNLIKELY(SIZE_MAX < fastlz_e)) return squash_error (SQUASH_RANGE); #endif *compressed_size = (size_t) fastlz_e; return HEDLEY_UNLIKELY(fastlz_e == 0) ? squash_error (SQUASH_FAILED) : SQUASH_OK; }
static SquashStatus squash_zpaq_splice (SquashCodec* codec, SquashOptions* options, SquashStreamType stream_type, SquashReadFunc read_cb, SquashWriteFunc write_cb, void* user_data) { try { SquashZpaqIO stream(user_data, read_cb, write_cb); if (stream_type == SQUASH_STREAM_COMPRESS) { char level_s[3] = { 0, }; snprintf (level_s, sizeof(level_s), "%d", squash_options_get_int_at (options, codec, SQUASH_ZPAQ_OPT_LEVEL)); compress (&stream, &stream, level_s); } else { decompress (&stream, &stream); } } catch (const std::bad_alloc& e) { (void) e; return squash_error (SQUASH_MEMORY); } catch (const SquashStatus e) { return e; } catch (...) { return SQUASH_FAILED; } return SQUASH_OK; }
static SquashLZ4FStream* squash_lz4f_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) { SquashLZ4FStream* stream; LZ4F_errorCode_t ec; assert (codec != NULL); stream = (SquashLZ4FStream*) squash_malloc (sizeof (SquashLZ4FStream)); if (HEDLEY_UNLIKELY(stream == NULL)) return (squash_error (SQUASH_MEMORY), NULL); squash_lz4f_stream_init (stream, codec, stream_type, options, squash_lz4f_stream_destroy); if (stream_type == SQUASH_STREAM_COMPRESS) { ec = LZ4F_createCompressionContext(&(stream->data.comp.ctx), LZ4F_VERSION); stream->data.comp.state = SQUASH_LZ4F_STATE_INIT; stream->data.comp.output_buffer = NULL; stream->data.comp.output_buffer_pos = 0; stream->data.comp.output_buffer_size = 0; stream->data.comp.input_buffer_size = 0; stream->data.comp.prefs = (LZ4F_preferences_t) { { (LZ4F_blockSizeID_t) squash_options_get_int_at (options, codec, SQUASH_LZ4F_OPT_BLOCK_SIZE), blockLinked, squash_options_get_bool_at (options, codec, SQUASH_LZ4F_OPT_CHECKSUM) ? contentChecksumEnabled : noContentChecksum, }, squash_options_get_int_at (options, codec, SQUASH_LZ4F_OPT_LEVEL) }; } else { ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION); } if (HEDLEY_UNLIKELY(LZ4F_isError (ec))) { squash_object_unref (stream); return (squash_error (SQUASH_FAILED), NULL); } return stream; }
static SquashStatus squash_pithy_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { const int level = squash_options_get_int_at (options, codec, SQUASH_PITHY_OPT_LEVEL); *compressed_size = pithy_Compress ((const char*) uncompressed, uncompressed_size, (char*) compressed, *compressed_size, level); return (*compressed_size != 0) ? SQUASH_OK : SQUASH_FAILED; }
static void squash_brotli_stream_init (SquashBrotliStream* s, SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options, SquashDestroyNotify destroy_notify) { SquashStream* stream = (SquashStream*) s; squash_stream_init (stream, codec, stream_type, (SquashOptions*) options, destroy_notify); if (stream_type == SQUASH_STREAM_COMPRESS) { s->ctx.encoder = BrotliEncoderCreateInstance(squash_brotli_malloc, squash_brotli_free, NULL); BrotliEncoderSetParameter(s->ctx.encoder, BROTLI_PARAM_QUALITY, squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_LEVEL)); BrotliEncoderSetParameter(s->ctx.encoder, BROTLI_PARAM_LGWIN, squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_WINDOW_SIZE)); BrotliEncoderSetParameter(s->ctx.encoder, BROTLI_PARAM_LGBLOCK, squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_BLOCK_SIZE)); BrotliEncoderSetParameter(s->ctx.encoder, BROTLI_PARAM_MODE, squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_MODE)); } else if (stream_type == SQUASH_STREAM_DECOMPRESS) { s->ctx.decoder = BrotliCreateState(squash_brotli_malloc, squash_brotli_free, NULL); } else { squash_assert_unreachable(); } }
static SquashStatus squash_brotli_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { brotli::BrotliParams params; params.quality = squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_LEVEL); params.mode = (brotli::BrotliParams::Mode) squash_options_get_int_at (options, codec, SQUASH_BROTLI_OPT_MODE); try { int res = brotli::BrotliCompressBuffer (params, uncompressed_size, uncompressed, compressed_size, compressed); return SQUASH_LIKELY(res == 1) ? SQUASH_OK : squash_error (SQUASH_FAILED); } catch (const std::bad_alloc& e) { (void) e; return squash_error (SQUASH_MEMORY); } catch (...) { return squash_error (SQUASH_FAILED); } }
static SquashStatus squash_libdeflate_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { const int level = squash_options_get_int_at (options, codec, SQUASH_LIBDEFLATE_OPT_LEVEL); struct deflate_compressor *compressor = deflate_alloc_compressor(level); *compressed_size = deflate_compress(compressor, uncompressed, uncompressed_size, compressed, *compressed_size); deflate_free_compressor(compressor); return HEDLEY_LIKELY(*compressed_size != 0) ? SQUASH_OK : squash_error (SQUASH_BUFFER_FULL); }
static SquashStatus squash_bsc_compress_buffer_unsafe (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { const int lzp_hash_size = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_LZP_HASH_SIZE); const int lzp_min_len = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_LZP_MIN_LEN); const int block_sorter = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_BLOCK_SORTER); const int coder = squash_options_get_int_at (options, codec, SQUASH_BSC_OPT_CODER); const int features = squash_bsc_options_get_features (codec, options); #if INT_MAX < SIZE_MAX if (HEDLEY_UNLIKELY(INT_MAX < uncompressed_size)) return squash_error (SQUASH_RANGE); #endif if (HEDLEY_UNLIKELY(*compressed_size < (uncompressed_size + LIBBSC_HEADER_SIZE))) return squash_error (SQUASH_BUFFER_FULL); const int res = bsc_compress (uncompressed, compressed, (int) uncompressed_size, lzp_hash_size, lzp_min_len, block_sorter, coder, features); if (HEDLEY_UNLIKELY(res < 0)) { return squash_error (SQUASH_FAILED); } #if SIZE_MAX < INT_MAX if (HEDLEY_UNLIKELY(SIZE_MAX < res)) return squash_error (SQUASH_RANGE); #endif *compressed_size = (size_t) res; return SQUASH_OK; }
static SquashStatus squash_lzg_compress_buffer (SquashCodec* codec, size_t* compressed_size, uint8_t compressed[HEDLEY_ARRAY_PARAM(*compressed_size)], size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOptions* options) { lzg_encoder_config_t cfg = { squash_options_get_int_at (options, codec, SQUASH_LZG_OPT_LEVEL), squash_options_get_bool_at (options, codec, SQUASH_LZG_OPT_FAST), NULL, NULL }; #if UINT32_MAX < SIZE_MAX if (HEDLEY_UNLIKELY(UINT32_MAX < uncompressed_size) || HEDLEY_UNLIKELY(UINT32_MAX < *compressed_size)) return squash_error (SQUASH_RANGE); #endif uint8_t* workmem = squash_calloc (LZG_WorkMemSize (&cfg), 1); if (HEDLEY_UNLIKELY(workmem == NULL)) return squash_error (SQUASH_MEMORY); lzg_uint32_t res = LZG_EncodeFull ((const unsigned char*) uncompressed, (lzg_uint32_t) uncompressed_size, (unsigned char*) compressed, (lzg_uint32_t) *compressed_size, &cfg, workmem); squash_free (workmem); if (res == 0) { return squash_error (SQUASH_FAILED); } else { #if SIZE_MAX < UINT32_MAX if (HEDLEY_UNLIKELY(SIZE_MAX < res)) return squash_error (SQUASH_RANGE); #endif *compressed_size = (size_t) res; return SQUASH_OK; } }
static SquashStatus squash_csc_splice (SquashCodec* codec, SquashOptions* options, SquashStreamType stream_type, SquashReadFunc read_cb, SquashWriteFunc write_cb, void* user_data) { int csc_res; SquashStatus res = SQUASH_OK; const struct SquashCscInStream in_stream = { { squash_csc_reader }, user_data, read_cb, write_cb }; const struct SquashCscOutStream out_stream = { { squash_csc_writer }, user_data, read_cb, write_cb }; CSCProps props; unsigned char props_buf[CSC_PROP_SIZE]; if (stream_type == SQUASH_STREAM_COMPRESS) { CSCEncProps_Init (&props, squash_codec_get_option_size_index (codec, options, SQUASH_CSC_OPT_DICT_SIZE), squash_options_get_int_at (options, codec, SQUASH_CSC_OPT_LEVEL)); props.DLTFilter = squash_options_get_bool_at (options, codec, SQUASH_CSC_OPT_DELTA_FILTER); props.EXEFilter = squash_options_get_bool_at (options, codec, SQUASH_CSC_OPT_EXE_FILTER); props.TXTFilter = squash_options_get_bool_at (options, codec, SQUASH_CSC_OPT_TXT_FILTER); CSCEnc_WriteProperties (&props, props_buf, 0); size_t bytes_written = squash_csc_writer ((void*) &out_stream, props_buf, CSC_PROP_SIZE); if (SQUASH_UNLIKELY(bytes_written != CSC_PROP_SIZE)) return squash_error (SQUASH_FAILED); CSCEncHandle comp = CSCEnc_Create (&props, (ISeqOutStream*) &out_stream, (ISzAlloc*) &squash_csc_allocator); csc_res = CSCEnc_Encode (comp, (ISeqInStream*) &in_stream, NULL); if (SQUASH_UNLIKELY(csc_res != 0)) { res = squash_error (SQUASH_FAILED); } else { csc_res = CSCEnc_Encode_Flush (comp); if (SQUASH_UNLIKELY(csc_res != 0)) { res = squash_error (SQUASH_FAILED); } } CSCEnc_Destroy (comp); } else { size_t prop_l = CSC_PROP_SIZE; squash_csc_reader ((void*) &in_stream, props_buf, &prop_l); if (SQUASH_UNLIKELY(prop_l != CSC_PROP_SIZE)) return squash_error (SQUASH_FAILED); CSCDec_ReadProperties (&props, props_buf); CSCDecHandle decomp = CSCDec_Create (&props, (ISeqInStream*) &in_stream, (ISzAlloc*) &squash_csc_allocator); csc_res = CSCDec_Decode (decomp, (ISeqOutStream*) &out_stream, NULL); if (csc_res != 0) { res = squash_error (SQUASH_FAILED); } CSCDec_Destroy (decomp); } return res; }
static size_t squash_lz4f_get_input_buffer_size (SquashStream* stream) { return squash_lz4f_block_size_id_to_size ((LZ4F_blockSizeID_t) squash_options_get_int_at (stream->options, stream->codec, SQUASH_LZ4F_OPT_BLOCK_SIZE)); }