Example #1
0
File: file.c Project: jibsen/squash
/**
 * @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;
}
Example #2
0
/**
 * @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;
  }
}
Example #3
0
/**
 * @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;
    }
}