001: package org.apache.lucene.store;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021:
022: /** Abstract base class for input from a file in a {@link Directory}. A
023: * random-access input stream. Used for all Lucene index input operations.
024: * @see Directory
025: */
026: public abstract class IndexInput implements Cloneable {
027: private char[] chars; // used by readString()
028:
029: /** Reads and returns a single byte.
030: * @see IndexOutput#writeByte(byte)
031: */
032: public abstract byte readByte() throws IOException;
033:
034: /** Reads a specified number of bytes into an array at the specified offset.
035: * @param b the array to read bytes into
036: * @param offset the offset in the array to start storing bytes
037: * @param len the number of bytes to read
038: * @see IndexOutput#writeBytes(byte[],int)
039: */
040: public abstract void readBytes(byte[] b, int offset, int len)
041: throws IOException;
042:
043: /** Reads a specified number of bytes into an array at the
044: * specified offset with control over whether the read
045: * should be buffered (callers who have their own buffer
046: * should pass in "false" for useBuffer). Currently only
047: * {@link BufferedIndexInput} respects this parameter.
048: * @param b the array to read bytes into
049: * @param offset the offset in the array to start storing bytes
050: * @param len the number of bytes to read
051: * @param useBuffer set to false if the caller will handle
052: * buffering.
053: * @see IndexOutput#writeBytes(byte[],int)
054: */
055: public void readBytes(byte[] b, int offset, int len,
056: boolean useBuffer) throws IOException {
057: // Default to ignoring useBuffer entirely
058: readBytes(b, offset, len);
059: }
060:
061: /** Reads four bytes and returns an int.
062: * @see IndexOutput#writeInt(int)
063: */
064: public int readInt() throws IOException {
065: return ((readByte() & 0xFF) << 24)
066: | ((readByte() & 0xFF) << 16)
067: | ((readByte() & 0xFF) << 8) | (readByte() & 0xFF);
068: }
069:
070: /** Reads an int stored in variable-length format. Reads between one and
071: * five bytes. Smaller values take fewer bytes. Negative numbers are not
072: * supported.
073: * @see IndexOutput#writeVInt(int)
074: */
075: public int readVInt() throws IOException {
076: byte b = readByte();
077: int i = b & 0x7F;
078: for (int shift = 7; (b & 0x80) != 0; shift += 7) {
079: b = readByte();
080: i |= (b & 0x7F) << shift;
081: }
082: return i;
083: }
084:
085: /** Reads eight bytes and returns a long.
086: * @see IndexOutput#writeLong(long)
087: */
088: public long readLong() throws IOException {
089: return (((long) readInt()) << 32) | (readInt() & 0xFFFFFFFFL);
090: }
091:
092: /** Reads a long stored in variable-length format. Reads between one and
093: * nine bytes. Smaller values take fewer bytes. Negative numbers are not
094: * supported. */
095: public long readVLong() throws IOException {
096: byte b = readByte();
097: long i = b & 0x7F;
098: for (int shift = 7; (b & 0x80) != 0; shift += 7) {
099: b = readByte();
100: i |= (b & 0x7FL) << shift;
101: }
102: return i;
103: }
104:
105: /** Reads a string.
106: * @see IndexOutput#writeString(String)
107: */
108: public String readString() throws IOException {
109: int length = readVInt();
110: if (chars == null || length > chars.length)
111: chars = new char[length];
112: readChars(chars, 0, length);
113: return new String(chars, 0, length);
114: }
115:
116: /** Reads UTF-8 encoded characters into an array.
117: * @param buffer the array to read characters into
118: * @param start the offset in the array to start storing characters
119: * @param length the number of characters to read
120: * @see IndexOutput#writeChars(String,int,int)
121: */
122: public void readChars(char[] buffer, int start, int length)
123: throws IOException {
124: final int end = start + length;
125: for (int i = start; i < end; i++) {
126: byte b = readByte();
127: if ((b & 0x80) == 0)
128: buffer[i] = (char) (b & 0x7F);
129: else if ((b & 0xE0) != 0xE0) {
130: buffer[i] = (char) (((b & 0x1F) << 6) | (readByte() & 0x3F));
131: } else
132: buffer[i] = (char) (((b & 0x0F) << 12)
133: | ((readByte() & 0x3F) << 6) | (readByte() & 0x3F));
134: }
135: }
136:
137: /**
138: * Expert
139: *
140: * Similar to {@link #readChars(char[], int, int)} but does not do any conversion operations on the bytes it is reading in. It still
141: * has to invoke {@link #readByte()} just as {@link #readChars(char[], int, int)} does, but it does not need a buffer to store anything
142: * and it does not have to do any of the bitwise operations, since we don't actually care what is in the byte except to determine
143: * how many more bytes to read
144: * @param length The number of chars to read
145: */
146: public void skipChars(int length) throws IOException {
147: for (int i = 0; i < length; i++) {
148: byte b = readByte();
149: if ((b & 0x80) == 0) {
150: //do nothing, we only need one byte
151: } else if ((b & 0xE0) != 0xE0) {
152: readByte();//read an additional byte
153: } else {
154: //read two additional bytes.
155: readByte();
156: readByte();
157: }
158: }
159: }
160:
161: /** Closes the stream to futher operations. */
162: public abstract void close() throws IOException;
163:
164: /** Returns the current position in this file, where the next read will
165: * occur.
166: * @see #seek(long)
167: */
168: public abstract long getFilePointer();
169:
170: /** Sets current position in this file, where the next read will occur.
171: * @see #getFilePointer()
172: */
173: public abstract void seek(long pos) throws IOException;
174:
175: /** The number of bytes in the file. */
176: public abstract long length();
177:
178: /** Returns a clone of this stream.
179: *
180: * <p>Clones of a stream access the same data, and are positioned at the same
181: * point as the stream they were cloned from.
182: *
183: * <p>Expert: Subclasses must ensure that clones may be positioned at
184: * different points in the input from each other and from the stream they
185: * were cloned from.
186: */
187: public Object clone() {
188: IndexInput clone = null;
189: try {
190: clone = (IndexInput) super .clone();
191: } catch (CloneNotSupportedException e) {
192: }
193:
194: clone.chars = null;
195:
196: return clone;
197: }
198:
199: }
|