Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » store » [javadoc | source]
    1   package org.apache.lucene.store;
    2   
    3   /**
    4    * Copyright 2004 The Apache Software Foundation
    5    *
    6    * Licensed under the Apache License, Version 2.0 (the "License");
    7    * you may not use this file except in compliance with the License.
    8    * You may obtain a copy of the License at
    9    *
   10    *     http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing, software
   13    * distributed under the License is distributed on an "AS IS" BASIS,
   14    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   15    * See the License for the specific language governing permissions and
   16    * limitations under the License.
   17    */
   18   
   19   import java.io.IOException;
   20   
   21   /** Abstract base class for input from a file in a {@link Directory}.  A
   22    * random-access input stream.  Used for all Lucene index input operations.
   23    * @see Directory
   24    * @see OutputStream
   25    */
   26   public abstract class InputStream implements Cloneable {
   27     static final int BUFFER_SIZE = OutputStream.BUFFER_SIZE;
   28   
   29     private byte[] buffer;
   30     private char[] chars;
   31   
   32     private long bufferStart = 0;			  // position in file of buffer
   33     private int bufferLength = 0;			  // end of valid bytes
   34     private int bufferPosition = 0;		  // next byte to read
   35   
   36     protected long length;			  // set by subclasses
   37   
   38     /** Reads and returns a single byte.
   39      * @see OutputStream#writeByte(byte)
   40      */
   41     public final byte readByte() throws IOException {
   42       if (bufferPosition >= bufferLength)
   43         refill();
   44       return buffer[bufferPosition++];
   45     }
   46   
   47     /** Reads a specified number of bytes into an array at the specified offset.
   48      * @param b the array to read bytes into
   49      * @param offset the offset in the array to start storing bytes
   50      * @param len the number of bytes to read
   51      * @see OutputStream#writeBytes(byte[],int)
   52      */
   53     public final void readBytes(byte[] b, int offset, int len)
   54          throws IOException {
   55       if (len < BUFFER_SIZE) {
   56         for (int i = 0; i < len; i++)		  // read byte-by-byte
   57   	b[i + offset] = (byte)readByte();
   58       } else {					  // read all-at-once
   59         long start = getFilePointer();
   60         seekInternal(start);
   61         readInternal(b, offset, len);
   62   
   63         bufferStart = start + len;		  // adjust stream variables
   64         bufferPosition = 0;
   65         bufferLength = 0;				  // trigger refill() on read
   66       }
   67     }
   68   
   69     /** Reads four bytes and returns an int.
   70      * @see OutputStream#writeInt(int)
   71      */
   72     public final int readInt() throws IOException {
   73       return ((readByte() & 0xFF) << 24) | ((readByte() & 0xFF) << 16)
   74            | ((readByte() & 0xFF) <<  8) |  (readByte() & 0xFF);
   75     }
   76   
   77     /** Reads an int stored in variable-length format.  Reads between one and
   78      * five bytes.  Smaller values take fewer bytes.  Negative numbers are not
   79      * supported.
   80      * @see OutputStream#writeVInt(int)
   81      */
   82     public final int readVInt() throws IOException {
   83       byte b = readByte();
   84       int i = b & 0x7F;
   85       for (int shift = 7; (b & 0x80) != 0; shift += 7) {
   86         b = readByte();
   87         i |= (b & 0x7F) << shift;
   88       }
   89       return i;
   90     }
   91   
   92     /** Reads eight bytes and returns a long.
   93      * @see OutputStream#writeLong(long)
   94      */
   95     public final long readLong() throws IOException {
   96       return (((long)readInt()) << 32) | (readInt() & 0xFFFFFFFFL);
   97     }
   98   
   99     /** Reads a long stored in variable-length format.  Reads between one and
  100      * nine bytes.  Smaller values take fewer bytes.  Negative numbers are not
  101      * supported. */
  102     public final long readVLong() throws IOException {
  103       byte b = readByte();
  104       long i = b & 0x7F;
  105       for (int shift = 7; (b & 0x80) != 0; shift += 7) {
  106         b = readByte();
  107         i |= (b & 0x7FL) << shift;
  108       }
  109       return i;
  110     }
  111   
  112     /** Reads a string.
  113      * @see OutputStream#writeString(String)
  114      */
  115     public final String readString() throws IOException {
  116       int length = readVInt();
  117       if (chars == null || length > chars.length)
  118         chars = new char[length];
  119       readChars(chars, 0, length);
  120       return new String(chars, 0, length);
  121     }
  122   
  123     /** Reads UTF-8 encoded characters into an array.
  124      * @param buffer the array to read characters into
  125      * @param start the offset in the array to start storing characters
  126      * @param length the number of characters to read
  127      * @see OutputStream#writeChars(String,int,int)
  128      */
  129     public final void readChars(char[] buffer, int start, int length)
  130          throws IOException {
  131       final int end = start + length;
  132       for (int i = start; i < end; i++) {
  133         byte b = readByte();
  134         if ((b & 0x80) == 0)
  135   	buffer[i] = (char)(b & 0x7F);
  136         else if ((b & 0xE0) != 0xE0) {
  137   	buffer[i] = (char)(((b & 0x1F) << 6)
  138   		 | (readByte() & 0x3F));
  139         } else
  140   	buffer[i] = (char)(((b & 0x0F) << 12)
  141   		| ((readByte() & 0x3F) << 6)
  142   	        |  (readByte() & 0x3F));
  143       }
  144     }
  145   
  146   
  147     private void refill() throws IOException {
  148       long start = bufferStart + bufferPosition;
  149       long end = start + BUFFER_SIZE;
  150       if (end > length)				  // don't read past EOF
  151         end = length;
  152       bufferLength = (int)(end - start);
  153       if (bufferLength == 0)
  154         throw new IOException("read past EOF");
  155   
  156       if (buffer == null)
  157         buffer = new byte[BUFFER_SIZE];		  // allocate buffer lazily
  158       readInternal(buffer, 0, bufferLength);
  159   
  160       bufferStart = start;
  161       bufferPosition = 0;
  162     }
  163   
  164     /** Expert: implements buffer refill.  Reads bytes from the current position
  165      * in the input.
  166      * @param b the array to read bytes into
  167      * @param offset the offset in the array to start storing bytes
  168      * @param length the number of bytes to read
  169      */
  170     protected abstract void readInternal(byte[] b, int offset, int length)
  171          throws IOException;
  172   
  173     /** Closes the stream to futher operations. */
  174     public abstract void close() throws IOException;
  175   
  176     /** Returns the current position in this file, where the next read will
  177      * occur.
  178      * @see #seek(long)
  179      */
  180     public final long getFilePointer() {
  181       return bufferStart + bufferPosition;
  182     }
  183   
  184     /** Sets current position in this file, where the next read will occur.
  185      * @see #getFilePointer()
  186      */
  187     public final void seek(long pos) throws IOException {
  188       if (pos >= bufferStart && pos < (bufferStart + bufferLength))
  189         bufferPosition = (int)(pos - bufferStart);  // seek within buffer
  190       else {
  191         bufferStart = pos;
  192         bufferPosition = 0;
  193         bufferLength = 0;				  // trigger refill() on read()
  194         seekInternal(pos);
  195       }
  196     }
  197   
  198     /** Expert: implements seek.  Sets current position in this file, where the
  199      * next {@link #readInternal(byte[],int,int)} will occur.
  200      * @see #readInternal(byte[],int,int)
  201      */
  202     protected abstract void seekInternal(long pos) throws IOException;
  203   
  204     /** The number of bytes in the file. */
  205     public final long length() {
  206       return length;
  207     }
  208   
  209     /** Returns a clone of this stream.
  210      *
  211      * <p>Clones of a stream access the same data, and are positioned at the same
  212      * point as the stream they were cloned from.
  213      *
  214      * <p>Expert: Subclasses must ensure that clones may be positioned at
  215      * different points in the input from each other and from the stream they
  216      * were cloned from.
  217      */
  218     public Object clone() {
  219       InputStream clone = null;
  220       try {
  221         clone = (InputStream)super.clone();
  222       } catch (CloneNotSupportedException e) {}
  223   
  224       if (buffer != null) {
  225         clone.buffer = new byte[BUFFER_SIZE];
  226         System.arraycopy(buffer, 0, clone.buffer, 0, bufferLength);
  227       }
  228   
  229       clone.chars = null;
  230   
  231       return clone;
  232     }
  233   
  234   }

Save This Page
Home » lucene-2.4.1-src » org.apache » lucene » store » [javadoc | source]