Exemple #1
0
/**
 * @brief Free a file
 *
 * This function will free the @ref SquashFile, but unlike @ref
 * squash_file_close it will not actually close the underlying *FILE*

 * pointer.  Instead, it will return the value in the @a fp argument,
 * allowing you to further manipulate it.
 *
 * @param file file to free
 * @param[out] fp location to store the underlying *FILE* pointer
 * @return @ref SQUASH_OK on success or a negative error code on
 *   failure
 */
SquashStatus
squash_file_free (SquashFile* file, FILE** fp) {
  SquashStatus res = SQUASH_OK;

  if (SQUASH_UNLIKELY(file == NULL)) {
    if (fp != NULL)
      *fp = NULL;
    return SQUASH_OK;
  }

  squash_file_lock (file);

  if (file->stream != NULL && file->stream->stream_type == SQUASH_STREAM_COMPRESS)
    res = squash_file_write_internal (file, 0, NULL, SQUASH_OPERATION_FINISH);

#if defined(SQUASH_MMAP_IO)
  squash_mapped_file_destroy (&(file->map), false);
#endif

  if (fp != NULL)
    *fp = file->fp;

  SQUASH_FUNLOCKFILE(file->fp);

  squash_object_unref (file->stream);
  squash_object_unref (file->options);

  squash_file_unlock (file);

  mtx_destroy (&(file->mtx));

  free (file);

  return res;
}
Exemple #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;
  }
}
Exemple #3
0
static SquashBZ2Stream*
squash_bz2_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashBZ2Options* options) {
  int bz2_e = 0;
  SquashBZ2Stream* stream;

  assert (codec != NULL);
  assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS);

  stream = (SquashBZ2Stream*) malloc (sizeof (SquashBZ2Stream));
  squash_bz2_stream_init (stream, codec, stream_type, options, squash_bz2_stream_free);

  if (stream_type == SQUASH_STREAM_COMPRESS) {
    bz2_e = BZ2_bzCompressInit (&(stream->stream),
                                squash_bz2_options_get_block_size_100k (options),
                                0,
                                squash_bz2_options_get_work_factor (options));
  } else if (stream_type == SQUASH_STREAM_DECOMPRESS) {
    bz2_e = BZ2_bzDecompressInit (&(stream->stream),
                                  0,
                                  squash_bz2_options_get_small (options) ? 1 : 0);
  } else {
    assert (false);
  }

  if (bz2_e != BZ_OK) {
    /* We validate the params so OOM is really the only time this
       should happen, and that really shouldn't be happening here. */
    stream = squash_object_unref (stream);
  }

  return stream;
}
Exemple #4
0
static void
benchmark_codec (SquashCodec* codec, void* data) {
  struct BenchmarkContext* context = (struct BenchmarkContext*) data;
  SquashOptions* opts;
  int level = 0;
  char level_s[4];
  bool have_results = false;

  umask (0100);

  fprintf (stdout, "  %s:%s\n",
           squash_plugin_get_name (squash_codec_get_plugin (codec)),
           squash_codec_get_name (codec));

  opts = squash_options_new (codec, NULL);
  if (opts != NULL) {
    squash_object_ref_sink (opts);
    for ( level = 0 ; level <= 999 ; level++ ) {
      snprintf (level_s, 4, "%d", level);
      if (squash_options_parse_option (opts, "level", level_s) == SQUASH_OK) {
        if (benchmark_codec_with_options (context, codec, opts)) {
          have_results = true;
        }
      }
    }
    squash_object_unref (opts);
  }

  if (!have_results) {
    benchmark_codec_with_options (context, codec, NULL);
  }
}
Exemple #5
0
static SquashMSCompStream*
squash_ms_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) {
    SquashMSCompStream* stream;

    assert (codec != NULL);
    assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS);

    stream = squash_malloc (sizeof (SquashMSCompStream));
    if (SQUASH_UNLIKELY(stream == NULL))
        return (squash_error (SQUASH_MEMORY), NULL);

    squash_ms_stream_init (stream, codec, stream_type, options, squash_ms_stream_destroy);

    MSCompStatus status;
    MSCompFormat format = squash_ms_format_from_codec (codec);
    if (stream->base_object.stream_type == SQUASH_STREAM_COMPRESS) {
        status = ms_deflate_init (format, &(stream->mscomp));
    } else {
        status = ms_inflate_init (format, &(stream->mscomp));
    }

    if (SQUASH_UNLIKELY(status != MSCOMP_OK)) {
        squash_object_unref (stream);
        return (squash_error (squash_ms_status_to_squash_status (status)), NULL);
    }

    return stream;
}
Exemple #6
0
/**
 * @brief Destroy a stream.
 * @protected
 *
 * @warning This function must only be used to implement a subclass of
 * @ref SquashObject.  Each subclass should implement a *_destroy
 * function which should perform any operations needed to destroy
 * their own data and chain up to the *_destroy function of the base
 * class, eventually invoking ::squash_object_destroy.  Invoking this
 * function in any other context is likely to cause a memory leak or
 * crash.  If you are not creating a subclass, you should be calling
 * @ref squash_object_unref instead.
 *
 * @param stream The stream.
 *
 * @see squash_object_destroy
 */
