1 | /* Generated by: ParserGeneratorCC: Do not edit this line. AbstractCharStream.java Version 1.1 */ |
---|---|
2 | /* ParserGeneratorCCOptions:SUPPORT_CLASS_VISIBILITY_PUBLIC=true */ |
3 | /* |
4 | * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. |
5 | * Copyright (C) 2011, 2013-2020 The JavaParser Team. |
6 | * |
7 | * This file is part of JavaParser. |
8 | * |
9 | * JavaParser can be used either under the terms of |
10 | * a) the GNU Lesser General Public License as published by |
11 | * the Free Software Foundation, either version 3 of the License, or |
12 | * (at your option) any later version. |
13 | * b) the terms of the Apache License |
14 | * |
15 | * You should have received a copy of both licenses in LICENCE.LGPL and |
16 | * LICENCE.APACHE. Please refer to those files for details. |
17 | * |
18 | * JavaParser is distributed in the hope that it will be useful, |
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | * GNU Lesser General Public License for more details. |
22 | */ |
23 | package com.github.javaparser; |
24 | |
25 | /** |
26 | * An implementation of interface CharStream, where the stream is assumed to |
27 | * contain only ASCII characters (without unicode processing). |
28 | */ |
29 | |
30 | public |
31 | abstract class AbstractCharStream |
32 | implements CharStream |
33 | { |
34 | /** Default buffer size if nothing is specified */ |
35 | public static final int DEFAULT_BUF_SIZE = 4096; |
36 | |
37 | static final int hexval (final char c) throws java.io.IOException |
38 | { |
39 | switch (c) |
40 | { |
41 | case '0': |
42 | return 0; |
43 | case '1': |
44 | return 1; |
45 | case '2': |
46 | return 2; |
47 | case '3': |
48 | return 3; |
49 | case '4': |
50 | return 4; |
51 | case '5': |
52 | return 5; |
53 | case '6': |
54 | return 6; |
55 | case '7': |
56 | return 7; |
57 | case '8': |
58 | return 8; |
59 | case '9': |
60 | return 9; |
61 | case 'a': |
62 | case 'A': |
63 | return 10; |
64 | case 'b': |
65 | case 'B': |
66 | return 11; |
67 | case 'c': |
68 | case 'C': |
69 | return 12; |
70 | case 'd': |
71 | case 'D': |
72 | return 13; |
73 | case 'e': |
74 | case 'E': |
75 | return 14; |
76 | case 'f': |
77 | case 'F': |
78 | return 15; |
79 | default: |
80 | throw new java.io.IOException ("Invalid hex char '" + c + "' (=" + (int) c + ") provided!"); |
81 | } |
82 | } |
83 | |
84 | /** Tab size for formatting. Usually in the range 1 to 8. */ |
85 | private int m_nTabSize = 1; |
86 | |
87 | /** Internal circular buffer */ |
88 | protected char[] buffer; |
89 | |
90 | /** Overall buffer size - same as buffer.length */ |
91 | protected int bufsize; |
92 | |
93 | /** Current read position in buffer. */ |
94 | protected int bufpos; |
95 | |
96 | /** The number of unoccupied buffer array positions */ |
97 | protected int available; |
98 | |
99 | /** The first array index (of `buffer`) that the current token starts */ |
100 | protected int tokenBegin; |
101 | |
102 | /** Characters in the backup/pushBack buffer */ |
103 | protected int inBuf; |
104 | protected int maxNextCharInd; |
105 | |
106 | private int[] m_aBufLine; |
107 | private int[] m_aBufColumn; |
108 | |
109 | // Current line number |
110 | private int m_nLineNo; |
111 | // Current column number |
112 | private int m_nColumnNo; |
113 | |
114 | // Was the previous character a "\r" char? |
115 | private boolean m_bPrevCharIsCR; |
116 | // Was the previous character a "\n" char? |
117 | private boolean m_bPrevCharIsLF; |
118 | |
119 | // Is line/column tracking enabled? |
120 | private boolean m_bTrackLineColumn = true; |
121 | |
122 | |
123 | /** Constructor. */ |
124 | public AbstractCharStream(final int nStartLine, |
125 | final int nStartColumn, |
126 | final int nBufferSize) |
127 | { |
128 | reInit (nStartLine, nStartColumn, nBufferSize); |
129 | } |
130 | |
131 | /** Reinitialise. */ |
132 | public final void reInit(final int nStartLine, |
133 | final int nStartColumn, |
134 | final int nBufferSize) |
135 | { |
136 | m_nLineNo = nStartLine; |
137 | m_nColumnNo = nStartColumn - 1; |
138 | m_bPrevCharIsCR = false; |
139 | m_bPrevCharIsLF = false; |
140 | if (buffer == null || nBufferSize != buffer.length) |
141 | { |
142 | bufsize = nBufferSize; |
143 | available = nBufferSize; |
144 | buffer = new char[nBufferSize]; |
145 | m_aBufLine = new int[nBufferSize]; |
146 | m_aBufColumn = new int[nBufferSize]; |
147 | } |
148 | maxNextCharInd = 0; |
149 | inBuf = 0; |
150 | tokenBegin = 0; |
151 | bufpos = -1; |
152 | } |
153 | |
154 | /** |
155 | * Read from the underlying stream. |
156 | * @param aBuf the buffer to be filled |
157 | * @param nOfs The offset into the buffer. 0-based |
158 | * @param nLen Number of chars to read. |
159 | * @return Number of effective chars read, or -1 on error. |
160 | */ |
161 | protected abstract int streamRead (char[] aBuf, int nOfs, int nLen) throws java.io.IOException; |
162 | |
163 | /** |
164 | * Close the underlying stream. |
165 | * @throws java.io.IOException If closing fails. |
166 | */ |
167 | protected abstract void streamClose () throws java.io.IOException; |
168 | |
169 | // Override this method if you need more aggressive buffer size expansion |
170 | protected int getBufSizeAfterExpansion () |
171 | { |
172 | // Double the size by default |
173 | return bufsize * 2; |
174 | } |
175 | |
176 | protected void expandBuff (final boolean bWrapAround) |
177 | { |
178 | // Get the new buffer size |
179 | final int nNewBufSize = getBufSizeAfterExpansion (); |
180 | |
181 | final char[] newbuffer = new char[nNewBufSize]; |
182 | final int[] newbufline = new int[nNewBufSize]; |
183 | final int[] newbufcolumn = new int[nNewBufSize]; |
184 | |
185 | // Number of chars to be preserved |
186 | final int nPreservedChars = bufsize - tokenBegin; |
187 | |
188 | if (bWrapAround) |
189 | { |
190 | // Move from offset "tokenBegin" to offset 0 |
191 | // arraycopy(src, srcPos, dest, destPos, length) |
192 | |
193 | // copy the "tail end" to the "start" (index 0) of the new buffer array |
194 | System.arraycopy(buffer, tokenBegin, newbuffer, 0, nPreservedChars); |
195 | |
196 | // copy the remaining "wrap around" content of the buffer from the start of the original buffer (starting at srcPos index 0) |
197 | System.arraycopy(buffer, 0, newbuffer, nPreservedChars, bufpos); |
198 | |
199 | // swap the new buffer in place of the old buffer |
200 | buffer = newbuffer; |
201 | |
202 | System.arraycopy(m_aBufLine, tokenBegin, newbufline, 0, nPreservedChars); |
203 | System.arraycopy(m_aBufLine, 0, newbufline, nPreservedChars, bufpos); |
204 | m_aBufLine = newbufline; |
205 | |
206 | System.arraycopy(m_aBufColumn, tokenBegin, newbufcolumn, 0, nPreservedChars); |
207 | System.arraycopy(m_aBufColumn, 0, newbufcolumn, nPreservedChars, bufpos); |
208 | m_aBufColumn = newbufcolumn; |
209 | |
210 | bufpos += nPreservedChars; |
211 | maxNextCharInd = bufpos; |
212 | } |
213 | else |
214 | { |
215 | // Move from offset "tokenBegin" to offset 0 |
216 | |
217 | System.arraycopy(buffer, tokenBegin, newbuffer, 0, nPreservedChars); |
218 | buffer = newbuffer; |
219 | |
220 | System.arraycopy(m_aBufLine, tokenBegin, newbufline, 0, nPreservedChars); |
221 | m_aBufLine = newbufline; |
222 | |
223 | System.arraycopy(m_aBufColumn, tokenBegin, newbufcolumn, 0, nPreservedChars); |
224 | m_aBufColumn = newbufcolumn; |
225 | |
226 | bufpos -= tokenBegin; |
227 | maxNextCharInd = bufpos; |
228 | } |
229 | |
230 | // Increase buffer size |
231 | bufsize = nNewBufSize; |
232 | available = nNewBufSize; |
233 | tokenBegin = 0; |
234 | } |
235 | |
236 | protected final void internalAdjustBuffSize() |
237 | { |
238 | final int nHalfBufferSize = bufsize / 2; |
239 | if (available == bufsize) |
240 | { |
241 | if (tokenBegin < 0) |
242 | { |
243 | // If this method is called from "beginToken()" |
244 | // Just refill the buffer from the start |
245 | bufpos = 0; |
246 | maxNextCharInd = 0; |
247 | } |
248 | else |
249 | if (tokenBegin > nHalfBufferSize) |
250 | { |
251 | // The token started in the second half - fill the front part |
252 | bufpos = 0; |
253 | maxNextCharInd = 0; |
254 | |
255 | // Available bytes are > 50% |
256 | available = tokenBegin; |
257 | } |
258 | else |
259 | { |
260 | // Token starts in the first half |
261 | // just append to existing buffer |
262 | expandBuff (false); |
263 | } |
264 | } |
265 | else |
266 | { |
267 | // A token was read across array boundaries |
268 | if (available > tokenBegin) |
269 | { |
270 | available = bufsize; |
271 | } |
272 | else |
273 | if ((tokenBegin - available) < nHalfBufferSize) |
274 | { |
275 | expandBuff (true); |
276 | } |
277 | else |
278 | { |
279 | available = tokenBegin; |
280 | } |
281 | } |
282 | } |
283 | |
284 | protected void fillBuff() throws java.io.IOException |
285 | { |
286 | if (maxNextCharInd == available) |
287 | internalAdjustBuffSize(); |
288 | |
289 | try |
290 | { |
291 | // Read from underlying stream |
292 | final int nCharsRead = streamRead (buffer, maxNextCharInd, available - maxNextCharInd); |
293 | if (nCharsRead == -1) |
294 | { |
295 | // We reached the end of the file |
296 | streamClose (); |
297 | |
298 | // Caught down below and re-thrown |
299 | throw new java.io.IOException("PGCC end of stream"); |
300 | } |
301 | maxNextCharInd += nCharsRead; |
302 | } |
303 | catch (final java.io.IOException ex) |
304 | { |
305 | --bufpos; |
306 | // ?What is the reason of this? Backup of 0 does nothing |
307 | backup (0); |
308 | if (tokenBegin == -1) |
309 | { |
310 | // Error occurred in "beginToken()" |
311 | tokenBegin = bufpos; |
312 | } |
313 | throw ex; |
314 | } |
315 | } |
316 | |
317 | protected final void internalSetBufLineColumn (final int nLine, final int nColumn) |
318 | { |
319 | m_aBufLine[bufpos] = nLine; |
320 | m_aBufColumn[bufpos] = nColumn; |
321 | } |
322 | |
323 | protected final void internalUpdateLineColumn(final char c) |
324 | { |
325 | m_nColumnNo++; |
326 | |
327 | if (m_bPrevCharIsLF) |
328 | { |
329 | // It's a "\r\n" or "\n" |
330 | // Start of a new line |
331 | m_bPrevCharIsLF = false; |
332 | m_nColumnNo = 1; |
333 | m_nLineNo++; |
334 | } |
335 | else |
336 | if (m_bPrevCharIsCR) |
337 | { |
338 | m_bPrevCharIsCR = false; |
339 | if (c == '\n') |
340 | { |
341 | // It's a "\r\n" |
342 | m_bPrevCharIsLF = true; |
343 | } |
344 | else |
345 | { |
346 | // It's only a "\r" |
347 | m_nColumnNo = 1; |
348 | m_nLineNo++; |
349 | } |
350 | } |
351 | |
352 | switch (c) |
353 | { |
354 | case '\r': |
355 | m_bPrevCharIsCR = true; |
356 | break; |
357 | case '\n': |
358 | m_bPrevCharIsLF = true; |
359 | break; |
360 | case '\t': |
361 | m_nColumnNo--; |
362 | m_nColumnNo += (m_nTabSize - (m_nColumnNo % m_nTabSize)); |
363 | break; |
364 | } |
365 | |
366 | internalSetBufLineColumn (m_nLineNo, m_nColumnNo); |
367 | } |
368 | |
369 | public char readChar() throws java.io.IOException |
370 | { |
371 | if (inBuf > 0) |
372 | { |
373 | // Something is left from last backup |
374 | --inBuf; |
375 | |
376 | ++bufpos; |
377 | if (bufpos == bufsize) |
378 | { |
379 | // Buffer overflow |
380 | bufpos = 0; |
381 | } |
382 | |
383 | return buffer[bufpos]; |
384 | } |
385 | |
386 | ++bufpos; |
387 | if (bufpos >= maxNextCharInd) |
388 | fillBuff(); |
389 | |
390 | final char c = buffer[bufpos]; |
391 | |
392 | if (m_bTrackLineColumn) |
393 | internalUpdateLineColumn(c); |
394 | return c; |
395 | } |
396 | |
397 | public char beginToken() throws java.io.IOException |
398 | { |
399 | tokenBegin = -1; |
400 | final char c = readChar(); |
401 | tokenBegin = bufpos; |
402 | return c; |
403 | } |
404 | |
405 | public int getBeginColumn () |
406 | { |
407 | return m_aBufColumn[tokenBegin]; |
408 | } |
409 | |
410 | public int getBeginLine () |
411 | { |
412 | return m_aBufLine[tokenBegin]; |
413 | } |
414 | |
415 | public int getEndColumn () |
416 | { |
417 | return m_aBufColumn[bufpos]; |
418 | } |
419 | |
420 | public int getEndLine () |
421 | { |
422 | return m_aBufLine[bufpos]; |
423 | } |
424 | |
425 | public void backup (final int nAmount) |
426 | { |
427 | if (nAmount > bufsize) |
428 | throw new IllegalStateException ("Cannot back " + nAmount + " chars which is larger than the internal buffer size (" + bufsize + ")"); |
429 | |
430 | inBuf += nAmount; |
431 | bufpos -= nAmount; |
432 | if (bufpos < 0) |
433 | { |
434 | // Buffer underflow (modulo) |
435 | bufpos += bufsize; |
436 | } |
437 | } |
438 | |
439 | public String getImage() |
440 | { |
441 | if (bufpos >= tokenBegin) |
442 | { |
443 | // from tokenBegin to bufpos |
444 | return new String (buffer, tokenBegin, bufpos - tokenBegin + 1); |
445 | } |
446 | |
447 | // from tokenBegin to bufsize, and from 0 to bufpos |
448 | return new String (buffer, tokenBegin, bufsize - tokenBegin) + |
449 | new String (buffer, 0, bufpos + 1); |
450 | } |
451 | |
452 | public char[] getSuffix (final int len) |
453 | { |
454 | char[] ret = new char[len]; |
455 | if ((bufpos + 1) >= len) |
456 | { |
457 | // one piece |
458 | System.arraycopy(buffer, bufpos - len + 1, ret, 0, len); |
459 | } |
460 | else |
461 | { |
462 | // Wrap around |
463 | final int nPart1 = len - bufpos - 1; |
464 | System.arraycopy(buffer, bufsize - nPart1, ret, 0, nPart1); |
465 | System.arraycopy(buffer, 0, ret, nPart1, bufpos + 1); |
466 | } |
467 | return ret; |
468 | } |
469 | |
470 | public void done() |
471 | { |
472 | buffer = null; |
473 | m_aBufLine = null; |
474 | m_aBufColumn = null; |
475 | } |
476 | |
477 | public final int getTabSize() |
478 | { |
479 | return m_nTabSize; |
480 | } |
481 | |
482 | public final void setTabSize (final int nTabSize) |
483 | { |
484 | m_nTabSize = nTabSize; |
485 | } |
486 | |
487 | /** |
488 | * Method to adjust line and column numbers for the start of a token. |
489 | * This is used internally to |
490 | */ |
491 | public final void adjustBeginLineColumn(final int nNewLine, final int newCol) |
492 | { |
493 | int start = tokenBegin; |
494 | int newLine = nNewLine; |
495 | |
496 | int len; |
497 | if (bufpos >= tokenBegin) |
498 | { |
499 | len = bufpos - tokenBegin + inBuf + 1; |
500 | } |
501 | else |
502 | { |
503 | len = bufsize - tokenBegin + bufpos + 1 + inBuf; |
504 | } |
505 | |
506 | int i = 0; |
507 | int j = 0; |
508 | int k = 0; |
509 | int nextColDiff = 0; |
510 | int columnDiff = 0; |
511 | |
512 | // TODO disassemble meaning and split up |
513 | while (i < len && m_aBufLine[j = start % bufsize] == m_aBufLine[k = ++start % bufsize]) |
514 | { |
515 | m_aBufLine[j] = newLine; |
516 | nextColDiff = columnDiff + m_aBufColumn[k] - m_aBufColumn[j]; |
517 | m_aBufColumn[j] = newCol + columnDiff; |
518 | columnDiff = nextColDiff; |
519 | i++; |
520 | } |
521 | |
522 | if (i < len) |
523 | { |
524 | m_aBufLine[j] = newLine++; |
525 | m_aBufColumn[j] = newCol + columnDiff; |
526 | |
527 | while (i++ < len) |
528 | { |
529 | // TODO disassemble meaning and split up |
530 | if (m_aBufLine[j = start % bufsize] != m_aBufLine[++start % bufsize]) |
531 | m_aBufLine[j] = newLine++; |
532 | else |
533 | m_aBufLine[j] = newLine; |
534 | } |
535 | } |
536 | |
537 | m_nLineNo = m_aBufLine[j]; |
538 | m_nColumnNo = m_aBufColumn[j]; |
539 | } |
540 | |
541 | /** |
542 | * @return the current line number. 0-based. |
543 | */ |
544 | protected final int getLine () |
545 | { |
546 | return m_nLineNo; |
547 | } |
548 | |
549 | /** |
550 | * @return the current column number. 0-based. |
551 | */ |
552 | protected final int getColumn () |
553 | { |
554 | return m_nColumnNo; |
555 | } |
556 | |
557 | public final boolean isTrackLineColumn () |
558 | { |
559 | return m_bTrackLineColumn; |
560 | } |
561 | |
562 | public final void setTrackLineColumn (final boolean bTrackLineColumn) |
563 | { |
564 | m_bTrackLineColumn = bTrackLineColumn; |
565 | } |
566 | } |
567 | /* ParserGeneratorCC - OriginalChecksum=af6292cb319b03fbec025497678ca090 (do not edit this line) */ |
568 |
Members