FastCharStream.java
001 // FastCharStream.java
002 package gate.creole.annic.apache.lucene.analysis.standard;
003 
004 /**
005  * Copyright 2004 The Apache Software Foundation
006  *
007  * Licensed under the Apache License, Version 2.0 (the "License");
008  * you may not use this file except in compliance with the License.
009  * 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.*;
021 
022 /** An efficient implementation of JavaCC's CharStream interface.  <p>Note that
023  * this does not do line-number counting, but instead keeps track of the
024  * character position of the token in the input, as required by Lucene's {@link
025  * gate.creole.annic.apache.lucene.analysis.Token} API. */
026 public final class FastCharStream implements CharStream {
027   char[] buffer = null;
028 
029   int bufferLength = 0;          // end of valid chars
030   int bufferPosition = 0;        // next char to read
031 
032   int tokenStart = 0;          // offset in buffer
033   int bufferStart = 0;          // position in file of buffer
034 
035   Reader input;            // source of chars
036 
037   /** Constructs from a Reader. */
038   public FastCharStream(Reader r) {
039     input = r;
040   }
041 
042   @Override
043   public final char readChar() throws IOException {
044     if (bufferPosition >= bufferLength)
045       refill();
046     return buffer[bufferPosition++];
047   }
048 
049   private final void refill() throws IOException {
050     int newPosition = bufferLength - tokenStart;
051 
052     if (tokenStart == 0) {        // token won't fit in buffer
053       if (buffer == null) {        // first time: alloc buffer
054   buffer = new char[2048];
055       else if (bufferLength == buffer.length) { // grow buffer
056   char[] newBuffer = new char[buffer.length*2];
057   System.arraycopy(buffer, 0, newBuffer, 0, bufferLength);
058   buffer = newBuffer;
059       }
060     else {            // shift token to front
061       System.arraycopy(buffer, tokenStart, buffer, 0, newPosition);
062     }
063 
064     bufferLength = newPosition;        // update state
065     bufferPosition = newPosition;
066     bufferStart += tokenStart;
067     tokenStart = 0;
068 
069     int charsRead =          // fill space in buffer
070       input.read(buffer, newPosition, buffer.length-newPosition);
071     if (charsRead == -1)
072       throw new IOException("read past eof");
073     else
074       bufferLength += charsRead;
075   }
076 
077   @Override
078   public final char BeginToken() throws IOException {
079     tokenStart = bufferPosition;
080     return readChar();
081   }
082 
083   @Override
084   public final void backup(int amount) {
085     bufferPosition -= amount;
086   }
087 
088   @Override
089   public final String GetImage() {
090     return new String(buffer, tokenStart, bufferPosition - tokenStart);
091   }
092 
093   @Override
094   public final char[] GetSuffix(int len) {
095     char[] value = new char[len];
096     System.arraycopy(buffer, bufferPosition - len, value, 0, len);
097     return value;
098   }
099 
100   @Override
101   public final void Done() {
102     try {
103       input.close();
104     catch (IOException e) {
105       System.err.println("Caught: " + e + "; ignoring.");
106     }
107   }
108 
109   @Override
110   @Deprecated public final int getColumn() {
111     return bufferStart + bufferPosition;
112   }  
113   @Override
114   @Deprecated public final int getLine() {
115     return 1;
116   }
117   @Override
118   public final int getEndColumn() {
119     return bufferStart + bufferPosition;
120   }
121   @Override
122   public final int getEndLine() {
123     return 1;
124   }
125   @Override
126   public final int getBeginColumn() {
127     return bufferStart + tokenStart;
128   }
129   @Override
130   public final int getBeginLine() {
131     return 1;
132   }
133 }