aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/rangecoder/range_decoder.h
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2008-08-28 22:53:15 +0300
committerLasse Collin <lasse.collin@tukaani.org>2008-08-28 22:53:15 +0300
commit3b34851de1eaf358cf9268922fa0eeed8278d680 (patch)
tree7bab212af647541df64227a8d350d17a2e789f6b /src/liblzma/rangecoder/range_decoder.h
parentFix test_filter_flags to match the new restriction of lc+lp. (diff)
downloadxz-3b34851de1eaf358cf9268922fa0eeed8278d680.tar.xz
Sort of garbage collection commit. :-| Many things are still
broken. API has changed a lot and it will still change a little more here and there. The command line tool doesn't have all the required changes to reflect the API changes, so it's easy to get "internal error" or trigger assertions.
Diffstat (limited to 'src/liblzma/rangecoder/range_decoder.h')
-rw-r--r--src/liblzma/rangecoder/range_decoder.h209
1 files changed, 86 insertions, 123 deletions
diff --git a/src/liblzma/rangecoder/range_decoder.h b/src/liblzma/rangecoder/range_decoder.h
index 62162448..ca2d392e 100644
--- a/src/liblzma/rangecoder/range_decoder.h
+++ b/src/liblzma/rangecoder/range_decoder.h
@@ -31,6 +31,7 @@ typedef struct {
} lzma_range_decoder;
+/// Reads the first five bytes to initialize the range decoder.
static inline bool
rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
size_t *restrict in_pos, size_t in_size)
@@ -48,14 +49,22 @@ rc_read_init(lzma_range_decoder *rc, const uint8_t *restrict in,
}
-/// Makes local copies of range decoder variables.
-#define rc_to_local(range_decoder) \
+/// Makes local copies of range decoder and *in_pos variables. Doing this
+/// improves speed significantly. The range decoder macros expect also
+/// variables `in' and `in_size' to be defined.
+#define rc_to_local(range_decoder, in_pos) \
lzma_range_decoder rc = range_decoder; \
+ size_t rc_in_pos = (in_pos); \
uint32_t rc_bound
+
/// Stores the local copes back to the range decoder structure.
-#define rc_from_local(range_decoder) \
- range_decoder = rc
+#define rc_from_local(range_decoder, in_pos) \
+do { \
+ range_decoder = rc; \
+ in_pos = rc_in_pos; \
+} while (0)
+
/// Resets the range decoder structure.
#define rc_reset(range_decoder) \
@@ -66,158 +75,112 @@ do { \
} while (0)
-// All of the macros in this file expect the following variables being defined:
-// - lzma_range_decoder range_decoder;
-// - uint32_t rc_bound; // Temporary variable
-// - uint8_t *in;
-// - size_t in_pos_local; // Local alias for *in_pos
-
+/// When decoding has been properly finished, rc.code is always zero unless
+/// the input stream is corrupt. So checking this can catch some corrupt
+/// files especially if they don't have any other integrity check.
+#define rc_is_finished(range_decoder) \
+ ((range_decoder).code == 0)
-//////////////////
-// Buffer "I/O" //
-//////////////////
-// Read the next byte of compressed data from buffer_in, if needed.
-#define rc_normalize() \
+/// Read the next input byte if needed. If more input is needed but there is
+/// no more input available, "goto out" is used to jump out of the main
+/// decoder loop.
+#define rc_normalize(seq) \
do { \
- if (rc.range < TOP_VALUE) { \
- rc.range <<= SHIFT_BITS; \
- rc.code = (rc.code << SHIFT_BITS) | in[in_pos_local++]; \
+ if (rc.range < RC_TOP_VALUE) { \
+ if (unlikely(rc_in_pos == in_size)) { \
+ coder->sequence = seq; \
+ goto out; \
+ } \
+ rc.range <<= RC_SHIFT_BITS; \
+ rc.code = (rc.code << RC_SHIFT_BITS) | in[rc_in_pos++]; \
} \
} while (0)
-//////////////////
-// Bit decoding //
-//////////////////
-
-// Range decoder's DecodeBit() is splitted into three macros:
-// if_bit_0(prob) {
-// update_bit_0(prob)
-// ...
-// } else {
-// update_bit_1(prob)
-// ...
-// }
-
-#define if_bit_0(prob) \
- rc_normalize(); \
- rc_bound = (rc.range >> BIT_MODEL_TOTAL_BITS) * (prob); \
+/// Start decoding a bit. This must be used together with rc_update_0()
+/// and rc_update_1():
+///
+/// rc_if_0(prob, seq) {
+/// rc_update_0(prob);
+/// // Do something
+/// } else {
+/// rc_update_1(prob);
+/// // Do something else
+/// }
+///
+#define rc_if_0(prob, seq) \
+ rc_normalize(seq); \
+ rc_bound = (rc.range >> RC_BIT_MODEL_TOTAL_BITS) * (prob); \
if (rc.code < rc_bound)
-#define update_bit_0(prob) \
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 0.
+#define rc_update_0(prob) \
do { \
rc.range = rc_bound; \
- prob += (BIT_MODEL_TOTAL - (prob)) >> MOVE_BITS; \
+ prob += (RC_BIT_MODEL_TOTAL - (prob)) >> RC_MOVE_BITS; \
} while (0)
-#define update_bit_1(prob) \
+/// Update the range decoder state and the used probability variable to
+/// match a decoded bit of 1.
+#define rc_update_1(prob) \
do { \
rc.range -= rc_bound; \
rc.code -= rc_bound; \
- prob -= (prob) >> MOVE_BITS; \
+ prob -= (prob) >> RC_MOVE_BITS; \
} while (0)
-#define rc_decode_direct(dest, count) \
+/// Decodes one bit and runs action0 or action1 depending on the decoded bit.
+/// This macro is used as the last step in bittree reverse decoders since
+/// those don't use "symbol" for anything else than indexing the probability
+/// arrays.
+#define rc_bit_last(prob, action0, action1, seq) \
do { \
- rc_normalize(); \
- rc.range >>= 1; \
- rc.code -= rc.range; \
- rc_bound = UINT32_C(0) - (rc.code >> 31); \
- rc.code += rc.range & rc_bound; \
- dest = (dest << 1) + (rc_bound + 1); \
-} while (--count > 0)
+ rc_if_0(prob, seq) { \
+ rc_update_0(prob); \
+ action0; \
+ } else { \
+ rc_update_1(prob); \
+ action1; \
+ } \
+} while (0)
-// Dummy versions don't update prob or dest.
-#define update_bit_0_dummy() \
- rc.range = rc_bound
+/// Decodes one bit, updates "symbol", and runs action0 or action1 depending
+/// on the decoded bit.
+#define rc_bit(prob, action0, action1, seq) \
+ rc_bit_last(prob, \
+ symbol <<= 1; action0, \
+ symbol = (symbol << 1) + 1; action1, \
+ seq);
-#define update_bit_1_dummy() \
-do { \
- rc.range -= rc_bound; \
- rc.code -= rc_bound; \
-} while (0)
+/// Like rc_bit() but add "case seq:" as a prefix. This makes the unrolled
+/// loops more readable because the code isn't littered with "case"
+/// statements. On the other hand this also makes it less readable, since
+/// spotting the places where the decoder loop may be restarted is less
+/// obvious.
+#define rc_bit_case(prob, action0, action1, seq) \
+ case seq: rc_bit(prob, action0, action1, seq)
-#define rc_decode_direct_dummy(count) \
+/// Decode a bit without using a probability.
+#define rc_direct(dest, seq) \
do { \
- rc_normalize(); \
+ rc_normalize(seq); \
rc.range >>= 1; \
rc.code -= rc.range; \
- rc.code += rc.range & (UINT32_C(0) - (rc.code >> 31)); \
-} while (--count > 0)
-
-
-///////////////////////
-// Bit tree decoding //
-///////////////////////
-
-#define bittree_decode(target, probs, bit_levels) \
-do { \
- uint32_t model_index = 1; \
- for (uint32_t bit_index = (bit_levels); bit_index != 0; --bit_index) { \
- if_bit_0((probs)[model_index]) { \
- update_bit_0((probs)[model_index]); \
- model_index <<= 1; \
- } else { \
- update_bit_1((probs)[model_index]); \
- model_index = (model_index << 1) | 1; \
- } \
- } \
- target += model_index - (1 << bit_levels); \
-} while (0)
-
-
-#define bittree_reverse_decode(target, probs, bit_levels) \
-do { \
- uint32_t model_index = 1; \
- for (uint32_t bit_index = 0; bit_index < bit_levels; ++bit_index) { \
- if_bit_0((probs)[model_index]) { \
- update_bit_0((probs)[model_index]); \
- model_index <<= 1; \
- } else { \
- update_bit_1((probs)[model_index]); \
- model_index = (model_index << 1) | 1; \
- target += 1 << bit_index; \
- } \
- } \
-} while (0)
-
-
-// Dummy versions don't update prob.
-#define bittree_decode_dummy(target, probs, bit_levels) \
-do { \
- uint32_t model_index = 1; \
- for (uint32_t bit_index = (bit_levels); bit_index != 0; --bit_index) { \
- if_bit_0((probs)[model_index]) { \
- update_bit_0_dummy(); \
- model_index <<= 1; \
- } else { \
- update_bit_1_dummy(); \
- model_index = (model_index << 1) | 1; \
- } \
- } \
- target += model_index - (1 << bit_levels); \
+ rc_bound = UINT32_C(0) - (rc.code >> 31); \
+ rc.code += rc.range & rc_bound; \
+ dest = (dest << 1) + (rc_bound + 1); \
} while (0)
-#define bittree_reverse_decode_dummy(probs, bit_levels) \
-do { \
- uint32_t model_index = 1; \
- for (uint32_t bit_index = 0; bit_index < bit_levels; ++bit_index) { \
- if_bit_0((probs)[model_index]) { \
- update_bit_0_dummy(); \
- model_index <<= 1; \
- } else { \
- update_bit_1_dummy(); \
- model_index = (model_index << 1) | 1; \
- } \
- } \
-} while (0)
+// NOTE: No macros are provided for bittree decoding. It seems to be simpler
+// to just write them open in the code.
#endif