/**
- * \brief Filters available for encoding
+ * \brief Test if the given Filter ID is supported for encoding
*
- * Pointer to an array containing the list of available Filter IDs that
- * can be used for encoding. The last element is LZMA_VLI_VALUE_UNKNOWN.
+ * Returns true if the give Filter ID is supported for encoding by this
+ * liblzma build. Otherwise false is returned.
*
- * If lzma_available_filter_encoders[0] == LZMA_VLI_VALUE_UNKNOWN, the
- * encoder components haven't been built at all. This means that the
- * encoding-specific functions are probably missing from the library
- * API/ABI completely.
+ * There is no way to list which filters are available in this particular
+ * liblzma version and build. It would be useless, because the application
+ * couldn't know what kind of options the filter would need.
*/
-extern const lzma_vli *const lzma_filter_encoders;
+extern lzma_bool lzma_filter_encoder_is_supported(lzma_vli id);
/**
- * \brief Filters available for decoding
+ * \brief Test if the given Filter ID is supported for decoding
*
- * Pointer to an array containing the list of available Filter IDs that
- * can be used for decoding. The last element is LZMA_VLI_VALUE_UNKNOWN.
- *
- * If lzma_available_filter_decoders[0] == LZMA_VLI_VALUE_UNKNOWN, the
- * decoder components haven't been built at all. This means that the
- * decoding-specific functions are probably missing from the library
- * API/ABI completely.
+ * Returns true if the give Filter ID is supported for decoding by this
+ * liblzma build. Otherwise false is returned.
*/
-extern const lzma_vli *const lzma_filter_decoders;
+extern lzma_bool lzma_filter_decoder_is_supported(lzma_vli id);
/**
- * \brief Calculate rough memory requirements for given filter chain
+ * \brief Calculate rough memory requirements for raw encoder
*
* \param filters Array of filters terminated with
* .id == LZMA_VLI_VALUE_UNKNOWN.
*
- * \return Number of mebibytes (MiB i.e. 2^20) required for the given
- * encoder or decoder filter chain.
- *
- * \note If calculating memory requirements of encoder, lzma_init() or
- * lzma_init_encoder() must have been called earlier. Similarly,
- * if calculating memory requirements of decoder, lzma_init() or
- * lzma_init_decoder() must have been called earlier.
+ * \return Rough number of bytes required for the given filter chain
+ * when encoding.
*/
-// extern uint32_t lzma_memory_usage(
-// const lzma_filter *filters, lzma_bool is_encoder);
-
extern uint64_t lzma_memusage_encoder(const lzma_filter *filters)
lzma_attr_pure;
+
+/**
+ * \brief Calculate rough memory requirements for raw decoder
+ *
+ * \param filters Array of filters terminated with
+ * .id == LZMA_VLI_VALUE_UNKNOWN.
+ *
+ * \return Rough number of bytes required for the given filter chain
+ * when decoding.
+ */
extern uint64_t lzma_memusage_decoder(const lzma_filter *filters)
lzma_attr_pure;
/**
- * \brief Initializes raw encoder
+ * \brief Initialize raw encoder
*
* This function may be useful when implementing custom file formats.
*
/**
- * \brief Initializes raw decoder
+ * \brief Initialize raw decoder
*
* The initialization of raw decoder goes similarly to raw encoder.
*
- * The `action' with lzma_code() can be LZMA_RUN or LZMA_SYNC_FLUSH.
+ * The `action' with lzma_code() can be LZMA_RUN or LZMA_FINISH. Using
+ * LZMA_FINISH is not required, it is supported just for convenience.
*
* \return - LZMA_OK
* - LZMA_MEM_ERROR
lzma_attr_warn_unused_result;
+/**
+ * \brief Get the size of the Filter Properties field
+ *
+ * This function may be useful when implementing custom file formats
+ * using the raw encoder and decoder.
+ *
+ * \param size Pointer to uint32_t to hold the size of the properties
+ * \param filter Filter ID and options (the size of the propeties may
+ * vary depending on the options)
+ *
+ * \return - LZMA_OK
+ * - LZMA_HEADER_ERROR
+ * - LZMA_PROG_ERROR
+ *
+ * \note This function validates the Filter ID, but does not
+ * necessarily validate the options. Thus, it is possible
+ * that this returns LZMA_OK while the following call to
+ * lzma_properties_encode() returns LZMA_HEADER_ERROR.
+ */
+extern lzma_ret lzma_properties_size(
+ uint32_t *size, const lzma_filter *filter);
+
+
+/**
+ * \brief Encode the Filter Properties field
+ *
+ * \param filter Filter ID and options
+ * \param props Buffer to hold the encoded options. The size of
+ * buffer must have been already determined with
+ * lzma_properties_size().
+ *
+ * \return - LZMA_OK
+ * - LZMA_HEADER_ERROR
+ * - LZMA_PROG_ERROR
+ *
+ * \note Even this function won't validate more options than actually
+ * necessary. Thus, it is possible that encoding the properties
+ * succeeds but using the same options to initialize the encoder
+ * will fail.
+ *
+ * \note It is OK to skip calling this function if
+ * lzma_properties_size() indicated that the size
+ * of the Filter Properties field is zero.
+ */
+extern lzma_ret lzma_properties_encode(
+ const lzma_filter *filter, uint8_t *props);
+
+
+/**
+ * \brief Decode the Filter Properties field
+ *
+ * \param filter filter->id must have been set to the correct
+ * Filter ID. filter->options doesn't need to be
+ * initialized (it's not freed by this function). The
+ * decoded options will be stored to filter->options.
+ * filter->options is set to NULL if there are no
+ * properties or if an error occurs.
+ * \param allocator Custom memory allocator used to allocate the
+ * options. Set to NULL to use the default malloc(),
+ * and in case of an error, also free().
+ * \param props Input buffer containing the properties.
+ * \param props_size Size of the properties. This must be the exact
+ * size; giving too much or too little input will
+ * return LZMA_HEADER_ERROR.
+ *
+ * \return - LZMA_OK
+ * - LZMA_HEADER_ERROR
+ * - LZMA_MEM_ERROR
+ */
+extern lzma_ret lzma_properties_decode(
+ lzma_filter *filter, lzma_allocator *allocator,
+ const uint8_t *props, size_t props_size);
+
+
/**
* \brief Calculates encoded size of a Filter Flags field
*
/// Both lzma_filter_encoder and lzma_filter_decoder begin with these members.
typedef struct {
+ /// Filter ID
+ lzma_vli id;
+
/// Initializes the filter encoder and calls lzma_next_filter_init()
/// for filters + 1.
lzma_init_function init;
typedef struct {
+ /// Filter ID
+ lzma_vli id;
+
/// Initializes the filter encoder and calls lzma_next_filter_init()
/// for filters + 1.
lzma_init_function init;
} lzma_filter_decoder;
-static const lzma_vli ids[] = {
-#ifdef HAVE_DECODER_LZMA
- LZMA_FILTER_LZMA,
-#endif
-
-#ifdef HAVE_DECODER_LZMA2
- LZMA_FILTER_LZMA2,
-#endif
-
-#ifdef HAVE_DECODER_SUBBLOCK
- LZMA_FILTER_SUBBLOCK,
- LZMA_FILTER_SUBBLOCK_HELPER,
-#endif
-
-#ifdef HAVE_DECODER_X86
- LZMA_FILTER_X86,
-#endif
-
-#ifdef HAVE_DECODER_POWERPC
- LZMA_FILTER_POWERPC,
-#endif
-
-#ifdef HAVE_DECODER_IA64
- LZMA_FILTER_IA64,
-#endif
-
-#ifdef HAVE_DECODER_ARM
- LZMA_FILTER_ARM,
-#endif
-
-#ifdef HAVE_DECODER_ARMTHUMB
- LZMA_FILTER_ARMTHUMB,
-#endif
-
-#ifdef HAVE_DECODER_SPARC
- LZMA_FILTER_SPARC,
-#endif
-
-#ifdef HAVE_DECODER_DELTA
- LZMA_FILTER_DELTA,
-#endif
-
- LZMA_VLI_VALUE_UNKNOWN
-};
-
-
-// Using a pointer to avoid putting the size of the array to API/ABI.
-LZMA_API const lzma_vli *const lzma_filter_decoders = ids;
-
-
-// These must be in the same order as ids[].
-static const lzma_filter_decoder funcs[] = {
+static const lzma_filter_decoder decoders[] = {
#ifdef HAVE_DECODER_LZMA
{
+ .id = LZMA_FILTER_LZMA,
.init = &lzma_lzma_decoder_init,
.memusage = &lzma_lzma_decoder_memusage,
.props_decode = &lzma_lzma_props_decode,
#endif
#ifdef HAVE_DECODER_LZMA2
{
+ .id = LZMA_FILTER_LZMA2,
.init = &lzma_lzma2_decoder_init,
.memusage = &lzma_lzma2_decoder_memusage,
.props_decode = &lzma_lzma2_props_decode,
#endif
#ifdef HAVE_DECODER_SUBBLOCK
{
+ .id = LZMA_FILTER_SUBBLOCK,
.init = &lzma_subblock_decoder_init,
// .memusage = &lzma_subblock_decoder_memusage,
.props_decode = NULL,
},
{
+ .id = LZMA_FILTER_SUBBLOCK_HELPER,
.init = &lzma_subblock_decoder_helper_init,
.memusage = NULL,
.props_decode = NULL,
#endif
#ifdef HAVE_DECODER_X86
{
+ .id = LZMA_FILTER_X86,
.init = &lzma_simple_x86_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_POWERPC
{
+ .id = LZMA_FILTER_POWERPC,
.init = &lzma_simple_powerpc_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_IA64
{
+ .id = LZMA_FILTER_IA64,
.init = &lzma_simple_ia64_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_ARM
{
+ .id = LZMA_FILTER_ARM,
.init = &lzma_simple_arm_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_ARMTHUMB
{
+ .id = LZMA_FILTER_ARMTHUMB,
.init = &lzma_simple_armthumb_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_SPARC
{
+ .id = LZMA_FILTER_SPARC,
.init = &lzma_simple_sparc_decoder_init,
.memusage = NULL,
.props_decode = &lzma_simple_props_decode,
#endif
#ifdef HAVE_DECODER_DELTA
{
+ .id = LZMA_FILTER_DELTA,
.init = &lzma_delta_decoder_init,
.memusage = NULL,
.props_decode = &lzma_delta_props_decode,
static const lzma_filter_decoder *
decoder_find(lzma_vli id)
{
- for (size_t i = 0; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
- if (ids[i] == id)
- return funcs + i;
+ for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i)
+ if (decoders[i].id == id)
+ return decoders + i;
return NULL;
}
+extern LZMA_API lzma_bool
+lzma_filter_decoder_is_supported(lzma_vli id)
+{
+ return decoder_find(id) != NULL;
+}
+
+
extern lzma_ret
lzma_raw_decoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter *options)
#include "common.h"
-// FIXME !!! Public API
-extern lzma_ret lzma_properties_decode(
- lzma_filter *filter, lzma_allocator *allocator,
- const uint8_t *props, size_t props_size);
-
extern lzma_ret lzma_raw_decoder_init(
lzma_next_coder *next, lzma_allocator *allocator,
typedef struct {
+ /// Filter ID
+ lzma_vli id;
+
/// Initializes the filter encoder and calls lzma_next_filter_init()
/// for filters + 1.
lzma_init_function init;
} lzma_filter_encoder;
-static const lzma_vli ids[] = {
-#ifdef HAVE_ENCODER_LZMA
- LZMA_FILTER_LZMA,
-#endif
-
-#ifdef HAVE_ENCODER_LZMA2
- LZMA_FILTER_LZMA2,
-#endif
-
-#ifdef HAVE_ENCODER_SUBBLOCK
- LZMA_FILTER_SUBBLOCK,
-#endif
-
-#ifdef HAVE_ENCODER_X86
- LZMA_FILTER_X86,
-#endif
-
-#ifdef HAVE_ENCODER_POWERPC
- LZMA_FILTER_POWERPC,
-#endif
-
-#ifdef HAVE_ENCODER_IA64
- LZMA_FILTER_IA64,
-#endif
-
-#ifdef HAVE_ENCODER_ARM
- LZMA_FILTER_ARM,
-#endif
-
-#ifdef HAVE_ENCODER_ARMTHUMB
- LZMA_FILTER_ARMTHUMB,
-#endif
-
-#ifdef HAVE_ENCODER_SPARC
- LZMA_FILTER_SPARC,
-#endif
-
-#ifdef HAVE_ENCODER_DELTA
- LZMA_FILTER_DELTA,
-#endif
-
- LZMA_VLI_VALUE_UNKNOWN
-};
-
-
-// Using a pointer to avoid putting the size of the array to API/ABI.
-LZMA_API const lzma_vli *const lzma_filter_encoders = ids;
-
-
-// These must be in the same order as ids[].
-static const lzma_filter_encoder funcs[] = {
+static const lzma_filter_encoder encoders[] = {
#ifdef HAVE_ENCODER_LZMA
{
+ .id = LZMA_FILTER_LZMA,
.init = &lzma_lzma_encoder_init,
.memusage = &lzma_lzma_encoder_memusage,
.chunk_size = NULL, // FIXME
#endif
#ifdef HAVE_ENCODER_LZMA2
{
+ .id = LZMA_FILTER_LZMA2,
.init = &lzma_lzma2_encoder_init,
.memusage = &lzma_lzma2_encoder_memusage,
.chunk_size = NULL, // FIXME
#endif
#ifdef HAVE_ENCODER_SUBBLOCK
{
+ .id = LZMA_FILTER_SUBBLOCK,
.init = &lzma_subblock_encoder_init,
// .memusage = &lzma_subblock_encoder_memusage,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_X86
{
+ .id = LZMA_FILTER_X86,
.init = &lzma_simple_x86_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_POWERPC
{
+ .id = LZMA_FILTER_POWERPC,
.init = &lzma_simple_powerpc_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_IA64
{
+ .id = LZMA_FILTER_IA64,
.init = &lzma_simple_ia64_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_ARM
{
+ .id = LZMA_FILTER_ARM,
.init = &lzma_simple_arm_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_ARMTHUMB
{
+ .id = LZMA_FILTER_ARMTHUMB,
.init = &lzma_simple_armthumb_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_SPARC
{
+ .id = LZMA_FILTER_SPARC,
.init = &lzma_simple_sparc_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
#endif
#ifdef HAVE_ENCODER_DELTA
{
+ .id = LZMA_FILTER_DELTA,
.init = &lzma_delta_encoder_init,
.memusage = NULL,
.chunk_size = NULL,
static const lzma_filter_encoder *
encoder_find(lzma_vli id)
{
- for (size_t i = 0; ids[i] != LZMA_VLI_VALUE_UNKNOWN; ++i)
- if (ids[i] == id)
- return funcs + i;
+ for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i)
+ if (encoders[i].id == id)
+ return encoders + i;
return NULL;
}
+extern LZMA_API lzma_bool
+lzma_filter_encoder_is_supported(lzma_vli id)
+{
+ return encoder_find(id) != NULL;
+}
+
+
extern lzma_ret
lzma_raw_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
const lzma_filter *options)
extern LZMA_API lzma_vli
lzma_chunk_size(const lzma_filter *filters)
{
- uint64_t max = 0;
+ lzma_vli max = 0;
for (size_t i = 0; filters[i].id != LZMA_VLI_VALUE_UNKNOWN; ++i) {
const lzma_filter_encoder *const fe
}
if (fe->props_size_get == NULL) {
- // No props_size() function, use props_size_fixed.
+ // No props_size_get() function, use props_size_fixed.
*size = fe->props_size_fixed;
return LZMA_OK;
}
// FIXME !!! Public API
extern lzma_vli lzma_chunk_size(const lzma_filter *filters);
-extern lzma_ret lzma_properties_size(
- uint32_t *size, const lzma_filter *filter);
-extern lzma_ret lzma_properties_encode(
- const lzma_filter *filter, uint8_t *props);
extern lzma_ret lzma_raw_encoder_init(