/** * @brief Open an existing stdio file using a codec instance with the specified options * * @param fp the stdio file to use * @param codec codec to use * @param options options * @return The opened file, or *NULL* on error * @see squash_file_steal_codec * @see squash_file_steal_with_options * @see squash_file_steal_codec_with_options */ SquashFile* squash_file_steal_codec_with_options (SquashCodec* codec, FILE* fp, SquashOptions* options) { assert (fp != NULL); assert (codec != NULL); SquashFile* file = malloc (sizeof (SquashFile)); if (file == NULL) return NULL; file->fp = fp; file->eof = false; file->stream = NULL; file->last_status = SQUASH_OK; file->codec = codec; file->options = (options != NULL) ? squash_object_ref (options) : NULL; #if defined(SQUASH_MMAP_IO) file->map = squash_mapped_file_empty; #endif mtx_init (&(file->mtx), mtx_recursive); SQUASH_FLOCKFILE(fp); return file; }
/** * @brief Decompress a buffer with an existing @ref SquashOptions * * @param codec The codec to use * @param[out] decompressed Location to store the decompressed data * @param[in,out] decompressed_length Location storing the size of the * @a decompressed buffer on input, replaced with the actual size of * the decompressed data * @param compressed The compressed data * @param compressed_length Length of the compressed data (in bytes) * @param options Compression options * @return A status code */ SquashStatus squash_codec_decompress_with_options (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) { SquashCodecImpl* impl = NULL; assert (codec != NULL); impl = squash_codec_get_impl (codec); if (impl == NULL) return squash_error (SQUASH_UNABLE_TO_LOAD); if (decompressed == compressed) return squash_error (SQUASH_INVALID_BUFFER); if (impl->decompress_buffer != NULL) { SquashStatus res; res = impl->decompress_buffer (codec, decompressed_length, decompressed, compressed_length, compressed, squash_object_ref (options)); squash_object_unref (options); return res; } else { SquashStatus status; SquashStream* stream; stream = squash_codec_create_stream_with_options (codec, SQUASH_STREAM_DECOMPRESS, options); stream->next_in = compressed; stream->avail_in = compressed_length; stream->next_out = decompressed; stream->avail_out = *decompressed_length; do { status = squash_stream_process (stream); } while (status == SQUASH_PROCESSING); if (status == SQUASH_END_OF_STREAM) { status = SQUASH_OK; *decompressed_length = stream->total_out; } else if (status == SQUASH_OK) { do { status = squash_stream_finish (stream); } while (status == SQUASH_PROCESSING); if (status == SQUASH_OK) { *decompressed_length = stream->total_out; } } assert (stream->stream_type == SQUASH_STREAM_DECOMPRESS); squash_object_unref (stream); return status; } }
/** * @brief Initialize a stream. * @protected * * @warning This function must only be used to implement a subclass of * @ref SquashStream. Streams returned by other functions will * already be initialized, and you *must* *not* call this function on * them; doing so will likely trigger a memory leak. * * @param stream The stream to initialize. * @param codec The codec to use. * @param stream_type The stream type. * @param options The options. * @param destroy_notify Function to call to destroy the instance. * * @see squash_object_init */ void squash_stream_init (void* stream, SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options, SquashDestroyNotify destroy_notify) { SquashStream* s; assert (stream != NULL); s = (SquashStream*) stream; squash_object_init (stream, false, destroy_notify); s->next_in = NULL; s->avail_in = 0; s->total_in = 0; s->next_out = NULL; s->avail_out = 0; s->total_out = 0; s->codec = codec; s->options = (options != NULL) ? squash_object_ref (options) : NULL; s->stream_type = stream_type; s->state = SQUASH_STREAM_STATE_IDLE; s->user_data = NULL; s->destroy_user_data = NULL; if (codec->impl.create_stream == NULL && codec->impl.splice != NULL) { s->priv = squash_malloc (sizeof (SquashStreamPrivate)); mtx_init (&(s->priv->io_mtx), mtx_plain); mtx_lock (&(s->priv->io_mtx)); s->priv->request = SQUASH_OPERATION_INVALID; cnd_init (&(s->priv->request_cnd)); s->priv->result = SQUASH_STATUS_INVALID; cnd_init (&(s->priv->result_cnd)); s->priv->finished = false; #if !defined(NDEBUG) int res = #endif thrd_create (&(s->priv->thread), (thrd_start_t) squash_stream_thread_func, s); assert (res == thrd_success); while (s->priv->result == SQUASH_STATUS_INVALID) cnd_wait (&(s->priv->result_cnd), &(s->priv->io_mtx)); s->priv->result = SQUASH_STATUS_INVALID; } else { s->priv = NULL; } }