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_libdeflate_decompress_buffer (SquashCodec* codec, size_t* decompressed_size, uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)], size_t compressed_size, const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)], SquashOptions* options) { struct deflate_decompressor *decompressor = deflate_alloc_decompressor(); size_t actual_out_nbytes; enum decompress_result ret = deflate_decompress(decompressor, compressed, compressed_size, decompressed, *decompressed_size, &actual_out_nbytes); deflate_free_decompressor(decompressor); *decompressed_size = actual_out_nbytes; switch (ret) { case DECOMPRESS_SUCCESS: return SQUASH_OK; case DECOMPRESS_BAD_DATA: return squash_error (SQUASH_FAILED); case DECOMPRESS_SHORT_OUTPUT: return squash_error (SQUASH_BUFFER_FULL); case DECOMPRESS_INSUFFICIENT_SPACE: return squash_error (SQUASH_BUFFER_FULL); } HEDLEY_UNREACHABLE (); }
static SquashStatus squash_lz4f_process_stream (SquashStream* stream, SquashOperation operation) { switch (stream->stream_type) { case SQUASH_STREAM_COMPRESS: return squash_lz4f_compress_stream (stream, operation); case SQUASH_STREAM_DECOMPRESS: return squash_lz4f_decompress_stream (stream, operation); default: HEDLEY_UNREACHABLE(); } }
static int test_unreachable(enum Foo code) { switch (code) { case FOO_BAR: case FOO_BAZ: case FOO_QUX: return 0; case FOO_QUUX: default: HEDLEY_UNREACHABLE(); } HEDLEY_UNREACHABLE_RETURN(0); }
static size_t squash_lz4f_block_size_id_to_size (LZ4F_blockSizeID_t blkid) { switch (blkid) { case LZ4F_max64KB: return 64 * 1024; case LZ4F_max256KB: return 256 * 1024; case LZ4F_max1MB: return 1 * 1024 * 1024; case LZ4F_max4MB: return 4 * 1024 * 1024; case LZ4F_default: default: HEDLEY_UNREACHABLE(); break; } }
static SquashStatus squash_lz4f_get_status (size_t res) { if (!LZ4F_isError (res)) return SQUASH_OK; switch ((LZ4F_errorCodes) (-(int)(res))) { case LZ4F_OK_NoError: return SQUASH_OK; case LZ4F_ERROR_GENERIC: return squash_error (SQUASH_FAILED); case LZ4F_ERROR_maxBlockSize_invalid: case LZ4F_ERROR_blockMode_invalid: case LZ4F_ERROR_contentChecksumFlag_invalid: case LZ4F_ERROR_headerVersion_wrong: case LZ4F_ERROR_blockChecksum_unsupported: case LZ4F_ERROR_reservedFlag_set: case LZ4F_ERROR_frameHeader_incomplete: case LZ4F_ERROR_frameType_unknown: case LZ4F_ERROR_frameSize_wrong: case LZ4F_ERROR_headerChecksum_invalid: case LZ4F_ERROR_contentChecksum_invalid: return squash_error (SQUASH_INVALID_BUFFER); case LZ4F_ERROR_compressionLevel_invalid: return squash_error (SQUASH_BAD_VALUE); case LZ4F_ERROR_allocation_failed: return squash_error (SQUASH_MEMORY); case LZ4F_ERROR_srcSize_tooLarge: case LZ4F_ERROR_dstMaxSize_tooSmall: return squash_error (SQUASH_BUFFER_FULL); case LZ4F_ERROR_decompressionFailed: case LZ4F_ERROR_srcPtr_wrong: case LZ4F_ERROR_maxCode: return squash_error (SQUASH_FAILED); default: HEDLEY_UNREACHABLE (); } }
static SquashStatus squash_lz4f_compress_stream (SquashStream* stream, SquashOperation operation) { SquashLZ4FStream* s = (SquashLZ4FStream*) stream; bool progress = false; if (s->data.comp.output_buffer_size != 0) { const size_t buffer_remaining = s->data.comp.output_buffer_size - s->data.comp.output_buffer_pos; const size_t cp_size = (buffer_remaining < stream->avail_out) ? buffer_remaining : stream->avail_out; memcpy (stream->next_out, s->data.comp.output_buffer + s->data.comp.output_buffer_pos, cp_size); stream->next_out += cp_size; stream->avail_out -= cp_size; s->data.comp.output_buffer_pos += cp_size; if (cp_size == buffer_remaining) { s->data.comp.output_buffer_size = 0; s->data.comp.output_buffer_pos = 0; progress = true; } else { return SQUASH_PROCESSING; } } while ((stream->avail_in != 0 || operation != SQUASH_OPERATION_PROCESS) && stream->avail_out != 0) { if (s->data.comp.state == SQUASH_LZ4F_STATE_INIT) { s->data.comp.state = SQUASH_LZ4F_STATE_ACTIVE; if (stream->avail_out < 19) { s->data.comp.output_buffer_size = LZ4F_compressBegin (s->data.comp.ctx, squash_lz4f_stream_get_output_buffer (stream), squash_lz4f_stream_get_output_buffer_size (stream), &(s->data.comp.prefs)); break; } else { size_t written = LZ4F_compressBegin (s->data.comp.ctx, stream->next_out, stream->avail_out, &(s->data.comp.prefs)); stream->next_out += written; stream->avail_out -= written; progress = true; } } else { const size_t input_buffer_size = squash_lz4f_get_input_buffer_size (stream); const size_t total_input = stream->avail_in + s->data.comp.input_buffer_size; const size_t output_buffer_max_size = squash_lz4f_stream_get_output_buffer_size (stream); if (progress && (total_input < input_buffer_size || stream->avail_out < output_buffer_max_size)) break; uint8_t* obuf; size_t olen; const size_t input_size = (total_input > input_buffer_size) ? (input_buffer_size - s->data.comp.input_buffer_size) : stream->avail_in; if (input_size > 0) { obuf = (output_buffer_max_size > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out; olen = LZ4F_compressUpdate (s->data.comp.ctx, obuf, output_buffer_max_size, stream->next_in, input_size, NULL); if (!LZ4F_isError (olen)) { if (input_size + s->data.comp.input_buffer_size == input_buffer_size) { s->data.comp.input_buffer_size = 0; } else { s->data.comp.input_buffer_size += input_size; assert (olen == 0); } stream->next_in += input_size; stream->avail_in -= input_size; } else { HEDLEY_UNREACHABLE(); } } else if (operation == SQUASH_OPERATION_FLUSH) { assert (stream->avail_in == 0); olen = squash_lz4f_stream_get_output_buffer_size (stream); obuf = (olen > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out; olen = LZ4F_flush (s->data.comp.ctx, obuf, olen, NULL); s->data.comp.input_buffer_size = 0; } else if (operation == SQUASH_OPERATION_FINISH) { assert (stream->avail_in == 0); olen = squash_lz4f_stream_get_output_buffer_size (stream); obuf = (olen > stream->avail_out) ? squash_lz4f_stream_get_output_buffer (stream) : stream->next_out; olen = LZ4F_compressEnd (s->data.comp.ctx, obuf, olen, NULL); s->data.comp.input_buffer_size = 0; } else if (progress) { break; } else { HEDLEY_UNREACHABLE(); } if (HEDLEY_UNLIKELY(LZ4F_isError (olen))) { HEDLEY_UNREACHABLE(); return squash_error (SQUASH_FAILED); } else { if (olen != 0) { if (obuf == s->data.comp.output_buffer) { s->data.comp.output_buffer_size = olen; break; } else { stream->next_out += olen; stream->avail_out -= olen; } } } if (operation != SQUASH_OPERATION_PROCESS) break; } } if (s->data.comp.output_buffer_size != 0) { const size_t buffer_remaining = s->data.comp.output_buffer_size - s->data.comp.output_buffer_pos; const size_t cp_size = (buffer_remaining < stream->avail_out) ? buffer_remaining : stream->avail_out; memcpy (stream->next_out, s->data.comp.output_buffer + s->data.comp.output_buffer_pos, cp_size); stream->next_out += cp_size; stream->avail_out -= cp_size; s->data.comp.output_buffer_pos += cp_size; if (cp_size == buffer_remaining) { s->data.comp.output_buffer_size = 0; s->data.comp.output_buffer_pos = 0; progress = true; } else { return SQUASH_PROCESSING; } } return (stream->avail_in == 0 && s->data.comp.output_buffer_size == 0) ? SQUASH_OK : SQUASH_PROCESSING; }
static SquashStatus squash_file_write_internal (SquashFile* file, size_t uncompressed_size, const uint8_t uncompressed[HEDLEY_ARRAY_PARAM(uncompressed_size)], SquashOperation operation) { SquashStatus res; assert (file != NULL); if (HEDLEY_UNLIKELY(file->last_status < 0)) return file->last_status; if (file->stream == NULL) { file->stream = squash_codec_create_stream_with_options (file->codec, SQUASH_STREAM_COMPRESS, file->options); if (HEDLEY_UNLIKELY(file->stream == NULL)) { res = squash_error (SQUASH_FAILED); goto cleanup; } } assert (file->stream->next_in == NULL); assert (file->stream->avail_in == 0); assert (file->stream->next_out == NULL); assert (file->stream->avail_out == 0); file->stream->next_in = uncompressed; file->stream->avail_in = uncompressed_size; do { file->stream->next_out = file->buf; file->stream->avail_out = SQUASH_FILE_BUF_SIZE; switch (operation) { case SQUASH_OPERATION_PROCESS: res = squash_stream_process (file->stream); break; case SQUASH_OPERATION_FLUSH: res = squash_stream_flush (file->stream); break; case SQUASH_OPERATION_FINISH: res = squash_stream_finish (file->stream); break; case SQUASH_OPERATION_TERMINATE: HEDLEY_UNREACHABLE (); break; } if (res > 0 && file->stream->avail_out != SQUASH_FILE_BUF_SIZE) { size_t bytes_written = SQUASH_FWRITE_UNLOCKED(file->buf, 1, SQUASH_FILE_BUF_SIZE - file->stream->avail_out, file->fp); if (bytes_written != SQUASH_FILE_BUF_SIZE - file->stream->avail_out) { res = SQUASH_IO; goto cleanup; } } } while (res == SQUASH_PROCESSING); cleanup: if (file->stream != NULL) { file->stream->next_in = NULL; file->stream->avail_in = 0; file->stream->next_out = NULL; file->stream->avail_out = 0; } return file->last_status = res; }