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