a0b42ce6306ddd8d1f88e0e639e859b333f41532
[jalview.git] / src / com / stevesoft / pat / RegexReader.java
1 //
2 // This software is now distributed according to
3 // the Lesser Gnu Public License.  Please see
4 // http://www.gnu.org/copyleft/lesser.txt for
5 // the details.
6 //    -- Happy Computing!
7 //
8 package com.stevesoft.pat;
9
10 import java.io.IOException;
11 import java.io.Reader;
12
13 import com.stevesoft.pat.wrap.StringBufferWrap;
14
15 /**
16  * This class allows you to replace the text in strings as you read them in. Be
17  * careful what you do with this freedom... using Regex.perlCode("s{.*}{x}s") as
18  * your pattern will result in loading the entire contents of the Reader into
19  * memory.
20  */
21 public class RegexReader extends Reader
22 {
23   RBuffer rb = new RBuffer(new StringBuffer());
24
25   PartialBuffer wrap = new PartialBuffer(rb.sb);
26
27   boolean moreToRead = true;
28
29   Reader r;
30
31   Replacer rp;
32
33   // the buffer size
34   int nmax = 2 * 1024;
35
36   public RegexReader(Regex rex, Reader r)
37   {
38     this.r = r;
39     rp = rex.getReplacer();
40   }
41
42   public RegexReader(Transformer tex, Reader r)
43   {
44     this.r = r;
45     rp = tex.getReplacer();
46   }
47
48   public void reset() throws IOException
49   {
50     r.reset();
51     rb = new RBuffer(new StringBuffer());
52     wrap = new PartialBuffer(rb.sb);
53     moreToRead = true;
54   }
55
56   void readData() throws IOException
57   {
58     int c;
59     int n = 0;
60     while ((c = r.read()) != -1)
61     {
62       rb.sb.append((char) c);
63       if (n++ > nmax)
64       {
65         break;
66       }
67     }
68     if (c == -1 && n == 0)
69     {
70       moreToRead = false;
71       wrap.allowOverRun = false;
72     }
73   }
74
75   void getMoreData() throws IOException
76   {
77     while (rb.pos >= rb.epos)
78     {
79       wrap.overRun = false;
80       if (rb.next != null)
81       {
82         rb = rb.next;
83       }
84       else if (rb.done)
85       {
86         break;
87       }
88       else if (rb.epos >= rb.sb.length() && rb.epos > nmax)
89       {
90         rb.pos = 1;
91         rb.epos = 1;
92         rb.sb.setLength(1);
93         readData();
94       }
95       else if (rb.epos >= rb.sb.length() && moreToRead)
96       {
97         readData();
98       }
99       else if (rp.getRegex().matchAt(wrap, rb.epos))
100       {
101         if (wrap.overRun)
102         {
103           readData();
104         }
105         else
106         {
107           StringBufferWrap sbw = new StringBufferWrap();
108           StringBufferLike sbl = new StringBufferLike(sbw);
109           /*
110            * ReplaceRule rr = rex.getReplaceRule(); while(rr != null) {
111            * rr.apply(sbl,rex); rr = rr.next; }
112            */
113           Regex rex = rp.getRegex();
114           int npos = rex.matchedTo();
115           rp.setBuffer(sbl);
116           rp.setSource(wrap);
117           rp.setPos(npos);
118           rp.apply(rex, rex.getReplaceRule());
119           int opos = rb.epos;
120           RBuffer rb2 = new RBuffer((StringBuffer) sbw.unwrap());
121           rb2.epos = rb2.sb.length();
122           RBuffer rb3 = new RBuffer(rb.sb);
123
124           rb.next = rb2;
125           rb2.next = rb3;
126
127           if (npos == opos)
128           {
129             rb3.epos = npos + 1;
130             if (rb3.epos > rb3.sb.length())
131             {
132               if (rb.pos >= rb.epos)
133               {
134                 rb = rb.next;
135               }
136               rb3.pos = rb3.epos = 0;
137               rb3.done = true;
138               // break;
139             }
140             rb3.pos = npos;
141           }
142           else
143           {
144             rb3.pos = rb3.epos = npos;
145           }
146
147         }
148       }
149       else
150       {
151         if (wrap.overRun)
152         {
153           readData();
154         }
155         else if (rb.epos < rb.sb.length())
156         {
157           rb.epos++;
158         }
159         else
160         {
161           break;
162         }
163       }
164     }
165   }
166
167   public int read() throws IOException
168   {
169     if (rb.pos >= rb.epos)
170     {
171       getMoreData();
172       if (rb.pos >= rb.epos)
173       {
174         return -1;
175       }
176     }
177     // System.out.println(rb);
178     return rb.sb.charAt(rb.pos++);
179   }
180
181   public int read(char[] buf, int off, int len) throws IOException
182   {
183     int c = -1;
184     int end = off + len;
185     for (int i = off; i < end; i++)
186     {
187       c = read();
188       if (c < 0)
189       {
190         if (i == off)
191         {
192           return -1;
193         }
194         return i - off;
195       }
196       buf[i] = (char) c;
197     }
198     return len;
199   }
200
201   public void close() throws IOException
202   {
203     r.close();
204   }
205
206   public boolean markSupported()
207   {
208     return false;
209   }
210
211   /**
212    * Get the size of the working buffer. The current buffer may be larger if the
213    * pattern demands it.
214    */
215   public int getBufferSize()
216   {
217     return nmax;
218   }
219
220   /**
221    * Set the size of the working buffer. The current buffer may be larger if the
222    * pattern demands it.
223    */
224   public void setBufferSize(int n)
225   {
226     nmax = n;
227   }
228
229   int max_lines = 2;
230
231   /**
232    * This function no longer serves any purpose.
233    * 
234    * @deprecated
235    */
236   @Deprecated
237   public int getMaxLines()
238   {
239     return max_lines;
240   }
241
242   /**
243    * This function no longer serves any purpose.
244    * 
245    * @deprecated
246    */
247   @Deprecated
248   public void setMaxLines(int ml)
249   {
250     max_lines = ml;
251   }
252
253   char EOLchar = '\n';
254
255   /**
256    * This function no longer serves any purpose.
257    * 
258    * @deprecated
259    */
260   @Deprecated
261   public char getEOLchar()
262   {
263     return EOLchar;
264   }
265
266   /**
267    * This function no longer serves any purpose.
268    * 
269    * @deprecated
270    */
271   @Deprecated
272   public void setEOLchar(char c)
273   {
274     EOLchar = c;
275   }
276
277   public long skip(long d) throws IOException
278   {
279     // This is probably inefficient, I just did it
280     // this way to avoid possible bugs.
281     long n = 0;
282     while (n < d && read() != -1)
283     {
284       n++;
285     }
286     return n;
287   }
288
289   /*
290    * static void test(String re,String inp,int n) throws Exception { Reader r =
291    * new StringReader(inp); r = new BufferedReader(r); Regex rex =
292    * Regex.perlCode(re); String res1 = rex.replaceAll(inp); int c = -1;
293    * StringBuffer sb = new StringBuffer(); RegexReader rr = new
294    * RegexReader(rex,r); rr.setBufferSize(n); while( (c = rr.read()) != -1)
295    * sb.append((char)c); String res2 = sb.toString(); if(!res1.equals(res2)) {
296    * System.out.println("nmax="+n); System.out.println("re="+re);
297    * System.out.println("inp="+inp); System.out.println("res1="+res1);
298    * System.out.println("res2="+res2); System.exit(255); } } public static void
299    * main(String[] args) throws Exception { for(int n=6;n<15;n++) {
300    * test("s/x/y/","-----x123456789",n); test("s/x/y/","x123456789",n);
301    * test("s/x/y/","-----x",n);
302    * test("s/x.*?x/y/",".xx..x..x...x...x....x....x",n);
303    * test("s/x.*x/[$&]/","--x........x--xx",n);
304    * test("s/x.*x/[$&]/","--x........x------",n);
305    * test("s/.$/a/m","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb",n);
306    * test("s/.$/a/","123",n);
307    * test("s/.$/a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);
308    * test("s/^./a/","bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb",n);
309    * test("s/$/a/","bbb",n); test("s/^/a/","bbb",n); test("s/^/a/","",n);
310    * test("s{.*}{N}","xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",n);
311    * test("s/.{0,7}/y/","AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",n);
312    * test("s/x/$&/","xxx",n); } System.out.println("Success!!!"); }
313    */
314 }