Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
RegexWriter | 39 | 90 | 37 |
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.StringWriter; | |
12 | import java.io.Writer; | |
13 | ||
14 | import com.stevesoft.pat.wrap.WriterWrap; | |
15 | ||
16 | /** | |
17 | * A basic extension of FilterWriter that uses Transformer to make replacements | |
18 | * in data as it is written out. It attempts to transform a string whenever the | |
19 | * End-of-Line (EOL) character is written (which is, by default, the carriage | |
20 | * return '\n'). Only the transformed portion of the line is written out, | |
21 | * allowing the RegexWriter to wait until a complete pattern is present before | |
22 | * attempting to write out info. Until a pattern completes, data is stored in a | |
23 | * StringBuffer -- which can be accessed through the length() and charAt() | |
24 | * methods of this class. | |
25 | * <p> | |
26 | * Note a subtlety here -- while a Transformer normally matches at higher | |
27 | * priority against the pattern added to it first, this will not necessarily be | |
28 | * true when a multi-line match is in progress because one of the complete | |
29 | * multi-line patterns may not be completely loaded in RegexWriter's buffer. For | |
30 | * this reason, the Transformer class is equipped with a way to add a pattern | |
31 | * and replacement rule in three pieces -- a beginning (once this matches, | |
32 | * nothing else in the Transformer can match until the whole pattern matches), | |
33 | * an ending (the whole pattern is a String formed by adding the beginning and | |
34 | * ending), and a ReplaceRule. | |
35 | * <p> | |
36 | * An illustration of this is given in the this | |
37 | * <a href="../test/trans.java">example.</a> | |
38 | */ | |
39 | public class RegexWriter extends Writer | |
40 | { | |
41 | Replacer repr; | |
42 | ||
43 | Writer w; | |
44 | ||
45 | WriterWrap ww; | |
46 | ||
47 | StringBuffer sb = new StringBuffer(); | |
48 | ||
49 | PartialBuffer wrap = new PartialBuffer(sb); | |
50 | ||
51 | int pos, epos; | |
52 | ||
53 | int interval = 128; | |
54 | ||
55 | int bufferSize = 2 * 1024; | |
56 | ||
57 | 0 | public RegexWriter(Transformer t, Writer w) |
58 | { | |
59 | 0 | this.w = w; |
60 | 0 | ww = new WriterWrap(w); |
61 | 0 | repr = t.getReplacer(); |
62 | 0 | repr.setBuffer(new StringBufferLike(ww)); |
63 | 0 | repr.setSource(wrap); |
64 | } | |
65 | ||
66 | 0 | public RegexWriter(Regex r, Writer w) |
67 | { | |
68 | 0 | this.w = w; |
69 | 0 | ww = new WriterWrap(w); |
70 | 0 | repr = r.getReplacer(); |
71 | 0 | repr.setBuffer(new StringBufferLike(ww)); |
72 | 0 | repr.setSource(wrap); |
73 | } | |
74 | ||
75 | char EOLchar = '\n'; | |
76 | ||
77 | /** | |
78 | * This method no longer serves any purpose. | |
79 | * | |
80 | * @deprecated | |
81 | */ | |
82 | 0 | @Deprecated |
83 | public char getEOLchar() | |
84 | { | |
85 | 0 | return EOLchar; |
86 | } | |
87 | ||
88 | /** | |
89 | * This method no longer serves any purpose. | |
90 | * | |
91 | * @deprecated | |
92 | */ | |
93 | 0 | @Deprecated |
94 | public void setEOLchar(char c) | |
95 | { | |
96 | 0 | EOLchar = c; |
97 | } | |
98 | ||
99 | int max_lines = 2; | |
100 | ||
101 | /** | |
102 | * This method no longer serves any purpose. | |
103 | * | |
104 | * @deprecated | |
105 | */ | |
106 | 0 | @Deprecated |
107 | public int getMaxLines() | |
108 | { | |
109 | 0 | return max_lines; |
110 | } | |
111 | ||
112 | /** | |
113 | * This method no longer serves any purpose. | |
114 | * | |
115 | * @deprecated | |
116 | */ | |
117 | 0 | @Deprecated |
118 | public void setMaxLines(int ml) | |
119 | { | |
120 | 0 | max_lines = ml; |
121 | } | |
122 | ||
123 | 0 | void write() throws IOException |
124 | { | |
125 | 0 | Regex rex = repr.getRegex(); |
126 | 0 | int eposOld = epos; |
127 | 0 | if (rex.matchAt(wrap, epos) && !wrap.overRun) |
128 | { | |
129 | 0 | while (pos < epos) |
130 | { | |
131 | 0 | w.write(sb.charAt(pos++)); |
132 | } | |
133 | 0 | int to = rex.matchedTo(); |
134 | 0 | repr.setPos(to); |
135 | 0 | repr.apply(rex, rex.getReplaceRule()); |
136 | 0 | epos = pos = to; |
137 | 0 | if (epos == eposOld && epos < sb.length()) |
138 | { | |
139 | 0 | epos++; |
140 | } | |
141 | } | |
142 | 0 | else if (!wrap.overRun && epos < sb.length()) |
143 | { | |
144 | 0 | epos++; |
145 | } | |
146 | 0 | while (pos < epos) |
147 | { | |
148 | 0 | w.write(sb.charAt(pos++)); |
149 | } | |
150 | 0 | if (epos == sb.length()) |
151 | { | |
152 | 0 | sb.setLength(1); |
153 | 0 | pos = epos = 1; |
154 | } | |
155 | 0 | else if (pos > bufferSize) |
156 | { | |
157 | 0 | for (int i = bufferSize; i < sb.length(); i++) |
158 | { | |
159 | 0 | sb.setCharAt(i - bufferSize, sb.charAt(i)); |
160 | } | |
161 | 0 | pos -= bufferSize; |
162 | 0 | epos -= bufferSize; |
163 | 0 | sb.setLength(sb.length() - bufferSize); |
164 | } | |
165 | } | |
166 | ||
167 | 0 | public void write(char[] ca, int b, int n) throws IOException |
168 | { | |
169 | 0 | int m = b + n; |
170 | 0 | for (int i = b; i < m; i++) |
171 | { | |
172 | 0 | sb.append(ca[i]); |
173 | 0 | if (sb.length() % interval == interval - 1) |
174 | { | |
175 | 0 | wrap.overRun = false; |
176 | 0 | while (epos + interval < sb.length() && !wrap.overRun) |
177 | { | |
178 | 0 | write(); |
179 | } | |
180 | } | |
181 | } | |
182 | } | |
183 | ||
184 | 0 | public void flush() throws IOException |
185 | { | |
186 | } | |
187 | ||
188 | 0 | public void close() throws IOException |
189 | { | |
190 | 0 | wrap.allowOverRun = false; |
191 | 0 | wrap.overRun = false; |
192 | 0 | while (epos < sb.length()) |
193 | { | |
194 | 0 | write(); |
195 | } | |
196 | 0 | write(); |
197 | 0 | w.close(); |
198 | } | |
199 | ||
200 | /** The current size of the StringBuffer in use by RegexWriter. */ | |
201 | 0 | public int length() |
202 | { | |
203 | 0 | return sb.length(); |
204 | } | |
205 | ||
206 | /** The character at location i in the StringBuffer. */ | |
207 | 0 | public char charAt(int i) |
208 | { | |
209 | 0 | return sb.charAt(i); |
210 | } | |
211 | ||
212 | /** Set the interval at which regex patterns are checked. */ | |
213 | 0 | public void setInterval(int i) |
214 | { | |
215 | 0 | interval = i; |
216 | } | |
217 | ||
218 | /** Get the interval at which regex matches are checked. */ | |
219 | 0 | public int getInterval() |
220 | { | |
221 | 0 | return interval; |
222 | } | |
223 | ||
224 | /** Get the buffer size. */ | |
225 | 0 | public int getBufferSize() |
226 | { | |
227 | 0 | return bufferSize; |
228 | } | |
229 | ||
230 | /** Set the buffer size. */ | |
231 | 0 | public void setBufferSize(int i) |
232 | { | |
233 | 0 | bufferSize = i; |
234 | } | |
235 | ||
236 | 0 | static void test(String re, String inp, int n) throws Exception |
237 | { | |
238 | 0 | StringWriter sw = new StringWriter(); |
239 | 0 | Regex rex = Regex.perlCode(re); |
240 | 0 | String res1 = rex.replaceAll(inp); |
241 | 0 | RegexWriter rw = new RegexWriter(rex, sw); |
242 | 0 | for (int i = 0; i < inp.length(); i++) |
243 | { | |
244 | 0 | rw.write(inp.charAt(i)); |
245 | } | |
246 | 0 | rw.close(); |
247 | 0 | String res2 = sw.toString(); |
248 | 0 | if (!res1.equals(res2)) |
249 | { | |
250 | 0 | System.out.println("nmax=" + n); |
251 | 0 | System.out.println("re=" + re); |
252 | 0 | System.out.println("inp=" + inp); |
253 | 0 | System.out.println("res1=" + res1); |
254 | 0 | System.out.println("res2=" + res2); |
255 | 0 | System.exit(255); |
256 | } | |
257 | } | |
258 | ||
259 | 0 | public static void main(String[] args) throws Exception |
260 | { | |
261 | 0 | for (int n = 1; n <= 1; n++) |
262 | { | |
263 | 0 | test("s/x/y/", "-----x123456789", n); |
264 | 0 | test("s/x/y/", "x123456789", n); |
265 | 0 | test("s/x/y/", "-----x", n); |
266 | 0 | test("s/x.*?x/y/", ".xx..x..x...x...x....x....x", n); |
267 | 0 | test("s/x.*x/[$&]/", "--x........x--xx", n); |
268 | 0 | test("s/x.*x/[$&]/", "--x........x------", n); |
269 | 0 | test("s/.$/a/m", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbbbbbbbbbbbb", n); |
270 | 0 | test("s/.$/a/", "123", n); |
271 | 0 | test("s/.$/a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n); |
272 | 0 | test("s/^./a/", "bb\nbbb\nbbbb\nbbbbb\nbbbbbb\nbb", n); |
273 | 0 | test("s/$/a/", "bbb", n); |
274 | 0 | test("s/^/a/", "bbb", n); |
275 | 0 | test("s/^/a/", "", n); |
276 | 0 | test("s{.*}{N}", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", n); |
277 | 0 | test("s/.{0,7}/y/", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", n); |
278 | 0 | test("s/x/$&/", "xxx", n); |
279 | } | |
280 | 0 | System.out.println("Success!!!"); |
281 | } | |
282 | } |