1 21 22 package net.percederberg.grammatica.parser; 23 24 import java.io.IOException ; 25 import java.io.Reader ; 26 27 41 public class LookAheadReader extends Reader { 42 43 47 private static final int STREAM_BLOCK_SIZE = 4096; 48 49 53 private static final int BUFFER_BLOCK_SIZE = 1024; 54 55 58 private char[] buffer = new char[STREAM_BLOCK_SIZE]; 59 60 63 private int pos = 0; 64 65 68 private int length = 0; 69 70 73 private Reader input = null; 74 75 79 private int line = 1; 80 81 85 private int column = 1; 86 87 92 public LookAheadReader(Reader input) { 93 super(); 94 this.input = input; 95 } 96 97 103 public int getLineNumber() { 104 return line; 105 } 106 107 113 public int getColumnNumber() { 114 return column; 115 } 116 117 125 public int read() throws IOException { 126 readAhead(1); 127 if (pos >= length) { 128 return -1; 129 } else { 130 updateLineColumnNumbers(1); 131 return buffer[pos++]; 132 } 133 } 134 135 146 public int read(char[] cbuf) throws IOException { 147 return read(cbuf, 0, cbuf.length); 148 } 149 150 163 public int read(char[] cbuf, int off, int len) throws IOException { 164 int count; 165 166 readAhead(len); 167 if (pos >= length) { 168 return -1; 169 } else { 170 count = length - pos; 171 if (count > len) { 172 count = len; 173 } 174 updateLineColumnNumbers(count); 175 System.arraycopy(buffer, pos, cbuf, off, count); 176 pos += count; 177 return count; 178 } 179 } 180 181 192 public String readString(int len) throws IOException { 193 int count; 194 String result; 195 196 readAhead(len); 197 if (pos >= length) { 198 return null; 199 } else { 200 count = length - pos; 201 if (count > len) { 202 count = len; 203 } 204 updateLineColumnNumbers(count); 205 result = new String (buffer, pos, count); 206 pos += count; 207 return result; 208 } 209 } 210 211 227 public int peek(int off) throws IOException { 228 readAhead(off + 1); 229 if (pos + off >= length) { 230 return -1; 231 } else { 232 return buffer[pos + off]; 233 } 234 } 235 236 253 public String peekString(int off, int len) throws IOException { 254 int count; 255 256 readAhead(off + len + 1); 257 if (pos + off >= length) { 258 return null; 259 } else { 260 count = length - (pos + off); 261 if (count > len) { 262 count = len; 263 } 264 return new String (buffer, pos + off, count); 265 } 266 } 267 268 275 public void close() throws IOException { 276 buffer = null; 277 pos = 0; 278 length = 0; 279 if (input != null) { 280 try { 281 input.close(); 282 } finally { 283 input = null; 284 } 285 } 286 } 287 288 300 private void readAhead(int offset) throws IOException { 301 int size; 302 int readSize; 303 304 if (input == null || pos + offset < length) { 306 return; 307 } 308 309 if (pos > BUFFER_BLOCK_SIZE) { 311 System.arraycopy(buffer, pos, buffer, 0, length - pos); 312 length -= pos; 313 pos = 0; 314 } 315 316 size = pos + offset - length + 1; 318 if (size % STREAM_BLOCK_SIZE != 0) { 319 size = (size / STREAM_BLOCK_SIZE) * STREAM_BLOCK_SIZE; 320 size += STREAM_BLOCK_SIZE; 321 } 322 ensureBufferCapacity(length + size); 323 324 try { 326 readSize = input.read(buffer, length, size); 327 } catch (IOException e) { 328 input = null; 329 throw e; 330 } 331 332 if (readSize > 0) { 334 length += readSize; 335 } 336 if (readSize < size) { 337 try { 338 input.close(); 339 } finally { 340 input = null; 341 } 342 } 343 } 344 345 350 private void ensureBufferCapacity(int size) { 351 char[] newbuf; 352 353 if (buffer.length >= size) { 354 return; 355 } 356 if (size % BUFFER_BLOCK_SIZE != 0) { 357 size = (size / BUFFER_BLOCK_SIZE) * BUFFER_BLOCK_SIZE; 358 size += BUFFER_BLOCK_SIZE; 359 } 360 newbuf = new char[size]; 361 System.arraycopy(buffer, 0, newbuf, 0, length); 362 buffer = newbuf; 363 } 364 365 373 private void updateLineColumnNumbers(int offset) { 374 for (int i = 0; i < offset; i++) { 375 if (buffer[pos + i] == '\n') { 376 line++; 377 column = 1; 378 } else { 379 column++; 380 } 381 } 382 } 383 } 384 | Popular Tags |