001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.util.parser;
033
034import java.io.IOException;
035
036/**
037 * An implementation of interface CharStream, where the stream is assumed to
038 * contain only ASCII characters (without unicode processing).
039 */
040
041public class SimpleCharStream {
042        /** Whether parser is static. */
043        public static final boolean staticFlag = false;
044        int bufsize;
045        int available;
046        int tokenBegin;
047        /** Position in buffer. */
048        public int bufpos = -1;
049        protected int bufline[];
050        protected int bufcolumn[];
051
052        protected int column = 0;
053        protected int line = 1;
054
055        protected boolean prevCharIsCR = false;
056        protected boolean prevCharIsLF = false;
057
058        protected java.io.Reader inputStream;
059
060        protected char[] buffer;
061        protected int maxNextCharInd = 0;
062        protected int inBuf = 0;
063        protected int tabSize = 8;
064
065        protected void setTabSize(int i) {
066                tabSize = i;
067        }
068
069        protected int getTabSize(int i) {
070                return tabSize;
071        }
072
073        protected void ExpandBuff(boolean wrapAround) {
074                char[] newbuffer = new char[bufsize + 2048];
075                int newbufline[] = new int[bufsize + 2048];
076                int newbufcolumn[] = new int[bufsize + 2048];
077
078                try {
079                        if (wrapAround) {
080                                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize
081                                                - tokenBegin);
082                                System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin,
083                                                bufpos);
084                                buffer = newbuffer;
085
086                                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize
087                                                - tokenBegin);
088                                System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin,
089                                                bufpos);
090                                bufline = newbufline;
091
092                                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0,
093                                                bufsize - tokenBegin);
094                                System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize
095                                                - tokenBegin, bufpos);
096                                bufcolumn = newbufcolumn;
097
098                                maxNextCharInd = (bufpos += (bufsize - tokenBegin));
099                        } else {
100                                System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize
101                                                - tokenBegin);
102                                buffer = newbuffer;
103
104                                System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize
105                                                - tokenBegin);
106                                bufline = newbufline;
107
108                                System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0,
109                                                bufsize - tokenBegin);
110                                bufcolumn = newbufcolumn;
111
112                                maxNextCharInd = (bufpos -= tokenBegin);
113                        }
114                } catch (Throwable t) {
115                        throw new Error(t.getMessage());
116                }
117
118                bufsize += 2048;
119                available = bufsize;
120                tokenBegin = 0;
121        }
122
123        protected void FillBuff() throws java.io.IOException {
124                if (maxNextCharInd == available) {
125                        if (available == bufsize) {
126                                if (tokenBegin > 2048) {
127                                        bufpos = maxNextCharInd = 0;
128                                        available = tokenBegin;
129                                } else if (tokenBegin < 0)
130                                        bufpos = maxNextCharInd = 0;
131                                else
132                                        ExpandBuff(false);
133                        } else if (available > tokenBegin)
134                                available = bufsize;
135                        else if ((tokenBegin - available) < 2048)
136                                ExpandBuff(true);
137                        else
138                                available = tokenBegin;
139                }
140
141                int i;
142                try {
143                        if ((i = inputStream.read(buffer, maxNextCharInd, available
144                                        - maxNextCharInd)) == -1) {
145                                inputStream.close();
146                                throw new java.io.IOException();
147                        } else
148                                maxNextCharInd += i;
149                        return;
150                } catch (java.io.IOException e) {
151                        --bufpos;
152                        backup(0);
153                        if (tokenBegin == -1)
154                                tokenBegin = bufpos;
155                        throw e;
156                }
157        }
158
159        /** Start. */
160        public char BeginToken() throws java.io.IOException {
161                tokenBegin = -1;
162                char c = readChar();
163                tokenBegin = bufpos;
164
165                return c;
166        }
167
168        protected void UpdateLineColumn(char c) {
169                column++;
170
171                if (prevCharIsLF) {
172                        prevCharIsLF = false;
173                        line += (column = 1);
174                } else if (prevCharIsCR) {
175                        prevCharIsCR = false;
176                        if (c == '\n') {
177                                prevCharIsLF = true;
178                        } else
179                                line += (column = 1);
180                }
181
182                switch (c) {
183                case '\r':
184                        prevCharIsCR = true;
185                        break;
186                case '\n':
187                        prevCharIsLF = true;
188                        break;
189                case '\t':
190                        column--;
191                        column += (tabSize - (column % tabSize));
192                        break;
193                default:
194                        break;
195                }
196
197                bufline[bufpos] = line;
198                bufcolumn[bufpos] = column;
199        }
200
201        /** Read a character. */
202        public char readChar() throws java.io.IOException {
203                if (inBuf > 0) {
204                        --inBuf;
205
206                        if (++bufpos == bufsize)
207                                bufpos = 0;
208
209                        return buffer[bufpos];
210                }
211
212                if (++bufpos >= maxNextCharInd)
213                        FillBuff();
214
215                char c = buffer[bufpos];
216
217                UpdateLineColumn(c);
218                return c;
219        }
220
221        @Deprecated
222        /**
223         * @deprecated
224         * @see #getEndColumn
225         */
226        public int getColumn() {
227                return bufcolumn[bufpos];
228        }
229
230        @Deprecated
231        /**
232         * @deprecated
233         * @see #getEndLine
234         */
235        public int getLine() {
236                return bufline[bufpos];
237        }
238
239        /** Get token end column number. */
240        public int getEndColumn() {
241                return bufcolumn[bufpos];
242        }
243
244        /** Get token end line number. */
245        public int getEndLine() {
246                return bufline[bufpos];
247        }
248
249        /** Get token beginning column number. */
250        public int getBeginColumn() {
251                return bufcolumn[tokenBegin];
252        }
253
254        /** Get token beginning line number. */
255        public int getBeginLine() {
256                return bufline[tokenBegin];
257        }
258
259        /** Backup a number of characters. */
260        public void backup(int amount) {
261
262                inBuf += amount;
263                if ((bufpos -= amount) < 0)
264                        bufpos += bufsize;
265        }
266
267        /** Constructor. */
268        public SimpleCharStream(java.io.Reader dstream, int startline,
269                        int startcolumn, int buffersize) {
270                inputStream = dstream;
271                line = startline;
272                column = startcolumn - 1;
273
274                available = bufsize = buffersize;
275                buffer = new char[buffersize];
276                bufline = new int[buffersize];
277                bufcolumn = new int[buffersize];
278        }
279
280        /** Constructor. */
281        public SimpleCharStream(java.io.Reader dstream, int startline,
282                        int startcolumn) {
283                this(dstream, startline, startcolumn, 4096);
284        }
285
286        /** Constructor. */
287        public SimpleCharStream(java.io.Reader dstream) {
288                this(dstream, 1, 1, 4096);
289        }
290
291        /** Reinitialise. */
292        public void ReInit(java.io.Reader dstream, int startline, int startcolumn,
293                        int buffersize) {
294                inputStream = dstream;
295                line = startline;
296                column = startcolumn - 1;
297
298                if (buffer == null || buffersize != buffer.length) {
299                        available = bufsize = buffersize;
300                        buffer = new char[buffersize];
301                        bufline = new int[buffersize];
302                        bufcolumn = new int[buffersize];
303                }
304                prevCharIsLF = prevCharIsCR = false;
305                tokenBegin = inBuf = maxNextCharInd = 0;
306                bufpos = -1;
307        }
308
309        /** Reinitialise. */
310        public void ReInit(java.io.Reader dstream, int startline, int startcolumn) {
311                ReInit(dstream, startline, startcolumn, 4096);
312        }
313
314        /** Reinitialise. */
315        public void ReInit(java.io.Reader dstream) {
316                ReInit(dstream, 1, 1, 4096);
317        }
318
319        /** Constructor. */
320        public SimpleCharStream(java.io.InputStream dstream, String encoding,
321                        int startline, int startcolumn, int buffersize)
322                        throws java.io.UnsupportedEncodingException {
323                this(encoding == null ? new java.io.InputStreamReader(dstream)
324                                : new java.io.InputStreamReader(dstream, encoding), startline,
325                                startcolumn, buffersize);
326        }
327
328        /** Constructor. */
329        public SimpleCharStream(java.io.InputStream dstream, int startline,
330                        int startcolumn, int buffersize) {
331                this(new java.io.InputStreamReader(dstream), startline, startcolumn,
332                                buffersize);
333        }
334
335        /** Constructor. */
336        public SimpleCharStream(java.io.InputStream dstream, String encoding,
337                        int startline, int startcolumn)
338                        throws java.io.UnsupportedEncodingException {
339                this(dstream, encoding, startline, startcolumn, 4096);
340        }
341
342        /** Constructor. */
343        public SimpleCharStream(java.io.InputStream dstream, int startline,
344                        int startcolumn) {
345                this(dstream, startline, startcolumn, 4096);
346        }
347
348        /** Constructor. */
349        public SimpleCharStream(java.io.InputStream dstream, String encoding)
350                        throws java.io.UnsupportedEncodingException {
351                this(dstream, encoding, 1, 1, 4096);
352        }
353
354        /** Constructor. */
355        public SimpleCharStream(java.io.InputStream dstream) {
356                this(dstream, 1, 1, 4096);
357        }
358
359        /** Reinitialise. */
360        public void ReInit(java.io.InputStream dstream, String encoding,
361                        int startline, int startcolumn, int buffersize)
362                        throws java.io.UnsupportedEncodingException {
363                ReInit(encoding == null ? new java.io.InputStreamReader(dstream)
364                                : new java.io.InputStreamReader(dstream, encoding), startline,
365                                startcolumn, buffersize);
366        }
367
368        /** Reinitialise. */
369        public void ReInit(java.io.InputStream dstream, int startline,
370                        int startcolumn, int buffersize) {
371                ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn,
372                                buffersize);
373        }
374
375        /** Reinitialise. */
376        public void ReInit(java.io.InputStream dstream, String encoding)
377                        throws java.io.UnsupportedEncodingException {
378                ReInit(dstream, encoding, 1, 1, 4096);
379        }
380
381        /** Reinitialise. */
382        public void ReInit(java.io.InputStream dstream) {
383                ReInit(dstream, 1, 1, 4096);
384        }
385
386        /** Reinitialise. */
387        public void ReInit(java.io.InputStream dstream, String encoding,
388                        int startline, int startcolumn)
389                        throws java.io.UnsupportedEncodingException {
390                ReInit(dstream, encoding, startline, startcolumn, 4096);
391        }
392
393        /** Reinitialise. */
394        public void ReInit(java.io.InputStream dstream, int startline,
395                        int startcolumn) {
396                ReInit(dstream, startline, startcolumn, 4096);
397        }
398
399        /** Get token literal value. */
400        public String GetImage() {
401                if (bufpos >= tokenBegin)
402                        return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
403                else
404                        return new String(buffer, tokenBegin, bufsize - tokenBegin)
405                                        + new String(buffer, 0, bufpos + 1);
406        }
407
408        /** Get the suffix. */
409        public char[] GetSuffix(int len) {
410                char[] ret = new char[len];
411
412                if ((bufpos + 1) >= len)
413                        System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
414                else {
415                        System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0, len
416                                        - bufpos - 1);
417                        System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
418                }
419
420                return ret;
421        }
422
423        /** Reset buffer when finished. */
424        public void Done() {
425                buffer = null;
426                bufline = null;
427                bufcolumn = null;
428        }
429        
430        public void close() throws IOException {
431                inputStream.close();
432        }
433
434        /**
435         * Method to adjust line and column numbers for the start of a token.
436         */
437        public void adjustBeginLineColumn(int newLine, int newCol) {
438                int start = tokenBegin;
439                int len;
440
441                if (bufpos >= tokenBegin) {
442                        len = bufpos - tokenBegin + inBuf + 1;
443                } else {
444                        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
445                }
446
447                int i = 0, j = 0, k = 0;
448                int nextColDiff = 0, columnDiff = 0;
449
450                while (i < len
451                                && bufline[j = start % bufsize] == bufline[k = ++start
452                                                % bufsize]) {
453                        bufline[j] = newLine;
454                        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
455                        bufcolumn[j] = newCol + columnDiff;
456                        columnDiff = nextColDiff;
457                        i++;
458                }
459
460                if (i < len) {
461                        bufline[j] = newLine++;
462                        bufcolumn[j] = newCol + columnDiff;
463
464                        while (i++ < len) {
465                                if (bufline[j = start % bufsize] != bufline[++start % bufsize])
466                                        bufline[j] = newLine++;
467                                else
468                                        bufline[j] = newLine;
469                        }
470                }
471
472                line = bufline[j];
473                column = bufcolumn[j];
474        }
475
476}
477/*
478 * JavaCC - OriginalChecksum=1b2e56df2b0de8bccc6f8ba3056859fb (do not edit this
479 * line)
480 */