Changeset 2782


Ignore:
Timestamp:
05/15/07 14:09:45 (13 years ago)
Author:
curtis
Message:
  • Move bzip2-related code to loci.formats.codec package.
  • No need for IFormatReader.setSeries to throw FormatException.
Location:
trunk/loci/formats
Files:
6 edited
3 moved

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/FileStitcher.java

    r2757 r2782  
    462462 
    463463  /* @see IFormatReader#setSeries(int) */ 
    464   public void setSeries(int no) throws FormatException { 
     464  public void setSeries(int no) { 
    465465    FormatTools.assertId(currentId, true, 2); 
    466466    reader.setSeries(no); 
  • trunk/loci/formats/FormatReader.java

    r2757 r2782  
    362362 
    363363  /* @see IFormatReader#setSeries(int) */ 
    364   public void setSeries(int no) throws FormatException { 
     364  public void setSeries(int no) { 
    365365    if (no < 0 || no >= getSeriesCount()) { 
    366       throw new FormatException("Invalid series: " + no); 
     366      throw new IllegalArgumentException("Invalid series: " + no); 
    367367    } 
    368368    series = no; 
  • trunk/loci/formats/IFormatReader.java

    r2757 r2782  
    177177 
    178178  /** Activates the specified series. */ 
    179   void setSeries(int no) throws FormatException; 
     179  void setSeries(int no); 
    180180 
    181181  /** Gets the currently active series. */ 
  • trunk/loci/formats/ImageReader.java

    r2761 r2782  
    321321 
    322322  /* @see IFormatReader#setSeries(int) */ 
    323   public void setSeries(int no) throws FormatException { 
     323  public void setSeries(int no) { 
    324324    FormatTools.assertId(currentId, true, 2); 
    325325    getReader().setSeries(no); 
  • trunk/loci/formats/ReaderWrapper.java

    r2757 r2782  
    186186  } 
    187187 
    188   public void setSeries(int no) throws FormatException { 
     188  public void setSeries(int no) { 
    189189    reader.setSeries(no); 
    190190  } 
  • trunk/loci/formats/codec/BZip2Constants.java

    r2178 r2782  
    2626 * Copyright  2001,2004 The Apache Software Foundation 
    2727 * 
    28  *  Licensed under the Apache License, Version 2.0 (the "License"); 
    29  *  you may not use this file except in compliance with the License. 
    30  *  You may obtain a copy of the License at 
     28 * Licensed under the Apache License, Version 2.0 (the "License"); 
     29 * you may not use this file except in compliance with the License. 
     30 * You may obtain a copy of the License at 
    3131 * 
    32  *      http://www.apache.org/licenses/LICENSE-2.0 
     32 *     http://www.apache.org/licenses/LICENSE-2.0 
    3333 * 
    34  *  Unless required by applicable law or agreed to in writing, software 
    35  *  distributed under the License is distributed on an "AS IS" BASIS, 
    36  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    37  *  See the License for the specific language governing permissions and 
    38  *  limitations under the License. 
    39  * 
     34 * Unless required by applicable law or agreed to in writing, software 
     35 * distributed under the License is distributed on an "AS IS" BASIS, 
     36 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     37 * See the License for the specific language governing permissions and 
     38 * limitations under the License. 
    4039 */ 
    4140 
     
    4645 */ 
    4746 
    48 package loci.formats.in; 
     47package loci.formats.codec; 
    4948 
    5049/** 
  • trunk/loci/formats/codec/CBZip2InputStream.java

    r2771 r2782  
     1// 
     2// CBZip2InputStream.java 
     3// 
     4 
    15/* 
    2  *  Licensed to the Apache Software Foundation (ASF) under one or more 
    3  *  contributor license agreements.  See the NOTICE file distributed with 
    4  *  this work for additional information regarding copyright ownership. 
    5  *  The ASF licenses this file to You under the Apache License, Version 2.0 
    6  *  (the "License"); you may not use this file except in compliance with 
    7  *  the License.  You may obtain a copy of the License at 
     6LOCI Bio-Formats package for reading and converting biological file formats. 
     7Copyright (C) 2005-@year@ Melissa Linkert, Curtis Rueden, Chris Allan, 
     8Eric Kjellman and Brian Loranger. 
     9 
     10This program is free software; you can redistribute it and/or modify 
     11it under the terms of the GNU Library General Public License as published by 
     12the Free Software Foundation; either version 2 of the License, or 
     13(at your option) any later version. 
     14 
     15This program is distributed in the hope that it will be useful, 
     16but WITHOUT ANY WARRANTY; without even the implied warranty of 
     17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     18GNU Library General Public License for more details. 
     19 
     20You should have received a copy of the GNU Library General Public License 
     21along with this program; if not, write to the Free Software 
     22Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
     23*/ 
     24 
     25/* 
     26 * Licensed to the Apache Software Foundation (ASF) under one or more 
     27 * contributor license agreements.  See the NOTICE file distributed with 
     28 * this work for additional information regarding copyright ownership. 
     29 * The ASF licenses this file to You under the Apache License, Version 2.0 
     30 * (the "License"); you may not use this file except in compliance with 
     31 * the License.  You may obtain a copy of the License at 
    832 * 
    9  *      http://www.apache.org/licenses/LICENSE-2.0 
     33 *     http://www.apache.org/licenses/LICENSE-2.0 
    1034 * 
    11  *  Unless required by applicable law or agreed to in writing, software 
    12  *  distributed under the License is distributed on an "AS IS" BASIS, 
    13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    14  *  See the License for the specific language governing permissions and 
    15  *  limitations under the License. 
    16  * 
     35 * Unless required by applicable law or agreed to in writing, software 
     36 * distributed under the License is distributed on an "AS IS" BASIS, 
     37 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     38 * See the License for the specific language governing permissions and 
     39 * limitations under the License. 
    1740 */ 
    1841 
     
    2245 * great code. 
    2346 */ 
    24 package loci.formats.in; 
     47 
     48package loci.formats.codec; 
    2549 
    2650import java.io.InputStream; 
     
    4165 * read()} method exclusively. Thus you should consider to use a 
    4266 * buffered source stream.</p> 
    43  *  
     67 * 
    4468 * <p>Instances of this class are not threadsafe.</p> 
    4569 */ 
    4670public class CBZip2InputStream extends InputStream implements BZip2Constants { 
    4771 
    48     private static void reportCRCError() throws IOException { 
    49         // The clean way would be to throw an exception. 
    50         //throw new IOException("crc error"); 
    51  
    52         // Just print a message, like the previous versions of this class did 
    53         System.err.println("BZip2 CRC error"); 
    54     } 
    55  
    56     private void makeMaps() { 
    57         final boolean[] inUse   = this.data.inUse; 
    58         final byte[] seqToUnseq = this.data.seqToUnseq; 
    59  
    60         int nInUseShadow = 0; 
    61  
    62         for (int i = 0; i < 256; i++) { 
    63             if (inUse[i]) 
    64                 seqToUnseq[nInUseShadow++] = (byte) i; 
     72  private static void reportCRCError() throws IOException { 
     73    // The clean way would be to throw an exception. 
     74    //throw new IOException("crc error"); 
     75 
     76    // Just print a message, like the previous versions of this class did 
     77    System.err.println("BZip2 CRC error"); 
     78  } 
     79 
     80  private void makeMaps() { 
     81    final boolean[] inUse  = this.data.inUse; 
     82    final byte[] seqToUnseq = this.data.seqToUnseq; 
     83 
     84    int nInUseShadow = 0; 
     85 
     86    for (int i = 0; i < 256; i++) { 
     87      if (inUse[i]) seqToUnseq[nInUseShadow++] = (byte) i; 
     88    } 
     89 
     90    this.nInUse = nInUseShadow; 
     91  } 
     92 
     93  /** 
     94   * Index of the last char in the block, so the block size == last + 1. 
     95   */ 
     96  private int  last; 
     97 
     98  /** 
     99   * Index in zptr[] of original string after sorting. 
     100   */ 
     101  private int  origPtr; 
     102 
     103  /** 
     104   * always: in the range 0 .. 9. 
     105   * The current block size is 100000 * this number. 
     106   */ 
     107  private int blockSize100k; 
     108 
     109  private boolean blockRandomised; 
     110 
     111  private int bsBuff; 
     112  private int bsLive; 
     113  private final CRC crc = new CRC(); 
     114 
     115  private int nInUse; 
     116 
     117  private InputStream in; 
     118 
     119  private int currentChar = -1; 
     120 
     121  private static final int EOF            = 0; 
     122  private static final int START_BLOCK_STATE = 1; 
     123  private static final int RAND_PART_A_STATE = 2; 
     124  private static final int RAND_PART_B_STATE = 3; 
     125  private static final int RAND_PART_C_STATE = 4; 
     126  private static final int NO_RAND_PART_A_STATE = 5; 
     127  private static final int NO_RAND_PART_B_STATE = 6; 
     128  private static final int NO_RAND_PART_C_STATE = 7; 
     129 
     130  private int currentState = START_BLOCK_STATE; 
     131 
     132  private int storedBlockCRC, storedCombinedCRC; 
     133  private int computedBlockCRC, computedCombinedCRC; 
     134 
     135  // Variables used by setup* methods exclusively 
     136 
     137  private int suCount; 
     138  private int suCh2; 
     139  private int suChPrev; 
     140  private int suI2; 
     141  private int suJ2; 
     142  private int suRNToGo; 
     143  private int suRTPos; 
     144  private int suTPos; 
     145  private char suZ; 
     146 
     147  /** 
     148   * All memory intensive stuff. 
     149   * This field is initialized by initBlock(). 
     150   */ 
     151  private CBZip2InputStream.Data data; 
     152 
     153  /** 
     154   * Constructs a new CBZip2InputStream which decompresses bytes read from 
     155   * the specified stream. 
     156   * 
     157   * <p>Although BZip2 headers are marked with the magic 
     158   * <tt>"Bz"</tt> this constructor expects the next byte in the 
     159   * stream to be the first one after the magic.  Thus callers have 
     160   * to skip the first two bytes. Otherwise this constructor will 
     161   * throw an exception. </p> 
     162   * 
     163   * @throws IOException 
     164   *   if the stream content is malformed or an I/O error occurs. 
     165   * @throws NullPointerException 
     166   *   if <tt>in == null</tt> 
     167   */ 
     168  public CBZip2InputStream(final InputStream in) throws IOException { 
     169    super(); 
     170 
     171    this.in = in; 
     172    init(); 
     173  } 
     174 
     175  public int read() throws IOException { 
     176    if (this.in != null) return read0(); 
     177    else throw new IOException("stream closed"); 
     178  } 
     179 
     180  public int read(final byte[] dest, final int offs, final int len) 
     181    throws IOException { 
     182    if (offs < 0) { 
     183      throw new IndexOutOfBoundsException("offs(" + offs + ") < 0."); 
     184    } 
     185    if (len < 0) { 
     186      throw new IndexOutOfBoundsException("len(" + len + ") < 0."); 
     187    } 
     188    if (offs + len > dest.length) { 
     189      throw new IndexOutOfBoundsException("offs(" + offs + ") + len(" + 
     190        len + ") > dest.length(" + dest.length + ")."); 
     191    } 
     192    if (this.in == null) throw new IOException("stream closed"); 
     193 
     194    final int hi = offs + len; 
     195    int destOffs = offs; 
     196    for (int b; (destOffs < hi) && ((b = read0()) >= 0);) { 
     197      dest[destOffs++] = (byte) b; 
     198    } 
     199 
     200    return (destOffs == offs) ? -1 : (destOffs - offs); 
     201  } 
     202 
     203  private int read0() throws IOException { 
     204    final int retChar = this.currentChar; 
     205 
     206    switch (this.currentState) { 
     207      case EOF: 
     208        return -1; 
     209 
     210      case START_BLOCK_STATE: 
     211        throw new IllegalStateException(); 
     212 
     213      case RAND_PART_A_STATE: 
     214        throw new IllegalStateException(); 
     215 
     216      case RAND_PART_B_STATE: 
     217        setupRandPartB(); 
     218        break; 
     219 
     220      case RAND_PART_C_STATE: 
     221        setupRandPartC(); 
     222        break; 
     223 
     224      case NO_RAND_PART_A_STATE: 
     225        throw new IllegalStateException(); 
     226 
     227      case NO_RAND_PART_B_STATE: 
     228        setupNoRandPartB(); 
     229        break; 
     230 
     231      case NO_RAND_PART_C_STATE: 
     232        setupNoRandPartC(); 
     233        break; 
     234 
     235      default: 
     236        throw new IllegalStateException(); 
     237    } 
     238 
     239    return retChar; 
     240  } 
     241 
     242  private void init() throws IOException { 
     243    int magic2 = this.in.read(); 
     244    if (magic2 != 'h') { 
     245      throw new IOException("Stream is not BZip2 formatted: expected 'h'" + 
     246        " as first byte but got '" + (char) magic2 + "'"); 
     247    } 
     248 
     249    int blockSize = this.in.read(); 
     250    if ((blockSize < '1') || (blockSize > '9')) { 
     251      throw new IOException("Stream is not BZip2 formatted: illegal " + 
     252        "blocksize " + (char) blockSize); 
     253    } 
     254 
     255    this.blockSize100k = blockSize - '0'; 
     256 
     257    initBlock(); 
     258    setupBlock(); 
     259  } 
     260 
     261  private void initBlock() throws IOException { 
     262    char magic0 = bsGetUByte(); 
     263    char magic1 = bsGetUByte(); 
     264    char magic2 = bsGetUByte(); 
     265    char magic3 = bsGetUByte(); 
     266    char magic4 = bsGetUByte(); 
     267    char magic5 = bsGetUByte(); 
     268 
     269    if (magic0 == 0x17 && 
     270      magic1 == 0x72 && 
     271      magic2 == 0x45 && 
     272      magic3 == 0x38 && 
     273      magic4 == 0x50 && 
     274      magic5 == 0x90) 
     275    { 
     276      complete(); // end of file 
     277    } 
     278    else if (magic0 != 0x31 || // '1' 
     279           magic1 != 0x41 || // ')' 
     280           magic2 != 0x59 || // 'Y' 
     281           magic3 != 0x26 || // '&' 
     282           magic4 != 0x53 || // 'S' 
     283           magic5 != 0x59) // 'Y' 
     284    { 
     285      this.currentState = EOF; 
     286      throw new IOException("bad block header"); 
     287    } 
     288    else { 
     289      this.storedBlockCRC = bsGetInt(); 
     290      this.blockRandomised = bsR(1) == 1; 
     291 
     292      // Allocate data here instead in constructor, so we do not 
     293      // allocate it if the input file is empty. 
     294      if (this.data == null) { 
     295         this.data = new Data(this.blockSize100k); 
     296      } 
     297 
     298      // currBlockNo++; 
     299      getAndMoveToFrontDecode(); 
     300 
     301      this.crc.initialiseCRC(); 
     302      this.currentState = START_BLOCK_STATE; 
     303    } 
     304  } 
     305 
     306  private void endBlock() throws IOException { 
     307    this.computedBlockCRC = this.crc.getFinalCRC(); 
     308 
     309    // A bad CRC is considered a fatal error. 
     310    if (this.storedBlockCRC != this.computedBlockCRC) { 
     311      // make next blocks readable without error 
     312      // (repair feature, not yet documented, not tested) 
     313      this.computedCombinedCRC = 
     314        (this.storedCombinedCRC << 1) | (this.storedCombinedCRC >>> 31); 
     315      this.computedCombinedCRC ^= this.storedBlockCRC; 
     316 
     317      reportCRCError(); 
     318    } 
     319 
     320    this.computedCombinedCRC = 
     321      (this.computedCombinedCRC << 1) | (this.computedCombinedCRC >>> 31); 
     322    this.computedCombinedCRC ^= this.computedBlockCRC; 
     323  } 
     324 
     325  private void complete() throws IOException { 
     326    this.storedCombinedCRC = bsGetInt(); 
     327    this.currentState = EOF; 
     328    this.data = null; 
     329 
     330    if (this.storedCombinedCRC != this.computedCombinedCRC) { 
     331      reportCRCError(); 
     332    } 
     333  } 
     334 
     335  public void close() throws IOException { 
     336    InputStream inShadow = this.in; 
     337    if (inShadow != null) { 
     338      try { 
     339        if (inShadow != System.in) inShadow.close(); 
     340      } 
     341      finally { 
     342        this.data = null; 
     343        this.in = null; 
     344      } 
     345    } 
     346  } 
     347 
     348  private int bsR(final int n) throws IOException { 
     349    int bsLiveShadow = this.bsLive; 
     350    int bsBuffShadow = this.bsBuff; 
     351 
     352    if (bsLiveShadow < n) { 
     353      final InputStream inShadow = this.in; 
     354      do { 
     355        int thech = inShadow.read(); 
     356 
     357        if (thech < 0) throw new IOException("unexpected end of stream"); 
     358 
     359        bsBuffShadow = (bsBuffShadow << 8) | thech; 
     360        bsLiveShadow += 8; 
     361      } 
     362      while (bsLiveShadow < n); 
     363 
     364      this.bsBuff = bsBuffShadow; 
     365    } 
     366 
     367    this.bsLive = bsLiveShadow - n; 
     368    return (bsBuffShadow >> (bsLiveShadow - n)) & ((1 << n) - 1); 
     369  } 
     370 
     371  private boolean bsGetBit() throws IOException { 
     372    int bsLiveShadow = this.bsLive; 
     373    int bsBuffShadow = this.bsBuff; 
     374 
     375    if (bsLiveShadow < 1) { 
     376      int thech = this.in.read(); 
     377 
     378      if (thech < 0) throw new IOException("unexpected end of stream"); 
     379 
     380      bsBuffShadow = (bsBuffShadow << 8) | thech; 
     381      bsLiveShadow += 8; 
     382      this.bsBuff = bsBuffShadow; 
     383    } 
     384 
     385    this.bsLive = bsLiveShadow - 1; 
     386    return ((bsBuffShadow >> (bsLiveShadow - 1)) & 1) != 0; 
     387  } 
     388 
     389  private char bsGetUByte() throws IOException { 
     390    return (char) bsR(8); 
     391  } 
     392 
     393  private int bsGetInt() throws IOException { 
     394    return (((((bsR(8) << 8) | bsR(8)) << 8) | bsR(8)) << 8) | bsR(8); 
     395  } 
     396 
     397  /** Called by createHuffmanDecodingTables() exclusively. */ 
     398  private static void hbCreateDecodeTables(final int[] limit, 
     399    final int[] base, final int[] perm, final char[] length, 
     400    final int minLen, final int maxLen, final int alphaSize) 
     401  { 
     402    for (int i = minLen, pp = 0; i <= maxLen; i++) { 
     403      for (int j = 0; j < alphaSize; j++) { 
     404        if (length[j] == i) perm[pp++] = j; 
     405      } 
     406    } 
     407 
     408    for (int i = MAX_CODE_LEN; --i > 0;) { 
     409      base[i] = 0; 
     410      limit[i] = 0; 
     411    } 
     412 
     413    for (int i = 0; i < alphaSize; i++) { 
     414      base[length[i] + 1]++; 
     415    } 
     416 
     417    for (int i = 1, b = base[0]; i < MAX_CODE_LEN; i++) { 
     418      b += base[i]; 
     419      base[i] = b; 
     420    } 
     421 
     422    for (int i = minLen, vec = 0, b = base[i]; i <= maxLen; i++) { 
     423      final int nb = base[i + 1]; 
     424      vec += nb - b; 
     425      b = nb; 
     426      limit[i] = vec - 1; 
     427      vec <<= 1; 
     428    } 
     429 
     430    for (int i = minLen + 1; i <= maxLen; i++) { 
     431      base[i] = ((limit[i - 1] + 1) << 1) - base[i]; 
     432    } 
     433  } 
     434 
     435  private void recvDecodingTables() throws IOException { 
     436    final Data dataShadow    = this.data; 
     437    final boolean[] inUse    = dataShadow.inUse; 
     438    final byte[] pos       = dataShadow.recvDecodingTablesPos; 
     439    final byte[] selector    = dataShadow.selector; 
     440    final byte[] selectorMtf  = dataShadow.selectorMtf; 
     441 
     442    int inUse16 = 0; 
     443 
     444    // Receive the mapping table 
     445    for (int i = 0; i < 16; i++) { 
     446      if (bsGetBit()) { 
     447        inUse16 |= 1 << i; 
     448      } 
     449    } 
     450 
     451    for (int i = 256; --i >= 0;) inUse[i] = false; 
     452 
     453    for (int i = 0; i < 16; i++) { 
     454      if ((inUse16 & (1 << i)) != 0) { 
     455        final int i16 = i << 4; 
     456        for (int j = 0; j < 16; j++) { 
     457          if (bsGetBit()) inUse[i16 + j] = true; 
    65458        } 
    66  
    67         this.nInUse = nInUseShadow; 
    68     } 
    69  
    70     /** 
    71      * Index of the last char in the block, so the block size == last + 1. 
    72      */ 
    73     private int  last; 
    74  
    75     /** 
    76      * Index in zptr[] of original string after sorting. 
    77      */ 
    78     private int  origPtr; 
    79  
    80     /** 
    81      * always: in the range 0 .. 9. 
    82      * The current block size is 100000 * this number. 
    83      */ 
    84     private int blockSize100k; 
    85  
    86     private boolean blockRandomised; 
    87  
    88     private int bsBuff; 
    89     private int bsLive; 
    90     private final CRC crc = new CRC(); 
    91  
    92     private int nInUse; 
    93  
    94     private InputStream in; 
    95  
    96     private int currentChar = -1; 
    97  
    98     private static final int EOF                  = 0; 
    99     private static final int START_BLOCK_STATE = 1; 
    100     private static final int RAND_PART_A_STATE = 2; 
    101     private static final int RAND_PART_B_STATE = 3; 
    102     private static final int RAND_PART_C_STATE = 4; 
    103     private static final int NO_RAND_PART_A_STATE = 5; 
    104     private static final int NO_RAND_PART_B_STATE = 6; 
    105     private static final int NO_RAND_PART_C_STATE = 7; 
    106  
    107     private int currentState = START_BLOCK_STATE; 
    108  
    109     private int storedBlockCRC, storedCombinedCRC; 
    110     private int computedBlockCRC, computedCombinedCRC; 
    111  
    112     // Variables used by setup* methods exclusively 
    113  
    114     private int su_count; 
    115     private int su_ch2; 
    116     private int su_chPrev; 
    117     private int su_i2; 
    118     private int su_j2; 
    119     private int su_rNToGo; 
    120     private int su_rTPos; 
    121     private int su_tPos; 
    122     private char su_z; 
    123  
    124     /** 
    125      * All memory intensive stuff. 
    126      * This field is initialized by initBlock(). 
    127      */ 
    128     private CBZip2InputStream.Data data; 
    129  
    130     /** 
    131      * Constructs a new CBZip2InputStream which decompresses bytes read from 
    132      * the specified stream. 
    133      * 
    134      * <p>Although BZip2 headers are marked with the magic 
    135      * <tt>"Bz"</tt> this constructor expects the next byte in the 
    136      * stream to be the first one after the magic.  Thus callers have 
    137      * to skip the first two bytes. Otherwise this constructor will 
    138      * throw an exception. </p> 
    139      * 
    140      * @throws IOException 
    141      *  if the stream content is malformed or an I/O error occurs. 
    142      * @throws NullPointerException 
    143      *  if <tt>in == null</tt> 
    144      */ 
    145     public CBZip2InputStream(final InputStream in) throws IOException { 
    146         super(); 
    147  
    148         this.in = in; 
    149         init(); 
    150     } 
    151  
    152     public int read() throws IOException { 
    153         if (this.in != null) { 
    154             return read0(); 
    155         } else { 
    156             throw new IOException("stream closed"); 
    157         } 
    158     } 
    159  
    160     public int read(final byte[] dest, final int offs, final int len) 
    161         throws IOException { 
    162         if (offs < 0) { 
    163             throw new IndexOutOfBoundsException("offs(" + offs + ") < 0."); 
    164         } 
    165         if (len < 0) { 
    166             throw new IndexOutOfBoundsException("len(" + len + ") < 0."); 
    167         } 
    168         if (offs + len > dest.length) { 
    169             throw new IndexOutOfBoundsException("offs(" + offs + ") + len(" 
    170                                                 + len + ") > dest.length(" 
    171                                                 + dest.length + ")."); 
    172         } 
    173         if (this.in == null) { 
    174             throw new IOException("stream closed"); 
    175         } 
    176  
    177         final int hi = offs + len; 
    178         int destOffs = offs; 
    179         for (int b; (destOffs < hi) && ((b = read0()) >= 0);) { 
    180             dest[destOffs++] = (byte) b; 
    181         } 
    182  
    183         return (destOffs == offs) ? -1 : (destOffs - offs); 
    184     } 
    185  
    186     private int read0() throws IOException { 
    187         final int retChar = this.currentChar; 
    188  
    189         switch (this.currentState) { 
    190         case EOF: 
    191             return -1; 
    192  
    193         case START_BLOCK_STATE: 
    194             throw new IllegalStateException(); 
    195  
    196         case RAND_PART_A_STATE: 
    197             throw new IllegalStateException(); 
    198  
    199         case RAND_PART_B_STATE: 
    200             setupRandPartB(); 
    201             break; 
    202  
    203         case RAND_PART_C_STATE: 
    204             setupRandPartC(); 
    205             break; 
    206  
    207         case NO_RAND_PART_A_STATE: 
    208             throw new IllegalStateException(); 
    209  
    210         case NO_RAND_PART_B_STATE: 
    211             setupNoRandPartB(); 
    212             break; 
    213  
    214         case NO_RAND_PART_C_STATE: 
    215             setupNoRandPartC(); 
    216             break; 
    217  
    218         default: 
    219             throw new IllegalStateException(); 
    220         } 
    221  
    222         return retChar; 
    223     } 
    224  
    225     private void init() throws IOException { 
    226         int magic2 = this.in.read(); 
    227         if (magic2 != 'h') { 
    228             throw new IOException("Stream is not BZip2 formatted: expected 'h'" 
    229                                   + " as first byte but got '" + (char) magic2 
    230                                   + "'"); 
    231         } 
    232  
    233         int blockSize = this.in.read(); 
    234         if ((blockSize < '1') || (blockSize > '9')) { 
    235             throw new IOException("Stream is not BZip2 formatted: illegal " 
    236                                   + "blocksize " + (char) blockSize); 
    237         } 
    238  
    239         this.blockSize100k = blockSize - '0'; 
    240  
    241         initBlock(); 
    242         setupBlock(); 
    243     } 
    244  
    245     private void initBlock() throws IOException { 
    246         char magic0 = bsGetUByte(); 
    247         char magic1 = bsGetUByte(); 
    248         char magic2 = bsGetUByte(); 
    249         char magic3 = bsGetUByte(); 
    250         char magic4 = bsGetUByte(); 
    251         char magic5 = bsGetUByte(); 
    252  
    253         if (magic0 == 0x17 && 
    254             magic1 == 0x72 && 
    255             magic2 == 0x45 && 
    256             magic3 == 0x38 && 
    257             magic4 == 0x50 && 
    258             magic5 == 0x90) { 
    259             complete(); // end of file 
    260         } else if (magic0 != 0x31 || // '1' 
    261                    magic1 != 0x41 || // ')' 
    262                    magic2 != 0x59 || // 'Y' 
    263                    magic3 != 0x26 || // '&' 
    264                    magic4 != 0x53 || // 'S' 
    265                    magic5 != 0x59   // 'Y' 
    266                    ) { 
    267             this.currentState = EOF; 
    268             throw new IOException("bad block header"); 
    269         } else { 
    270             this.storedBlockCRC = bsGetInt(); 
    271             this.blockRandomised = bsR(1) == 1; 
    272  
    273             /** 
    274              * Allocate data here instead in constructor, so we do not 
    275              * allocate it if the input file is empty. 
    276              */ 
    277             if (this.data == null) { 
    278                 this.data = new Data(this.blockSize100k); 
     459      } 
     460    } 
     461 
     462    makeMaps(); 
     463    final int alphaSize = this.nInUse + 2; 
     464 
     465    // Now the selectors 
     466    final int nGroups = bsR(3); 
     467    final int nSelectors = bsR(15); 
     468 
     469    for (int i = 0; i < nSelectors; i++) { 
     470      int j = 0; 
     471      while (bsGetBit()) j++; 
     472      selectorMtf[i] = (byte) j; 
     473    } 
     474 
     475    // Undo the MTF values for the selectors. 
     476    for (int v = nGroups; --v >= 0;) pos[v] = (byte) v; 
     477 
     478    for (int i = 0; i < nSelectors; i++) { 
     479      int v = selectorMtf[i] & 0xff; 
     480      final byte tmp = pos[v]; 
     481      while (v > 0) { 
     482        // nearly all times v is zero, 4 in most other cases 
     483        pos[v] = pos[v - 1]; 
     484        v--; 
     485      } 
     486      pos[0] = tmp; 
     487      selector[i] = tmp; 
     488    } 
     489 
     490    final char[][] len  = dataShadow.tempCharArray2d; 
     491 
     492    // Now the coding tables 
     493    for (int t = 0; t < nGroups; t++) { 
     494      int curr = bsR(5); 
     495      final char[] tLen = len[t]; 
     496      for (int i = 0; i < alphaSize; i++) { 
     497        while (bsGetBit()) curr += bsGetBit() ? -1 : 1; 
     498        tLen[i] = (char) curr; 
     499      } 
     500    } 
     501 
     502    // finally create the Huffman tables 
     503    createHuffmanDecodingTables(alphaSize, nGroups); 
     504  } 
     505 
     506  /** Called by recvDecodingTables() exclusively. */ 
     507  private void createHuffmanDecodingTables(final int alphaSize, 
     508    final int nGroups) 
     509  { 
     510    final Data dataShadow = this.data; 
     511    final char[][] len  = dataShadow.tempCharArray2d; 
     512    final int[] minLens = dataShadow.minLens; 
     513    final int[][] limit = dataShadow.limit; 
     514    final int[][] base  = dataShadow.base; 
     515    final int[][] perm  = dataShadow.perm; 
     516 
     517    for (int t = 0; t < nGroups; t++) { 
     518      int minLen = 32; 
     519      int maxLen = 0; 
     520      final char[] tLen = len[t]; 
     521      for (int i = alphaSize; --i >= 0;) { 
     522        final char lent = tLen[i]; 
     523        if (lent > maxLen) maxLen = lent; 
     524        if (lent < minLen) minLen = lent; 
     525      } 
     526      hbCreateDecodeTables(limit[t], base[t], perm[t], len[t], minLen, 
     527        maxLen, alphaSize); 
     528      minLens[t] = minLen; 
     529    } 
     530  } 
     531 
     532  private void getAndMoveToFrontDecode() throws IOException { 
     533    this.origPtr = bsR(24); 
     534    recvDecodingTables(); 
     535 
     536    final InputStream inShadow = this.in; 
     537    final Data dataShadow  = this.data; 
     538    final byte[] ll8      = dataShadow.ll8; 
     539    final int[] unzftab    = dataShadow.unzftab; 
     540    final byte[] selector  = dataShadow.selector; 
     541    final byte[] seqToUnseq = dataShadow.seqToUnseq; 
     542    final char[] yy      = dataShadow.getAndMoveToFrontDecodeYY; 
     543    final int[] minLens    = dataShadow.minLens; 
     544    final int[][] limit    = dataShadow.limit; 
     545    final int[][] base    = dataShadow.base; 
     546    final int[][] perm    = dataShadow.perm; 
     547    final int limitLast    = this.blockSize100k * 100000; 
     548 
     549    // Setting up the unzftab entries here is not strictly 
     550    // necessary, but it does save having to do it later 
     551    // in a separate pass, and so saves a block's worth of 
     552    // cache misses. 
     553    for (int i = 256; --i >= 0;) { 
     554      yy[i] = (char) i; 
     555      unzftab[i] = 0; 
     556    } 
     557 
     558    int groupNo    = 0; 
     559    int groupPos   = G_SIZE - 1; 
     560    final int eob  = this.nInUse + 1; 
     561    int nextSym    = getAndMoveToFrontDecode0(0); 
     562    int bsBuffShadow    = this.bsBuff; 
     563    int bsLiveShadow    = this.bsLive; 
     564    int lastShadow      = -1; 
     565    int zt       = selector[groupNo] & 0xff; 
     566    int[] baseZT  = base[zt]; 
     567    int[] limitZT  = limit[zt]; 
     568    int[] permZT  = perm[zt]; 
     569    int minLensZT  = minLens[zt]; 
     570 
     571    while (nextSym != eob) { 
     572      if ((nextSym == RUNA) || (nextSym == RUNB)) { 
     573        int s = -1; 
     574 
     575        for (int n = 1; true; n <<= 1) { 
     576          if (nextSym == RUNA) s += n; 
     577          else if (nextSym == RUNB) s += n << 1; 
     578          else break; 
     579 
     580          if (groupPos == 0) { 
     581            groupPos   = G_SIZE - 1; 
     582            zt       = selector[++groupNo] & 0xff; 
     583            baseZT    = base[zt]; 
     584            limitZT   = limit[zt]; 
     585            permZT    = perm[zt]; 
     586            minLensZT  = minLens[zt]; 
     587          } 
     588          else groupPos--; 
     589 
     590          int zn = minLensZT; 
     591 
     592          // Inlined: 
     593          // int zvec = bsR(zn); 
     594          while (bsLiveShadow < zn) { 
     595            final int thech = inShadow.read(); 
     596            if (thech >= 0) { 
     597              bsBuffShadow = (bsBuffShadow << 8) | thech; 
     598              bsLiveShadow += 8; 
     599              continue; 
    279600            } 
    280  
    281             // currBlockNo++; 
    282             getAndMoveToFrontDecode(); 
    283  
    284             this.crc.initialiseCRC(); 
    285             this.currentState = START_BLOCK_STATE; 
    286         } 
    287     } 
    288  
    289     private void endBlock() throws IOException { 
    290         this.computedBlockCRC = this.crc.getFinalCRC(); 
    291  
    292         // A bad CRC is considered a fatal error. 
    293         if (this.storedBlockCRC != this.computedBlockCRC) { 
    294             // make next blocks readable without error 
    295             // (repair feature, not yet documented, not tested) 
    296             this.computedCombinedCRC 
    297                 = (this.storedCombinedCRC << 1) 
    298                 | (this.storedCombinedCRC >>> 31); 
    299             this.computedCombinedCRC ^= this.storedBlockCRC; 
    300  
    301             reportCRCError(); 
    302         } 
    303  
    304         this.computedCombinedCRC 
    305             = (this.computedCombinedCRC << 1) 
    306             | (this.computedCombinedCRC >>> 31); 
    307         this.computedCombinedCRC ^= this.computedBlockCRC; 
    308     } 
    309  
    310     private void complete() throws IOException { 
    311         this.storedCombinedCRC = bsGetInt(); 
    312         this.currentState = EOF; 
    313         this.data = null; 
    314  
    315         if (this.storedCombinedCRC != this.computedCombinedCRC) { 
    316             reportCRCError(); 
    317         } 
    318     } 
    319  
    320     public void close() throws IOException { 
    321         InputStream inShadow = this.in; 
    322         if (inShadow != null) { 
    323             try { 
    324                 if (inShadow != System.in) { 
    325                     inShadow.close(); 
    326                 } 
    327             } finally { 
    328                 this.data = null; 
    329                 this.in = null; 
    330             } 
    331         } 
    332     } 
    333  
    334     private int bsR(final int n) throws IOException { 
    335         int bsLiveShadow = this.bsLive; 
    336         int bsBuffShadow = this.bsBuff; 
    337  
    338         if (bsLiveShadow < n) { 
    339             final InputStream inShadow = this.in; 
    340             do { 
    341                 int thech = inShadow.read(); 
    342  
    343                 if (thech < 0) { 
    344                     throw new IOException("unexpected end of stream"); 
    345                 } 
    346  
     601            else throw new IOException("unexpected end of stream"); 
     602          } 
     603          int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1); 
     604          bsLiveShadow -= zn; 
     605 
     606          while (zvec > limitZT[zn]) { 
     607            zn++; 
     608            while (bsLiveShadow < 1) { 
     609              final int thech = inShadow.read(); 
     610              if (thech >= 0) { 
    347611                bsBuffShadow = (bsBuffShadow << 8) | thech; 
    348612                bsLiveShadow += 8; 
    349             } while (bsLiveShadow < n); 
    350  
    351             this.bsBuff = bsBuffShadow; 
    352         } 
    353  
    354         this.bsLive = bsLiveShadow - n; 
    355         return (bsBuffShadow >> (bsLiveShadow - n)) & ((1 << n) - 1); 
    356     } 
    357  
    358     private boolean bsGetBit() throws IOException { 
    359         int bsLiveShadow = this.bsLive; 
    360         int bsBuffShadow = this.bsBuff; 
    361  
    362         if (bsLiveShadow < 1) { 
    363             int thech = this.in.read(); 
    364  
    365             if (thech < 0) { 
    366                 throw new IOException("unexpected end of stream"); 
    367             } 
    368  
    369             bsBuffShadow = (bsBuffShadow << 8) | thech; 
    370             bsLiveShadow += 8; 
    371             this.bsBuff = bsBuffShadow; 
    372         } 
    373  
    374         this.bsLive = bsLiveShadow - 1; 
    375         return ((bsBuffShadow >> (bsLiveShadow - 1)) & 1) != 0; 
    376     } 
    377  
    378     private char bsGetUByte() throws IOException { 
    379         return (char) bsR(8); 
    380     } 
    381  
    382     private int bsGetInt() throws IOException { 
    383         return (((((bsR(8) << 8) | bsR(8)) << 8) | bsR(8)) << 8) | bsR(8); 
    384     } 
    385  
    386     /** 
    387      * Called by createHuffmanDecodingTables() exclusively. 
    388      */ 
    389     private static void hbCreateDecodeTables(final int[] limit, 
    390                                              final int[] base, 
    391                                              final int[] perm, 
    392                                              final char[] length, 
    393                                              final int minLen, 
    394                                              final int maxLen, 
    395                                              final int alphaSize) { 
    396         for (int i = minLen, pp = 0; i <= maxLen; i++) { 
    397             for (int j = 0; j < alphaSize; j++) { 
    398                 if (length[j] == i) { 
    399                     perm[pp++] = j; 
    400                 } 
    401             } 
    402         } 
    403  
    404         for (int i = MAX_CODE_LEN; --i > 0;) { 
    405             base[i] = 0; 
    406             limit[i] = 0; 
    407         } 
    408  
    409         for (int i = 0; i < alphaSize; i++) { 
    410             base[length[i] + 1]++; 
    411         } 
    412  
    413         for (int i = 1, b = base[0]; i < MAX_CODE_LEN; i++) { 
    414             b += base[i]; 
    415             base[i] = b; 
    416         } 
    417  
    418         for (int i = minLen, vec = 0, b = base[i]; i <= maxLen; i++) { 
    419             final int nb = base[i + 1]; 
    420             vec += nb - b; 
    421             b = nb; 
    422             limit[i] = vec - 1; 
    423             vec <<= 1; 
    424         } 
    425  
    426         for (int i = minLen + 1; i <= maxLen; i++) { 
    427             base[i] = ((limit[i - 1] + 1) << 1) - base[i]; 
    428         } 
    429     } 
    430  
    431     private void recvDecodingTables() throws IOException { 
    432         final Data dataShadow     = this.data; 
    433         final boolean[] inUse     = dataShadow.inUse; 
    434         final byte[] pos          = dataShadow.recvDecodingTables_pos; 
    435         final byte[] selector     = dataShadow.selector; 
    436         final byte[] selectorMtf  = dataShadow.selectorMtf; 
    437  
    438         int inUse16 = 0; 
    439  
    440         /* Receive the mapping table */ 
    441         for (int i = 0; i < 16; i++) { 
    442             if (bsGetBit()) { 
    443                 inUse16 |= 1 << i; 
    444             } 
    445         } 
    446  
    447         for (int i = 256; --i >= 0;) { 
    448             inUse[i] = false; 
    449         } 
    450  
    451         for (int i = 0; i < 16; i++) { 
    452             if ((inUse16 & (1 << i)) != 0) { 
    453                 final int i16 = i << 4; 
    454                 for (int j = 0; j < 16; j++) { 
    455                     if (bsGetBit()) { 
    456                         inUse[i16 + j] = true; 
    457                     } 
    458                 } 
    459             } 
    460         } 
    461  
    462         makeMaps(); 
    463         final int alphaSize = this.nInUse + 2; 
    464  
    465         /* Now the selectors */ 
    466         final int nGroups = bsR(3); 
    467         final int nSelectors = bsR(15); 
    468  
    469         for (int i = 0; i < nSelectors; i++) { 
    470             int j = 0; 
    471             while (bsGetBit()) { 
    472                 j++; 
    473             } 
    474             selectorMtf[i] = (byte) j; 
    475         } 
    476  
    477         /* Undo the MTF values for the selectors. */ 
    478         for (int v = nGroups; --v >= 0;) { 
    479             pos[v] = (byte) v; 
    480         } 
    481  
    482         for (int i = 0; i < nSelectors; i++) { 
    483             int v = selectorMtf[i] & 0xff; 
    484             final byte tmp = pos[v]; 
    485             while (v > 0) { 
    486                 // nearly all times v is zero, 4 in most other cases 
    487                 pos[v] = pos[v - 1]; 
    488                 v--; 
    489             } 
    490             pos[0] = tmp; 
    491             selector[i] = tmp; 
    492         } 
    493  
    494         final char[][] len  = dataShadow.temp_charArray2d; 
    495  
    496         /* Now the coding tables */ 
    497         for (int t = 0; t < nGroups; t++) { 
    498             int curr = bsR(5); 
    499             final char[] len_t = len[t]; 
    500             for (int i = 0; i < alphaSize; i++) { 
    501                 while (bsGetBit()) { 
    502                     curr += bsGetBit() ? -1 : 1; 
    503                 } 
    504                 len_t[i] = (char) curr; 
    505             } 
    506         } 
    507  
    508         // finally create the Huffman tables 
    509         createHuffmanDecodingTables(alphaSize, nGroups); 
    510     } 
    511  
    512     /** 
    513      * Called by recvDecodingTables() exclusively. 
    514      */ 
    515     private void createHuffmanDecodingTables(final int alphaSize, 
    516                                              final int nGroups) { 
    517         final Data dataShadow = this.data; 
    518         final char[][] len  = dataShadow.temp_charArray2d; 
    519         final int[] minLens = dataShadow.minLens; 
    520         final int[][] limit = dataShadow.limit; 
    521         final int[][] base  = dataShadow.base; 
    522         final int[][] perm  = dataShadow.perm; 
    523  
    524         for (int t = 0; t < nGroups; t++) { 
    525             int minLen = 32; 
    526             int maxLen = 0; 
    527             final char[] len_t = len[t]; 
    528             for (int i = alphaSize; --i >= 0;) { 
    529                 final char lent = len_t[i]; 
    530                 if (lent > maxLen) { 
    531                     maxLen = lent; 
    532                 } 
    533                 if (lent < minLen) { 
    534                     minLen = lent; 
    535                 } 
    536             } 
    537             hbCreateDecodeTables(limit[t], base[t], perm[t], len[t], minLen, 
    538                                  maxLen, alphaSize); 
    539             minLens[t] = minLen; 
    540         } 
    541     } 
    542  
    543     private void getAndMoveToFrontDecode() throws IOException { 
    544         this.origPtr = bsR(24); 
    545         recvDecodingTables(); 
    546  
    547         final InputStream inShadow = this.in; 
    548         final Data dataShadow   = this.data; 
    549         final byte[] ll8        = dataShadow.ll8; 
    550         final int[] unzftab     = dataShadow.unzftab; 
    551         final byte[] selector   = dataShadow.selector; 
    552         final byte[] seqToUnseq = dataShadow.seqToUnseq; 
    553         final char[] yy         = dataShadow.getAndMoveToFrontDecode_yy; 
    554         final int[] minLens     = dataShadow.minLens; 
    555         final int[][] limit     = dataShadow.limit; 
    556         final int[][] base      = dataShadow.base; 
    557         final int[][] perm      = dataShadow.perm; 
    558         final int limitLast     = this.blockSize100k * 100000; 
    559  
    560         /* 
    561           Setting up the unzftab entries here is not strictly 
    562           necessary, but it does save having to do it later 
    563           in a separate pass, and so saves a block's worth of 
    564           cache misses. 
    565         */ 
    566         for (int i = 256; --i >= 0;) { 
    567             yy[i] = (char) i; 
    568             unzftab[i] = 0; 
    569         } 
    570  
    571         int groupNo     = 0; 
    572         int groupPos    = G_SIZE - 1; 
    573         final int eob   = this.nInUse + 1; 
    574         int nextSym     = getAndMoveToFrontDecode0(0); 
    575         int bsBuffShadow      = this.bsBuff; 
    576         int bsLiveShadow      = this.bsLive; 
    577         int lastShadow        = -1; 
    578         int zt          = selector[groupNo] & 0xff; 
    579         int[] base_zt   = base[zt]; 
    580         int[] limit_zt  = limit[zt]; 
    581         int[] perm_zt   = perm[zt]; 
    582         int minLens_zt  = minLens[zt]; 
    583  
    584         while (nextSym != eob) { 
    585             if ((nextSym == RUNA) || (nextSym == RUNB)) { 
    586                 int s = -1; 
    587  
    588                 for (int n = 1; true; n <<= 1) { 
    589                     if (nextSym == RUNA) { 
    590                         s += n; 
    591                     } else if (nextSym == RUNB) { 
    592                         s += n << 1; 
    593                     } else { 
    594                         break; 
    595                     } 
    596  
    597                     if (groupPos == 0) { 
    598                         groupPos    = G_SIZE - 1; 
    599                         zt          = selector[++groupNo] & 0xff; 
    600                         base_zt     = base[zt]; 
    601                         limit_zt    = limit[zt]; 
    602                         perm_zt     = perm[zt]; 
    603                         minLens_zt  = minLens[zt]; 
    604                     } else { 
    605                         groupPos--; 
    606                     } 
    607  
    608                     int zn = minLens_zt; 
    609  
    610                     // Inlined: 
    611                     // int zvec = bsR(zn); 
    612                     while (bsLiveShadow < zn) { 
    613                         final int thech = inShadow.read(); 
    614                         if (thech >= 0) { 
    615                             bsBuffShadow = (bsBuffShadow << 8) | thech; 
    616                             bsLiveShadow += 8; 
    617                             continue; 
    618                         } else { 
    619                             throw new IOException("unexpected end of stream"); 
    620                         } 
    621                     } 
    622                     int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1); 
    623                     bsLiveShadow -= zn; 
    624  
    625                     while (zvec > limit_zt[zn]) { 
    626                         zn++; 
    627                         while (bsLiveShadow < 1) { 
    628                             final int thech = inShadow.read(); 
    629                             if (thech >= 0) { 
    630                                 bsBuffShadow = (bsBuffShadow << 8) | thech; 
    631                                 bsLiveShadow += 8; 
    632                                 continue; 
    633                             } else { 
    634                                 throw new IOException("unexpected end of stream"); 
    635                             } 
    636                         } 
    637                         bsLiveShadow--; 
    638                         zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1); 
    639                     } 
    640                     nextSym = perm_zt[zvec - base_zt[zn]]; 
    641                 } 
    642  
    643                 final byte ch = seqToUnseq[yy[0]]; 
    644                 unzftab[ch & 0xff] += s + 1; 
    645  
    646                 while (s-- >= 0) { 
    647                     ll8[++lastShadow] = ch; 
    648                 } 
    649  
    650                 if (lastShadow >= limitLast) { 
    651                     throw new IOException("block overrun"); 
    652                 } 
    653             } else { 
    654                 if (++lastShadow >= limitLast) { 
    655                     throw new IOException("block overrun"); 
    656                 } 
    657  
    658                 final char tmp = yy[nextSym - 1]; 
    659                 unzftab[seqToUnseq[tmp] & 0xff]++; 
    660                 ll8[lastShadow] = seqToUnseq[tmp]; 
    661  
    662                 /* 
    663                   This loop is hammered during decompression, 
    664                   hence avoid native method call overhead of 
    665                   System.arraycopy for very small ranges to copy. 
    666                 */ 
    667                 if (nextSym <= 16) { 
    668                     for (int j = nextSym - 1; j > 0;) { 
    669                         yy[j] = yy[--j]; 
    670                     } 
    671                 } else { 
    672                     System.arraycopy(yy, 0, yy, 1, nextSym - 1); 
    673                 } 
    674  
    675                 yy[0] = tmp; 
    676  
    677                 if (groupPos == 0) { 
    678                     groupPos    = G_SIZE - 1; 
    679                     zt          = selector[++groupNo] & 0xff; 
    680                     base_zt     = base[zt]; 
    681                     limit_zt    = limit[zt]; 
    682                     perm_zt     = perm[zt]; 
    683                     minLens_zt  = minLens[zt]; 
    684                 } else { 
    685                     groupPos--; 
    686                 } 
    687  
    688                 int zn = minLens_zt; 
    689  
    690                 // Inlined: 
    691                 // int zvec = bsR(zn); 
    692                 while (bsLiveShadow < zn) { 
    693                     final int thech = inShadow.read(); 
    694                     if (thech >= 0) { 
    695                         bsBuffShadow = (bsBuffShadow << 8) | thech; 
    696                         bsLiveShadow += 8; 
    697                         continue; 
    698                     } else { 
    699                         throw new IOException("unexpected end of stream"); 
    700                     } 
    701                 } 
    702                 int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1); 
    703                 bsLiveShadow -= zn; 
    704  
    705                 while (zvec > limit_zt[zn]) { 
    706                     zn++; 
    707                     while (bsLiveShadow < 1) { 
    708                         final int thech = inShadow.read(); 
    709                         if (thech >= 0) { 
    710                             bsBuffShadow = (bsBuffShadow << 8) | thech; 
    711                             bsLiveShadow += 8; 
    712                             continue; 
    713                         } else { 
    714                             throw new IOException("unexpected end of stream"); 
    715                         } 
    716                     } 
    717                     bsLiveShadow--; 
    718                     zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1); 
    719                 } 
    720                 nextSym = perm_zt[zvec - base_zt[zn]]; 
    721             } 
    722         } 
    723  
    724         this.last = lastShadow; 
    725         this.bsLive = bsLiveShadow; 
    726         this.bsBuff = bsBuffShadow; 
    727     } 
    728  
    729     private int getAndMoveToFrontDecode0(final int groupNo) 
    730         throws IOException { 
    731         final InputStream inShadow  = this.in; 
    732         final Data dataShadow  = this.data; 
    733         final int zt          = dataShadow.selector[groupNo] & 0xff; 
    734         final int[] limit_zt  = dataShadow.limit[zt]; 
    735         int zn = dataShadow.minLens[zt]; 
    736         int zvec = bsR(zn); 
    737         int bsLiveShadow = this.bsLive; 
    738         int bsBuffShadow = this.bsBuff; 
    739  
    740         while (zvec > limit_zt[zn]) { 
    741             zn++; 
    742             while (bsLiveShadow < 1) { 
    743                 final int thech = inShadow.read(); 
    744  
    745                 if (thech >= 0) { 
    746                     bsBuffShadow = (bsBuffShadow << 8) | thech; 
    747                     bsLiveShadow += 8; 
    748                     continue; 
    749                 } else { 
    750                     throw new IOException("unexpected end of stream"); 
    751                 } 
     613                continue; 
     614              } 
     615              else throw new IOException("unexpected end of stream"); 
    752616            } 
    753617            bsLiveShadow--; 
    754618            zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1); 
     619          } 
     620          nextSym = permZT[zvec - baseZT[zn]]; 
    755621        } 
    756622 
    757         this.bsLive = bsLiveShadow; 
    758         this.bsBuff = bsBuffShadow; 
    759  
    760         return dataShadow.perm[zt][zvec - dataShadow.base[zt][zn]]; 
    761     } 
    762  
    763     private void setupBlock() throws IOException { 
    764         if (this.data == null) { 
    765             return; 
     623        final byte ch = seqToUnseq[yy[0]]; 
     624        unzftab[ch & 0xff] += s + 1; 
     625 
     626        while (s-- >= 0) ll8[++lastShadow] = ch; 
     627 
     628        if (lastShadow >= limitLast) throw new IOException("block overrun"); 
     629      } 
     630      else { 
     631        if (++lastShadow >= limitLast) { 
     632          throw new IOException("block overrun"); 
    766633        } 
    767634 
    768         final int[] cftab = this.data.cftab; 
    769         final int[] tt    = this.data.initTT(this.last + 1); 
    770         final byte[] ll8  = this.data.ll8; 
    771         cftab[0] = 0; 
    772         System.arraycopy(this.data.unzftab, 0, cftab, 1, 256); 
    773  
    774         for (int i = 1, c = cftab[0]; i <= 256; i++) { 
    775             c += cftab[i]; 
    776             cftab[i] = c; 
     635        final char tmp = yy[nextSym - 1]; 
     636        unzftab[seqToUnseq[tmp] & 0xff]++; 
     637        ll8[lastShadow] = seqToUnseq[tmp]; 
     638 
     639        /* 
     640         This loop is hammered during decompression, 
     641         hence avoid native method call overhead of 
     642         System.arraycopy for very small ranges to copy. 
     643        */ 
     644        if (nextSym <= 16) { 
     645          for (int j = nextSym - 1; j > 0;) yy[j] = yy[--j]; 
    777646        } 
    778  
    779         for (int i = 0, lastShadow = this.last; i <= lastShadow; i++) { 
    780             tt[cftab[ll8[i] & 0xff]++] = i; 
     647        else System.arraycopy(yy, 0, yy, 1, nextSym - 1); 
     648 
     649        yy[0] = tmp; 
     650 
     651        if (groupPos == 0) { 
     652          groupPos   = G_SIZE - 1; 
     653          zt       = selector[++groupNo] & 0xff; 
     654          baseZT    = base[zt]; 
     655          limitZT   = limit[zt]; 
     656          permZT    = perm[zt]; 
     657          minLensZT  = minLens[zt]; 
    781658        } 
    782  
    783         if ((this.origPtr < 0) || (this.origPtr >= tt.length)) { 
    784             throw new IOException("stream corrupted"); 
     659        else groupPos--; 
     660 
     661        int zn = minLensZT; 
     662 
     663        // Inlined: 
     664        // int zvec = bsR(zn); 
     665        while (bsLiveShadow < zn) { 
     666          final int thech = inShadow.read(); 
     667          if (thech >= 0) { 
     668            bsBuffShadow = (bsBuffShadow << 8) | thech; 
     669            bsLiveShadow += 8; 
     670            continue; 
     671          } 
     672          else throw new IOException("unexpected end of stream"); 
    785673        } 
    786  
    787         this.su_tPos = tt[this.origPtr]; 
    788         this.su_count = 0; 
    789         this.su_i2 = 0; 
    790         this.su_ch2 = 256;   /* not a char and not EOF */ 
    791  
    792         if (this.blockRandomised) { 
    793             this.su_rNToGo = 0; 
    794             this.su_rTPos = 0; 
    795             setupRandPartA(); 
    796         } else { 
    797             setupNoRandPartA(); 
     674        int zvec = (bsBuffShadow >> (bsLiveShadow - zn)) & ((1 << zn) - 1); 
     675        bsLiveShadow -= zn; 
     676 
     677        while (zvec > limitZT[zn]) { 
     678          zn++; 
     679          while (bsLiveShadow < 1) { 
     680            final int thech = inShadow.read(); 
     681            if (thech >= 0) { 
     682              bsBuffShadow = (bsBuffShadow << 8) | thech; 
     683              bsLiveShadow += 8; 
     684              continue; 
     685            } 
     686            else throw new IOException("unexpected end of stream"); 
     687          } 
     688          bsLiveShadow--; 
     689          zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1); 
    798690        } 
    799     } 
    800  
    801     private void setupRandPartA() throws IOException { 
    802         if (this.su_i2 <= this.last) { 
    803             this.su_chPrev = this.su_ch2; 
    804             int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff; 
    805             this.su_tPos = this.data.tt[this.su_tPos]; 
    806             if (this.su_rNToGo == 0) { 
    807                 this.su_rNToGo = BZip2Constants.R_NUMS[this.su_rTPos] - 1; 
    808                 if (++this.su_rTPos == 512) { 
    809                     this.su_rTPos = 0; 
    810                 } 
    811             } else { 
    812                 this.su_rNToGo--; 
    813             } 
    814             this.su_ch2 = su_ch2Shadow ^= (this.su_rNToGo == 1) ? 1 : 0; 
    815             this.su_i2++; 
    816             this.currentChar = su_ch2Shadow; 
    817             this.currentState = RAND_PART_B_STATE; 
    818             this.crc.updateCRC(su_ch2Shadow); 
    819         } else { 
    820             endBlock(); 
    821             initBlock(); 
    822             setupBlock(); 
     691        nextSym = permZT[zvec - baseZT[zn]]; 
     692      } 
     693    } 
     694 
     695    this.last = lastShadow; 
     696    this.bsLive = bsLiveShadow; 
     697    this.bsBuff = bsBuffShadow; 
     698  } 
     699 
     700  private int getAndMoveToFrontDecode0(final int groupNo) 
     701    throws IOException 
     702  { 
     703    final InputStream inShadow  = this.in; 
     704    final Data dataShadow  = this.data; 
     705    final int zt       = dataShadow.selector[groupNo] & 0xff; 
     706    final int[] limitZT  = dataShadow.limit[zt]; 
     707    int zn = dataShadow.minLens[zt]; 
     708    int zvec = bsR(zn); 
     709    int bsLiveShadow = this.bsLive; 
     710    int bsBuffShadow = this.bsBuff; 
     711 
     712    while (zvec > limitZT[zn]) { 
     713      zn++; 
     714      while (bsLiveShadow < 1) { 
     715        final int thech = inShadow.read(); 
     716 
     717        if (thech >= 0) { 
     718          bsBuffShadow = (bsBuffShadow << 8) | thech; 
     719          bsLiveShadow += 8; 
     720          continue; 
    823721        } 
    824     } 
    825  
    826     private void setupNoRandPartA() throws IOException { 
    827         if (this.su_i2 <= this.last) { 
    828             this.su_chPrev = this.su_ch2; 
    829             int su_ch2Shadow = this.data.ll8[this.su_tPos] & 0xff; 
    830             this.su_ch2 = su_ch2Shadow; 
    831             this.su_tPos = this.data.tt[this.su_tPos]; 
    832             this.su_i2++; 
    833             this.currentChar = su_ch2Shadow; 
    834             this.currentState = NO_RAND_PART_B_STATE; 
    835             this.crc.updateCRC(su_ch2Shadow); 
    836         } else { 
    837             this.currentState = NO_RAND_PART_A_STATE; 
    838             endBlock(); 
    839             initBlock(); 
    840             setupBlock(); 
     722        else throw new IOException("unexpected end of stream"); 
     723      } 
     724      bsLiveShadow--; 
     725      zvec = (zvec << 1) | ((bsBuffShadow >> bsLiveShadow) & 1); 
     726    } 
     727 
     728    this.bsLive = bsLiveShadow; 
     729    this.bsBuff = bsBuffShadow; 
     730 
     731    return dataShadow.perm[zt][zvec - dataShadow.base[zt][zn]]; 
     732  } 
     733 
     734  private void setupBlock() throws IOException { 
     735     if (this.data == null) return; 
     736 
     737     final int[] cftab = this.data.cftab; 
     738     final int[] tt   = this.data.initTT(this.last + 1); 
     739     final byte[] ll8  = this.data.ll8; 
     740     cftab[0] = 0; 
     741     System.arraycopy(this.data.unzftab, 0, cftab, 1, 256); 
     742 
     743     for (int i = 1, c = cftab[0]; i <= 256; i++) { 
     744       c += cftab[i]; 
     745       cftab[i] = c; 
     746     } 
     747 
     748     for (int i = 0, lastShadow = this.last; i <= lastShadow; i++) { 
     749       tt[cftab[ll8[i] & 0xff]++] = i; 
     750     } 
     751 
     752     if ((this.origPtr < 0) || (this.origPtr >= tt.length)) { 
     753       throw new IOException("stream corrupted"); 
     754     } 
     755 
     756     this.suTPos = tt[this.origPtr]; 
     757     this.suCount = 0; 
     758     this.suI2 = 0; 
     759     this.suCh2 = 256;  /* not a char and not EOF */ 
     760 
     761     if (this.blockRandomised) { 
     762       this.suRNToGo = 0; 
     763       this.suRTPos = 0; 
     764       setupRandPartA(); 
     765     } 
     766     else setupNoRandPartA(); 
     767  } 
     768 
     769  private void setupRandPartA() throws IOException { 
     770    if (this.suI2 <= this.last) { 
     771      this.suChPrev = this.suCh2; 
     772      int suCh2Shadow = this.data.ll8[this.suTPos] & 0xff; 
     773      this.suTPos = this.data.tt[this.suTPos]; 
     774      if (this.suRNToGo == 0) { 
     775         this.suRNToGo = BZip2Constants.R_NUMS[this.suRTPos] - 1; 
     776         if (++this.suRTPos == 512) { 
     777            this.suRTPos = 0; 
     778         } 
     779      } 
     780      else this.suRNToGo--; 
     781      this.suCh2 = suCh2Shadow ^= (this.suRNToGo == 1) ? 1 : 0; 
     782      this.suI2++; 
     783      this.currentChar = suCh2Shadow; 
     784      this.currentState = RAND_PART_B_STATE; 
     785      this.crc.updateCRC(suCh2Shadow); 
     786    } 
     787    else { 
     788      endBlock(); 
     789      initBlock(); 
     790      setupBlock(); 
     791    } 
     792  } 
     793 
     794  private void setupNoRandPartA() throws IOException { 
     795     if (this.suI2 <= this.last) { 
     796       this.suChPrev = this.suCh2; 
     797       int suCh2Shadow = this.data.ll8[this.suTPos] & 0xff; 
     798       this.suCh2 = suCh2Shadow; 
     799       this.suTPos = this.data.tt[this.suTPos]; 
     800       this.suI2++; 
     801       this.currentChar = suCh2Shadow; 
     802       this.currentState = NO_RAND_PART_B_STATE; 
     803       this.crc.updateCRC(suCh2Shadow); 
     804     } 
     805     else { 
     806       this.currentState = NO_RAND_PART_A_STATE; 
     807       endBlock(); 
     808       initBlock(); 
     809       setupBlock(); 
     810     } 
     811  } 
     812 
     813  private void setupRandPartB() throws IOException { 
     814    if (this.suCh2 != this.suChPrev) { 
     815      this.currentState = RAND_PART_A_STATE; 
     816      this.suCount = 1; 
     817      setupRandPartA(); 
     818    } 
     819    else if (++this.suCount >= 4) { 
     820      this.suZ = (char) (this.data.ll8[this.suTPos] & 0xff); 
     821      this.suTPos = this.data.tt[this.suTPos]; 
     822      if (this.suRNToGo == 0) { 
     823        this.suRNToGo = BZip2Constants.R_NUMS[this.suRTPos] - 1; 
     824        if (++this.suRTPos == 512) { 
     825          this.suRTPos = 0; 
    841826        } 
    842     } 
    843  
    844     private void setupRandPartB() throws IOException { 
    845         if (this.su_ch2 != this.su_chPrev) { 
    846             this.currentState = RAND_PART_A_STATE; 
    847             this.su_count = 1; 
    848             setupRandPartA(); 
    849         } else if (++this.su_count >= 4) { 
    850             this.su_z = (char) (this.data.ll8[this.su_tPos] & 0xff); 
    851             this.su_tPos = this.data.tt[this.su_tPos]; 
    852             if (this.su_rNToGo == 0) { 
    853                 this.su_rNToGo = BZip2Constants.R_NUMS[this.su_rTPos] - 1; 
    854                 if (++this.su_rTPos == 512) { 
    855                     this.su_rTPos = 0; 
    856                 } 
    857             } else { 
    858                 this.su_rNToGo--; 
    859             } 
    860             this.su_j2 = 0; 
    861             this.currentState = RAND_PART_C_STATE; 
    862             if (this.su_rNToGo == 1) { 
    863                 this.su_z ^= 1; 
    864             } 
    865             setupRandPartC(); 
    866         } else { 
    867             this.currentState = RAND_PART_A_STATE; 
    868             setupRandPartA(); 
    869         } 
    870     } 
    871  
    872     private void setupRandPartC() throws IOException { 
    873         if (this.su_j2 < this.su_z) { 
    874             this.currentChar = this.su_ch2; 
    875             this.crc.updateCRC(this.su_ch2); 
    876             this.su_j2++; 
    877         } else { 
    878             this.currentState = RAND_PART_A_STATE; 
    879             this.su_i2++; 
    880             this.su_count = 0; 
    881             setupRandPartA(); 
    882         } 
    883     } 
    884  
    885     private void setupNoRandPartB() throws IOException { 
    886         if (this.su_ch2 != this.su_chPrev) { 
    887             this.su_count = 1; 
    888             setupNoRandPartA(); 
    889         } else if (++this.su_count >= 4) { 
    890             this.su_z = (char) (this.data.ll8[this.su_tPos] & 0xff); 
    891             this.su_tPos = this.data.tt[this.su_tPos]; 
    892             this.su_j2 = 0; 
    893             setupNoRandPartC(); 
    894         } else { 
    895             setupNoRandPartA(); 
    896         } 
    897     } 
    898  
    899     private void setupNoRandPartC() throws IOException { 
    900         if (this.su_j2 < this.su_z) { 
    901             int su_ch2Shadow = this.su_ch2; 
    902             this.currentChar = su_ch2Shadow; 
    903             this.crc.updateCRC(su_ch2Shadow); 
    904             this.su_j2++; 
    905             this.currentState = NO_RAND_PART_C_STATE; 
    906         } else { 
    907             this.su_i2++; 
    908             this.su_count = 0; 
    909             setupNoRandPartA(); 
    910         } 
    911     } 
    912  
    913     private static final class Data extends Object { 
    914  
    915         // (with blockSize 900k) 
    916         final boolean[] inUse   = new boolean[256];                                   //      256 byte 
    917  
    918         final byte[] seqToUnseq   = new byte[256];                                    //      256 byte 
    919         final byte[] selector     = new byte[MAX_SELECTORS];                          //    18002 byte 
    920         final byte[] selectorMtf  = new byte[MAX_SELECTORS];                          //    18002 byte 
    921  
    922         /** 
    923          * Freq table collected to save a pass over the data during 
    924          * decompression. 
    925          */ 
    926         final int[] unzftab = new int[256];                                           //     1024 byte 
    927  
    928         final int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte 
    929         final int[][] base  = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte 
    930         final int[][] perm  = new int[N_GROUPS][MAX_ALPHA_SIZE];                      //     6192 byte 
    931         final int[] minLens = new int[N_GROUPS];                                      //       24 byte 
    932  
    933         final int[]     cftab     = new int[257];                                     //     1028 byte 
    934         final char[]    getAndMoveToFrontDecode_yy = new char[256];                   //      512 byte 
    935         final char[][]  temp_charArray2d  = new char[N_GROUPS][MAX_ALPHA_SIZE];       //     3096 byte 
    936         final byte[] recvDecodingTables_pos = new byte[N_GROUPS];                     //        6 byte 
    937         //--------------- 
    938         //    60798 byte 
    939  
    940         int[] tt;                                                                     //  3600000 byte 
    941         byte[] ll8;                                                                   //   900000 byte 
    942         //--------------- 
    943         //  4560782 byte 
    944         //=============== 
    945  
    946         Data(int blockSize100k) { 
    947             super(); 
    948  
    949             this.ll8 = new byte[blockSize100k * BZip2Constants.BASE_BLOCK_SIZE]; 
    950         } 
    951  
    952         /** 
    953          * Initializes the {@link #tt} array. 
    954          * 
    955          * This method is called when the required length of the array 
    956          * is known.  I don't initialize it at construction time to 
    957          * avoid unneccessary memory allocation when compressing small 
    958          * files. 
    959          */ 
    960         final int[] initTT(int length) { 
    961             int[] ttShadow = this.tt; 
    962  
    963             // tt.length should always be >= length, but theoretically 
    964             // it can happen, if the compressor mixed small and large 
    965             // blocks.  Normally only the last block will be smaller 
    966             // than others. 
    967             if ((ttShadow == null) || (ttShadow.length < length)) { 
    968                 this.tt = ttShadow = new int[length]; 
    969             } 
    970  
    971             return ttShadow; 
    972         } 
    973  
    974     } 
     827      } 
     828      else this.suRNToGo--; 
     829      this.suJ2 = 0; 
     830      this.currentState = RAND_PART_C_STATE; 
     831      if (this.suRNToGo == 1) { 
     832         this.suZ ^= 1; 
     833      } 
     834      setupRandPartC(); 
     835    } 
     836    else { 
     837      this.currentState = RAND_PART_A_STATE; 
     838      setupRandPartA(); 
     839    } 
     840  } 
     841 
     842  private void setupRandPartC() throws IOException { 
     843    if (this.suJ2 < this.suZ) { 
     844      this.currentChar = this.suCh2; 
     845      this.crc.updateCRC(this.suCh2); 
     846      this.suJ2++; 
     847    } 
     848    else { 
     849      this.currentState = RAND_PART_A_STATE; 
     850      this.suI2++; 
     851      this.suCount = 0; 
     852      setupRandPartA(); 
     853    } 
     854  } 
     855 
     856  private void setupNoRandPartB() throws IOException { 
     857    if (this.suCh2 != this.suChPrev) { 
     858      this.suCount = 1; 
     859      setupNoRandPartA(); 
     860    } 
     861    else if (++this.suCount >= 4) { 
     862      this.suZ = (char) (this.data.ll8[this.suTPos] & 0xff); 
     863      this.suTPos = this.data.tt[this.suTPos]; 
     864      this.suJ2 = 0; 
     865      setupNoRandPartC(); 
     866    } 
     867    else setupNoRandPartA(); 
     868  } 
     869 
     870  private void setupNoRandPartC() throws IOException { 
     871    if (this.suJ2 < this.suZ) { 
     872      int suCh2Shadow = this.suCh2; 
     873      this.currentChar = suCh2Shadow; 
     874      this.crc.updateCRC(suCh2Shadow); 
     875      this.suJ2++; 
     876      this.currentState = NO_RAND_PART_C_STATE; 
     877    } 
     878    else { 
     879      this.suI2++; 
     880      this.suCount = 0; 
     881      setupNoRandPartA(); 
     882    } 
     883  } 
     884 
     885  private static final class Data extends Object { 
     886    // (with blockSize 900k) 
     887    final boolean[] inUse  = new boolean[256];                  //     256 byte 
     888 
     889    final byte[] seqToUnseq  = new byte[256];                   //     256 byte 
     890    final byte[] selector    = new byte[MAX_SELECTORS];         //   18002 byte 
     891    final byte[] selectorMtf  = new byte[MAX_SELECTORS];        //   18002 byte 
     892 
     893    /** 
     894     * Freq table collected to save a pass over the data during 
     895     * decompression. 
     896     */ 
     897    final int[] unzftab = new int[256];                         //    1024 byte 
     898 
     899    final int[][] limit = new int[N_GROUPS][MAX_ALPHA_SIZE];    //    6192 byte 
     900    final int[][] base  = new int[N_GROUPS][MAX_ALPHA_SIZE];    //    6192 byte 
     901    final int[][] perm  = new int[N_GROUPS][MAX_ALPHA_SIZE];    //    6192 byte 
     902    final int[] minLens = new int[N_GROUPS];                    //      24 byte 
     903 
     904    final int[]    cftab    = new int[257];                     //    1028 byte 
     905    final char[]   getAndMoveToFrontDecodeYY = new char[256];   //     512 byte 
     906 
     907    //                                                                3096 byte 
     908    final char[][]  tempCharArray2d  = new char[N_GROUPS][MAX_ALPHA_SIZE]; 
     909 
     910    final byte[] recvDecodingTablesPos = new byte[N_GROUPS];    //       6 byte 
     911    //--------------- 
     912    //   60798 byte 
     913 
     914    int[] tt;                                                   // 3600000 byte 
     915    byte[] ll8;                                                 //  900000 byte 
     916    //--------------- 
     917    //  4560782 byte 
     918    //=============== 
     919 
     920    Data(int blockSize100k) { 
     921      super(); 
     922 
     923      this.ll8 = new byte[blockSize100k * BZip2Constants.BASE_BLOCK_SIZE]; 
     924    } 
     925 
     926    /** 
     927     * Initializes the {@link #tt} array. 
     928     * 
     929     * This method is called when the required length of the array 
     930     * is known.  I don't initialize it at construction time to 
     931     * avoid unneccessary memory allocation when compressing small 
     932     * files. 
     933     */ 
     934    final int[] initTT(int length) { 
     935      int[] ttShadow = this.tt; 
     936 
     937      // tt.length should always be >= length, but theoretically 
     938      // it can happen, if the compressor mixed small and large 
     939      // blocks.  Normally only the last block will be smaller 
     940      // than others. 
     941      if ((ttShadow == null) || (ttShadow.length < length)) { 
     942         this.tt = ttShadow = new int[length]; 
     943      } 
     944 
     945      return ttShadow; 
     946    } 
     947  } 
     948 
    975949} 
    976950 
  • trunk/loci/formats/codec/CRC.java

    r2455 r2782  
    2626 * Copyright  2001-2002,2004 The Apache Software Foundation 
    2727 * 
    28  *  Licensed under the Apache License, Version 2.0 (the "License"); 
    29  *  you may not use this file except in compliance with the License. 
    30  *  You may obtain a copy of the License at 
     28 * Licensed under the Apache License, Version 2.0 (the "License"); 
     29 * you may not use this file except in compliance with the License. 
     30 * You may obtain a copy of the License at 
    3131 * 
    32  *      http://www.apache.org/licenses/LICENSE-2.0 
     32 *     http://www.apache.org/licenses/LICENSE-2.0 
    3333 * 
    34  *  Unless required by applicable law or agreed to in writing, software 
    35  *  distributed under the License is distributed on an "AS IS" BASIS, 
    36  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
    37  *  See the License for the specific language governing permissions and 
    38  *  limitations under the License. 
    39  * 
     34 * Unless required by applicable law or agreed to in writing, software 
     35 * distributed under the License is distributed on an "AS IS" BASIS, 
     36 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
     37 * See the License for the specific language governing permissions and 
     38 * limitations under the License. 
    4039 */ 
    4140 
     
    4645 */ 
    4746 
    48 package loci.formats.in; 
     47package loci.formats.codec; 
    4948 
    5049/** 
  • trunk/loci/formats/in/OMEXMLReader.java

    r2721 r2782  
    3131import loci.formats.*; 
    3232import loci.formats.codec.Base64Codec; 
     33import loci.formats.codec.CBZip2InputStream; 
    3334 
    3435/** 
Note: See TracChangeset for help on using the changeset viewer.