Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/KeywordFilter.java @ 113:67ae317408c9
Filter implementation for newline translation
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 02 Feb 2011 21:19:02 +0100 |
parents | d488c7638b87 |
children | 46291ec605a0 |
comparison
equal
deleted
inserted
replaced
112:d488c7638b87 | 113:67ae317408c9 |
---|---|
20 import java.io.FileInputStream; | 20 import java.io.FileInputStream; |
21 import java.io.FileOutputStream; | 21 import java.io.FileOutputStream; |
22 import java.nio.ByteBuffer; | 22 import java.nio.ByteBuffer; |
23 import java.util.TreeMap; | 23 import java.util.TreeMap; |
24 | 24 |
25 import javax.swing.text.html.Option; | |
26 | |
25 import org.tmatesoft.hg.core.Path; | 27 import org.tmatesoft.hg.core.Path; |
26 import org.tmatesoft.hg.repo.HgRepository; | 28 import org.tmatesoft.hg.repo.HgRepository; |
27 | 29 |
28 /** | 30 /** |
29 * | 31 * |
30 * @author Artem Tikhomirov | 32 * @author Artem Tikhomirov |
31 * @author TMate Software Ltd. | 33 * @author TMate Software Ltd. |
32 */ | 34 */ |
33 public class KeywordFilter implements Filter { | 35 public class KeywordFilter implements Filter { |
36 // present implementation is stateless, however, filter use pattern shall not assume that. In fact, Factory may us that | |
34 private final boolean isExpanding; | 37 private final boolean isExpanding; |
35 private final TreeMap<String,String> keywords; | 38 private final TreeMap<String,String> keywords; |
36 private final int minBufferLen; | 39 private final int minBufferLen; |
37 | 40 |
38 /** | 41 /** |
43 isExpanding = expand; | 46 isExpanding = expand; |
44 keywords = new TreeMap<String,String>(); | 47 keywords = new TreeMap<String,String>(); |
45 keywords.put("Id", "Id"); | 48 keywords.put("Id", "Id"); |
46 keywords.put("Revision", "Revision"); | 49 keywords.put("Revision", "Revision"); |
47 keywords.put("Author", "Author"); | 50 keywords.put("Author", "Author"); |
51 keywords.put("Date", "Date"); | |
52 keywords.put("LastChangedRevision", "LastChangedRevision"); | |
53 keywords.put("LastChangedBy", "LastChangedBy"); | |
54 keywords.put("LastChangedDate", "LastChangedDate"); | |
55 keywords.put("Source", "Source"); | |
56 keywords.put("Header", "Header"); | |
57 | |
48 int l = 0; | 58 int l = 0; |
49 for (String s : keywords.keySet()) { | 59 for (String s : keywords.keySet()) { |
50 if (s.length() > l) { | 60 if (s.length() > l) { |
51 l = s.length(); | 61 l = s.length(); |
52 } | 62 } |
97 // bytes). To prevent this, either shall copy bytes [keywordStart..buffer.limit()) to local buffer and use it on the next invocation, | 107 // bytes). To prevent this, either shall copy bytes [keywordStart..buffer.limit()) to local buffer and use it on the next invocation, |
98 // or add lookup of the keywords right after first '$' is found (do not wait for closing '$'). For now, large enough src buffer would be sufficient | 108 // or add lookup of the keywords right after first '$' is found (do not wait for closing '$'). For now, large enough src buffer would be sufficient |
99 // not to run into such situation | 109 // not to run into such situation |
100 throw new IllegalStateException("Try src buffer of a greater size"); | 110 throw new IllegalStateException("Try src buffer of a greater size"); |
101 } | 111 } |
102 rv = ByteBuffer.allocateDirect(keywordStart - x); | 112 rv = ByteBuffer.allocate(keywordStart - x); |
103 } | 113 } |
104 // copy all from source till latest possible kw start | 114 // copy all from source till latest possible kw start |
105 copySlice(src, x, keywordStart, rv); | 115 copySlice(src, x, keywordStart, rv); |
106 rv.flip(); | 116 rv.flip(); |
107 // and tell caller we've consumed only to the potential kw start | 117 // and tell caller we've consumed only to the potential kw start |
110 } else if (src.get(i) == '$') { | 120 } else if (src.get(i) == '$') { |
111 // end of keyword, or start of a new one. | 121 // end of keyword, or start of a new one. |
112 String keyword; | 122 String keyword; |
113 if ((keyword = matchKeyword(src, keywordStart, i)) != null) { | 123 if ((keyword = matchKeyword(src, keywordStart, i)) != null) { |
114 if (rv == null) { | 124 if (rv == null) { |
115 rv = ByteBuffer.allocateDirect(isExpanding ? src.capacity() * 4 : src.capacity()); | 125 // src.remaining(), not .capacity because src is not read, and remaining represents |
126 // actual bytes count, while capacity - potential. | |
127 // Factor of 4 is pure guess and a HACK, need to be fixed with re-expanding buffer on demand | |
128 rv = ByteBuffer.allocate(isExpanding ? src.remaining() * 4 : src.remaining()); | |
116 } | 129 } |
117 copySlice(src, x, keywordStart+1, rv); | 130 copySlice(src, x, keywordStart+1, rv); |
118 rv.put(keyword.getBytes()); | 131 rv.put(keyword.getBytes()); |
119 if (isExpanding) { | 132 if (isExpanding) { |
120 rv.put((byte) ':'); | 133 rv.put((byte) ':'); |
148 } | 161 } |
149 } | 162 } |
150 if (keywordStart != -1) { | 163 if (keywordStart != -1) { |
151 if (rv == null) { | 164 if (rv == null) { |
152 // no expansion happened yet, and we have potential kw start | 165 // no expansion happened yet, and we have potential kw start |
153 rv = ByteBuffer.allocateDirect(keywordStart - src.position()); | 166 rv = ByteBuffer.allocate(keywordStart - src.position()); |
154 copySlice(src, src.position(), keywordStart, rv); | 167 copySlice(src, src.position(), keywordStart, rv); |
155 } | 168 } |
156 src.position(keywordStart); | 169 src.position(keywordStart); |
157 } | 170 } |
158 if (rv != null) { | 171 if (rv != null) { |
187 break; | 200 break; |
188 } | 201 } |
189 chars[i] = c; | 202 chars[i] = c; |
190 } | 203 } |
191 String kw = new String(chars, 0, i); | 204 String kw = new String(chars, 0, i); |
205 System.out.println(keywords.subMap("I", "J")); | |
206 System.out.println(keywords.subMap("A", "B")); | |
207 System.out.println(keywords.subMap("Au", "B")); | |
192 return keywords.get(kw); | 208 return keywords.get(kw); |
193 } | 209 } |
194 | 210 |
195 // copies part of the src buffer, [from..to). doesn't modify src position | 211 // copies part of the src buffer, [from..to). doesn't modify src position |
196 private static void copySlice(ByteBuffer src, int from, int to, ByteBuffer dst) { | 212 static void copySlice(ByteBuffer src, int from, int to, ByteBuffer dst) { |
197 if (to > src.limit()) { | 213 if (to > src.limit()) { |
198 throw new IllegalArgumentException("Bad right boundary"); | 214 throw new IllegalArgumentException("Bad right boundary"); |
199 } | 215 } |
200 if (dst.remaining() < to - from) { | 216 if (dst.remaining() < to - from) { |
201 throw new IllegalArgumentException("Not enough room in the destination buffer"); | 217 throw new IllegalArgumentException("Not enough room in the destination buffer"); |
204 dst.put(src.get(i)); | 220 dst.put(src.get(i)); |
205 } | 221 } |
206 } | 222 } |
207 | 223 |
208 private static int indexOf(ByteBuffer b, char ch, int from, boolean newlineBreaks) { | 224 private static int indexOf(ByteBuffer b, char ch, int from, boolean newlineBreaks) { |
209 for (int i = from; i < b.limit(); i++) { | 225 for (int i = from; i < b.limit(); i++) { |
210 byte c = b.get(i); | 226 byte c = b.get(i); |
211 if (ch == c) { | 227 if (ch == c) { |
212 return i; | 228 return i; |
213 } | 229 } |
214 if (newlineBreaks && (c == '\n' || c == '\r')) { | 230 if (newlineBreaks && (c == '\n' || c == '\r')) { |
236 return "<Sample> sample@sample.org"; | 252 return "<Sample> sample@sample.org"; |
237 } | 253 } |
238 | 254 |
239 public static class Factory implements Filter.Factory { | 255 public static class Factory implements Filter.Factory { |
240 | 256 |
241 public Filter create(HgRepository hgRepo, Path path) { | 257 public Filter create(HgRepository hgRepo, Path path, Options opts) { |
242 return new KeywordFilter(true); | 258 return new KeywordFilter(true); |
243 } | 259 } |
244 } | 260 } |
245 | 261 |
246 | 262 |
247 public static void main(String[] args) throws Exception { | 263 public static void main(String[] args) throws Exception { |
248 FileInputStream fis = new FileInputStream(new File("/temp/kwoutput.txt")); | 264 FileInputStream fis = new FileInputStream(new File("/temp/kwoutput.txt")); |
249 FileOutputStream fos = new FileOutputStream(new File("/temp/kwoutput2.txt")); | 265 FileOutputStream fos = new FileOutputStream(new File("/temp/kwoutput2.txt")); |
250 ByteBuffer b = ByteBuffer.allocateDirect(256); | 266 ByteBuffer b = ByteBuffer.allocate(256); |
251 KeywordFilter kwFilter = new KeywordFilter(false); | 267 KeywordFilter kwFilter = new KeywordFilter(false); |
252 while (fis.getChannel().read(b) != -1) { | 268 while (fis.getChannel().read(b) != -1) { |
253 b.flip(); // get ready to be read | 269 b.flip(); // get ready to be read |
254 ByteBuffer f = kwFilter.filter(b); | 270 ByteBuffer f = kwFilter.filter(b); |
255 fos.getChannel().write(f); | 271 fos.getChannel().write(f); // XXX in fact, f may not be fully consumed |
256 if (b.hasRemaining()) { | 272 if (b.hasRemaining()) { |
257 ByteBuffer remaining = b.slice(); | 273 b.compact(); |
258 b.clear(); | |
259 b.put(remaining); | |
260 } else { | 274 } else { |
261 b.clear(); | 275 b.clear(); |
262 } | 276 } |
263 } | 277 } |
264 fis.close(); | 278 fis.close(); |