coder.c (207842) | coder.c (213700) |
---|---|
1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file coder.c 4/// \brief Compresses or uncompresses a file 5// 6// Author: Lasse Collin 7// 8// This file has been put into the public domain. --- 8 unchanged lines hidden (view full) --- 17enum coder_init_ret { 18 CODER_INIT_NORMAL, 19 CODER_INIT_PASSTHRU, 20 CODER_INIT_ERROR, 21}; 22 23 24enum operation_mode opt_mode = MODE_COMPRESS; | 1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file coder.c 4/// \brief Compresses or uncompresses a file 5// 6// Author: Lasse Collin 7// 8// This file has been put into the public domain. --- 8 unchanged lines hidden (view full) --- 17enum coder_init_ret { 18 CODER_INIT_NORMAL, 19 CODER_INIT_PASSTHRU, 20 CODER_INIT_ERROR, 21}; 22 23 24enum operation_mode opt_mode = MODE_COMPRESS; |
25 | |
26enum format_type opt_format = FORMAT_AUTO; | 25enum format_type opt_format = FORMAT_AUTO; |
26bool opt_auto_adjust = true; |
|
27 28 29/// Stream used to communicate with liblzma 30static lzma_stream strm = LZMA_STREAM_INIT; 31 32/// Filters needed for all encoding all formats, and also decoding in raw data 33static lzma_filter filters[LZMA_FILTERS_MAX + 1]; 34 35/// Input and output buffers 36static io_buf in_buf; 37static io_buf out_buf; 38 39/// Number of filters. Zero indicates that we are using a preset. 40static size_t filters_count = 0; 41 42/// Number of the preset (0-9) 43static size_t preset_number = 6; 44 | 27 28 29/// Stream used to communicate with liblzma 30static lzma_stream strm = LZMA_STREAM_INIT; 31 32/// Filters needed for all encoding all formats, and also decoding in raw data 33static lzma_filter filters[LZMA_FILTERS_MAX + 1]; 34 35/// Input and output buffers 36static io_buf in_buf; 37static io_buf out_buf; 38 39/// Number of filters. Zero indicates that we are using a preset. 40static size_t filters_count = 0; 41 42/// Number of the preset (0-9) 43static size_t preset_number = 6; 44 |
45/// True if we should auto-adjust the compression settings to use less memory 46/// if memory usage limit is too low for the original settings. 47static bool auto_adjust = true; 48 49/// Indicate if no preset has been explicitly given. In that case, if we need 50/// to auto-adjust for lower memory usage, we won't print a warning. 51static bool preset_default = true; 52 | |
53/// If a preset is used (no custom filter chain) and preset_extreme is true, 54/// a significantly slower compression is used to achieve slightly better 55/// compression ratio. 56static bool preset_extreme = false; 57 58/// Integrity check type 59static lzma_check check; 60 --- 9 unchanged lines hidden (view full) --- 70 return; 71} 72 73 74extern void 75coder_set_preset(size_t new_preset) 76{ 77 preset_number = new_preset; | 45/// If a preset is used (no custom filter chain) and preset_extreme is true, 46/// a significantly slower compression is used to achieve slightly better 47/// compression ratio. 48static bool preset_extreme = false; 49 50/// Integrity check type 51static lzma_check check; 52 --- 9 unchanged lines hidden (view full) --- 62 return; 63} 64 65 66extern void 67coder_set_preset(size_t new_preset) 68{ 69 preset_number = new_preset; |
78 preset_default = false; | 70 71 // Setting a preset makes us forget a possibly defined custom 72 // filter chain. 73 while (filters_count > 0) { 74 --filters_count; 75 free(filters[filters_count].options); 76 filters[filters_count].options = NULL; 77 } 78 |
79 return; 80} 81 82 83extern void 84coder_set_extreme(void) 85{ 86 preset_extreme = true; --- 53 unchanged lines hidden (view full) --- 140 if (lzma_lzma_preset(&opt_lzma, preset_number)) 141 message_bug(); 142 143 // Use LZMA2 except with --format=lzma we use LZMA1. 144 filters[0].id = opt_format == FORMAT_LZMA 145 ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2; 146 filters[0].options = &opt_lzma; 147 filters_count = 1; | 79 return; 80} 81 82 83extern void 84coder_set_extreme(void) 85{ 86 preset_extreme = true; --- 53 unchanged lines hidden (view full) --- 140 if (lzma_lzma_preset(&opt_lzma, preset_number)) 141 message_bug(); 142 143 // Use LZMA2 except with --format=lzma we use LZMA1. 144 filters[0].id = opt_format == FORMAT_LZMA 145 ? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2; 146 filters[0].options = &opt_lzma; 147 filters_count = 1; |
148 } else { 149 preset_default = false; | |
150 } 151 152 // Terminate the filter options array. 153 filters[filters_count].id = LZMA_VLI_UNKNOWN; 154 155 // If we are using the .lzma format, allow exactly one filter 156 // which has to be LZMA1. 157 if (opt_format == FORMAT_LZMA && (filters_count != 1 --- 5 unchanged lines hidden (view full) --- 163 // filter to prevent LZMA_PROG_ERROR. 164 if (opt_format == FORMAT_XZ) 165 for (size_t i = 0; i < filters_count; ++i) 166 if (filters[i].id == LZMA_FILTER_LZMA1) 167 message_fatal(_("LZMA1 cannot be used " 168 "with the .xz format")); 169 170 // Print the selected filter chain. | 148 } 149 150 // Terminate the filter options array. 151 filters[filters_count].id = LZMA_VLI_UNKNOWN; 152 153 // If we are using the .lzma format, allow exactly one filter 154 // which has to be LZMA1. 155 if (opt_format == FORMAT_LZMA && (filters_count != 1 --- 5 unchanged lines hidden (view full) --- 161 // filter to prevent LZMA_PROG_ERROR. 162 if (opt_format == FORMAT_XZ) 163 for (size_t i = 0; i < filters_count; ++i) 164 if (filters[i].id == LZMA_FILTER_LZMA1) 165 message_fatal(_("LZMA1 cannot be used " 166 "with the .xz format")); 167 168 // Print the selected filter chain. |
171 message_filters(V_DEBUG, filters); | 169 message_filters_show(V_DEBUG, filters); |
172 173 // If using --format=raw, we can be decoding. The memusage function 174 // also validates the filter chain and the options used for the 175 // filters. | 170 171 // If using --format=raw, we can be decoding. The memusage function 172 // also validates the filter chain and the options used for the 173 // filters. |
176 const uint64_t memory_limit = hardware_memlimit_get(); | 174 const uint64_t memory_limit = hardware_memlimit_get(opt_mode); |
177 uint64_t memory_usage; 178 if (opt_mode == MODE_COMPRESS) 179 memory_usage = lzma_raw_encoder_memusage(filters); 180 else 181 memory_usage = lzma_raw_decoder_memusage(filters); 182 183 if (memory_usage == UINT64_MAX) 184 message_fatal(_("Unsupported filter chain or filter options")); 185 186 // Print memory usage info before possible dictionary 187 // size auto-adjusting. 188 message_mem_needed(V_DEBUG, memory_usage); | 175 uint64_t memory_usage; 176 if (opt_mode == MODE_COMPRESS) 177 memory_usage = lzma_raw_encoder_memusage(filters); 178 else 179 memory_usage = lzma_raw_decoder_memusage(filters); 180 181 if (memory_usage == UINT64_MAX) 182 message_fatal(_("Unsupported filter chain or filter options")); 183 184 // Print memory usage info before possible dictionary 185 // size auto-adjusting. 186 message_mem_needed(V_DEBUG, memory_usage); |
187 if (opt_mode == MODE_COMPRESS) { 188 const uint64_t decmem = lzma_raw_decoder_memusage(filters); 189 if (decmem != UINT64_MAX) 190 message(V_DEBUG, _("Decompression will need " 191 "%s MiB of memory."), uint64_to_str( 192 round_up_to_mib(decmem), 0)); 193 } |
|
189 190 if (memory_usage > memory_limit) { 191 // If --no-auto-adjust was used or we didn't find LZMA1 or 192 // LZMA2 as the last filter, give an error immediately. 193 // --format=raw implies --no-auto-adjust. | 194 195 if (memory_usage > memory_limit) { 196 // If --no-auto-adjust was used or we didn't find LZMA1 or 197 // LZMA2 as the last filter, give an error immediately. 198 // --format=raw implies --no-auto-adjust. |
194 if (!auto_adjust || opt_format == FORMAT_RAW) | 199 if (!opt_auto_adjust || opt_format == FORMAT_RAW) |
195 memlimit_too_small(memory_usage); 196 197 assert(opt_mode == MODE_COMPRESS); 198 199 // Look for the last filter if it is LZMA2 or LZMA1, so 200 // we can make it use less RAM. With other filters we don't 201 // know what to do. 202 size_t i = 0; --- 31 unchanged lines hidden (view full) --- 234 235 // Otherwise 1 MiB down and try again. I hope this 236 // isn't too slow method for cases where the original 237 // dict_size is very big. 238 opt->dict_size -= UINT32_C(1) << 20; 239 } 240 241 // Tell the user that we decreased the dictionary size. | 200 memlimit_too_small(memory_usage); 201 202 assert(opt_mode == MODE_COMPRESS); 203 204 // Look for the last filter if it is LZMA2 or LZMA1, so 205 // we can make it use less RAM. With other filters we don't 206 // know what to do. 207 size_t i = 0; --- 31 unchanged lines hidden (view full) --- 239 240 // Otherwise 1 MiB down and try again. I hope this 241 // isn't too slow method for cases where the original 242 // dict_size is very big. 243 opt->dict_size -= UINT32_C(1) << 20; 244 } 245 246 // Tell the user that we decreased the dictionary size. |
242 // However, omit the message if no preset or custom chain 243 // was given. FIXME: Always warn? 244 if (!preset_default) 245 message(V_WARNING, _("Adjusted LZMA%c dictionary size " 246 "from %s MiB to %s MiB to not exceed " 247 "the memory usage limit of %s MiB"), 248 filters[i].id == LZMA_FILTER_LZMA2 249 ? '2' : '1', 250 uint64_to_str(orig_dict_size >> 20, 0), 251 uint64_to_str(opt->dict_size >> 20, 1), 252 uint64_to_str(round_up_to_mib( 253 memory_limit), 2)); | 247 message(V_WARNING, _("Adjusted LZMA%c dictionary size " 248 "from %s MiB to %s MiB to not exceed " 249 "the memory usage limit of %s MiB"), 250 filters[i].id == LZMA_FILTER_LZMA2 251 ? '2' : '1', 252 uint64_to_str(orig_dict_size >> 20, 0), 253 uint64_to_str(opt->dict_size >> 20, 1), 254 uint64_to_str(round_up_to_mib( 255 memory_limit), 2)); |
254 } 255 256/* 257 // Limit the number of worker threads so that memory usage 258 // limit isn't exceeded. 259 assert(memory_usage > 0); 260 size_t thread_limit = memory_limit / memory_usage; 261 if (thread_limit == 0) --- 143 unchanged lines hidden (view full) --- 405 && opt_stdout && opt_force) 406 return CODER_INIT_PASSTHRU; 407 408 ret = LZMA_FORMAT_ERROR; 409 break; 410 411 case FORMAT_XZ: 412 ret = lzma_stream_decoder(&strm, | 256 } 257 258/* 259 // Limit the number of worker threads so that memory usage 260 // limit isn't exceeded. 261 assert(memory_usage > 0); 262 size_t thread_limit = memory_limit / memory_usage; 263 if (thread_limit == 0) --- 143 unchanged lines hidden (view full) --- 407 && opt_stdout && opt_force) 408 return CODER_INIT_PASSTHRU; 409 410 ret = LZMA_FORMAT_ERROR; 411 break; 412 413 case FORMAT_XZ: 414 ret = lzma_stream_decoder(&strm, |
413 hardware_memlimit_get(), flags); | 415 hardware_memlimit_get( 416 MODE_DECOMPRESS), flags); |
414 break; 415 416 case FORMAT_LZMA: 417 ret = lzma_alone_decoder(&strm, | 417 break; 418 419 case FORMAT_LZMA: 420 ret = lzma_alone_decoder(&strm, |
418 hardware_memlimit_get()); | 421 hardware_memlimit_get( 422 MODE_DECOMPRESS)); |
419 break; 420 421 case FORMAT_RAW: 422 // Memory usage has already been checked in 423 // coder_set_compression_settings(). 424 ret = lzma_raw_decoder(&strm, filters); 425 break; 426 } --- 233 unchanged lines hidden --- | 423 break; 424 425 case FORMAT_RAW: 426 // Memory usage has already been checked in 427 // coder_set_compression_settings(). 428 ret = lzma_raw_decoder(&strm, filters); 429 break; 430 } --- 233 unchanged lines hidden --- |