void
squash_stream_destroy (void* stream) {
    SquashStream* s;

    assert (stream != NULL);

    s = (SquashStream*) stream;

    if (SQUASH_UNLIKELY(s->priv != NULL)) {
        SquashStreamPrivate* priv = (SquashStreamPrivate*) s->priv;

        if (!priv->finished) {
            squash_stream_send_to_thread (s, SQUASH_OPERATION_TERMINATE);
        }
        cnd_destroy (&(priv->request_cnd));
        cnd_destroy (&(priv->result_cnd));
        mtx_destroy (&(priv->io_mtx));

        squash_free (s->priv);
    }

    if (s->destroy_user_data != NULL && s->user_data != NULL) {
        s->destroy_user_data (s->user_data);
    }

    if (s->options != NULL) {
        s->options = squash_object_unref (s->options);
    }

    squash_object_destroy (stream);
}
Exemple #7
0
static SquashBZ2Stream*
squash_bz2_stream_new (SquashCodec* codec, SquashStreamType stream_type, SquashOptions* options) {
  int bz2_e = 0;
  SquashBZ2Stream* stream;

  assert (codec != NULL);
  assert (stream_type == SQUASH_STREAM_COMPRESS || stream_type == SQUASH_STREAM_DECOMPRESS);

  stream = squash_malloc (sizeof (SquashBZ2Stream));
  squash_bz2_stream_init (stream, codec, stream_type, options, squash_bz2_stream_destroy);

  if (stream_type == SQUASH_STREAM_COMPRESS) {
    bz2_e = BZ2_bzCompressInit (&(stream->stream),
                                squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_LEVEL),
                                0,
                                squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_WORK_FACTOR));
  } else if (stream_type == SQUASH_STREAM_DECOMPRESS) {
    bz2_e = BZ2_bzDecompressInit (&(stream->stream),
                                  0,
                                  squash_codec_get_option_int_index (codec, options, SQUASH_BZ2_OPT_SMALL));
  } else {
    squash_assert_unreachable();
  }

  if (bz2_e != BZ_OK) {
    /* We validate the params so OOM is really the only time this
       should happen, and that really shouldn't be happening here. */
    stream = squash_object_unref (stream);
  }

  return stream;
}
Exemple #8
0
	//----------
	void Stream::clear() {
		if (this->squashStream) {
			squash_stream_destroy(this->squashStream);
			squash_object_unref(this->squashStream);
			this->squashStream = nullptr;
		}
	}
Exemple #9
0
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;
}
Exemple #10
0
	//----------
	Stream & Stream::operator<<(const Finish &) {
		if (this->squashStream == nullptr)
		{
			OFXSQUASH_WARNING << "Stream already finished. You need to make a new one.";
			return* this;
		}

		SquashStatus status;

		do {
			this->squashStream->next_out = this->buffer.data();
			this->squashStream->avail_out = this->buffer.size();

			status = squash_stream_finish(this->squashStream);

			if (status != SQUASH_OK && status != SQUASH_PROCESSING) {
				OFXSQUASH_ERROR << "Processing failed: " << squash_status_to_string(status);
				return * this;
			}

			const size_t outputSize = this->buffer.size() - this->squashStream->avail_out;
			if (outputSize > 0)
			{
				if (this->writeFunction) {
					WriteFunctionArguments args{ this->buffer.data(), outputSize, false };
					this->writeFunction(args);
				}
				else {
					OFXSQUASH_WARNING << "Cannot write stream output. No WriteFunction has been set";
				}
			}
		} while (status == SQUASH_PROCESSING);

		if (this->writeFunction) {
			WriteFunctionArguments args{ nullptr, 0, true };
			this->writeFunction(args);
		}

		squash_stream_destroy(this->squashStream);
		squash_object_unref(this->squashStream);
		this->squashStream = nullptr;

		return * this;
	}
