129
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2006 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Port to the D programming language:
|
|
11 * Frank Benoit <benoit@tionex.de>
|
|
12 *******************************************************************************/
|
|
13 module dwtx.jface.text.SequentialRewriteTextStore;
|
|
14
|
|
15 import dwt.dwthelper.utils;
|
|
16
|
|
17
|
|
18 import java.util.Iterator;
|
|
19 import java.util.LinkedList;
|
|
20
|
|
21
|
|
22 /**
|
|
23 * A text store that optimizes a given source text store for sequential rewriting.
|
|
24 * While rewritten it keeps a list of replace command that serve as patches for
|
|
25 * the source store. Only on request, the source store is indeed manipulated
|
|
26 * by applying the patch commands to the source text store.
|
|
27 *
|
|
28 * @since 2.0
|
|
29 * @deprecated since 3.3 as {@link GapTextStore} performs better even for sequential rewrite scenarios
|
|
30 */
|
|
31 public class SequentialRewriteTextStore : ITextStore {
|
|
32
|
|
33 /**
|
|
34 * A buffered replace command.
|
|
35 */
|
|
36 private static class Replace {
|
|
37 public int newOffset;
|
|
38 public final int offset;
|
|
39 public final int length;
|
|
40 public final String text;
|
|
41
|
|
42 public Replace(int offset, int newOffset, int length, String text) {
|
|
43 this.newOffset= newOffset;
|
|
44 this.offset= offset;
|
|
45 this.length= length;
|
|
46 this.text= text;
|
|
47 }
|
|
48 }
|
|
49
|
|
50 /** The list of buffered replacements. */
|
|
51 private LinkedList fReplaceList;
|
|
52 /** The source text store */
|
|
53 private ITextStore fSource;
|
|
54 /** A flag to enforce sequential access. */
|
|
55 private static final bool ASSERT_SEQUENTIALITY= false;
|
|
56
|
|
57
|
|
58 /**
|
|
59 * Creates a new sequential rewrite store for the given source store.
|
|
60 *
|
|
61 * @param source the source text store
|
|
62 */
|
|
63 public SequentialRewriteTextStore(ITextStore source) {
|
|
64 fReplaceList= new LinkedList();
|
|
65 fSource= source;
|
|
66 }
|
|
67
|
|
68 /**
|
|
69 * Returns the source store of this rewrite store.
|
|
70 *
|
|
71 * @return the source store of this rewrite store
|
|
72 */
|
|
73 public ITextStore getSourceStore() {
|
|
74 commit();
|
|
75 return fSource;
|
|
76 }
|
|
77
|
|
78 /*
|
|
79 * @see dwtx.jface.text.ITextStore#replace(int, int, java.lang.String)
|
|
80 */
|
|
81 public void replace(int offset, int length, String text) {
|
|
82 if (text is null)
|
|
83 text= ""; //$NON-NLS-1$
|
|
84
|
|
85 if (fReplaceList.size() is 0) {
|
|
86 fReplaceList.add(new Replace(offset, offset, length, text));
|
|
87
|
|
88 } else {
|
|
89 Replace firstReplace= (Replace) fReplaceList.getFirst();
|
|
90 Replace lastReplace= (Replace) fReplaceList.getLast();
|
|
91
|
|
92 // backward
|
|
93 if (offset + length <= firstReplace.newOffset) {
|
|
94 int delta= text.length() - length;
|
|
95 if (delta !is 0) {
|
|
96 for (Iterator i= fReplaceList.iterator(); i.hasNext(); ) {
|
|
97 Replace replace= (Replace) i.next();
|
|
98 replace.newOffset += delta;
|
|
99 }
|
|
100 }
|
|
101
|
|
102 fReplaceList.addFirst(new Replace(offset, offset, length, text));
|
|
103
|
|
104 // forward
|
|
105 } else if (offset >= lastReplace.newOffset + lastReplace.text.length()) {
|
|
106 int delta= getDelta(lastReplace);
|
|
107 fReplaceList.add(new Replace(offset - delta, offset, length, text));
|
|
108
|
|
109 } else if (ASSERT_SEQUENTIALITY) {
|
|
110 throw new IllegalArgumentException();
|
|
111
|
|
112 } else {
|
|
113 commit();
|
|
114 fSource.replace(offset, length, text);
|
|
115 }
|
|
116 }
|
|
117 }
|
|
118
|
|
119 /*
|
|
120 * @see dwtx.jface.text.ITextStore#set(java.lang.String)
|
|
121 */
|
|
122 public void set(String text) {
|
|
123 fSource.set(text);
|
|
124 fReplaceList.clear();
|
|
125 }
|
|
126
|
|
127 /*
|
|
128 * @see dwtx.jface.text.ITextStore#get(int, int)
|
|
129 */
|
|
130 public String get(int offset, int length) {
|
|
131
|
|
132 if (fReplaceList.isEmpty())
|
|
133 return fSource.get(offset, length);
|
|
134
|
|
135
|
|
136 Replace firstReplace= (Replace) fReplaceList.getFirst();
|
|
137 Replace lastReplace= (Replace) fReplaceList.getLast();
|
|
138
|
|
139 // before
|
|
140 if (offset + length <= firstReplace.newOffset) {
|
|
141 return fSource.get(offset, length);
|
|
142
|
|
143 // after
|
|
144 } else if (offset >= lastReplace.newOffset + lastReplace.text.length()) {
|
|
145 int delta= getDelta(lastReplace);
|
|
146 return fSource.get(offset - delta, length);
|
|
147
|
|
148 } else if (ASSERT_SEQUENTIALITY) {
|
|
149 throw new IllegalArgumentException();
|
|
150
|
|
151 } else {
|
|
152
|
|
153 int delta= 0;
|
|
154 for (Iterator i= fReplaceList.iterator(); i.hasNext(); ) {
|
|
155 Replace replace= (Replace) i.next();
|
|
156
|
|
157 if (offset + length < replace.newOffset) {
|
|
158 return fSource.get(offset - delta, length);
|
|
159
|
|
160 } else if (offset >= replace.newOffset && offset + length <= replace.newOffset + replace.text.length()) {
|
|
161 return replace.text.substring(offset - replace.newOffset, offset - replace.newOffset + length);
|
|
162
|
|
163 } else if (offset >= replace.newOffset + replace.text.length()) {
|
|
164 delta= getDelta(replace);
|
|
165 continue;
|
|
166
|
|
167 } else {
|
|
168 commit();
|
|
169 return fSource.get(offset, length);
|
|
170 }
|
|
171 }
|
|
172
|
|
173 return fSource.get(offset - delta, length);
|
|
174 }
|
|
175
|
|
176 }
|
|
177
|
|
178 /**
|
|
179 * Returns the difference between the offset in the source store and the "same" offset in the
|
|
180 * rewrite store after the replace operation.
|
|
181 *
|
|
182 * @param replace the replace command
|
|
183 * @return the difference
|
|
184 */
|
|
185 private static final int getDelta(Replace replace) {
|
|
186 return replace.newOffset - replace.offset + replace.text.length() - replace.length;
|
|
187 }
|
|
188
|
|
189 /*
|
|
190 * @see dwtx.jface.text.ITextStore#get(int)
|
|
191 */
|
|
192 public char get(int offset) {
|
|
193 if (fReplaceList.isEmpty())
|
|
194 return fSource.get(offset);
|
|
195
|
|
196 Replace firstReplace= (Replace) fReplaceList.getFirst();
|
|
197 Replace lastReplace= (Replace) fReplaceList.getLast();
|
|
198
|
|
199 // before
|
|
200 if (offset < firstReplace.newOffset) {
|
|
201 return fSource.get(offset);
|
|
202
|
|
203 // after
|
|
204 } else if (offset >= lastReplace.newOffset + lastReplace.text.length()) {
|
|
205 int delta= getDelta(lastReplace);
|
|
206 return fSource.get(offset - delta);
|
|
207
|
|
208 } else if (ASSERT_SEQUENTIALITY) {
|
|
209 throw new IllegalArgumentException();
|
|
210
|
|
211 } else {
|
|
212
|
|
213 int delta= 0;
|
|
214 for (Iterator i= fReplaceList.iterator(); i.hasNext(); ) {
|
|
215 Replace replace= (Replace) i.next();
|
|
216
|
|
217 if (offset < replace.newOffset)
|
|
218 return fSource.get(offset - delta);
|
|
219
|
|
220 else if (offset < replace.newOffset + replace.text.length())
|
|
221 return replace.text.charAt(offset - replace.newOffset);
|
|
222
|
|
223 delta= getDelta(replace);
|
|
224 }
|
|
225
|
|
226 return fSource.get(offset - delta);
|
|
227 }
|
|
228 }
|
|
229
|
|
230 /*
|
|
231 * @see dwtx.jface.text.ITextStore#getLength()
|
|
232 */
|
|
233 public int getLength() {
|
|
234 if (fReplaceList.isEmpty())
|
|
235 return fSource.getLength();
|
|
236
|
|
237 Replace lastReplace= (Replace) fReplaceList.getLast();
|
|
238 return fSource.getLength() + getDelta(lastReplace);
|
|
239 }
|
|
240
|
|
241 /**
|
|
242 * Disposes this rewrite store.
|
|
243 */
|
|
244 public void dispose() {
|
|
245 fReplaceList= null;
|
|
246 fSource= null;
|
|
247 }
|
|
248
|
|
249 /**
|
|
250 * Commits all buffered replace commands.
|
|
251 */
|
|
252 private void commit() {
|
|
253
|
|
254 if (fReplaceList.isEmpty())
|
|
255 return;
|
|
256
|
|
257 StringBuffer buffer= new StringBuffer();
|
|
258
|
|
259 int delta= 0;
|
|
260 for (Iterator i= fReplaceList.iterator(); i.hasNext(); ) {
|
|
261 Replace replace= (Replace) i.next();
|
|
262
|
|
263 int offset= buffer.length() - delta;
|
|
264 buffer.append(fSource.get(offset, replace.offset - offset));
|
|
265 buffer.append(replace.text);
|
|
266 delta= getDelta(replace);
|
|
267 }
|
|
268
|
|
269 int offset= buffer.length() - delta;
|
|
270 buffer.append(fSource.get(offset, fSource.getLength() - offset));
|
|
271
|
|
272 fSource.set(buffer.toString());
|
|
273 fReplaceList.clear();
|
|
274 }
|
|
275 }
|