aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/liblzma/common/filter_flags_encoder.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/src/liblzma/common/filter_flags_encoder.c b/src/liblzma/common/filter_flags_encoder.c
index d8f260a1..2d11dd3a 100644
--- a/src/liblzma/common/filter_flags_encoder.c
+++ b/src/liblzma/common/filter_flags_encoder.c
@@ -19,6 +19,7 @@
#include "common.h"
#include "lzma_encoder.h"
+#include "fastpos.h"
/// \brief Calculates the size of the Filter Properties field
@@ -204,35 +205,32 @@ properties_lzma(uint8_t *out, size_t *out_pos, size_t out_size,
// Dictionary flags
//
- // Dictionary size is encoded using six bits of
- // which one is mantissa and five are exponent.
+ // Dictionary size is encoded using similar encoding that is used
+ // internally by LZMA.
//
- // There are some limits that must hold to keep
- // this coding working.
-# if LZMA_DICTIONARY_SIZE_MAX > UINT32_MAX / 2
-# error LZMA_DICTIONARY_SIZE_MAX is too big.
-# endif
+ // This won't work if dictionary size can be zero:
# if LZMA_DICTIONARY_SIZE_MIN < 1
# error LZMA_DICTIONARY_SIZE_MIN cannot be zero.
# endif
+ uint32_t d = options->dictionary_size;
+
// Validate it:
- if (options->dictionary_size < LZMA_DICTIONARY_SIZE_MIN
- || options->dictionary_size > LZMA_DICTIONARY_SIZE_MAX)
+ if (d < LZMA_DICTIONARY_SIZE_MIN || d > LZMA_DICTIONARY_SIZE_MAX)
return LZMA_HEADER_ERROR;
- if (options->dictionary_size == 1) {
- // Special case
- out[*out_pos] = 0x00;
- } else {
- // TODO This could be more elegant.
- uint32_t i = 1;
- while (((2 | ((i + 1) & 1)) << ((i - 1) / 2))
- < options->dictionary_size)
- ++i;
- out[*out_pos] = i;
- }
-
+ // Round up to to the next 2^n or 2^n + 2^(n - 1) depending on which
+ // one is the next:
+ --d;
+ d |= d >> 2;
+ d |= d >> 3;
+ d |= d >> 4;
+ d |= d >> 8;
+ d |= d >> 16;
+ ++d;
+
+ // Get the highest two bits using the proper encoding:
+ out[*out_pos] = get_pos_slot(d) - 1;
++*out_pos;
return LZMA_OK;