예제 #1
0
    static InflaterHuffmanTree()
    {
      var codeLengths = new byte[288];
      var i = 0;
      while (i < 144)
      {
        codeLengths[i++] = 8;
      }
      while (i < 256)
      {
        codeLengths[i++] = 9;
      }
      while (i < 280)
      {
        codeLengths[i++] = 7;
      }
      while (i < 288)
      {
        codeLengths[i++] = 8;
      }
      defLitLenTree = new InflaterHuffmanTree(codeLengths);

      codeLengths = new byte[32];
      i = 0;
      while (i < 32)
      {
        codeLengths[i++] = 5;
      }
      defDistTree = new InflaterHuffmanTree(codeLengths);
    }
예제 #2
0
    /// <summary>
    ///   Decodes the deflated stream.
    /// </summary>
    /// <returns>
    ///   false if more input is needed, or if finished.
    /// </returns>
    /// <exception cref="SharpZipBaseException">
    ///   if deflated stream is invalid.
    /// </exception>
    private bool Decode()
    {
      switch (mode)
      {
        case DECODE_HEADER:
          return DecodeHeader();

        case DECODE_DICT:
          return DecodeDict();

        case DECODE_CHKSUM:
          return DecodeChksum();

        case DECODE_BLOCKS:
          if (isLastBlock)
          {
            if (noHeader)
            {
              mode = FINISHED;
              return false;
            }

            input.SkipToByteBoundary();
            neededBits = 32;
            mode = DECODE_CHKSUM;
            return true;
          }

          var type = input.PeekBits(3);
          if (type < 0)
          {
            return false;
          }
          input.DropBits(3);

          if ((type & 1) != 0)
          {
            isLastBlock = true;
          }
          switch (type >> 1)
          {
            case DeflaterConstants.STORED_BLOCK:
              input.SkipToByteBoundary();
              mode = DECODE_STORED_LEN1;
              break;
            case DeflaterConstants.STATIC_TREES:
              litlenTree = InflaterHuffmanTree.defLitLenTree;
              distTree = InflaterHuffmanTree.defDistTree;
              mode = DECODE_HUFFMAN;
              break;
            case DeflaterConstants.DYN_TREES:
              dynHeader = new InflaterDynHeader();
              mode = DECODE_DYN_HEADER;
              break;
            default:
              throw new SharpZipBaseException("Unknown block type " + type);
          }
          return true;

        case DECODE_STORED_LEN1:
        {
          if ((uncomprLen = input.PeekBits(16)) < 0)
          {
            return false;
          }
          input.DropBits(16);
          mode = DECODE_STORED_LEN2;
        }
          goto case DECODE_STORED_LEN2; // fall through

        case DECODE_STORED_LEN2:
        {
          var nlen = input.PeekBits(16);
          if (nlen < 0)
          {
            return false;
          }
          input.DropBits(16);
          if (nlen != (uncomprLen ^ 0xffff))
          {
            throw new SharpZipBaseException("broken uncompressed block");
          }
          mode = DECODE_STORED;
        }
          goto case DECODE_STORED; // fall through

        case DECODE_STORED:
        {
          var more = outputWindow.CopyStored(input, uncomprLen);
          uncomprLen -= more;
          if (uncomprLen == 0)
          {
            mode = DECODE_BLOCKS;
            return true;
          }
          return !input.IsNeedingInput;
        }

        case DECODE_DYN_HEADER:
          if (!dynHeader.Decode(input))
          {
            return false;
          }

          litlenTree = dynHeader.BuildLitLenTree();
          distTree = dynHeader.BuildDistTree();
          mode = DECODE_HUFFMAN;
          goto case DECODE_HUFFMAN; // fall through

        case DECODE_HUFFMAN:
        case DECODE_HUFFMAN_LENBITS:
        case DECODE_HUFFMAN_DIST:
        case DECODE_HUFFMAN_DISTBITS:
          return DecodeHuffman();

        case FINISHED:
          return false;

        default:
          throw new SharpZipBaseException("Inflater.Decode unknown mode");
      }
    }
예제 #3
0
 /// <summary>
 ///   Resets the inflater so that a new stream can be decompressed.  All
 ///   pending input and output will be discarded.
 /// </summary>
 public void Reset()
 {
   mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;
   input.Reset();
   outputWindow.Reset();
   dynHeader = null;
   litlenTree = null;
   distTree = null;
   isLastBlock = false;
   adler.Reset();
 }
