Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/KeywordFilter.java @ 119:ed2b4adac51c
Index and start of the copy are distinct
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 04 Feb 2011 03:09:15 +0100 |
parents | 68ba22a2133a |
children | b1d6208fb517 |
comparison
equal
deleted
inserted
replaced
118:68ba22a2133a | 119:ed2b4adac51c |
---|---|
83 throw new IllegalStateException(String.format("Need buffer of at least %d bytes to ensure filter won't hang", minBufferLen)); | 83 throw new IllegalStateException(String.format("Need buffer of at least %d bytes to ensure filter won't hang", minBufferLen)); |
84 } | 84 } |
85 ByteBuffer rv = null; | 85 ByteBuffer rv = null; |
86 int keywordStart = -1; | 86 int keywordStart = -1; |
87 int x = src.position(); | 87 int x = src.position(); |
88 int copyFrom = x; // needs to be updated each time we copy a slice, but not each time we modify source index (x) | |
88 while (x < src.limit()) { | 89 while (x < src.limit()) { |
89 if (keywordStart == -1) { | 90 if (keywordStart == -1) { |
90 int i = indexOf(src, '$', x, false); | 91 int i = indexOf(src, '$', x, false); |
91 if (i == -1) { | 92 if (i == -1) { |
92 if (rv == null) { | 93 if (rv == null) { |
93 return src; | 94 return src; |
94 } else { | 95 } else { |
95 copySlice(src, x, src.limit(), rv); | 96 copySlice(src, copyFrom, src.limit(), rv); |
96 rv.flip(); | 97 rv.flip(); |
97 src.position(src.limit()); | 98 src.position(src.limit()); |
98 return rv; | 99 return rv; |
99 } | 100 } |
100 } | 101 } |
115 throw new IllegalStateException("Try src buffer of a greater size"); | 116 throw new IllegalStateException("Try src buffer of a greater size"); |
116 } | 117 } |
117 rv = ByteBuffer.allocate(keywordStart - x); | 118 rv = ByteBuffer.allocate(keywordStart - x); |
118 } | 119 } |
119 // copy all from source till latest possible kw start | 120 // copy all from source till latest possible kw start |
120 copySlice(src, x, keywordStart, rv); | 121 copySlice(src, copyFrom, keywordStart, rv); |
121 rv.flip(); | 122 rv.flip(); |
122 // and tell caller we've consumed only to the potential kw start | 123 // and tell caller we've consumed only to the potential kw start |
123 src.position(keywordStart); | 124 src.position(keywordStart); |
124 return rv; | 125 return rv; |
125 } else if (src.get(i) == '$') { | 126 } else if (src.get(i) == '$') { |
130 // src.remaining(), not .capacity because src is not read, and remaining represents | 131 // src.remaining(), not .capacity because src is not read, and remaining represents |
131 // actual bytes count, while capacity - potential. | 132 // actual bytes count, while capacity - potential. |
132 // Factor of 4 is pure guess and a HACK, need to be fixed with re-expanding buffer on demand | 133 // Factor of 4 is pure guess and a HACK, need to be fixed with re-expanding buffer on demand |
133 rv = ByteBuffer.allocate(isExpanding ? src.remaining() * 4 : src.remaining()); | 134 rv = ByteBuffer.allocate(isExpanding ? src.remaining() * 4 : src.remaining()); |
134 } | 135 } |
135 copySlice(src, x, keywordStart+1, rv); | 136 copySlice(src, copyFrom, keywordStart+1, rv); |
136 rv.put(keyword.getBytes()); | 137 rv.put(keyword.getBytes()); |
137 if (isExpanding) { | 138 if (isExpanding) { |
138 rv.put((byte) ':'); | 139 rv.put((byte) ':'); |
139 rv.put((byte) ' '); | 140 rv.put((byte) ' '); |
140 expandKeywordValue(keyword, rv); | 141 expandKeywordValue(keyword, rv); |
141 rv.put((byte) ' '); | 142 rv.put((byte) ' '); |
142 } | 143 } |
143 rv.put((byte) '$'); | 144 rv.put((byte) '$'); |
144 keywordStart = -1; | 145 keywordStart = -1; |
145 x = i+1; | 146 x = i+1; |
147 copyFrom = x; | |
146 continue; | 148 continue; |
147 } else { | 149 } else { |
148 if (rv != null) { | 150 if (rv != null) { |
149 // we've already did some substitution, thus need to copy bytes we've scanned. | 151 // we've already did some substitution, thus need to copy bytes we've scanned. |
150 copySlice(src, x, i, rv); | 152 copySlice(src, x, i, rv); |
153 copyFrom = i; | |
151 } // no else in attempt to avoid rv creation if no real kw would be found | 154 } // no else in attempt to avoid rv creation if no real kw would be found |
152 keywordStart = i; | 155 keywordStart = i; |
153 x = i; // '$' at i wasn't consumed, hence x points to i, not i+1. This is to avoid problems with case: "sdfsd $ asdfs $Id$ sdf" | 156 x = i; // '$' at i wasn't consumed, hence x points to i, not i+1. This is to avoid problems with case: "sdfsd $ asdfs $Id$ sdf" |
154 continue; | 157 continue; |
155 } | 158 } |
156 } else { | 159 } else { |
157 assert src.get(i) == '\n' || src.get(i) == '\r'; | 160 assert src.get(i) == '\n' || src.get(i) == '\r'; |
158 // line break | 161 // line break |
159 if (rv != null) { | 162 if (rv != null) { |
160 copySlice(src, x, i+1, rv); | 163 copySlice(src, x, i+1, rv); |
164 copyFrom = i+1; | |
161 } | 165 } |
162 x = i+1; | 166 x = i+1; |
163 keywordStart = -1; // Wasn't keyword, really | 167 keywordStart = -1; // Wasn't keyword, really |
164 continue; // try once again | 168 continue; // try once again |
165 } | 169 } |