]> granicus.if.org Git - xz/commitdiff
LZMA2 decoder cleanups. Make it require new LZMA properties
authorLasse Collin <lasse.collin@tukaani.org>
Mon, 1 Dec 2008 20:50:28 +0000 (22:50 +0200)
committerLasse Collin <lasse.collin@tukaani.org>
Mon, 1 Dec 2008 20:50:28 +0000 (22:50 +0200)
also in the first LZMA chunk after a dictionary reset in
uncompressed chunk.

src/liblzma/lzma/lzma2_decoder.c

index af1da746a2175461c3257c8764db200571af4351..7f1f45f426de00c76c113ea531918548033f6829 100644 (file)
@@ -70,76 +70,63 @@ lzma2_decode(lzma_coder *restrict coder, lzma_dict *restrict dict,
        // at least one byte of input.
        while (*in_pos < in_size || coder->sequence == SEQ_LZMA)
        switch (coder->sequence) {
-       case SEQ_CONTROL:
-               if (in[*in_pos] & 0x80) {
-                       // Get the highest five bits of uncompressed size.
-                       coder->uncompressed_size
-                                       = (uint32_t)(in[*in_pos] & 0x1F) << 16;
-                       coder->sequence = SEQ_UNCOMPRESSED_1;
-
-                       // See if we need to reset dictionary or state.
-                       switch ((in[(*in_pos)++] >> 5) & 3) {
-                       case 3:
-                               dict_reset(dict);
-                               coder->need_dictionary_reset = false;
-
-                       // Fall through
+       case SEQ_CONTROL: {
+               const uint32_t control = in[*in_pos];
+               ++*in_pos;
+
+               // Dictionary reset implies that next LZMA chunk has to set
+               // new properties.
+               if (control >= 0xE0 || control == 1) {
+                       dict_reset(dict);
+                       coder->need_dictionary_reset = false;
+                       coder->need_properties = true;
+               } else if (coder->need_dictionary_reset) {
+                       return LZMA_DATA_ERROR;
+               }
 
-                       case 2:
-                               if (coder->need_dictionary_reset)
-                                       return LZMA_DATA_ERROR;
+               if (control >= 0x80) {
+                       // LZMA chunk. The highest five bits of the
+                       // uncompressed size are taken from the control byte.
+                       coder->uncompressed_size = (control & 0x1F) << 16;
+                       coder->sequence = SEQ_UNCOMPRESSED_1;
 
+                       // See if there are new properties or if we need to
+                       // reset the state.
+                       if (control >= 0xC0) {
+                               // When there are new properties, state reset
+                               // is done at SEQ_PROPERTIES.
                                coder->need_properties = false;
                                coder->next_sequence = SEQ_PROPERTIES;
-                               break;
-
-                       case 1:
-                               if (coder->need_properties)
-                                       return LZMA_DATA_ERROR;
 
-                               coder->lzma.reset(coder->lzma.coder,
-                                               &coder->options);
+                       } else if (coder->need_properties) {
+                               return LZMA_DATA_ERROR;
 
+                       } else {
                                coder->next_sequence = SEQ_LZMA;
-                               break;
-
-                       case 0:
-                               if (coder->need_properties)
-                                       return LZMA_DATA_ERROR;
 
-                               coder->next_sequence = SEQ_LZMA;
-                               break;
+                               // If only state reset is wanted with old
+                               // properties, do the resetting here for
+                               // simplicity.
+                               if (control >= 0xA0)
+                                       coder->lzma.reset(coder->lzma.coder,
+                                                       &coder->options);
                        }
-
                } else {
-                       switch (in[(*in_pos)++]) {
-                       case 0:
-                               // End of payload marker
+                       // End marker
+                       if (control == 0x00)
                                return LZMA_STREAM_END;
 
-                       case 1:
-                               // Dictionary reset
-                               dict_reset(dict);
-                               coder->need_dictionary_reset = false;
-
-                       // Fall through
-
-                       case 2:
-                               if (coder->need_dictionary_reset)
-                                       return LZMA_DATA_ERROR;
-
-                               // Uncompressed chunk; we need to read total
-                               // size first.
-                               coder->sequence = SEQ_COMPRESSED_0;
-                               coder->next_sequence = SEQ_COPY;
-                               break;
-
-                       default:
+                       // Invalid control values
+                       if (control > 2)
                                return LZMA_DATA_ERROR;
-                       }
+
+                       // It's uncompressed chunk
+                       coder->sequence = SEQ_COMPRESSED_0;
+                       coder->next_sequence = SEQ_COPY;
                }
 
                break;
+       }
 
        case SEQ_UNCOMPRESSED_1:
                coder->uncompressed_size += (uint32_t)(in[(*in_pos)++]) << 8;