View Javadoc

1   
2   package org.tartarus.snowball;
3   import java.lang.reflect.InvocationTargetException;
4   
5   public class SnowballProgram {
6       protected SnowballProgram()
7       {
8   	current = new StringBuffer();
9   	setCurrent("");
10      }
11  
12      /***
13       * Set the current string.
14       */
15      public void setCurrent(String value)
16      {
17  	current.replace(0, current.length(), value);
18  	cursor = 0;
19  	limit = current.length();
20  	limit_backward = 0;
21  	bra = cursor;
22  	ket = limit;
23      }
24  
25      /***
26       * Get the current string.
27       */
28      public String getCurrent()
29      {
30          String result = current.toString();
31          // Make a new StringBuffer.  If we reuse the old one, and a user of
32          // the library keeps a reference to the buffer returned (for example,
33          // by converting it to a String in a way which doesn't force a copy),
34          // the buffer size will not decrease, and we will risk wasting a large
35          // amount of memory.
36          // Thanks to Wolfram Esser for spotting this problem.
37          current = new StringBuffer();
38          return result;
39      }
40  
41      // current string
42      protected StringBuffer current;
43  
44      protected int cursor;
45      protected int limit;
46      protected int limit_backward;
47      protected int bra;
48      protected int ket;
49  
50      protected void copy_from(SnowballProgram other)
51      {
52  	current          = other.current;
53  	cursor           = other.cursor;
54  	limit            = other.limit;
55  	limit_backward   = other.limit_backward;
56  	bra              = other.bra;
57  	ket              = other.ket;
58      }
59  
60      protected boolean in_grouping(char [] s, int min, int max)
61      {
62  	if (cursor >= limit) return false;
63  	char ch = current.charAt(cursor);
64  	if (ch > max || ch < min) return false;
65  	ch -= min;
66  	if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return false;
67  	cursor++;
68  	return true;
69      }
70  
71      protected boolean in_grouping_b(char [] s, int min, int max)
72      {
73  	if (cursor <= limit_backward) return false;
74  	char ch = current.charAt(cursor - 1);
75  	if (ch > max || ch < min) return false;
76  	ch -= min;
77  	if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) return false;
78  	cursor--;
79  	return true;
80      }
81  
82      protected boolean out_grouping(char [] s, int min, int max)
83      {
84  	if (cursor >= limit) return false;
85  	char ch = current.charAt(cursor);
86  	if (ch > max || ch < min) {
87  	    cursor++;
88  	    return true;
89  	}
90  	ch -= min;
91  	if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) {
92  	    cursor ++;
93  	    return true;
94  	}
95  	return false;
96      }
97  
98      protected boolean out_grouping_b(char [] s, int min, int max)
99      {
100 	if (cursor <= limit_backward) return false;
101 	char ch = current.charAt(cursor - 1);
102 	if (ch > max || ch < min) {
103 	    cursor--;
104 	    return true;
105 	}
106 	ch -= min;
107 	if ((s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) {
108 	    cursor--;
109 	    return true;
110 	}
111 	return false;
112     }
113 
114     protected boolean in_range(int min, int max)
115     {
116 	if (cursor >= limit) return false;
117 	char ch = current.charAt(cursor);
118 	if (ch > max || ch < min) return false;
119 	cursor++;
120 	return true;
121     }
122 
123     protected boolean in_range_b(int min, int max)
124     {
125 	if (cursor <= limit_backward) return false;
126 	char ch = current.charAt(cursor - 1);
127 	if (ch > max || ch < min) return false;
128 	cursor--;
129 	return true;
130     }
131 
132     protected boolean out_range(int min, int max)
133     {
134 	if (cursor >= limit) return false;
135 	char ch = current.charAt(cursor);
136 	if (!(ch > max || ch < min)) return false;
137 	cursor++;
138 	return true;
139     }
140 
141     protected boolean out_range_b(int min, int max)
142     {
143 	if (cursor <= limit_backward) return false;
144 	char ch = current.charAt(cursor - 1);
145 	if(!(ch > max || ch < min)) return false;
146 	cursor--;
147 	return true;
148     }
149 
150     protected boolean eq_s(int s_size, String s)
151     {
152 	if (limit - cursor < s_size) return false;
153 	int i;
154 	for (i = 0; i != s_size; i++) {
155 	    if (current.charAt(cursor + i) != s.charAt(i)) return false;
156 	}
157 	cursor += s_size;
158 	return true;
159     }
160 
161     protected boolean eq_s_b(int s_size, String s)
162     {
163 	if (cursor - limit_backward < s_size) return false;
164 	int i;
165 	for (i = 0; i != s_size; i++) {
166 	    if (current.charAt(cursor - s_size + i) != s.charAt(i)) return false;
167 	}
168 	cursor -= s_size;
169 	return true;
170     }
171 
172     protected boolean eq_v(CharSequence s)
173     {
174 	return eq_s(s.length(), s.toString());
175     }
176 
177     protected boolean eq_v_b(CharSequence s)
178     {   return eq_s_b(s.length(), s.toString());
179     }
180 
181     protected int find_among(Among v[], int v_size)
182     {
183 	int i = 0;
184 	int j = v_size;
185 
186 	int c = cursor;
187 	int l = limit;
188 
189 	int common_i = 0;
190 	int common_j = 0;
191 
192 	boolean first_key_inspected = false;
193 
194 	while(true) {
195 	    int k = i + ((j - i) >> 1);
196 	    int diff = 0;
197 	    int common = common_i < common_j ? common_i : common_j; // smaller
198 	    Among w = v[k];
199 	    int i2;
200 	    for (i2 = common; i2 < w.s_size; i2++) {
201 		if (c + common == l) {
202 		    diff = -1;
203 		    break;
204 		}
205 		diff = current.charAt(c + common) - w.s[i2];
206 		if (diff != 0) break;
207 		common++;
208 	    }
209 	    if (diff < 0) {
210 		j = k;
211 		common_j = common;
212 	    } else {
213 		i = k;
214 		common_i = common;
215 	    }
216 	    if (j - i <= 1) {
217 		if (i > 0) break; // v->s has been inspected
218 		if (j == i) break; // only one item in v
219 
220 		// - but now we need to go round once more to get
221 		// v->s inspected. This looks messy, but is actually
222 		// the optimal approach.
223 
224 		if (first_key_inspected) break;
225 		first_key_inspected = true;
226 	    }
227 	}
228 	while(true) {
229 	    Among w = v[i];
230 	    if (common_i >= w.s_size) {
231 		cursor = c + w.s_size;
232 		if (w.method == null) return w.result;
233 		boolean res;
234 		try {
235 		    Object resobj = w.method.invoke(w.methodobject,
236 						    new Object[0]);
237 		    res = resobj.toString().equals("true");
238 		} catch (InvocationTargetException e) {
239 		    res = false;
240 		    // FIXME - debug message
241 		} catch (IllegalAccessException e) {
242 		    res = false;
243 		    // FIXME - debug message
244 		}
245 		cursor = c + w.s_size;
246 		if (res) return w.result;
247 	    }
248 	    i = w.substring_i;
249 	    if (i < 0) return 0;
250 	}
251     }
252 
253     // find_among_b is for backwards processing. Same comments apply
254     protected int find_among_b(Among v[], int v_size)
255     {
256 	int i = 0;
257 	int j = v_size;
258 
259 	int c = cursor;
260 	int lb = limit_backward;
261 
262 	int common_i = 0;
263 	int common_j = 0;
264 
265 	boolean first_key_inspected = false;
266 
267 	while(true) {
268 	    int k = i + ((j - i) >> 1);
269 	    int diff = 0;
270 	    int common = common_i < common_j ? common_i : common_j;
271 	    Among w = v[k];
272 	    int i2;
273 	    for (i2 = w.s_size - 1 - common; i2 >= 0; i2--) {
274 		if (c - common == lb) {
275 		    diff = -1;
276 		    break;
277 		}
278 		diff = current.charAt(c - 1 - common) - w.s[i2];
279 		if (diff != 0) break;
280 		common++;
281 	    }
282 	    if (diff < 0) {
283 		j = k;
284 		common_j = common;
285 	    } else {
286 		i = k;
287 		common_i = common;
288 	    }
289 	    if (j - i <= 1) {
290 		if (i > 0) break;
291 		if (j == i) break;
292 		if (first_key_inspected) break;
293 		first_key_inspected = true;
294 	    }
295 	}
296 	while(true) {
297 	    Among w = v[i];
298 	    if (common_i >= w.s_size) {
299 		cursor = c - w.s_size;
300 		if (w.method == null) return w.result;
301 
302 		boolean res;
303 		try {
304 		    Object resobj = w.method.invoke(w.methodobject,
305 						    new Object[0]);
306 		    res = resobj.toString().equals("true");
307 		} catch (InvocationTargetException e) {
308 		    res = false;
309 		    // FIXME - debug message
310 		} catch (IllegalAccessException e) {
311 		    res = false;
312 		    // FIXME - debug message
313 		}
314 		cursor = c - w.s_size;
315 		if (res) return w.result;
316 	    }
317 	    i = w.substring_i;
318 	    if (i < 0) return 0;
319 	}
320     }
321 
322     /* to replace chars between c_bra and c_ket in current by the
323      * chars in s.
324      */
325     protected int replace_s(int c_bra, int c_ket, String s)
326     {
327 	int adjustment = s.length() - (c_ket - c_bra);
328 	current.replace(c_bra, c_ket, s);
329 	limit += adjustment;
330 	if (cursor >= c_ket) cursor += adjustment;
331 	else if (cursor > c_bra) cursor = c_bra;
332 	return adjustment;
333     }
334 
335     protected void slice_check()
336     {
337 	if (bra < 0 ||
338 	    bra > ket ||
339 	    ket > limit ||
340 	    limit > current.length())   // this line could be removed
341 	{
342 	    System.err.println("faulty slice operation");
343 	// FIXME: report error somehow.
344 	/*
345 	    fprintf(stderr, "faulty slice operation:\n");
346 	    debug(z, -1, 0);
347 	    exit(1);
348 	    */
349 	}
350     }
351 
352     protected void slice_from(String s)
353     {
354 	slice_check();
355 	replace_s(bra, ket, s);
356     }
357 
358     protected void slice_from(CharSequence s)
359     {
360         slice_from(s.toString());
361     }
362 
363     protected void slice_del()
364     {
365 	slice_from("");
366     }
367 
368     protected void insert(int c_bra, int c_ket, String s)
369     {
370 	int adjustment = replace_s(c_bra, c_ket, s);
371 	if (c_bra <= bra) bra += adjustment;
372 	if (c_bra <= ket) ket += adjustment;
373     }
374 
375     protected void insert(int c_bra, int c_ket, CharSequence s)
376     {
377 	insert(c_bra, c_ket, s.toString());
378     }
379 
380     /* Copy the slice into the supplied StringBuffer */
381     protected StringBuffer slice_to(StringBuffer s)
382     {
383 	slice_check();
384 	int len = ket - bra;
385 	s.replace(0, s.length(), current.substring(bra, ket));
386 	return s;
387     }
388 
389     /* Copy the slice into the supplied StringBuilder */
390     protected StringBuilder slice_to(StringBuilder s)
391     {
392 	slice_check();
393 	int len = ket - bra;
394 	s.replace(0, s.length(), current.substring(bra, ket));
395 	return s;
396     }
397 
398     protected StringBuffer assign_to(StringBuffer s)
399     {
400 	s.replace(0, s.length(), current.substring(0, limit));
401 	return s;
402     }
403 
404     protected StringBuilder assign_to(StringBuilder s)
405     {
406 	s.replace(0, s.length(), current.substring(0, limit));
407 	return s;
408     }
409 
410 /*
411 extern void debug(struct SN_env * z, int number, int line_count)
412 {   int i;
413     int limit = SIZE(z->p);
414     //if (number >= 0) printf("%3d (line %4d): '", number, line_count);
415     if (number >= 0) printf("%3d (line %4d): [%d]'", number, line_count,limit);
416     for (i = 0; i <= limit; i++)
417     {   if (z->lb == i) printf("{");
418         if (z->bra == i) printf("[");
419         if (z->c == i) printf("|");
420         if (z->ket == i) printf("]");
421         if (z->l == i) printf("}");
422         if (i < limit)
423         {   int ch = z->p[i];
424             if (ch == 0) ch = '#';
425             printf("%c", ch);
426         }
427     }
428     printf("'\n");
429 }
430 */
431 
432 };