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