1 19 20 package org.netbeans.lib.lexer.batch; 21 22 import java.io.IOException ; 23 import java.io.Reader ; 24 import org.netbeans.api.lexer.TokenId; 25 import org.netbeans.lib.lexer.LexerInputOperation; 26 import org.netbeans.lib.lexer.TokenList; 27 import org.netbeans.lib.lexer.token.AbstractToken; 28 import org.netbeans.spi.lexer.LexerInput; 29 30 36 37 public final class SkimLexerInputOperation<T extends TokenId> extends LexerInputOperation<T> { 38 39 private static final char[] EMPTY_CHAR_ARRAY = new char[0]; 40 41 44 private static final int DEFAULT_READ_CHAR_ARRAY_SIZE = 4096; 45 46 49 private static final int MIN_READ_SIZE = 512; 50 51 private static final int DEFAULT_CLUSTER_SIZE = 4096; 52 53 63 private static final int MAX_UNUSED_CLUSTER_SIZE_FRACTION = 50; 64 65 66 70 private Reader reader; 71 72 75 private char[] readCharArray; 76 77 80 private CharSequence readCharSequence; 81 82 85 private int readStartIndex; 86 87 90 private int readEndIndex; 91 92 95 private boolean eofRead; 96 97 100 private SkimTokenList<T> cluster; 101 102 private int clusterTextEndIndex; 103 104 private int defaultClusterSize = DEFAULT_CLUSTER_SIZE; 105 106 109 private int clusterStartOffset; 110 111 117 private int offsetShift; 118 119 public SkimLexerInputOperation(TokenList<T> tokenList, Reader reader) { 120 super(tokenList, 0, null); 121 this.reader = reader; 122 this.readCharArray = new char[DEFAULT_READ_CHAR_ARRAY_SIZE]; 123 } 124 125 public SkimLexerInputOperation(TokenList<T> tokenList, CharSequence readCharSequence) { 126 super(tokenList, 0, null); 127 this.readCharSequence = readCharSequence; 128 this.readEndIndex = readCharSequence.length(); 129 } 130 131 public int read(int index) { index += readStartIndex; 133 if (index < readEndIndex) { 134 return (readCharArray != null) 135 ? readCharArray[index] 136 : readCharSequence.charAt(index); 137 138 } else { if (!eofRead) { 140 eofRead = (readCharArray != null) 141 ? readNextCharArray() 142 : true; 144 return read(index); 145 146 } else { 147 return LexerInput.EOF; 148 } 149 } 150 } 151 152 public char readExisting(int index) { 153 return (readCharArray != null) 154 ? readCharArray[index] 155 : readCharSequence.charAt(index); 156 } 157 158 public void approveToken(AbstractToken<T> token) { 159 int tokenLength = token.length(); 160 if (isSkipToken(token)) { 161 preventFlyToken(); 162 skipChars(tokenLength()); 163 164 } else if (token.isFlyweight()) { 165 assert isFlyTokenAllowed(); 166 flyTokenAdded(); 167 skipChars(tokenLength); 168 169 } else { if (clusterTextEndIndex != 0) { if (tokenLength + clusterTextEndIndex > cluster.getText().length) { 173 finishCluster(); 175 } 176 } 177 178 if (clusterTextEndIndex == 0) { int clusterSize = defaultClusterSize; 180 if (clusterSize < tokenLength) { clusterSize = tokenLength; 182 } 183 defaultClusterSize = clusterSize; 184 cluster = new SkimTokenList<T>((CopyTextTokenList<T>)tokenList(), 185 clusterStartOffset, new char[clusterSize]); 186 } 187 188 char[] clusterText = cluster.getText(); 191 if (readCharArray != null) { 192 System.arraycopy(readCharArray, readStartIndex, clusterText, 193 clusterTextEndIndex, tokenLength); 194 } else { for (int i = 0; i < tokenLength; i++) { 196 clusterText[clusterTextEndIndex + i] 197 = readCharSequence.charAt(readStartIndex + i); 198 } 199 } 200 201 int rawOffset = (offsetShift << 16) | clusterTextEndIndex; 202 token.setTokenList(cluster); 203 token.setRawOffset(rawOffset); 204 clusterTextEndIndex += tokenLength; 205 clearFlySequence(); 206 } 207 208 readStartIndex += tokenLength; 209 tokenApproved(); 210 } 211 212 private void skipChars(int skipLength) { 213 if (clusterTextEndIndex != 0) { if (offsetShift + skipLength > Short.MAX_VALUE) { 215 finishCluster(); 217 clusterStartOffset += skipLength; 218 219 } else { offsetShift += skipLength; 221 } 222 223 } else { clusterStartOffset += skipLength; 225 } 226 } 227 228 public void finish() { 229 if (clusterTextEndIndex != 0) { 230 finishCluster(); 231 } 232 } 233 234 private void finishCluster() { 235 int clusterTextLength = cluster.getText().length; 238 if (clusterTextLength / MAX_UNUSED_CLUSTER_SIZE_FRACTION 239 > (clusterTextLength - clusterTextEndIndex) 240 ) { char[] newText = new char[clusterTextEndIndex]; 242 System.arraycopy(cluster.getText(), 0, newText, 0, clusterTextEndIndex); 243 cluster.setText(newText); 244 } 245 clusterStartOffset += clusterTextEndIndex + offsetShift; 246 clusterTextEndIndex = 0; 247 offsetShift = 0; 248 cluster = null; } 250 251 private boolean readNextCharArray() { 252 int retainLength = readEndIndex - readStartIndex; 254 int minReadSize = readCharArray.length - retainLength; 255 char[] newReadCharArray = readCharArray; if (minReadSize < MIN_READ_SIZE) { newReadCharArray = new char[readCharArray.length * 2]; 259 } 260 System.arraycopy(readCharArray, readStartIndex, newReadCharArray, 0, retainLength); 261 readCharArray = newReadCharArray; 262 readStartIndex = 0; 263 readEndIndex = retainLength; 264 265 boolean eof = false; 266 while (readEndIndex < readCharArray.length) { 267 int readSize; 268 try { 269 readSize = reader.read(readCharArray, readEndIndex, 270 readCharArray.length - readEndIndex); 271 } catch (IOException e) { 272 readSize = -1; 276 } 277 if (readSize == -1) { 278 eof = true; 279 try { 280 reader.close(); 281 } catch (IOException e) { 282 } 286 break; 287 } else { 288 readEndIndex += readSize; 289 } 290 } 291 return eof; 292 } 293 294 } 295 | Popular Tags |