Exemple #11
0
/**
 * @brief Compress a buffer with an existing @ref SquashOptions
 *
 * @param codec The codec to use
 * @param[out] compressed Location to store the compressed data
 * @param[in,out] compressed_length Location storing the size of the
 *   @a compressed buffer on input, replaced with the actual size of
 *   the compressed data
 * @param uncompressed The uncompressed data
 * @param uncompressed_length Length of the uncompressed data (in bytes)
 * @param options Compression options
 * @return A status code
 */
SquashStatus
squash_codec_compress_with_options (SquashCodec* codec,
                                    size_t* compressed_length,
                                    uint8_t compressed[SQUASH_ARRAY_PARAM(*compressed_length)],
                                    size_t uncompressed_length,
                                    const uint8_t uncompressed[SQUASH_ARRAY_PARAM(uncompressed_length)],
                                    SquashOptions* options) {
  SquashCodecImpl* impl = NULL;

  assert (codec != NULL);

  assert (compressed != NULL);
  assert (uncompressed != NULL);

  impl = squash_codec_get_impl (codec);
  if (impl == NULL)
    return squash_error (SQUASH_UNABLE_TO_LOAD);

  if (compressed == uncompressed)
    return squash_error (SQUASH_INVALID_BUFFER);

  if (impl->compress_buffer ||
      impl->compress_buffer_unsafe) {
    size_t max_compressed_length = squash_codec_get_max_compressed_size (codec, uncompressed_length);

    if (*compressed_length >= max_compressed_length) {
      if (impl->compress_buffer_unsafe != NULL) {
        return impl->compress_buffer_unsafe (codec,
                                              compressed_length, compressed,
                                              uncompressed_length, uncompressed,
                                              options);
      } else {
        return impl->compress_buffer (codec,
                                       compressed_length, compressed,
                                       uncompressed_length, uncompressed,
                                       options);
      }
    } else if (impl->compress_buffer != NULL) {
      return impl->compress_buffer (codec,
                                     compressed_length, compressed,
                                     uncompressed_length, uncompressed,
                                     options);
    } else {
      SquashStatus status;
      uint8_t* tmp_buf = malloc (max_compressed_length);
      if (tmp_buf == NULL)
        return squash_error (SQUASH_MEMORY);

      status = impl->compress_buffer_unsafe (codec,
                                              &max_compressed_length, tmp_buf,
                                              uncompressed_length, uncompressed,
                                              options);
      if (status == SQUASH_OK) {
        if (*compressed_length < max_compressed_length) {
          *compressed_length = max_compressed_length;
          free (tmp_buf);
          return squash_error (SQUASH_BUFFER_FULL);
        } else {
          *compressed_length = max_compressed_length;
          memcpy (compressed, tmp_buf, max_compressed_length);
          free (tmp_buf);
          return SQUASH_OK;
        }
      } else {
        free (tmp_buf);
        return status;
      }
    }
  } else {
    SquashStatus status;
    SquashStream* stream;

    stream = squash_codec_create_stream_with_options (codec, SQUASH_STREAM_COMPRESS, options);
    if (stream == NULL)
      return squash_error (SQUASH_FAILED);

    stream->next_in = uncompressed;
    stream->avail_in = uncompressed_length;
    stream->next_out = compressed;
    stream->avail_out = *compressed_length;

    do {
      status = squash_stream_process (stream);
    } while (status == SQUASH_PROCESSING);

    if (status != SQUASH_OK) {
      squash_object_unref (stream);
      return status;
    }

    do {
      status = squash_stream_finish (stream);
    } while (status == SQUASH_PROCESSING);

    if (status != SQUASH_OK) {
      squash_object_unref (stream);
      return status;
    }

    *compressed_length = stream->total_out;
    squash_object_unref (stream);
    return status;
  }
}