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 }