From 123ab0acec435c9e9866a99e30482116cfbd9ba5 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Wed, 10 Sep 2008 16:44:32 +0300 Subject: [PATCH] Filter handling cleanups --- src/liblzma/api/lzma/filter.h | 133 +++++++++++++++++++++------- src/liblzma/common/filter_common.h | 3 + src/liblzma/common/filter_decoder.c | 80 ++++++----------- src/liblzma/common/filter_decoder.h | 5 -- src/liblzma/common/filter_encoder.c | 82 ++++++----------- src/liblzma/common/filter_encoder.h | 4 - 6 files changed, 156 insertions(+), 151 deletions(-) diff --git a/src/liblzma/api/lzma/filter.h b/src/liblzma/api/lzma/filter.h index d5903f8..f9c30d5 100644 --- a/src/liblzma/api/lzma/filter.h +++ b/src/liblzma/api/lzma/filter.h @@ -55,59 +55,55 @@ typedef struct { /** - * \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. * @@ -131,11 +127,12 @@ extern lzma_ret lzma_raw_encoder( /** - * \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 @@ -147,6 +144,80 @@ extern lzma_ret lzma_raw_decoder( 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 * diff --git a/src/liblzma/common/filter_common.h b/src/liblzma/common/filter_common.h index 9def50b..5241e5d 100644 --- a/src/liblzma/common/filter_common.h +++ b/src/liblzma/common/filter_common.h @@ -25,6 +25,9 @@ /// 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; diff --git a/src/liblzma/common/filter_decoder.c b/src/liblzma/common/filter_decoder.c index 5eb6d77..fb5632e 100644 --- a/src/liblzma/common/filter_decoder.c +++ b/src/liblzma/common/filter_decoder.c @@ -28,6 +28,9 @@ typedef struct { + /// Filter ID + lzma_vli id; + /// Initializes the filter encoder and calls lzma_next_filter_init() /// for filters + 1. lzma_init_function init; @@ -47,60 +50,10 @@ typedef struct { } 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, @@ -108,6 +61,7 @@ static const lzma_filter_decoder funcs[] = { #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, @@ -115,11 +69,13 @@ static const lzma_filter_decoder funcs[] = { #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, @@ -127,6 +83,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_X86 { + .id = LZMA_FILTER_X86, .init = &lzma_simple_x86_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -134,6 +91,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_POWERPC { + .id = LZMA_FILTER_POWERPC, .init = &lzma_simple_powerpc_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -141,6 +99,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_IA64 { + .id = LZMA_FILTER_IA64, .init = &lzma_simple_ia64_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -148,6 +107,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_ARM { + .id = LZMA_FILTER_ARM, .init = &lzma_simple_arm_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -155,6 +115,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_ARMTHUMB { + .id = LZMA_FILTER_ARMTHUMB, .init = &lzma_simple_armthumb_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -162,6 +123,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_SPARC { + .id = LZMA_FILTER_SPARC, .init = &lzma_simple_sparc_decoder_init, .memusage = NULL, .props_decode = &lzma_simple_props_decode, @@ -169,6 +131,7 @@ static const lzma_filter_decoder funcs[] = { #endif #ifdef HAVE_DECODER_DELTA { + .id = LZMA_FILTER_DELTA, .init = &lzma_delta_decoder_init, .memusage = NULL, .props_decode = &lzma_delta_props_decode, @@ -180,14 +143,21 @@ static const lzma_filter_decoder funcs[] = { 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) diff --git a/src/liblzma/common/filter_decoder.h b/src/liblzma/common/filter_decoder.h index 33e491d..6d651e6 100644 --- a/src/liblzma/common/filter_decoder.h +++ b/src/liblzma/common/filter_decoder.h @@ -22,11 +22,6 @@ #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, diff --git a/src/liblzma/common/filter_encoder.c b/src/liblzma/common/filter_encoder.c index 55862e1..8f2c517 100644 --- a/src/liblzma/common/filter_encoder.c +++ b/src/liblzma/common/filter_encoder.c @@ -27,6 +27,9 @@ typedef struct { + /// Filter ID + lzma_vli id; + /// Initializes the filter encoder and calls lzma_next_filter_init() /// for filters + 1. lzma_init_function init; @@ -58,59 +61,10 @@ typedef struct { } 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 @@ -121,6 +75,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_LZMA2 { + .id = LZMA_FILTER_LZMA2, .init = &lzma_lzma2_encoder_init, .memusage = &lzma_lzma2_encoder_memusage, .chunk_size = NULL, // FIXME @@ -131,6 +86,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_SUBBLOCK { + .id = LZMA_FILTER_SUBBLOCK, .init = &lzma_subblock_encoder_init, // .memusage = &lzma_subblock_encoder_memusage, .chunk_size = NULL, @@ -141,6 +97,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_X86 { + .id = LZMA_FILTER_X86, .init = &lzma_simple_x86_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -150,6 +107,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_POWERPC { + .id = LZMA_FILTER_POWERPC, .init = &lzma_simple_powerpc_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -159,6 +117,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_IA64 { + .id = LZMA_FILTER_IA64, .init = &lzma_simple_ia64_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -168,6 +127,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_ARM { + .id = LZMA_FILTER_ARM, .init = &lzma_simple_arm_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -177,6 +137,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_ARMTHUMB { + .id = LZMA_FILTER_ARMTHUMB, .init = &lzma_simple_armthumb_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -186,6 +147,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_SPARC { + .id = LZMA_FILTER_SPARC, .init = &lzma_simple_sparc_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -195,6 +157,7 @@ static const lzma_filter_encoder funcs[] = { #endif #ifdef HAVE_ENCODER_DELTA { + .id = LZMA_FILTER_DELTA, .init = &lzma_delta_encoder_init, .memusage = NULL, .chunk_size = NULL, @@ -209,14 +172,21 @@ static const lzma_filter_encoder funcs[] = { 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) @@ -251,7 +221,7 @@ lzma_memusage_encoder(const lzma_filter *filters) 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 @@ -285,7 +255,7 @@ lzma_properties_size(uint32_t *size, const lzma_filter *filter) } 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; } diff --git a/src/liblzma/common/filter_encoder.h b/src/liblzma/common/filter_encoder.h index b2bf851..5520125 100644 --- a/src/liblzma/common/filter_encoder.h +++ b/src/liblzma/common/filter_encoder.h @@ -25,10 +25,6 @@ // 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( -- 2.39.2