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 (SQUASH_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_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_BLOCK_SIZE), blockLinked, squash_codec_get_option_bool_index (codec, options, SQUASH_LZ4F_OPT_CHECKSUM) ? contentChecksumEnabled : noContentChecksum, }, squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_LEVEL) }; } else { ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION); } if (SQUASH_UNLIKELY(LZ4F_isError (ec))) { squash_object_unref (stream); return (squash_error (SQUASH_FAILED), NULL); } return stream; }
static SquashStatus squash_bz2_decompress_buffer (SquashCodec* codec, size_t* decompressed_length, uint8_t decompressed[SQUASH_ARRAY_PARAM(*decompressed_length)], size_t compressed_length, const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_length)], SquashOptions* options) { int small = squash_codec_get_option_bool_index (codec, options, SQUASH_BZ2_OPT_SMALL) ? 1 : 0; unsigned int decompressed_length_ui = (unsigned int) *decompressed_length; int bz2_res; bz2_res = BZ2_bzBuffToBuffDecompress ((char*) decompressed, &decompressed_length_ui, (char*) compressed, (unsigned int) compressed_length, small, 0); if (bz2_res == BZ_OK) { *decompressed_length = decompressed_length_ui; } return squash_bz2_status_to_squash_status (bz2_res); }
static void squash_lz4f_stream_init (SquashLZ4FStream* stream, SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options, SquashDestroyNotify destroy_notify) { LZ4F_errorCode_t ec; squash_stream_init ((SquashStream*) stream, codec, stream_type, (SquashOptions*) options, destroy_notify); 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_length = 0; stream->data.comp.input_buffer_length = 0; stream->data.comp.prefs = (LZ4F_preferences_t) { { squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_BLOCK_SIZE), blockLinked, squash_codec_get_option_bool_index (codec, options, SQUASH_LZ4F_OPT_CHECKSUM) ? contentChecksumEnabled : noContentChecksum, }, squash_codec_get_option_int_index (codec, options, SQUASH_LZ4F_OPT_LEVEL) }; } else { ec = LZ4F_createDecompressionContext(&(stream->data.decomp.ctx), LZ4F_VERSION); } assert (!LZ4F_isError (ec)); }
static SquashStatus squash_density_process_stream (SquashStream* stream, SquashOperation operation) { SquashDensityStream* s = (SquashDensityStream*) stream; if (s->buffer_size > 0) { squash_density_flush_internal_buffer (stream); return SQUASH_PROCESSING; } if (s->next == SQUASH_DENSITY_ACTION_INIT) { s->active_input_size = (stream->stream_type == SQUASH_STREAM_COMPRESS) ? ((stream->avail_in / SQUASH_DENSITY_INPUT_MULTIPLE) * SQUASH_DENSITY_INPUT_MULTIPLE) : stream->avail_in; if (stream->avail_out < DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE) { s->buffer_active = true; s->state = density_stream_prepare (s->stream, (uint8_t*) stream->next_in, s->active_input_size, s->buffer, DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE); } else { s->buffer_active = false; s->state = density_stream_prepare (s->stream, (uint8_t*) stream->next_in, s->active_input_size, stream->next_out, stream->avail_out); } if (SQUASH_UNLIKELY(s->state != DENSITY_STREAM_STATE_READY)) return squash_error (SQUASH_FAILED); } switch (s->state) { case DENSITY_STREAM_STATE_STALL_ON_INPUT: if (s->input_buffer_size != 0 || (stream->avail_in < SQUASH_DENSITY_INPUT_MULTIPLE && stream->stream_type == SQUASH_STREAM_COMPRESS && operation == SQUASH_OPERATION_PROCESS)) { const size_t remaining = SQUASH_DENSITY_INPUT_MULTIPLE - s->input_buffer_size; const size_t cp_size = remaining < stream->avail_in ? remaining : stream->avail_in; if (cp_size != 0) { memcpy (s->input_buffer + s->input_buffer_size, stream->next_in, cp_size); s->input_buffer_size += cp_size; stream->next_in += cp_size; stream->avail_in -= cp_size; assert (cp_size != 0); } } if (s->input_buffer_size != 0) { if (s->input_buffer_size == SQUASH_DENSITY_INPUT_MULTIPLE || operation != SQUASH_OPERATION_PROCESS) { s->active_input_size = s->input_buffer_size; s->input_buffer_active = true; density_stream_update_input (s->stream, s->input_buffer, s->input_buffer_size); s->state = DENSITY_STREAM_STATE_READY; } else { assert (stream->avail_in == 0); return SQUASH_OK; } } else { s->active_input_size = (stream->stream_type == SQUASH_STREAM_COMPRESS) ? ((stream->avail_in / SQUASH_DENSITY_INPUT_MULTIPLE) * SQUASH_DENSITY_INPUT_MULTIPLE) : stream->avail_in; density_stream_update_input (s->stream, stream->next_in, s->active_input_size); s->state = DENSITY_STREAM_STATE_READY; } break; case DENSITY_STREAM_STATE_STALL_ON_OUTPUT: { if (!s->output_invalid) { const size_t written = density_stream_output_available_for_use (s->stream); total_bytes_written += written; if (s->buffer_active) { s->buffer_size = written; s->buffer_pos = 0; const size_t cp_size = s->buffer_size < stream->avail_out ? s->buffer_size : stream->avail_out; memcpy (stream->next_out, s->buffer, cp_size); stream->next_out += cp_size; stream->avail_out -= cp_size; s->buffer_pos += cp_size; if (s->buffer_pos == s->buffer_size) { s->buffer_pos = 0; s->buffer_size = 0; } } else { assert (written <= stream->avail_out); stream->next_out += written; stream->avail_out -= written; } s->output_invalid = true; return SQUASH_PROCESSING; } else { if (stream->avail_out < DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE) { s->buffer_active = true; density_stream_update_output (s->stream, s->buffer, DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE); } else { s->buffer_active = false; density_stream_update_output (s->stream, stream->next_out, stream->avail_out); } s->output_invalid = false; s->state = DENSITY_STREAM_STATE_READY; } } break; case DENSITY_STREAM_STATE_READY: break; case DENSITY_STREAM_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL: case DENSITY_STREAM_STATE_ERROR_INVALID_INTERNAL_STATE: case DENSITY_STREAM_STATE_ERROR_INTEGRITY_CHECK_FAIL: return squash_error (SQUASH_FAILED); } assert (s->output_invalid == false); while (s->state == DENSITY_STREAM_STATE_READY && s->next != SQUASH_DENSITY_ACTION_FINISHED) { switch (s->next) { case SQUASH_DENSITY_ACTION_INIT: if (stream->stream_type == SQUASH_STREAM_COMPRESS) { DENSITY_COMPRESSION_MODE compression_mode = squash_density_level_to_mode (squash_codec_get_option_int_index (stream->codec, stream->options, SQUASH_DENSITY_OPT_LEVEL)); DENSITY_BLOCK_TYPE block_type = squash_codec_get_option_bool_index (stream->codec, stream->options, SQUASH_DENSITY_OPT_CHECKSUM) ? DENSITY_BLOCK_TYPE_WITH_HASHSUM_INTEGRITY_CHECK : DENSITY_BLOCK_TYPE_DEFAULT; s->state = density_stream_compress_init (s->stream, compression_mode, block_type); } else { s->state = density_stream_decompress_init (s->stream, NULL); } if (SQUASH_UNLIKELY(s->state != DENSITY_STREAM_STATE_READY)) return squash_error (SQUASH_FAILED); s->next = SQUASH_DENSITY_ACTION_CONTINUE; break; case SQUASH_DENSITY_ACTION_CONTINUE_OR_FINISH: s->next = (operation == SQUASH_OPERATION_PROCESS) ? SQUASH_DENSITY_ACTION_CONTINUE : SQUASH_DENSITY_ACTION_FINISH; break; case SQUASH_DENSITY_ACTION_CONTINUE: if (stream->stream_type == SQUASH_STREAM_COMPRESS) { s->state = density_stream_compress_continue (s->stream); } else { s->state = density_stream_decompress_continue (s->stream); } if (s->state == DENSITY_STREAM_STATE_STALL_ON_INPUT) s->next = SQUASH_DENSITY_ACTION_CONTINUE_OR_FINISH; break; case SQUASH_DENSITY_ACTION_FINISH: if (stream->stream_type == SQUASH_STREAM_COMPRESS) { s->state = density_stream_compress_finish (s->stream); } else { s->state = density_stream_decompress_finish (s->stream); } if (s->state == DENSITY_STREAM_STATE_READY) { s->state = DENSITY_STREAM_STATE_STALL_ON_OUTPUT; s->output_invalid = false; s->next = SQUASH_DENSITY_ACTION_FINISHED; } break; case SQUASH_DENSITY_ACTION_FINISHED: default: squash_assert_unreachable(); break; } } if (s->state == DENSITY_STREAM_STATE_STALL_ON_INPUT) { if (s->input_buffer_active) { assert (s->active_input_size == s->input_buffer_size); s->input_buffer_active = false; s->input_buffer_size = 0; } else { assert (s->active_input_size <= stream->avail_in); stream->next_in += s->active_input_size; stream->avail_in -= s->active_input_size; } s->active_input_size = 0; } else if (s->state == DENSITY_STREAM_STATE_STALL_ON_OUTPUT) { { if (!s->output_invalid) { const size_t written = density_stream_output_available_for_use (s->stream); total_bytes_written += written; if (s->buffer_active) { s->buffer_size = written; s->buffer_pos = 0; const size_t cp_size = s->buffer_size < stream->avail_out ? s->buffer_size : stream->avail_out; memcpy (stream->next_out, s->buffer, cp_size); stream->next_out += cp_size; stream->avail_out -= cp_size; s->buffer_pos += cp_size; if (s->buffer_pos == s->buffer_size) { s->buffer_pos = 0; s->buffer_size = 0; } } else { assert (written <= stream->avail_out); stream->next_out += written; stream->avail_out -= written; } s->output_invalid = true; return SQUASH_PROCESSING; } else { squash_assert_unreachable(); } } } if (operation == SQUASH_OPERATION_FINISH) total_bytes_written = 0; if (stream->avail_in == 0) { return SQUASH_OK; } else { return SQUASH_PROCESSING; } }