public int readLengths() throws BitStreamException
    {
        int count = EntropyUtils.decodeAlphabet(this.bitstream, this.ranks);
        ExpGolombDecoder egdec = new ExpGolombDecoder(this.bitstream, true);
        int currSize ;
        this.minCodeLen = MAX_SYMBOL_SIZE; // max code length
        int prevSize = 2;
        
        // Read lengths
        for (int i=0; i<count; i++)
        {
           final int r = this.ranks[i];
           
           if ((r < 0) || (r >= this.codes.length))
           {
              throw new BitStreamException("Invalid bitstream: incorrect Huffman symbol " + r, 
                 BitStreamException.INVALID_STREAM);
           }
           
           this.codes[r] = 0;
           currSize = prevSize + egdec.decodeByte();

           if (currSize <= 0)
           {
              throw new BitStreamException("Invalid bitstream: incorrect size " + currSize +
                      " for Huffman symbol " + r, BitStreamException.INVALID_STREAM);
           }
           
           if (currSize > MAX_SYMBOL_SIZE)
           {
              throw new BitStreamException("Invalid bitstream: incorrect max size " + currSize +
                 " for Huffman symbol " + r, BitStreamException.INVALID_STREAM);
           }

           if (this.minCodeLen > currSize)
              this.minCodeLen = currSize;
           
           this.sizes[r] = (short) currSize;
           prevSize = currSize;
        }
 
        if (count == 0)
           return 0;

        // Create canonical codes
        if (HuffmanCommon.generateCanonicalCodes(this.sizes, this.codes, this.ranks, count) < 0)
        {
           throw new BitStreamException("Could not generate codes: max code length " +
                "(" + MAX_SYMBOL_SIZE + " bits) exceeded", BitStreamException.INVALID_STREAM);
        }

        // Build decoding tables
        this.buildDecodingTables(count);
        return count;
    }