1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file filter_decoder.c 4207753Smm/// \brief Filter ID mapping to filter-specific functions 5207753Smm// 6207753Smm// Author: Lasse Collin 7207753Smm// 8207753Smm// This file has been put into the public domain. 9207753Smm// You can do whatever you want with this file. 10207753Smm// 11207753Smm/////////////////////////////////////////////////////////////////////////////// 12207753Smm 13207753Smm#include "filter_encoder.h" 14207753Smm#include "filter_common.h" 15207753Smm#include "lzma_encoder.h" 16207753Smm#include "lzma2_encoder.h" 17207753Smm#include "simple_encoder.h" 18207753Smm#include "delta_encoder.h" 19207753Smm 20207753Smm 21207753Smmtypedef struct { 22207753Smm /// Filter ID 23207753Smm lzma_vli id; 24207753Smm 25207753Smm /// Initializes the filter encoder and calls lzma_next_filter_init() 26207753Smm /// for filters + 1. 27207753Smm lzma_init_function init; 28207753Smm 29207753Smm /// Calculates memory usage of the encoder. If the options are 30207753Smm /// invalid, UINT64_MAX is returned. 31207753Smm uint64_t (*memusage)(const void *options); 32207753Smm 33292588Sdelphij /// Calculates the recommended Uncompressed Size for .xz Blocks to 34292588Sdelphij /// which the input data can be split to make multithreaded 35292588Sdelphij /// encoding possible. If this is NULL, it is assumed that 36292588Sdelphij /// the encoder is fast enough with single thread. 37292588Sdelphij uint64_t (*block_size)(const void *options); 38207753Smm 39207753Smm /// Tells the size of the Filter Properties field. If options are 40207753Smm /// invalid, UINT32_MAX is returned. If this is NULL, props_size_fixed 41207753Smm /// is used. 42207753Smm lzma_ret (*props_size_get)(uint32_t *size, const void *options); 43207753Smm uint32_t props_size_fixed; 44207753Smm 45207753Smm /// Encodes Filter Properties. 46207753Smm /// 47207753Smm /// \return - LZMA_OK: Properties encoded successfully. 48207753Smm /// - LZMA_OPTIONS_ERROR: Unsupported options 49207753Smm /// - LZMA_PROG_ERROR: Invalid options or not enough 50207753Smm /// output space 51207753Smm lzma_ret (*props_encode)(const void *options, uint8_t *out); 52207753Smm 53207753Smm} lzma_filter_encoder; 54207753Smm 55207753Smm 56207753Smmstatic const lzma_filter_encoder encoders[] = { 57207753Smm#ifdef HAVE_ENCODER_LZMA1 58207753Smm { 59207753Smm .id = LZMA_FILTER_LZMA1, 60207753Smm .init = &lzma_lzma_encoder_init, 61207753Smm .memusage = &lzma_lzma_encoder_memusage, 62292588Sdelphij .block_size = NULL, // FIXME 63207753Smm .props_size_get = NULL, 64207753Smm .props_size_fixed = 5, 65207753Smm .props_encode = &lzma_lzma_props_encode, 66207753Smm }, 67207753Smm#endif 68207753Smm#ifdef HAVE_ENCODER_LZMA2 69207753Smm { 70207753Smm .id = LZMA_FILTER_LZMA2, 71207753Smm .init = &lzma_lzma2_encoder_init, 72207753Smm .memusage = &lzma_lzma2_encoder_memusage, 73292588Sdelphij .block_size = &lzma_lzma2_block_size, // FIXME 74207753Smm .props_size_get = NULL, 75207753Smm .props_size_fixed = 1, 76207753Smm .props_encode = &lzma_lzma2_props_encode, 77207753Smm }, 78207753Smm#endif 79207753Smm#ifdef HAVE_ENCODER_X86 80207753Smm { 81207753Smm .id = LZMA_FILTER_X86, 82207753Smm .init = &lzma_simple_x86_encoder_init, 83207753Smm .memusage = NULL, 84292588Sdelphij .block_size = NULL, 85207753Smm .props_size_get = &lzma_simple_props_size, 86207753Smm .props_encode = &lzma_simple_props_encode, 87207753Smm }, 88207753Smm#endif 89207753Smm#ifdef HAVE_ENCODER_POWERPC 90207753Smm { 91207753Smm .id = LZMA_FILTER_POWERPC, 92207753Smm .init = &lzma_simple_powerpc_encoder_init, 93207753Smm .memusage = NULL, 94292588Sdelphij .block_size = NULL, 95207753Smm .props_size_get = &lzma_simple_props_size, 96207753Smm .props_encode = &lzma_simple_props_encode, 97207753Smm }, 98207753Smm#endif 99207753Smm#ifdef HAVE_ENCODER_IA64 100207753Smm { 101207753Smm .id = LZMA_FILTER_IA64, 102207753Smm .init = &lzma_simple_ia64_encoder_init, 103207753Smm .memusage = NULL, 104292588Sdelphij .block_size = NULL, 105207753Smm .props_size_get = &lzma_simple_props_size, 106207753Smm .props_encode = &lzma_simple_props_encode, 107207753Smm }, 108207753Smm#endif 109207753Smm#ifdef HAVE_ENCODER_ARM 110207753Smm { 111207753Smm .id = LZMA_FILTER_ARM, 112207753Smm .init = &lzma_simple_arm_encoder_init, 113207753Smm .memusage = NULL, 114292588Sdelphij .block_size = NULL, 115207753Smm .props_size_get = &lzma_simple_props_size, 116207753Smm .props_encode = &lzma_simple_props_encode, 117207753Smm }, 118207753Smm#endif 119207753Smm#ifdef HAVE_ENCODER_ARMTHUMB 120207753Smm { 121207753Smm .id = LZMA_FILTER_ARMTHUMB, 122207753Smm .init = &lzma_simple_armthumb_encoder_init, 123207753Smm .memusage = NULL, 124292588Sdelphij .block_size = NULL, 125207753Smm .props_size_get = &lzma_simple_props_size, 126207753Smm .props_encode = &lzma_simple_props_encode, 127207753Smm }, 128207753Smm#endif 129207753Smm#ifdef HAVE_ENCODER_SPARC 130207753Smm { 131207753Smm .id = LZMA_FILTER_SPARC, 132207753Smm .init = &lzma_simple_sparc_encoder_init, 133207753Smm .memusage = NULL, 134292588Sdelphij .block_size = NULL, 135207753Smm .props_size_get = &lzma_simple_props_size, 136207753Smm .props_encode = &lzma_simple_props_encode, 137207753Smm }, 138207753Smm#endif 139207753Smm#ifdef HAVE_ENCODER_DELTA 140207753Smm { 141207753Smm .id = LZMA_FILTER_DELTA, 142207753Smm .init = &lzma_delta_encoder_init, 143207753Smm .memusage = &lzma_delta_coder_memusage, 144292588Sdelphij .block_size = NULL, 145207753Smm .props_size_get = NULL, 146207753Smm .props_size_fixed = 1, 147207753Smm .props_encode = &lzma_delta_props_encode, 148207753Smm }, 149207753Smm#endif 150207753Smm}; 151207753Smm 152207753Smm 153207753Smmstatic const lzma_filter_encoder * 154207753Smmencoder_find(lzma_vli id) 155207753Smm{ 156207753Smm for (size_t i = 0; i < ARRAY_SIZE(encoders); ++i) 157207753Smm if (encoders[i].id == id) 158207753Smm return encoders + i; 159207753Smm 160207753Smm return NULL; 161207753Smm} 162207753Smm 163207753Smm 164207753Smmextern LZMA_API(lzma_bool) 165207753Smmlzma_filter_encoder_is_supported(lzma_vli id) 166207753Smm{ 167207753Smm return encoder_find(id) != NULL; 168207753Smm} 169207753Smm 170207753Smm 171207753Smmextern LZMA_API(lzma_ret) 172207753Smmlzma_filters_update(lzma_stream *strm, const lzma_filter *filters) 173207753Smm{ 174207753Smm if (strm->internal->next.update == NULL) 175207753Smm return LZMA_PROG_ERROR; 176207753Smm 177207753Smm // Validate the filter chain. 178207753Smm if (lzma_raw_encoder_memusage(filters) == UINT64_MAX) 179207753Smm return LZMA_OPTIONS_ERROR; 180207753Smm 181207753Smm // The actual filter chain in the encoder is reversed. Some things 182207753Smm // still want the normal order chain, so we provide both. 183207753Smm size_t count = 1; 184207753Smm while (filters[count].id != LZMA_VLI_UNKNOWN) 185207753Smm ++count; 186207753Smm 187207753Smm lzma_filter reversed_filters[LZMA_FILTERS_MAX + 1]; 188207753Smm for (size_t i = 0; i < count; ++i) 189207753Smm reversed_filters[count - i - 1] = filters[i]; 190207753Smm 191207753Smm reversed_filters[count].id = LZMA_VLI_UNKNOWN; 192207753Smm 193207753Smm return strm->internal->next.update(strm->internal->next.coder, 194207753Smm strm->allocator, filters, reversed_filters); 195207753Smm} 196207753Smm 197207753Smm 198207753Smmextern lzma_ret 199292588Sdelphijlzma_raw_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 200207753Smm const lzma_filter *options) 201207753Smm{ 202207753Smm return lzma_raw_coder_init(next, allocator, 203207753Smm options, (lzma_filter_find)(&encoder_find), true); 204207753Smm} 205207753Smm 206207753Smm 207207753Smmextern LZMA_API(lzma_ret) 208207753Smmlzma_raw_encoder(lzma_stream *strm, const lzma_filter *options) 209207753Smm{ 210207753Smm lzma_next_strm_init(lzma_raw_coder_init, strm, options, 211207753Smm (lzma_filter_find)(&encoder_find), true); 212207753Smm 213207753Smm strm->internal->supported_actions[LZMA_RUN] = true; 214207753Smm strm->internal->supported_actions[LZMA_SYNC_FLUSH] = true; 215207753Smm strm->internal->supported_actions[LZMA_FINISH] = true; 216207753Smm 217207753Smm return LZMA_OK; 218207753Smm} 219207753Smm 220207753Smm 221207753Smmextern LZMA_API(uint64_t) 222207753Smmlzma_raw_encoder_memusage(const lzma_filter *filters) 223207753Smm{ 224207753Smm return lzma_raw_coder_memusage( 225207753Smm (lzma_filter_find)(&encoder_find), filters); 226207753Smm} 227207753Smm 228207753Smm 229292588Sdelphijextern uint64_t 230292588Sdelphijlzma_mt_block_size(const lzma_filter *filters) 231207753Smm{ 232292588Sdelphij uint64_t max = 0; 233207753Smm 234207753Smm for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) { 235207753Smm const lzma_filter_encoder *const fe 236207753Smm = encoder_find(filters[i].id); 237292588Sdelphij if (fe->block_size != NULL) { 238292588Sdelphij const uint64_t size 239292588Sdelphij = fe->block_size(filters[i].options); 240292588Sdelphij if (size == 0) 241292588Sdelphij return 0; 242207753Smm 243207753Smm if (size > max) 244207753Smm max = size; 245207753Smm } 246207753Smm } 247207753Smm 248207753Smm return max; 249207753Smm} 250207753Smm 251207753Smm 252207753Smmextern LZMA_API(lzma_ret) 253207753Smmlzma_properties_size(uint32_t *size, const lzma_filter *filter) 254207753Smm{ 255207753Smm const lzma_filter_encoder *const fe = encoder_find(filter->id); 256207753Smm if (fe == NULL) { 257207753Smm // Unknown filter - if the Filter ID is a proper VLI, 258207753Smm // return LZMA_OPTIONS_ERROR instead of LZMA_PROG_ERROR, 259207753Smm // because it's possible that we just don't have support 260207753Smm // compiled in for the requested filter. 261207753Smm return filter->id <= LZMA_VLI_MAX 262207753Smm ? LZMA_OPTIONS_ERROR : LZMA_PROG_ERROR; 263207753Smm } 264207753Smm 265207753Smm if (fe->props_size_get == NULL) { 266207753Smm // No props_size_get() function, use props_size_fixed. 267207753Smm *size = fe->props_size_fixed; 268207753Smm return LZMA_OK; 269207753Smm } 270207753Smm 271207753Smm return fe->props_size_get(size, filter->options); 272207753Smm} 273207753Smm 274207753Smm 275207753Smmextern LZMA_API(lzma_ret) 276207753Smmlzma_properties_encode(const lzma_filter *filter, uint8_t *props) 277207753Smm{ 278207753Smm const lzma_filter_encoder *const fe = encoder_find(filter->id); 279207753Smm if (fe == NULL) 280207753Smm return LZMA_PROG_ERROR; 281207753Smm 282207753Smm if (fe->props_encode == NULL) 283207753Smm return LZMA_OK; 284207753Smm 285207753Smm return fe->props_encode(filter->options, props); 286207753Smm} 287