예제 #4
0
    /// <summary>
    ///   Decodes the huffman encoded symbols in the input stream.
    /// </summary>
    /// <returns>
    ///   false if more input is needed, true if output window is
    ///   full or the current block ends.
    /// </returns>
    /// <exception cref="SharpZipBaseException">
    ///   if deflated stream is invalid.
    /// </exception>
    private bool DecodeHuffman()
    {
      var free = outputWindow.GetFreeSpace();
      while (free >= 258)
      {
        int symbol;
        switch (mode)
        {
          case DECODE_HUFFMAN:
            // This is the inner loop so it is optimized a bit
            while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0)
            {
              outputWindow.Write(symbol);
              if (--free < 258)
              {
                return true;
              }
            }

            if (symbol < 257)
            {
              if (symbol < 0)
              {
                return false;
              }

              // symbol == 256: end of block
              distTree = null;
              litlenTree = null;
              mode = DECODE_BLOCKS;
              return true;
            }

            try
            {
              repLength = CPLENS[symbol - 257];
              neededBits = CPLEXT[symbol - 257];
            }
            catch (Exception)
            {
              throw new SharpZipBaseException("Illegal rep length code");
            }
            goto case DECODE_HUFFMAN_LENBITS; // fall through

          case DECODE_HUFFMAN_LENBITS:
            if (neededBits > 0)
            {
              mode = DECODE_HUFFMAN_LENBITS;
              var i = input.PeekBits(neededBits);
              if (i < 0)
              {
                return false;
              }
              input.DropBits(neededBits);
              repLength += i;
            }
            mode = DECODE_HUFFMAN_DIST;
            goto case DECODE_HUFFMAN_DIST; // fall through

          case DECODE_HUFFMAN_DIST:
            symbol = distTree.GetSymbol(input);
            if (symbol < 0)
            {
              return false;
            }

            try
            {
              repDist = CPDIST[symbol];
              neededBits = CPDEXT[symbol];
            }
            catch (Exception)
            {
              throw new SharpZipBaseException("Illegal rep dist code");
            }

            goto case DECODE_HUFFMAN_DISTBITS; // fall through

          case DECODE_HUFFMAN_DISTBITS:
            if (neededBits > 0)
            {
              mode = DECODE_HUFFMAN_DISTBITS;
              var i = input.PeekBits(neededBits);
              if (i < 0)
              {
                return false;
              }
              input.DropBits(neededBits);
              repDist += i;
            }

            outputWindow.Repeat(repLength, repDist);
            free -= repLength;
            mode = DECODE_HUFFMAN;
            break;

          default:
            throw new SharpZipBaseException("Inflater unknown mode");
        }
      }
      return true;
    }
예제 #5
0
    public bool Decode(StreamManipulator input)
    {
      decode_loop:
      for (;;)
      {
        switch (mode)
        {
          case LNUM:
            lnum = input.PeekBits(5);
            if (lnum < 0)
            {
              return false;
            }
            lnum += 257;
            input.DropBits(5);
            //        System.err.println("LNUM: "+lnum);
            mode = DNUM;
            goto case DNUM; // fall through
          case DNUM:
            dnum = input.PeekBits(5);
            if (dnum < 0)
            {
              return false;
            }
            dnum++;
            input.DropBits(5);
            //        System.err.println("DNUM: "+dnum);
            num = lnum + dnum;
            litdistLens = new byte[num];
            mode = BLNUM;
            goto case BLNUM; // fall through
          case BLNUM:
            blnum = input.PeekBits(4);
            if (blnum < 0)
            {
              return false;
            }
            blnum += 4;
            input.DropBits(4);
            blLens = new byte[19];
            ptr = 0;
            //        System.err.println("BLNUM: "+blnum);
            mode = BLLENS;
            goto case BLLENS; // fall through
          case BLLENS:
            while (ptr < blnum)
            {
              var len = input.PeekBits(3);
              if (len < 0)
              {
                return false;
              }
              input.DropBits(3);
              //      System.err.println("blLens["+BL_ORDER[ptr]+"]: "+len);
              blLens[BL_ORDER[ptr]] = (byte) len;
              ptr++;
            }
            blTree = new InflaterHuffmanTree(blLens);
            blLens = null;
            ptr = 0;
            mode = LENS;
            goto case LENS; // fall through
          case LENS:
          {
            int symbol;
            while (((symbol = blTree.GetSymbol(input)) & ~15) == 0)
            {
              /* Normal case: symbol in [0..15] */

              //        System.err.println("litdistLens["+ptr+"]: "+symbol);
              litdistLens[ptr++] = lastLen = (byte) symbol;

              if (ptr == num)
              {
                /* Finished */
                return true;
              }
            }

            /* need more input ? */
            if (symbol < 0)
            {
              return false;
            }

            /* otherwise repeat code */
            if (symbol >= 17)
            {
              /* repeat zero */
              //        System.err.println("repeating zero");
              lastLen = 0;
            }
            else
            {
              if (ptr == 0)
              {
                throw new SharpZipBaseException();
              }
            }
            repSymbol = symbol - 16;
          }
            mode = REPS;
            goto case REPS; // fall through
          case REPS:
          {
            var bits = repBits[repSymbol];
            var count = input.PeekBits(bits);
            if (count < 0)
            {
              return false;
            }
            input.DropBits(bits);
            count += repMin[repSymbol];
            //          System.err.println("litdistLens repeated: "+count);

            if (ptr + count > num)
            {
              throw new SharpZipBaseException();
            }
            while (count-- > 0)
            {
              litdistLens[ptr++] = lastLen;
            }

            if (ptr == num)
            {
              /* Finished */
              return true;
            }
          }
            mode = LENS;
            goto decode_loop;
        }
      }
    }