Save This Page
Home » openjdk-7 » java » util » zip » [javadoc | source]
    1   /* java.util.zip.StreamManipulator
    2      Copyright (C) 2001 Free Software Foundation, Inc.
    3   
    4   This file is part of GNU Classpath.
    5   
    6   GNU Classpath is free software; you can redistribute it and/or modify
    7   it under the terms of the GNU General Public License as published by
    8   the Free Software Foundation; either version 2, or (at your option)
    9   any later version.
   10   
   11   GNU Classpath is distributed in the hope that it will be useful, but
   12   WITHOUT ANY WARRANTY; without even the implied warranty of
   13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14   General Public License for more details.
   15   
   16   You should have received a copy of the GNU General Public License
   17   along with GNU Classpath; see the file COPYING.  If not, write to the
   18   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   19   02110-1301 USA.
   20   
   21   Linking this library statically or dynamically with other modules is
   22   making a combined work based on this library.  Thus, the terms and
   23   conditions of the GNU General Public License cover the whole
   24   combination.
   25   
   26   As a special exception, the copyright holders of this library give you
   27   permission to link this library with independent modules to produce an
   28   executable, regardless of the license terms of these independent
   29   modules, and to copy and distribute the resulting executable under
   30   terms of your choice, provided that you also meet, for each linked
   31   independent module, the terms and conditions of the license of that
   32   module.  An independent module is a module which is not derived from
   33   or based on this library.  If you modify this library, you may extend
   34   this exception to your version of the library, but you are not
   35   obligated to do so.  If you do not wish to do so, delete this
   36   exception statement from your version. */
   37   
   38   package java.util.zip;
   39   
   40   /**
   41    * This class allows us to retrieve a specified amount of bits from
   42    * the input buffer, as well as copy big byte blocks.
   43    *
   44    * It uses an int buffer to store up to 31 bits for direct
   45    * manipulation.  This guarantees that we can get at least 16 bits,
   46    * but we only need at most 15, so this is all safe.
   47    *
   48    * There are some optimizations in this class, for example, you must
   49    * never peek more then 8 bits more than needed, and you must first 
   50    * peek bits before you may drop them.  This is not a general purpose
   51    * class but optimized for the behaviour of the Inflater.
   52    *
   53    * @author John Leuner, Jochen Hoenicke
   54    */
   55   
   56   class StreamManipulator
   57   {
   58     private byte[] window;
   59     private int window_start = 0;
   60     private int window_end = 0;
   61   
   62     private int buffer = 0;
   63     private int bits_in_buffer = 0;
   64   
   65     /**
   66      * Get the next n bits but don't increase input pointer.  n must be
   67      * less or equal 16 and if you if this call succeeds, you must drop
   68      * at least n-8 bits in the next call.
   69      * 
   70      * @return the value of the bits, or -1 if not enough bits available.  */
   71     public final int peekBits(int n)
   72     {
   73       if (bits_in_buffer < n)
   74         {
   75   	if (window_start == window_end)
   76   	  return -1;
   77   	buffer |= (window[window_start++] & 0xff
   78   		   | (window[window_start++] & 0xff) << 8) << bits_in_buffer;
   79   	bits_in_buffer += 16;
   80         }
   81       return buffer & ((1 << n) - 1);
   82     }
   83   
   84     /* Drops the next n bits from the input.  You should have called peekBits
   85      * with a bigger or equal n before, to make sure that enough bits are in
   86      * the bit buffer.
   87      */
   88     public final void dropBits(int n)
   89     {
   90       buffer >>>= n;
   91       bits_in_buffer -= n;
   92     }
   93   
   94     /**
   95      * Gets the next n bits and increases input pointer.  This is equivalent
   96      * to peekBits followed by dropBits, except for correct error handling.
   97      * @return the value of the bits, or -1 if not enough bits available. 
   98      */
   99     public final int getBits(int n)
  100     {
  101       int bits = peekBits(n);
  102       if (bits >= 0)
  103         dropBits(n);
  104       return bits;
  105     }
  106     /**
  107      * Gets the number of bits available in the bit buffer.  This must be
  108      * only called when a previous peekBits() returned -1.
  109      * @return the number of bits available.
  110      */
  111     public final int getAvailableBits()
  112     {
  113       return bits_in_buffer;
  114     }
  115   
  116     /**
  117      * Gets the number of bytes available.  
  118      * @return the number of bytes available.
  119      */
  120     public final int getAvailableBytes()
  121     {
  122       return window_end - window_start + (bits_in_buffer >> 3);
  123     }
  124   
  125     /**
  126      * Skips to the next byte boundary.
  127      */
  128     public void skipToByteBoundary()
  129     {
  130       buffer >>= (bits_in_buffer & 7);
  131       bits_in_buffer &= ~7;
  132     }
  133   
  134     public final boolean needsInput() {
  135       return window_start == window_end;
  136     }
  137   
  138   
  139     /* Copies length bytes from input buffer to output buffer starting
  140      * at output[offset].  You have to make sure, that the buffer is
  141      * byte aligned.  If not enough bytes are available, copies fewer
  142      * bytes.
  143      * @param length the length to copy, 0 is allowed.
  144      * @return the number of bytes copied, 0 if no byte is available.  
  145      */
  146     public int copyBytes(byte[] output, int offset, int length)
  147     {
  148       if (length < 0)
  149         throw new IllegalArgumentException("length negative");
  150       if ((bits_in_buffer & 7) != 0)  
  151         /* bits_in_buffer may only be 0 or 8 */
  152         throw new IllegalStateException("Bit buffer is not aligned!");
  153   
  154       int count = 0;
  155       while (bits_in_buffer > 0 && length > 0)
  156         {
  157   	output[offset++] = (byte) buffer;
  158   	buffer >>>= 8;
  159   	bits_in_buffer -= 8;
  160   	length--;
  161   	count++;
  162         }
  163       if (length == 0)
  164         return count;
  165   
  166       int avail = window_end - window_start;
  167       if (length > avail)
  168         length = avail;
  169       System.arraycopy(window, window_start, output, offset, length);
  170       window_start += length;
  171   
  172       if (((window_start - window_end) & 1) != 0)
  173         {
  174   	/* We always want an even number of bytes in input, see peekBits */
  175   	buffer = (window[window_start++] & 0xff);
  176   	bits_in_buffer = 8;
  177         }
  178       return count + length;
  179     }
  180   
  181     public StreamManipulator()
  182     {
  183     }
  184   
  185     public void reset()
  186     {
  187       window_start = window_end = buffer = bits_in_buffer = 0;
  188     }
  189   
  190     public void setInput(byte[] buf, int off, int len)
  191     {
  192       if (window_start < window_end)
  193         throw new IllegalStateException
  194   	("Old input was not completely processed");
  195   
  196       int end = off + len;
  197   
  198       /* We want to throw an ArrayIndexOutOfBoundsException early.  The
  199        * check is very tricky: it also handles integer wrap around.  
  200        */
  201       if (0 > off || off > end || end > buf.length)
  202         throw new ArrayIndexOutOfBoundsException();
  203       
  204       if ((len & 1) != 0)
  205         {
  206   	/* We always want an even number of bytes in input, see peekBits */
  207   	buffer |= (buf[off++] & 0xff) << bits_in_buffer;
  208   	bits_in_buffer += 8;
  209         }
  210       
  211       window = buf;
  212       window_start = off;
  213       window_end = end;
  214     }
  215   }
  216   

Save This Page
Home » openjdk-7 » java » util » zip » [javadoc | source]