d972ea336a2967e27c559a3a52f6e4ebbf49b187
[org.ibex.core.git] / src / gnu / regexp / CharIndexedInputStream.java
1 /*
2  *  gnu/regexp/CharIndexedReader.java
3  *  Copyright (C) 1998-2001 Wes Biggs
4  *
5  *  This library is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU Lesser General Public License as published
7  *  by the Free Software Foundation; either version 2.1 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 package gnu.regexp;
21 import java.io.InputStream;
22 import java.io.BufferedInputStream;
23 import java.io.IOException;
24
25 // TODO: move(x) shouldn't rely on calling next() x times
26
27 class CharIndexedInputStream implements CharIndexed {
28     private static final int BUFFER_INCREMENT = 1024;
29     private static final int UNKNOWN = Integer.MAX_VALUE; // value for end
30     
31     private BufferedInputStream br;
32
33     // so that we don't try to reset() right away
34     private int index = -1;
35
36     private int bufsize = BUFFER_INCREMENT;
37
38     private int end = UNKNOWN;
39
40     private char cached = OUT_OF_BOUNDS;
41
42     // Big enough for a \r\n pair
43     // lookBehind[0] = most recent
44     // lookBehind[1] = second most recent
45     private char[] lookBehind = new char[] { OUT_OF_BOUNDS, OUT_OF_BOUNDS }; 
46     
47     CharIndexedInputStream(InputStream str, int index) {
48         if (str instanceof BufferedInputStream) br = (BufferedInputStream) str;
49         else br = new BufferedInputStream(str,BUFFER_INCREMENT);
50         next();
51         if (index > 0) move(index);
52     }
53     
54     private boolean next() {
55         if (end == 1) return false;
56         end--; // closer to end
57
58         try {
59             if (index != -1) {
60                 br.reset();
61             }
62             int i = br.read();
63             br.mark(bufsize);
64             if (i == -1) {
65                 end = 1;
66                 cached = OUT_OF_BOUNDS;
67                 return false;
68             }
69             cached = (char) i;
70             index = 1;
71         } catch (IOException e) { 
72             e.printStackTrace();
73             cached = OUT_OF_BOUNDS;
74             return false; 
75         }
76         return true;
77     }
78     
79     public char charAt(int index) {
80         if (index == 0) {
81             return cached;
82         } else if (index >= end) {
83             return OUT_OF_BOUNDS;
84         } else if (index == -1) {
85             return lookBehind[0];
86         } else if (index == -2) {
87             return lookBehind[1];
88         } else if (index < -2) {
89             return OUT_OF_BOUNDS;
90         } else if (index >= bufsize) {
91             // Allocate more space in the buffer.
92             try {
93                 while (bufsize <= index) bufsize += BUFFER_INCREMENT;
94                 br.reset();
95                 br.mark(bufsize);
96                 br.skip(index-1);
97             } catch (IOException e) { }
98         } else if (this.index != index) {
99             try {
100                 br.reset();
101                 br.skip(index-1);
102             } catch (IOException e) { }
103         }
104         char ch = OUT_OF_BOUNDS;
105         
106         try {
107             int i = br.read();
108             this.index = index+1; // this.index is index of next pos relative to charAt(0)
109             if (i == -1) {
110                 // set flag that next should fail next time?
111                 end = index;
112                 return ch;
113             }
114             ch = (char) i;
115         } catch (IOException ie) { }
116         
117         return ch;
118     }
119     
120     public boolean move(int index) {
121         // move read position [index] clicks from 'charAt(0)'
122         boolean retval = true;
123         while (retval && (index-- > 0)) retval = next();
124         return retval;
125     }
126     
127     public boolean isValid() {
128         return (cached != OUT_OF_BOUNDS);
129     }
130 }
131